Prechádzať zdrojové kódy

Remove old PHP target (#6612)

* remove old PHP generator

* remove failing test

* remove more PHP code

* renamed php7 stuff to php

* some cleanup

* cleanup

* case var (#6608)

* [matcher] allow and encourage `case var <ident>` (see #6207)

* [std] add `case var` everywhere

* [matcher] give similarity warnings for plain idents

* fix tests

* remove old PHP generator

* remove failing test

* remove more PHP code

* renamed php7 stuff to php

* some cleanup

* cleanup

* typo

* resolve appveyor conflict
Alexander Kuzmenko 7 rokov pred
rodič
commit
36cbdad8a4
100 zmenil súbory, kde vykonal 2533 pridanie a 5199 odobranie
  1. 1 1
      .travis.yml
  2. 1 1
      appveyor.yml
  3. 1 0
      extra/CHANGES.txt
  4. 1 6
      extra/ImportAll.hx
  5. 0 6
      extra/all.hxml
  6. 2 12
      src/compiler/main.ml
  7. 7 16
      src/context/common.ml
  8. 5 7
      src/context/meta.ml
  9. 0 2437
      src/generators/genphp.ml
  10. 1 1
      src/generators/genphp7.ml
  11. 3 14
      src/optimization/analyzerTexpr.ml
  12. 0 1
      src/optimization/filters.ml
  13. 1 1
      src/typing/typeload.ml
  14. 1 1
      src/typing/typer.ml
  15. 0 4
      std/Math.hx
  16. 0 14
      std/haxe/CallStack.hx
  17. 1 1
      std/haxe/Int32.hx
  18. 0 2
      std/haxe/Resource.hx
  19. 2 4
      std/haxe/Serializer.hx
  20. 3 7
      std/haxe/crypto/Md5.hx
  21. 2 15
      std/haxe/crypto/Sha1.hx
  22. 0 8
      std/haxe/crypto/Sha224.hx
  23. 2 10
      std/haxe/crypto/Sha256.hx
  24. 1 24
      std/haxe/io/Bytes.hx
  25. 0 12
      std/haxe/io/BytesBuffer.hx
  26. 0 2
      std/haxe/io/BytesData.hx
  27. 0 4
      std/haxe/io/BytesInput.hx
  28. 0 16
      std/haxe/io/FPHelper.hx
  29. 20 26
      std/haxe/rtti/Meta.hx
  30. 0 0
      std/php/ArrayAccess.hx
  31. 731 800
      std/php/Boot.hx
  32. 0 94
      std/php/BytesData.hx
  33. 0 0
      std/php/Closure.hx
  34. 0 0
      std/php/Const.hx
  35. 0 0
      std/php/Error.hx
  36. 0 0
      std/php/ErrorException.hx
  37. 14 16
      std/php/Exception.hx
  38. 0 0
      std/php/Global.hx
  39. 0 30
      std/php/HException.hx
  40. 1 0
      std/php/IteratorAggregate.hx
  41. 79 97
      std/php/Lib.hx
  42. 43 2
      std/php/NativeArray.hx
  43. 0 0
      std/php/NativeAssocArray.hx
  44. 0 0
      std/php/NativeIndexedArray.hx
  45. 6 1
      std/php/NativeString.hx
  46. 0 0
      std/php/NativeStructArray.hx
  47. 0 364
      std/php/NativeXml.hx
  48. 0 0
      std/php/Ref.hx
  49. 9 0
      std/php/Resource.hx
  50. 2 25
      std/php/RuntimeException.hx
  51. 0 0
      std/php/Scalar.hx
  52. 34 31
      std/php/Session.hx
  53. 0 0
      std/php/SessionHandlerInterface.hx
  54. 0 0
      std/php/StdClass.hx
  55. 0 0
      std/php/SuperGlobal.hx
  56. 0 0
      std/php/Syntax.hx
  57. 0 0
      std/php/Throwable.hx
  58. 0 0
      std/php/Traversable.hx
  59. 102 85
      std/php/Web.hx
  60. 0 0
      std/php/_std/Array.hx
  61. 18 14
      std/php/_std/Date.hx
  62. 44 28
      std/php/_std/EReg.hx
  63. 31 44
      std/php/_std/Math.hx
  64. 109 53
      std/php/_std/Reflect.hx
  65. 36 26
      std/php/_std/Std.hx
  66. 0 0
      std/php/_std/String.hx
  67. 13 2
      std/php/_std/StringBuf.hx
  68. 33 26
      std/php/_std/StringTools.hx
  69. 53 43
      std/php/_std/Sys.hx
  70. 252 158
      std/php/_std/Type.hx
  71. 0 0
      std/php/_std/haxe/CallStack.hx
  72. 63 51
      std/php/_std/haxe/Json.hx
  73. 1 8
      std/php/_std/haxe/Log.hx
  74. 2 1
      std/php/_std/haxe/Resource.hx
  75. 13 10
      std/php/_std/haxe/Utf8.hx
  76. 0 0
      std/php/_std/haxe/crypto/Md5.hx
  77. 0 0
      std/php/_std/haxe/crypto/Sha1.hx
  78. 0 0
      std/php/_std/haxe/crypto/Sha224.hx
  79. 0 0
      std/php/_std/haxe/crypto/Sha256.hx
  80. 55 41
      std/php/_std/haxe/ds/IntMap.hx
  81. 0 167
      std/php/_std/haxe/ds/List.hx
  82. 22 29
      std/php/_std/haxe/ds/ObjectMap.hx
  83. 30 40
      std/php/_std/haxe/ds/StringMap.hx
  84. 0 0
      std/php/_std/haxe/io/Bytes.hx
  85. 0 0
      std/php/_std/haxe/io/BytesBuffer.hx
  86. 0 0
      std/php/_std/haxe/io/BytesData.hx
  87. 0 0
      std/php/_std/haxe/io/BytesInput.hx
  88. 0 0
      std/php/_std/haxe/io/BytesOutput.hx
  89. 0 0
      std/php/_std/haxe/io/FPHelper.hx
  90. 44 44
      std/php/_std/sys/FileSystem.hx
  91. 210 21
      std/php/_std/sys/db/Mysql.hx
  92. 164 2
      std/php/_std/sys/db/Sqlite.hx
  93. 9 9
      std/php/_std/sys/io/File.hx
  94. 31 26
      std/php/_std/sys/io/FileInput.hx
  95. 22 18
      std/php/_std/sys/io/FileOutput.hx
  96. 153 96
      std/php/_std/sys/io/Process.hx
  97. 7 4
      std/php/_std/sys/net/Host.hx
  98. 42 40
      std/php/_std/sys/net/Socket.hx
  99. 0 0
      std/php/db/Mysqli.hx
  100. 0 0
      std/php/db/Mysqli_driver.hx

+ 1 - 1
.travis.yml

@@ -183,7 +183,7 @@ matrix:
     #########
     - os: linux
       env:
-        - TEST=macro,neko,js,php,php7,flash9,as3,java,cs,python,hl,lua
+        - TEST=macro,neko,js,php,flash9,as3,java,cs,python,hl,lua
         - DEPLOY_API_DOCS=1
         - DEPLOY_NIGHTLIES=1
         # - SAUCE=1

+ 1 - 1
appveyor.yml

@@ -14,7 +14,7 @@ environment:
           secure: ewwkKcjnSKl/Vtrz1SXmI6XKk1ENmJDyzm5YaR2wi03foRhTke29TvymB21rDTSl
     matrix:
         - ARCH: 64
-          TEST: "neko,python,cs,java,php7,php,macro"
+          TEST: "neko,python,cs,java,php,macro"
           DEPLOY_NIGHTLIES: 1
         - ARCH: 64
           TEST: "cpp"

+ 1 - 0
extra/CHANGES.txt

@@ -13,6 +13,7 @@
 
 	all : moved haxe.unit to hx3compat
 	all : moved haxe.web.Request to hx3compat
+	php : dropped php5 support; minimum supported php version is 7.0 now
 
 	Bugfixes:
 

+ 1 - 6
extra/ImportAll.hx

@@ -29,10 +29,8 @@ class ImportAll {
 			haxe.macro.Compiler.define("doc_gen");
 		}
 		switch( pack ) {
-		case "php7":
-			if( !Context.defined("php7") ) return;
 		case "php":
-			if( !Context.defined("php") || Context.defined("php7") ) return;
+			if( !Context.defined("php") ) return;
 		case "neko":
 			if( !Context.defined("neko") ) return;
 		case "js":
@@ -87,9 +85,6 @@ class ImportAll {
 					case "haxe.remoting.SyncSocketConnection": if( !(Context.defined("neko") || Context.defined("php") || Context.defined("cpp")) ) continue;
 					case "sys.db.Sqlite" | "sys.db.Mysql" | "cs.db.AdoNet": continue;
 					}
-					if( Context.defined("php7") && cl.indexOf("php7.") == 0 ) {
-						cl = "php." + cl.substr("php7.".length);
-					}
 					Context.getModule(cl);
 				} else if( sys.FileSystem.isDirectory(p + "/" + file) )
 					run(full);

+ 0 - 6
extra/all.hxml

@@ -19,12 +19,6 @@
 
 --next
 
--D php7
--php all_php7
--xml php7.xml
-
---next
-
 -php all_php
 -xml php.xml
 

+ 2 - 12
src/compiler/main.ml

@@ -242,14 +242,7 @@ module Initialize = struct
 				add_std "lua";
 				"lua"
 			| Php ->
-				if Common.is_php7 com then
-					begin
-						com.package_rules <- PMap.add "php" (Directory "php7") com.package_rules;
-						com.package_rules <- PMap.add "php7" Forbidden com.package_rules;
-						add_std "php7"
-					end
-				else
-					add_std "php";
+				add_std "php";
 				"php"
 			| Cpp ->
 				Common.define_value com Define.HxcppApiLevel "332";
@@ -321,10 +314,7 @@ let generate tctx ext xml_out interp swf_header =
 		| Lua ->
 			Genlua.generate,"lua"
 		| Php ->
-			if Common.is_php7 com then
-				Genphp7.generate,"php"
-			else
-				Genphp.generate,"php"
+			Genphp7.generate,"php"
 		| Cpp ->
 			Gencpp.generate,"cpp"
 		| Cs ->

+ 7 - 16
src/context/common.ml

@@ -324,8 +324,6 @@ let get_signature com =
 		com.defines_signature <- Some s;
 		s
 
-let is_php7 com = com.platform = Php && PMap.exists "php7" com.defines
-
 module CompilationServer = struct
 	type cache = {
 		c_haxelib : (string list, string list) Hashtbl.t;
@@ -607,7 +605,7 @@ module Define = struct
 		| JsEnumsAsObjects -> "js_enums_as_objects",("Generate enum representation as object instead of as array",[Platform Js])
 		| JsUnflatten -> "js_unflatten",("Generate nested objects for packages and types",[Platform Js])
 		| JsSourceMap -> "js_source_map",("Generate JavaScript source map even in non-debug mode",[Platform Js])
-		| SourceMap -> "source_map",("Generate source map for compiled files (Currently supported for php7 only)",[Platform Php])
+		| SourceMap -> "source_map",("Generate source map for compiled files (Currently supported for php only)",[Platform Php])
 		| KeepOldOutput -> "keep_old_output",("Keep old source files in the output directory (for C#/Java)",[Platforms [Cs;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)",[Platform Lua])
@@ -634,8 +632,8 @@ module Define = struct
 		| Objc -> "objc",("Sets the hxcpp output to objective-c++ classes. Must be defined for interop",[Platform Cpp])
 		| OldConstructorInline -> "old-constructor-inline",("Use old constructor inlining logic (from haxe 3.4.2) instead of the reworked version.",[])
 		| OldErrorFormat -> "old-error-format",("Use Haxe 3.x zero-based column error messages instead of new one-based format.",[])
-		| PhpPrefix -> "php_prefix",("Compiled with --php-prefix",[Platform Php])
-		| RealPosition -> "real_position",("Disables Haxe source mapping when targetting C#, removes position comments in Java and Php7 output",[Platforms [Cs;Java;Php]])
+		| PhpPrefix -> "php_prefix",("Root namespace for generated php classes. E.g. if compiled with`--php-prefix some.sub`, then all classes will be generated in `\\some\\sub` namespace.",[Platform Php])
+		| RealPosition -> "real_position",("Disables Haxe source mapping when targetting C#, removes position comments in Java and Php output",[Platforms [Cs;Java;Php]])
 		| ReplaceFiles -> "replace_files",("GenCommon internal",[Platforms [Java;Cs]])
 		| Scriptable -> "scriptable",("GenCPP internal",[Platform Cpp])
 		| ShallowExpose -> "shallow-expose",("Expose types to surrounding scope of Haxe generated closure without writing to window object",[Platform Js])
@@ -756,17 +754,10 @@ let get_config com =
 			pf_reserved_type_paths = [([],"Object");([],"Error")];
 		}
 	| Php ->
-		if is_php7 com then
-			{
-				default_config with
-				pf_static = false;
-			}
-		else
-			{
-				default_config with
-				pf_static = false;
-				pf_pad_nulls = true;
-			}
+		{
+			default_config with
+			pf_static = false;
+		}
 	| Cpp ->
 		{
 			default_config with

+ 5 - 7
src/context/meta.ml

@@ -89,7 +89,7 @@ type strict_meta =
 	| LibType
 	| LoopLabel
 	| LuaRequire
-	| LuaDotMethod 
+	| LuaDotMethod
 	| Meta
 	| Macro
 	| MaybeUsed
@@ -119,7 +119,6 @@ type strict_meta =
 	| Op
 	| Optional
 	| Overload
-	| PhpConstants
 	| PhpGlobal
 	| PhpClassConst
 	| PhpMagic
@@ -317,11 +316,10 @@ let get_info = function
 	| Op -> ":op",("Declares an abstract field as being an operator overload",[HasParam "The operation";UsedOn TAbstractField])
 	| Optional -> ":optional",("Marks the field of a structure as optional",[UsedOn TClassField])
 	| Overload -> ":overload",("Allows the field to be called with different argument types",[HasParam "Function specification (no expression)";UsedOn TClassField])
-	| PhpConstants -> ":phpConstants",("Marks the static fields of a class as PHP constants, without $",[Platform Php;UsedOn TClass])
-	| PhpGlobal -> ":phpGlobal",("(php7) Puts the static fields of a class in the global PHP namespace",[Platform Php;UsedOn TClass])
-	| PhpClassConst -> ":phpClassConst",("(php7)  Generate static var of an extern class as a PHP class constant",[Platform Php;UsedOn TClass])
-	| PhpMagic -> ":phpMagic",("(php7) Treat annotated field as special PHP magic field",[Platform Php;UsedOn TClassField])
-	| PhpNoConstructor -> ":phpNoConstructor",("(php7) Special meta for extern classes which does not have native constructor in PHP, but need a constructor in Haxe extern",[Platform Php;UsedOn TClass])
+	| PhpGlobal -> ":phpGlobal",("Indicates that static fields of an extern class actually are located in the global PHP namespace",[Platform Php;UsedOn TClass])
+	| PhpClassConst -> ":phpClassConst",("Indicates that a static var of an extern class is a PHP class constant",[Platform Php;UsedOn TClassField])
+	| PhpMagic -> ":phpMagic",("Treat annotated field as special PHP magic field. This meta makes compiler avoid renaming such fields on generating PHP code.",[Platform Php;UsedOn TClassField])
+	| PhpNoConstructor -> ":phpNoConstructor",("Special meta for extern classes which do not have native constructor in PHP, but need a constructor in Haxe extern",[Platform Php;UsedOn TClass])
 	| Pos -> ":pos",("Sets the position of a reified expression",[HasParam "Position";UsedOn TExpr])
 	| Public -> ":public",("Marks a class field as being public",[UsedOn TClassField;UsedInternally])
 	| PublicFields -> ":publicFields",("Forces all class fields of inheriting classes to be public",[UsedOn TClass])

+ 0 - 2437
src/generators/genphp.ml

@@ -1,2437 +0,0 @@
-(*
-	The Haxe Compiler
-	Copyright (C) 2005-2017  Haxe Foundation
-
-	This program is free software; you can redistribute it and/or
-	modify it under the terms of the GNU General Public License
-	as published by the Free Software Foundation; either version 2
-	of the License, or (at your option) any later version.
-
-	This program is distributed in the hope that it will be useful,
-	but WITHOUT ANY WARRANTY; without even the implied warranty of
-	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-	GNU General Public License for more details.
-
-	You should have received a copy of the GNU General Public License
-	along with this program; if not, write to the Free Software
-	Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- *)
-
-open Ast
-open Type
-open Common
-open Codegen
-
-type method_name = {
-	mutable mpath : path;
-	mutable mname : string;
-}
-
-type inline_method = {
-	iname       : string;
-	iindex      : int;
-	iexpr       : texpr;
-	ihasthis    : bool;
-	iin_block   : bool;
-	iarguments  : string list;
-	ilocals     : (string,string) PMap.t;
-	iinv_locals : (string,string) PMap.t;
-}
-
-type context = {
-	com : Common.context;
-	ch : out_channel;
-	buf : Buffer.t;
-	path : path;
-	stack : Codegen.stack_context;
-	mutable nested_loops : int;
-	mutable inline_index : int;
-	mutable curclass : tclass;
-	mutable curmethod : string;
-	mutable tabs : string;
-	mutable in_value : string option;
-	mutable in_loop : bool;
-	mutable in_block : bool;
-	mutable in_instance_method : bool;
-	mutable imports : (string,string list list) Hashtbl.t;
-	mutable extern_required_paths : (string list * string) list;
-	mutable extern_classes_with_init : path list;
-	mutable locals : (string,string) PMap.t;
-	mutable inv_locals : (string,string) PMap.t;
-	mutable local_types : t list;
-	mutable inits : texpr list;
-	mutable constructor_block : bool;
-	mutable all_dynamic_methods: method_name list;
-	mutable dynamic_methods: tclass_field list;
-	mutable is_call : bool;
-	mutable cwd : string;
-	mutable inline_methods : inline_method list;
-	mutable lib_path : string;
-}
-
-let follow = Abstract.follow_with_abstracts
-
-(**
-	Check if specified expression is of `Float` type
-*)
-let is_float expr = match follow expr.etype with TAbstract ({ a_path = ([], "Float") }, _) -> true | _ -> false
-
-(**
-	If `expr` is a TCast or TMeta, then returns underlying expression (recursively bypassing nested casts).
-	Otherwise returns `expr` as is.
-*)
-let rec reveal_expr expr =
-	match expr.eexpr with
-		| TCast (e, _) -> reveal_expr e
-		| TMeta (_, e) -> reveal_expr e
-		| _ -> expr
-
-let join_class_path path separator =
-	let result = match fst path, snd path with
-	| [], s -> s
-	| el, s -> String.concat separator el ^ separator ^ s in
-	if (String.contains result '+') then begin
-		let idx = String.index result '+' in
-		(String.sub result 0 idx) ^ (String.sub result (idx+1) ((String.length result) - idx -1 ) )
-	end else
-		result;;
-
-(*  Get a string to represent a type.
-	 The "suffix" will be nothing or "_obj", depending if we want the name of the
-	 pointer class or the pointee (_obj class *)
-let rec class_string klass suffix params =
-	(match klass.cl_path with
-	(* Array class *)
-	|  ([],"Array") -> (snd klass.cl_path) ^ suffix ^ "<" ^ (String.concat ","
-					 (List.map type_string  params) ) ^ " >"
-	| _ when (match klass.cl_kind with KTypeParameter _ -> true | _ -> false) -> "Dynamic"
-	|  ([],"#Int") -> "/* # */int"
-	|  (["haxe";"io"],"Unsigned_char__") -> "unsigned char"
-	|  ([],"Class") -> "Class"
-	|  ([],"Null") -> (match params with
-			| [t] ->
-				(match follow t with
-				| TInst ({ cl_path = [],"Int" },_)
-				| TInst ({ cl_path = [],"Float" },_)
-				| TEnum ({ e_path = [],"Bool" },_) -> "Dynamic"
-				| _ -> "/*NULL*/" ^ (type_string t) )
-			| _ -> assert false);
-	(* Normal class *)
-	| _ -> (join_class_path klass.cl_path "::") ^ suffix
-	)
-and type_string_suff suffix haxe_type =
-	(match haxe_type with
-	| TMono r -> (match !r with None -> "Dynamic" | Some t -> type_string_suff suffix t)
-	| TAbstract ({ a_path = [],"Int" },[]) -> "int"
-	| TAbstract ({ a_path = [],"Float" },[]) -> "double"
-	| TAbstract ({ a_path = [],"Bool" },[]) -> "bool"
-	| TAbstract ({ a_path = [],"Void" },[]) -> "Void"
-	| TAbstract ({ a_path = [],"Null"},[t]) ->
-		(match follow t with
-		| TInst ({ cl_path = [],"Int" },_)
-		| TInst ({ cl_path = [],"Float" },_)
-		| TEnum ({ e_path = [],"Bool" },_) -> "Dynamic"
-		| _ -> type_string_suff suffix t)
-	| TEnum (enum,params) ->  (join_class_path enum.e_path "::") ^ suffix
-	| TInst (klass,params) ->  (class_string klass suffix params)
-	| TAbstract (abs,params) ->  (join_class_path abs.a_path "::") ^ suffix
-	| TType (type_def,params) ->
-		(match type_def.t_path with
-		| [] , "Array" ->
-			(match params with
-			| [t] -> "Array<" ^ (type_string (follow t) ) ^ " >"
-			| _ -> assert false)
-		| _ ->  type_string_suff suffix (apply_params type_def.t_params params type_def.t_type)
-		)
-	| TFun (args,haxe_type) -> "Dynamic"
-	| TAnon anon -> "Dynamic"
-	| TDynamic haxe_type -> "Dynamic"
-	| TLazy func -> type_string_suff suffix (lazy_type func)
-	)
-and type_string haxe_type =
-	type_string_suff "" haxe_type;;
-
-let debug_expression expression type_too =
-	"/* " ^ Type.s_expr_kind expression ^ (if (type_too) then " = " ^ (type_string (follow expression.etype)) else "") ^ " */";;
-
-let rec register_extern_required_path ctx path =
-	if (List.exists(fun p -> p = path) ctx.extern_classes_with_init) && not (List.exists(fun p -> p = path) ctx.extern_required_paths) then
-		ctx.extern_required_paths <- path :: ctx.extern_required_paths
-
-let s_expr_expr = Type.s_expr_kind
-
-let s_expr_name e =
-	s_type (print_context()) (follow e.etype)
-
-let s_type_name t =
-	s_type (print_context()) t
-
-
-
-and start_with s test =
-	let len = String.length test in
-	(String.length s > len && String.sub s 0 len = test)
-
-let rec is_uncertain_type t =
-	match follow t with
-	| TInst (c, _) -> c.cl_interface
-	| TMono _ -> true
-	| TAnon a ->
-	  (match !(a.a_status) with
-	  | Statics _
-	  | EnumStatics _ -> false
-	  | _ -> true)
-	| TDynamic _ -> true
-	| _ -> false
-
-let is_uncertain_expr e =
-	is_uncertain_type e.etype
-
-let rec is_anonym_type t =
-	match follow t with
-	| TAnon a ->
-	  (match !(a.a_status) with
-	  | Statics _
-	  | EnumStatics _ -> false
-	  | _ -> true)
-	| TDynamic _ -> true
-	| _ -> false
-
-let is_anonym_expr e = is_anonym_type e.etype
-
-let rec is_unknown_type t =
-	match follow t with
-	| TMono r ->
-		(match !r with
-		| None -> true
-		| Some t -> is_unknown_type t)
-	| _ -> false
-
-let is_unknown_expr e =	is_unknown_type e.etype
-
-let rec is_string_type t =
-	match follow t with
-	| TInst ({cl_path = ([], "String")}, _) -> true
-	| TAnon a ->
-	   (match !(a.a_status) with
-	   | Statics ({cl_path = ([], "String")}) -> true
-	   | _ -> false)
-	| TAbstract (a,pl) -> is_string_type (Abstract.get_underlying_type a pl)
-	| _ -> false
-
-let is_string_expr e = is_string_type e.etype
-
-let to_string ctx e =
-	let f = mk (TIdent "__call__") t_dynamic e.epos in
-	mk (TCall (f, [ ExprBuilder.make_string ctx.com "_hx_string_rec" e.epos; e; ExprBuilder.make_string ctx.com "" e.epos])) ctx.com.basic.tstring e.epos
-
-let as_string_expr ctx e =
-	match e.eexpr with
-	| TConst (TNull) ->
-		to_string ctx e
-	| _ when not (is_string_expr e) ->
-		to_string ctx e
-	| _ -> e
-(* for known String type that could have null value *)
-let to_string_null ctx e =
-	let f = mk (TIdent "__call__") t_dynamic e.epos in
-	mk (TCall (f, [ ExprBuilder.make_string ctx.com "_hx_string_or_null" e.epos; e])) ctx.com.basic.tstring e.epos
-
-
-let as_string_expr ctx e =	match e.eexpr with
-	| TConst (TNull) ->  to_string ctx e
-	| TConst (TString s) -> e
-	| TBinop (op,_,_) when (is_string_expr e)-> e
-	| TCall ({eexpr = TField({eexpr = TTypeExpr(TClassDecl {cl_path = ([],"Std")})},FStatic(c,f) )}, [_]) when (f.cf_name="string") -> e
-	| TCall ({eexpr = TLocal _}, [{eexpr = TConst (TString ("_hx_string_rec" | "_hx_str_or_null"))}]) -> e
-	| _ when not (is_string_expr e) -> to_string ctx e
-	| _ -> to_string_null ctx e
-
-let spr ctx s = Buffer.add_string ctx.buf s
-let print ctx = Printf.kprintf (fun s -> Buffer.add_string ctx.buf s)
-
-(*--php-prefix - added by skial bainn*)
-let prefix_class com name =
-	match com.php_prefix with
-	| Some prefix_class (* when not (String.length name <= 2 || String.sub name 0 2 = "__") *) ->
-		prefix_class ^ name
-	| _ ->
-		name
-
-let prefix_init_replace com code =
-	let r = Str.regexp "php_Boot" in
-	Str.global_replace r ("php_" ^ (prefix_class com "Boot")) code
-
-let s_path ctx path isextern p =
-	if isextern then begin
-		register_extern_required_path ctx path;
-		snd path
-	end else begin
-		(match path with
-		(*--php-prefix*)
-		| ([],"List")			-> (prefix_class ctx.com "HList")
-		(*--php-prefix*)
-		| ([],name)				-> (prefix_class ctx.com name)
-		| (pack,name) ->
-			(try
-				(match Hashtbl.find ctx.imports name with
-				| [p] when p = pack ->
-					()
-				| packs ->
-					if not (List.mem pack packs) then Hashtbl.replace ctx.imports name (pack :: packs))
-			with Not_found ->
-				Hashtbl.add ctx.imports name [pack]);
-			(*--php-prefix*)
-			String.concat "_" pack ^ "_" ^ (prefix_class ctx.com name))
-	end
-
-let s_path_haxe path =
-	match fst path, snd path with
-	| [], s -> s
-	| el, s -> String.concat "." el ^ "." ^ s
-
-let escape_bin s =
-	let b = Buffer.create 0 in
-	for i = 0 to String.length s - 1 do
-		match Char.code (String.unsafe_get s i) with
-		| c when c = Char.code('\\') || c = Char.code('"') || c = Char.code('$') ->
-			Buffer.add_string b "\\";
-			Buffer.add_char b (Char.chr c)
-		| c when c < 32 ->
-			Buffer.add_string b (Printf.sprintf "\\x%.2X" c)
-		| c ->
-			Buffer.add_char b (Char.chr c)
-	done;
-	Buffer.contents b
-
-(*
-haxe reserved words that match php ones: break, case, class, continue, default, do, else, extends, for, function, if, new, return, static, switch, var, while, interface, implements, public, private, try, catch, throw
- *)
-(* PHP only (for future use): cfunction, old_function *)
-let is_keyword n =
-	match String.lowercase n with
-	| "and" | "or" | "xor" | "__file__" | "exception" | "__line__" | "array"
-	| "as" | "const" | "declare" | "die" | "echo"| "elseif" | "empty"
-	| "enddeclare" | "endfor" | "endforeach" | "endif" | "endswitch"
-	| "endwhile" | "eval" | "exit" | "foreach"| "global" | "include"
-	| "include_once" | "isset" | "list" | "namespace" | "print" | "require" | "require_once"
-	| "unset" | "use" | "__function__" | "__class__" | "__method__" | "final"
-	| "php_user_filter" | "protected" | "abstract" | "__set" | "__get" | "__call"
-	| "clone" | "instanceof" | "break" | "case" | "class" | "continue" | "default"
-	| "do" | "else" | "extends" | "for" | "function" | "if" | "new" | "return"
-	| "static" | "switch" | "var" | "while" | "interface" | "implements" | "public"
-	| "private" | "try" | "catch" | "throw" | "goto" | "yield"
-		-> true
-	| _ -> false
-
-let s_ident n =
-	let suf = "h" in
-	if (is_keyword n) then (suf ^ n) else n
-
-let s_ident_field n =
-	if (is_keyword n) then ("{\"" ^ (escape_bin n) ^ "\"}") else n
-
-let s_ident_local n =
-	let suf = "h" in
-	match String.lowercase n with
-	| "globals" | "_server" | "_get" | "_post" | "_cookie" | "_files"
-	| "_env" | "_request" | "_session" -> suf ^ n
-	| _ -> n
-
-let create_directory com ldir =
- 	let atm_path = ref com.file in
- 	if not (Sys.file_exists com.file) then (Unix.mkdir com.file 0o755);
- 	(List.iter (fun p -> atm_path := !atm_path ^ "/" ^ p; if not (Sys.file_exists !atm_path) then (Unix.mkdir !atm_path 0o755);) ldir)
-
-let write_resource dir name data =
-	let rdir = dir ^ "/res" in
-	if not (Sys.file_exists dir) then Unix.mkdir dir 0o755;
-	if not (Sys.file_exists rdir) then Unix.mkdir rdir 0o755;
-	let name = Codegen.escape_res_name name false in
-	let ch = open_out_bin (rdir ^ "/" ^ name) in
-	output_string ch data;
-	close_out ch
-
-let stack_init com use_add =
-	Codegen.stack_context_init com "GLOBALS['%s']" "GLOBALS['%e']" "__hx__spos" "tmp" use_add Globals.null_pos
-
-let init com cwd path def_type =
-	let rec create acc = function
-		| [] -> ()
-		| d :: l ->
-			let pdir = String.concat "/" (List.rev (d :: acc)) in
-			if not (Sys.file_exists pdir) then Unix.mkdir pdir 0o755;
-			create (d :: acc) l
-	in
-	let dir = if cwd <> "" then com.file :: (cwd :: fst path) else com.file :: fst path; in
-	create [] dir;
-	let filename path =
-		prefix_class com (match path with
-		| [], "List" -> "HList";
-		| _, s -> s) in
-	(*--php-prefix*)
-	let ch = open_out (String.concat "/" dir ^ "/" ^ (filename path) ^ (if def_type = 0 then ".class" else if def_type = 1 then ".enum"  else if def_type = 2 then ".interface" else ".extern") ^ ".php") in
-	let imports = Hashtbl.create 0 in
-	Hashtbl.add imports (snd path) [fst path];
-	let ctx = {
-		com = com;
-		stack = stack_init com false;
-		tabs = "";
-		ch = ch;
-		path = path;
-		buf = Buffer.create (1 lsl 14);
-		in_value = None;
-		in_loop = false;
-		in_instance_method = false;
-		imports = imports;
-		extern_required_paths = [];
-		extern_classes_with_init = [];
-		curclass = null_class;
-		curmethod = "";
-		locals = PMap.empty;
-		inv_locals = PMap.empty;
-		local_types = [];
-		inits = [];
-		constructor_block = false;
-		dynamic_methods = [];
-		all_dynamic_methods = [];
-		is_call = false;
-		cwd = cwd;
-		inline_methods = [];
-		nested_loops = 0;
-		inline_index = 0;
-		in_block = false;
-		lib_path = match com.php_lib with None -> "lib" | Some s -> s;
-	} in
-	Codegen.map_source_header com (fun s -> print ctx "// %s\n" s);
-	ctx
-
-let unsupported msg p = abort ("This expression cannot be generated to PHP: " ^ msg) p
-
-let newline ctx =
-	match Buffer.nth ctx.buf (Buffer.length ctx.buf - 1) with
-	| '{' | ':' | ' '
-	| '}' when Buffer.nth ctx.buf (Buffer.length ctx.buf - 2) != '"' ->
-		print ctx "\n%s" ctx.tabs
-	| _ ->
-		print ctx ";\n%s" ctx.tabs
-
-let rec concat ctx s f = function
-	| [] -> ()
-	| [x] -> f x
-	| x :: l ->
-		f x;
-		spr ctx s;
-		concat ctx s f l
-
-let open_block ctx =
-	let oldt = ctx.tabs in
-	ctx.tabs <- "\t" ^ ctx.tabs;
-	(fun() -> ctx.tabs <- oldt)
-
-let parent e =
-	match e.eexpr with
-	| TParenthesis _ -> e
-	| _ -> mk (TParenthesis e) e.etype e.epos
-
-let inc_extern_path ctx path =
-	let rec slashes n =
-		if n = 0 then "" else ("../" ^ slashes (n-1))
-	in
-	let pre = if ctx.cwd = "" then ctx.lib_path ^ "/" else "" in
-	match path with
-		| ([],name) ->
-		pre ^ (slashes (List.length (fst ctx.path))) ^ (prefix_class ctx.com name) ^ ".extern.php"
-		| (pack,name) ->
-		pre ^ (slashes (List.length (fst ctx.path))) ^ String.concat "/" pack ^ "/" ^ (prefix_class ctx.com name) ^ ".extern.php"
-
-let close ctx =
-	output_string ctx.ch "<?php\n";
-	List.iter (fun path ->
-		if path <> ctx.path then output_string ctx.ch ("require_once dirname(__FILE__).'/" ^ (inc_extern_path ctx path) ^ "';\n");
-	) (List.rev ctx.extern_required_paths);
-	output_string ctx.ch "\n";
-	output_string ctx.ch (Buffer.contents ctx.buf);
-	close_out ctx.ch
-
-let save_locals ctx =
-	let old = ctx.locals in
-	let old_inv = ctx.inv_locals in
-	(fun() -> ctx.locals <- old; ctx.inv_locals <- old_inv)
-
-let define_local ctx l =
-	let rec loop n =
-	let name = (if n = 1 then s_ident_local l else s_ident_local (l ^ string_of_int n)) in
-	if PMap.mem name ctx.inv_locals then
-		loop (n+1)
-	else begin
-		ctx.locals <- PMap.add l name ctx.locals;
-		ctx.inv_locals <- PMap.add name l ctx.inv_locals;
-		name
-	end
-	in
-	loop 1
-
-let this ctx =
-	if ctx.in_value <> None then "$__hx__this" else "$this"
-
-let gen_constant ctx p = function
-	| TInt i -> print ctx "%ld" i
-	| TFloat s -> spr ctx s
-	| TString s ->
-		print ctx "\"%s\"" (escape_bin s)
-	| TBool b -> spr ctx (if b then "true" else "false")
-	| TNull -> spr ctx "null"
-	| TThis -> spr ctx (this ctx)
-	| TSuper -> spr ctx "ERROR /* unexpected call to super in gen_constant */"
-
-let arg_is_opt c =
-	match c with
-	| Some _ -> true
-	| None -> false
-
-let s_funarg ctx arg t p o =
-	let byref = if (String.length arg > 7 && String.sub arg 0 7 = "byref__") then "&" else "" in
-	print ctx "%s$%s" byref (s_ident_local arg);
-	if o then spr ctx " = null"
-(*
-	match c with
-	| _, Some _ -> spr ctx " = null"
-	| _, None -> ()
-*)
-let is_in_dynamic_methods ctx e s =
-	List.exists (fun dm ->
-		(* TODO: I agree, this is a mess ... but after hours of trials and errors I gave up; maybe in a calmer day *)
-		((String.concat "." ((fst dm.mpath) @ ["#" ^ (snd dm.mpath)])) ^ "." ^ dm.mname) = (s_type_name e.etype ^ "." ^ s)
-	) ctx.all_dynamic_methods
-
-let is_dynamic_method f =
-	(match f.cf_kind with
-		| Var _ -> true
-		| Method MethDynamic -> true
-		| _ -> false)
-
-let fun_block ctx f p =
-	let e = (match f.tf_expr with { eexpr = TBlock [{ eexpr = TBlock _ } as e] } -> e | e -> e) in
-	let e = List.fold_left (fun e (v,c) ->
-		match c with
-		| None | Some TNull -> e
-		| Some c -> Type.concat (Codegen.set_default ctx.com v c p) e
-	) e f.tf_args in
-	if ctx.com.debug then begin
-		Codegen.stack_block ctx.stack ctx.curclass ctx.curmethod e
-	end else
-		mk_block e
-
-let rec gen_array_args ctx lst =
-	match lst with
-	| [] -> ()
-	| h :: t ->
-		spr ctx "[";
-		gen_value ctx h;
-		spr ctx "]";
-		gen_array_args ctx t
-
-and gen_call ctx e el =
-	let rec genargs lst =
-		(match lst with
-		| [] -> ()
-		| h :: [] ->
-			spr ctx " = ";
-			gen_value ctx h;
-		| h :: t ->
-			spr ctx "[";
-			gen_value ctx h;
-			spr ctx "]";
-			genargs t)
-	in
-	match (reveal_expr e).eexpr , el with
-	| TConst TSuper , params ->
-		(match ctx.curclass.cl_super with
-		| None -> assert false
-		| Some (c,_) ->
-			spr ctx "parent::__construct(";
-			concat ctx "," (gen_value ctx) params;
-			spr ctx ")";
-		);
-	| TField ({ eexpr = TConst TSuper },f) , params ->
-		(match ctx.curclass.cl_super with
-		| None -> assert false
-		| Some (c,_) ->
-			print ctx "parent::%s(" (s_ident (field_name f));
-			concat ctx "," (gen_value ctx) params;
-			spr ctx ")";
-		);
-	| TField ({ eexpr = TTypeExpr _ }, FStatic (_, {cf_type = TDynamic _; cf_kind = Var _})) , params ->
-		spr ctx "call_user_func(";
-		ctx.is_call <- true;
-		gen_value ctx e;
-		ctx.is_call <- false;
-		spr ctx ", ";
-		concat ctx ", " (gen_value ctx) el;
-		spr ctx ")";
-	| TIdent "__set__", { eexpr = TConst (TString code) } :: el ->
-		print ctx "$%s" code;
-		genargs el;
-	| TIdent "__set__", e :: el ->
-		gen_value ctx e;
-		genargs el;
-	| TIdent "__setfield__", e :: (f :: el) ->
-		gen_value ctx e;
-		spr ctx "->{";
-		gen_value ctx f;
-		spr ctx "}";
-		genargs el;
-	| TIdent "__field__", e :: ({ eexpr = TConst (TString code) } :: el) ->
-		gen_value ctx e;
-		spr ctx "->";
-		spr ctx code;
-		gen_array_args ctx el;
-	| TIdent "__field__", e :: (f :: el) ->
-		gen_value ctx e;
-		spr ctx "->";
-		gen_value ctx f;
-		gen_array_args ctx el;
-	| TIdent "__prefix__", [] ->
-		(match ctx.com.php_prefix with
-		| Some prefix ->
-			print ctx "\"%s\"" prefix
-		| None ->
-			spr ctx "null")
-	| TIdent "__var__", { eexpr = TConst (TString code) } :: el ->
-		print ctx "$%s" code;
-		gen_array_args ctx el;
-	| TIdent "__var__", e :: el ->
-		gen_value ctx e;
-		gen_array_args ctx el;
-	| TIdent "__call__", { eexpr = TConst (TString code) } :: el ->
-		spr ctx code;
-		spr ctx "(";
-		concat ctx ", " (gen_value ctx) el;
-		spr ctx ")";
-	| TIdent "__php__", [{ eexpr = TConst (TString code) }] ->
-		(*--php-prefix*)
-		spr ctx (prefix_init_replace ctx.com code)
-	| TIdent "__php__", { eexpr = TConst (TString code); epos = p } :: tl ->
-		Codegen.interpolate_code ctx.com code tl (spr ctx) (gen_expr ctx) p
-	| TIdent "__instanceof__",  [e1;{ eexpr = TConst (TString t) }] ->
-		gen_value ctx e1;
-		print ctx " instanceof %s" t;
-	| TIdent "__physeq__",  [e1;e2] ->
-		spr ctx "(";
-		gen_value ctx e1;
-		spr ctx " === ";
-		gen_value ctx e2;
-		spr ctx ")"
-	| TLocal _, []
-	| TFunction _, []
-	| TCall _, []
-	| TParenthesis _, []
-	| TMeta _, []
-	| TBlock _, [] ->
-		ctx.is_call <- true;
-		spr ctx "call_user_func(";
-		gen_value ctx e;
-		ctx.is_call <- false;
-		spr ctx ")";
-	| TLocal _, el
-	| TFunction _, el
-	| TCall _, el
-	| TParenthesis _, el
-	| TMeta _, el
-	| TBlock _, el ->
-		ctx.is_call <- true;
-		spr ctx "call_user_func_array(";
-		gen_value ctx e;
-		ctx.is_call <- false;
-		spr ctx ", array(";
-		concat ctx ", " (gen_value ctx) el;
-		spr ctx "))"
-(*
-	| TCall (x,_), el when (match x.eexpr with | TLocal _ -> false | _ -> true) ->
-		ctx.is_call <- true;
-		spr ctx "call_user_func_array(";
-		gen_value ctx e;
-		ctx.is_call <- false;
-		spr ctx ", array(";
-		concat ctx ", " (gen_value ctx) el;
-		spr ctx "))"
-*)
-	| _ ->
-		ctx.is_call <- true;
-		gen_value ctx e;
-		ctx.is_call <- false;
-		spr ctx "(";
-		concat ctx ", " (gen_value ctx) el;
-		spr ctx ")";
-
-and could_be_string_var s =
-	s = "length"
-
-and gen_uncertain_string_var ctx s e =
-	match s with
-	| "length" ->
-		spr ctx "_hx_len(";
-		gen_value ctx e;
-		spr ctx ")"
-	| _ ->
-		gen_field_access ctx true e s;
-
-and gen_string_var ctx s e =
-	match s with
-	| "length" ->
-		spr ctx "strlen(";
-		gen_value ctx e;
-		spr ctx ")"
-	| _ ->
-		unsupported "gen_string_var " e.epos;
-
-and gen_string_static_call ctx s e el =
-	match s with
-	| "fromCharCode" ->
-		spr ctx "chr(";
-		concat ctx ", " (gen_value ctx) el;
-		spr ctx ")";
-	| _ -> unsupported "gen_string_static_call " e.epos;
-
-and could_be_string_call s =
-	s = "substr" || s = "substring" || s = "charAt" || s = "charCodeAt" || s = "indexOf" ||
-	s = "lastIndexOf" || s = "split" || s = "toLowerCase" || s = "toString" || s = "toUpperCase"
-
-and gen_string_call ctx s e el =
-	match s with
-	| "substr" ->
-		spr ctx "_hx_substr(";
-		gen_value ctx e;
-		spr ctx ", ";
-		concat ctx ", " (gen_value ctx) el;
-		spr ctx ")"
-	| "substring" ->
-		spr ctx "_hx_substring(";
-		gen_value ctx e;
-		spr ctx ", ";
-		concat ctx ", " (gen_value ctx) el;
-		spr ctx ")"
-	| "charAt" ->
-		spr ctx "_hx_char_at(";
-		gen_value ctx e;
-		spr ctx ", ";
-		concat ctx ", " (gen_value ctx) el;
-		spr ctx ")"
-	| "cca" ->
-		spr ctx "ord(substr(";
-		gen_value ctx e;
-		spr ctx ",";
-		concat ctx ", " (gen_value ctx) el;
-		spr ctx ",1))"
-	| "charCodeAt" ->
-		spr ctx "_hx_char_code_at(";
-		gen_value ctx e;
-		spr ctx ", ";
-		concat ctx ", " (gen_value ctx) el;
-		spr ctx ")"
-	| "indexOf" ->
-		spr ctx "_hx_index_of(";
-		gen_value ctx e;
-		spr ctx ", ";
-		concat ctx ", " (gen_value ctx) el;
-		spr ctx ")"
-	| "lastIndexOf" ->
-		spr ctx "_hx_last_index_of(";
-		gen_value ctx e;
-		spr ctx ", ";
-		concat ctx ", " (gen_value ctx) el;
-		spr ctx ")"
-	| "split" ->
-		spr ctx "_hx_explode(";
-		concat ctx ", " (gen_value ctx) el;
-		spr ctx ", ";
-		gen_value ctx e;
-		spr ctx ")"
-	| "toLowerCase" ->
-		spr ctx "strtolower(";
-		gen_value ctx e;
-		spr ctx ")"
-	| "toUpperCase" ->
-		spr ctx "strtoupper(";
-		gen_value ctx e;
-		spr ctx ")"
-	| "toString" ->
-		gen_value ctx e;
-	| _ ->
-		unsupported "gen_string_call" e.epos;
-
-and gen_uncertain_string_call ctx s e el =
-	spr ctx "_hx_string_call(";
-	gen_value ctx e;
-	print ctx ", \"%s\", array(" s;
-	concat ctx ", " (gen_value ctx) el;
-	spr ctx "))"
-
-and gen_field_op ctx e =
-	match e.eexpr with
-	| TField (f,s) ->
-		(match follow e.etype with
-		| TFun _ ->
-			gen_field_access ctx true f (field_name s)
-		| _ ->
-			gen_value_op ctx e)
-	| _ ->
-		gen_value_op ctx e
-
-and gen_value_op ctx e =
-	match e.eexpr with
-	| TBinop (op,_,_) when op = Ast.OpAnd || op = Ast.OpOr || op = Ast.OpXor ->
-		gen_value ctx e;
-	| _ ->
-		gen_value ctx e
-
-and is_static t =
-	match follow t with
-	| TAnon a -> (match !(a.a_status) with
-		| Statics c -> true
-		| _ -> false)
-	| _ -> false
-
-and get_constant_prefix meta =
-	let (_, args, pos) = Meta.get Meta.PhpConstants meta in
-	(match args with
-		| [EConst(String prefix), _] -> prefix
-		| [] -> ""
-		| _ -> abort "Invalid @:phpConstant parameters" pos)
-
-and gen_member_access ctx isvar e s =
-	match follow e.etype with
-	| TAnon a ->
-		(match !(a.a_status) with
-		| EnumStatics _ ->
-			let (isvar, access_operator) =
-				match e.eexpr with
-					| TField _ -> (false, "->")
-					| _ -> (isvar, "::")
-			in
-			print ctx "%s%s" (access_operator ^ (if isvar then "$" else "")) (s_ident s)
-		| Statics sta ->
-			let (sep, no_dollar) = if Meta.has Meta.PhpGlobal sta.cl_meta then
-					("", false)
-				else
-					match e.eexpr with
-						| TField _ -> ("->", true)
-						| _ -> ("::", false)
-			in
-			let isconst = Meta.has Meta.PhpConstants sta.cl_meta in
-			let cprefix = if isconst then get_constant_prefix sta.cl_meta else "" in
-			print ctx "%s%s%s" sep (if isvar && not isconst && not no_dollar then "$" else cprefix)
-			(if sta.cl_extern && sep = "" then s else s_ident s)
-		| _ -> print ctx "->%s" (if isvar then s_ident_field s else s_ident s))
-	| _ -> print ctx "->%s" (if isvar then s_ident_field s else s_ident s)
-
-and gen_field_access ctx isvar e s =
-	match (reveal_expr e).eexpr with
-	| TTypeExpr t ->
-		let isglobal = match t with
-		| TClassDecl(c) -> Meta.has Meta.PhpGlobal c.cl_meta && c.cl_extern
-		| _ -> false in
-		spr ctx (if isglobal then "" else (s_path ctx (t_path t) false e.epos));
-		gen_member_access ctx isvar e s
-	| TLocal _ ->
-		gen_expr ctx e;
-		print ctx "->%s" (if isvar then s_ident_field s else s_ident s)
-	| TArray (e1,e2) ->
-		spr ctx "_hx_array_get(";
-		gen_value ctx e1;
-		spr ctx ", ";
-		gen_value ctx e2;
-		spr ctx ")";
-		gen_member_access ctx isvar e s
-	| TBlock _
-	| TParenthesis _
-	| TMeta _
-	| TObjectDecl _
-	| TArrayDecl _
-	| TNew _ ->
-		spr ctx "_hx_deref(";
-		ctx.is_call <- false;
-		gen_value ctx e;
-		spr ctx ")";
-		gen_member_access ctx isvar e s
-	| 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;
-		spr ctx ")";
-		gen_member_access ctx isvar e s
-	| TConst TNull ->
-		spr ctx "_hx_deref(null)";
-		gen_member_access ctx isvar e s
-	| _ ->
-		gen_expr ctx e;
-		gen_member_access ctx isvar e s
-
-and gen_dynamic_function ctx isstatic name f params p =
-	let old = ctx.in_value in
-	let old_l = ctx.locals in
-	let old_li = ctx.inv_locals in
-	let old_t = ctx.local_types in
-	ctx.in_value <- None;
-	ctx.local_types <- List.map snd params @ ctx.local_types;
-	let byref = if (String.length name > 9 && String.sub name 0 9 = "__byref__") then "&" else "" in
-	print ctx "function %s%s(" byref name;
-	concat ctx ", " (fun (v,c) ->
-		let arg = define_local ctx v.v_name in
-		s_funarg ctx arg v.v_type p (arg_is_opt c);
-	) f.tf_args;
-	spr ctx ") {";
-
-	if (List.length f.tf_args) > 0 then begin
-		if isstatic then
-			print ctx " return call_user_func_array(self::$%s, array("  name
-		else
-			print ctx " return call_user_func_array($this->%s, array("  name;
-		concat ctx ", " (fun (v,_) ->
-			spr ctx ("$" ^ v.v_name)
-		) f.tf_args;
-		print ctx ")); }";
-	end else if isstatic then
-		print ctx " return call_user_func(self::$%s); }"  name
-	else
-		print ctx " return call_user_func($this->%s); }"  name;
-
-	newline ctx;
-	if isstatic then
-		print ctx "public static $%s = null" name
-	else
-		print ctx "public $%s = null" name;
-	ctx.in_value <- old;
-	ctx.locals <- old_l;
-	ctx.inv_locals <- old_li;
-	ctx.local_types <- old_t
-
-and gen_function ctx name f params p =
-	let old = ctx.in_value in
-	let old_l = ctx.locals in
-	let old_li = ctx.inv_locals in
-	let old_t = ctx.local_types in
-	ctx.in_value <- None;
-	ctx.local_types <- List.map snd params @ ctx.local_types;
-	let byref = if (String.length name > 9 && String.sub name 0 9 = "__byref__") then "&" else "" in
-	print ctx "function %s%s(" byref name;
-	concat ctx ", " (fun (v,o) ->
-		let arg = define_local ctx v.v_name in
-		s_funarg ctx arg v.v_type p (arg_is_opt o);
-	) f.tf_args;
-	print ctx ") ";
-	gen_expr ctx (fun_block ctx f p);
-	ctx.in_value <- old;
-	ctx.locals <- old_l;
-	ctx.inv_locals <- old_li;
-	ctx.local_types <- old_t
-
-
-and gen_inline_function ctx f hasthis p =
-	ctx.nested_loops <- ctx.nested_loops - 1;
-	let old = ctx.in_value in
-	let old_l = ctx.locals in
-	let old_li = ctx.inv_locals in
-	let old_t = ctx.local_types in
-	ctx.in_value <- Some "closure";
-
-	let args a = List.map (fun (v,_) -> v.v_name) a in
-
-	let used_locals = ref PMap.empty in
-
-	let rec loop e = match e.eexpr with
-		| TLocal v when not (start_with v.v_name "__hx__") && PMap.mem v.v_name old_l ->
-			used_locals := PMap.add v.v_name v.v_name !used_locals
-		| _ ->
-			Type.iter loop e
-	in
-	loop f.tf_expr;
-
-	spr ctx "array(new _hx_lambda(array(";
-
-	let c = ref 0 in
-
-	let print_arg a =
-		if !c > 0 then spr ctx ", ";
-		incr c;
-		print ctx "&$%s" a;
-	in
-	if hasthis then print_arg "this";
-	PMap.iter (fun _ a -> print_arg a) !used_locals;
-
-	spr ctx "), \"";
-
-	spr ctx (inline_function ctx (args f.tf_args) hasthis !used_locals (fun_block ctx f p));
-	print ctx "\"), 'execute')";
-
-	ctx.in_value <- old;
-	ctx.locals <- old_l;
-	ctx.inv_locals <- old_li;
-	ctx.local_types <- old_t;
-	ctx.nested_loops <- ctx.nested_loops + 1;
-
-and unset_locals ctx old_l =
-	let lst = ref [] in
-	PMap.iter (fun n _ ->
-		if not (PMap.exists n old_l) then
-			lst := ["$" ^  n] @ !lst;
-	) ctx.inv_locals;
-	if (List.length !lst) > 0 then begin
-		newline ctx;
-		spr ctx "unset(";
-		concat ctx "," (fun (s) -> spr ctx s; ) !lst;
-		spr ctx ")"
-	end
-
-and gen_while_expr ctx e =
-	let old_loop = ctx.in_loop in
-	ctx.in_loop <- true;
-	let old_nested_loops = ctx.nested_loops in
-	ctx.nested_loops <- 1;
-	let old_l = ctx.inv_locals in
-	let b = save_locals ctx in
-	(match e.eexpr with
-	| TBlock (el) ->
-		List.iter (fun e -> newline ctx; gen_expr ctx e) el;
-	| _ ->
-		newline ctx;
-		gen_expr ctx e);
-	unset_locals ctx old_l;
-	b();
-	ctx.nested_loops <- old_nested_loops;
-	ctx.in_loop <- old_loop
-
-and gen_tfield ctx e e1 s =
-	let name = (field_name s) in
-	match follow e.etype with
-	| TFun (args, _) ->
-		(if ctx.is_call then begin
-			gen_field_access ctx false e1 name
-	  	end else if is_in_dynamic_methods ctx e1 name then begin
-	  		gen_field_access ctx true e1 name;
-	  	end else begin
-			let ob ex =
-				(match ex with
-				| TTypeExpr t ->
-					print ctx "\"";
-					spr ctx (s_path ctx (t_path t) false e1.epos);
-					print ctx "\""
-				| _ ->
-					gen_expr ctx e1) in
-
-			spr ctx "(property_exists(";
-			ob e1.eexpr;
-			print ctx ", \"%s\") ? " (s_ident name);
-			gen_field_access ctx true e1 name;
-			spr ctx ": array(";
-			ob e1.eexpr;
-			print ctx ", \"%s\"))" (s_ident name);
-
-		end)
-	| TMono _ ->
-		if ctx.is_call then
-			gen_field_access ctx false e1 name
-		else
-			gen_uncertain_string_var ctx name e1
-	| TDynamic _ when not ctx.is_call && (match s with FDynamic _ -> true | _ -> false) ->
-		spr ctx "_hx_field(";
-		gen_value ctx e1;
-		print ctx ", \"%s\")" name
-	| _ ->
-		if is_string_expr e1 then
-			gen_string_var ctx name e1
-		else if is_uncertain_expr e1 then
-			gen_uncertain_string_var ctx name e1
-		else
-			gen_field_access ctx true e1 name
-
-and gen_expr ctx e =
-	let in_block = ctx.in_block in
-	ctx.in_block <- false;
-	let restore_in_block ctx inb =
-		if inb then ctx.in_block <- true
-	in
-	match e.eexpr with
-	| TConst c ->
-		gen_constant ctx e.epos c
-	| TLocal v ->
-		spr ctx ("$" ^ (try PMap.find v.v_name ctx.locals with Not_found -> (s_ident_local v.v_name)))
-	| TArray (e1,e2) ->
-		(match e1.eexpr with
-		| TCall _
-		| TBlock _
-		| TParenthesis _
-		| TMeta _
-		| TArrayDecl _ ->
-			spr ctx "_hx_array_get(";
-			gen_value ctx e1;
-			spr ctx ", ";
-			gen_value ctx e2;
-			spr ctx ")";
-		| TCast (ec, _) when (match ec.eexpr with | TArrayDecl _  | TBlock _ -> true | _ -> false) ->
-			spr ctx "_hx_array_get(";
-			gen_value ctx e1;
-			spr ctx ", ";
-			gen_value ctx e2;
-			spr ctx ")";
-		| _ ->
-			gen_value ctx e1;
-			spr ctx "[";
-			gen_value ctx e2;
-			spr ctx "]");
-	| TBinop (op,e1,e2) ->
-		(* these operators are non-assoc in php, let let's make sure to separate them with parenthesises *)
-		let non_assoc = function
-			| (Ast.OpEq | Ast.OpNotEq | Ast.OpGt | Ast.OpGte | Ast.OpLt | Ast.OpLte) -> true
-			| _ -> false
-		in
-		(match e1.eexpr with
-		| TBinop (op2,_,_) when non_assoc op && non_assoc op2 ->
-			gen_expr ctx { e with eexpr = TBinop (op,mk (TParenthesis e1) e1.etype e1.epos,e2) }
-		| _ ->
-		let leftside e =
-			(match e.eexpr with
-			| TArray(te1, te2) ->
-				gen_value ctx te1;
-				spr ctx "->a[";
-				gen_value ctx te2;
-				spr ctx "]";
-			| _ ->
-				gen_field_op ctx e1;) in
-		let leftsidec e =
-			(match e.eexpr with
-			| TArray(te1, te2) ->
-				gen_value ctx te1;
-				spr ctx "->a[";
-				gen_value ctx te2;
-				spr ctx "]";
-			| TField (e1,s) ->
-				gen_field_access ctx true e1 (field_name s)
-			| _ ->
-				gen_field_op ctx e1;) in
-		let leftsidef e =
-			(match e.eexpr with
-			| TField (e1,s) ->
-				gen_field_access ctx true e1 (field_name s)
-			| _ ->
-				gen_field_op ctx e1;
-				) in
-		(match op with
-		| Ast.OpMod ->
-			spr ctx "_hx_mod(";
-			gen_value_op ctx e1;
-			spr ctx ", ";
-			gen_value_op ctx e2;
-			spr ctx ")";
-		| Ast.OpAssign ->
-			(match e1.eexpr with
-			| TArray(te1, te2) when (match te1.eexpr with | TCall _ | TParenthesis _ -> true | _ -> false) ->
-				spr ctx "_hx_array_assign(";
-				gen_value ctx te1;
-				spr ctx ", ";
-				gen_value ctx te2;
-				spr ctx ", ";
-				gen_value_op ctx e2;
-				spr ctx ")";
-			| _ ->
-				leftsidef e1;
-				spr ctx " = ";
-				gen_value_op ctx e2;
-			)
-		| Ast.OpAssignOp(Ast.OpAdd) when (is_uncertain_expr e1 && is_uncertain_expr e2) ->
-			(match e1.eexpr with
-			| TArray(te1, te2) ->
-				let t1 = define_local ctx "__hx__t1" in
-				let t2 = define_local ctx "__hx__t2" in
-
-				print ctx "_hx_array_assign($%s = " t1;
-				gen_value ctx te1;
-				print ctx ", $%s = " t2;
-				gen_value ctx te2;
-				print ctx ", $%s->a[$%s] + " t1 t2;
-				gen_value_op ctx e2;
-				spr ctx ")";
-			| _ ->
-				leftside e1;
-				spr ctx " = ";
-				spr ctx "_hx_add(";
-				gen_value_op ctx e1;
-				spr ctx ", ";
-				gen_value_op ctx e2;
-				spr ctx ")";
-			)
-		| Ast.OpAssignOp(Ast.OpAdd) when (is_string_expr e1 || is_string_expr e2) ->
-			leftside e1;
-			spr ctx " .= ";
-			gen_value_op ctx (as_string_expr ctx e2);
-		| Ast.OpAssignOp(Ast.OpShl) ->
-			leftside e1;
-			spr ctx " <<= ";
-			gen_value_op ctx e2;
-		| Ast.OpAssignOp(Ast.OpUShr) ->
-			leftside e1;
-			spr ctx " = ";
-			spr ctx "_hx_shift_right(";
-			gen_value_op ctx e1;
-			spr ctx ", ";
-			gen_value_op ctx e2;
-			spr ctx ")";
-		| Ast.OpAssignOp(Ast.OpMod) ->
-			leftside e1;
-			spr ctx " = ";
-			spr ctx "_hx_mod(";
-			gen_value_op ctx e1;
-			spr ctx ", ";
-			gen_value_op ctx e2;
-			spr ctx ")";
-		| Ast.OpAssignOp(_) ->
-			leftsidec e1;
-			print ctx " %s " (Ast.s_binop op);
-			gen_value_op ctx e2;
-		| Ast.OpAdd when (is_uncertain_expr e1 && is_uncertain_expr e2) ->
-			spr ctx "_hx_add(";
-			gen_value_op ctx e1;
-			spr ctx ", ";
-			gen_value_op ctx e2;
-			spr ctx ")";
-		| Ast.OpAdd when (is_string_expr e1 || is_string_expr e2) ->
-			gen_value_op ctx (as_string_expr ctx e1);
-			spr ctx " . ";
-			gen_value_op ctx (as_string_expr ctx e2);
-		| Ast.OpShl ->
-			gen_value_op ctx e1;
-			spr ctx " << ";
-			gen_value_op ctx e2;
-		| Ast.OpUShr ->
-			spr ctx "_hx_shift_right(";
-			gen_value_op ctx e1;
-			spr ctx ", ";
-			gen_value_op ctx e2;
-			spr ctx ")";
-		| Ast.OpNotEq
-		| Ast.OpEq ->
-			let s_op = if op = Ast.OpNotEq then " != " else " == " in
-			let s_phop = if op = Ast.OpNotEq then " !== " else " === " in
-			let se1 = s_expr_name e1 in
-			let se2 = s_expr_name e2 in
-			if
-				   e1.eexpr = TConst (TNull)
-				|| e2.eexpr = TConst (TNull)
-			then begin
-				(match e1.eexpr with
-				| TField (f, s) when is_anonym_expr e1 || is_unknown_expr e1 ->
-					spr ctx "_hx_field(";
-					gen_value ctx f;
-					print ctx ", \"%s\")" (field_name s);
-				| _ ->
-					gen_field_op ctx e1;
-				);
-				spr ctx s_phop;
-
-				(match e2.eexpr with
-				| TField (f, s) when is_anonym_expr e2 || is_unknown_expr e2 ->
-					spr ctx "_hx_field(";
-					gen_value ctx f;
-					print ctx ", \"%s\")" (field_name s);
-				| _ ->
-					gen_field_op ctx e2);
-			end else if
-				   ((se1 = "Int" || se1 = "Null<Int>") && (se2 = "Int" || se2 = "Null<Int>"))
-				|| ((se1 = "Float" || se1 = "Null<Float>") && (se2 = "Float" || se2 = "Null<Float>"))
-				&& not (is_float e1 && is_float e2)
-			then begin
-				gen_field_op ctx e1;
-				spr ctx s_phop;
-				gen_field_op ctx e2;
-			end else if
-				   ((se1 = "Int" || se1 = "Float" || se1 = "Null<Int>" || se1 = "Null<Float>")
-				&& (se1 = "Int" || se1 = "Float" || se1 = "Null<Int>" || se1 = "Null<Float>"))
-				|| (is_unknown_expr e1 && is_unknown_expr e2)
-				|| is_anonym_expr e1
-				|| is_anonym_expr e2
-			then begin
-				if op = Ast.OpNotEq then spr ctx "!";
-				spr ctx "_hx_equal(";
-				gen_field_op ctx e1;
-				spr ctx ", ";
-				gen_field_op ctx e2;
-				spr ctx ")";
-			end else if
-				(
-					   se1 == se2
-					|| (match e1.eexpr with | TConst _ | TLocal _ | TArray _  | TNew _ -> true | _ -> false)
-					|| (match e2.eexpr with | TConst _ | TLocal _ | TArray _  | TNew _ -> true | _ -> false)
-					|| is_string_expr e1
-					|| is_string_expr e2
-					|| is_anonym_expr e1
-					|| is_anonym_expr e2
-					|| is_unknown_expr e1
-					|| is_unknown_expr e2
-				)
-				&& (type_string (follow e1.etype)) <> "Dynamic"
-				&& (type_string (follow e2.etype)) <> "Dynamic"
-			then begin
-				gen_field_op ctx e1;
-				spr ctx s_phop;
-				gen_field_op ctx e2;
-			end else begin
-				let tmp = define_local ctx "_t" in
-				print ctx "(is_object($%s = " tmp;
-				gen_field_op ctx e1;
-				print ctx ") && ($%s instanceof Enum) ? $%s%s" tmp tmp s_op;
-				gen_field_op ctx e2;
-				print ctx " : ";
-				if op = Ast.OpNotEq then spr ctx "!";
-				print ctx "_hx_equal($%s, " tmp;
-				gen_field_op ctx e2;
-				spr ctx "))";
-			end
-		| Ast.OpGt | Ast.OpGte | Ast.OpLt | Ast.OpLte when is_string_expr e1 ->
-			spr ctx "(strcmp(";
-			gen_field_op ctx e1;
-			spr ctx ", ";
-			gen_field_op ctx e2;
-			spr ctx ")";
-			let op_str = match op with
-				| Ast.OpGt -> ">"
-				| Ast.OpGte -> ">="
-				| Ast.OpLt -> "<"
-				| Ast.OpLte -> "<="
-				| _ -> assert false
-			in
-			print ctx "%s 0)" op_str
-		| _ ->
-			leftside e1;
-			print ctx " %s " (Ast.s_binop op);
-			gen_value_op ctx e2;
-		));
-	| TEnumParameter(e1,_,i) ->
-		spr ctx "_hx_deref(";
-		gen_value ctx e1;
-		spr ctx ")";
-		print ctx "->params[%d]" i;
-	| TEnumIndex e1 ->
-		spr ctx "_hx_deref(";
-		gen_value ctx e1;
-		spr ctx ")";
-		print ctx "->index";
-	| TField (e1,s) ->
-		gen_tfield ctx e e1 s
-	| TTypeExpr t ->
-		print ctx "_hx_qtype(\"%s\")" (s_path_haxe (t_path t))
-	| TParenthesis e ->
-		(match e.eexpr with
-		| TParenthesis _
-		| TReturn _ ->
-			gen_value ctx e;
-		| _ ->
-			spr ctx "(";
-			gen_value ctx e;
-			spr ctx ")"
-		);
-	| TMeta (_,e) ->
-		gen_expr ctx e
-	| TReturn eo ->
-		(match eo with
-		| None ->
-			spr ctx "return"
-		| Some e when (match follow e.etype with TEnum({ e_path = [],"Void" },[]) | TAbstract ({ a_path = [],"Void" },[]) -> true | _ -> false) ->
-			gen_value ctx e;
-			newline ctx;
-			spr ctx "return"
-		| Some e ->
-			(match e.eexpr with
-			| TThrow _ -> ()
-			| _ -> spr ctx "return ");
-			gen_value ctx e;
-			);
-	| TBreak ->
-		if ctx.in_loop then spr ctx "break" else print ctx "break %d" ctx.nested_loops
-	| TContinue ->
-		if ctx.in_loop then spr ctx "continue" else print ctx "continue %d" ctx.nested_loops
-	| TBlock [] when List.length ctx.dynamic_methods = 0 ->
-		spr ctx "{}"
-	| TBlock el ->
-		let old_l = ctx.inv_locals in
-		let b = save_locals ctx in
-		print ctx "{";
-		let bend = open_block ctx in
-		let cb = (
-			if not ctx.constructor_block then
-				(fun () -> ())
-			else begin
-				ctx.constructor_block <- false;
-				if List.length ctx.dynamic_methods > 0 then newline ctx else spr ctx " ";
-				List.iter (fun (f) ->
-					let name = f.cf_name in
-					match f.cf_expr with
-					| Some { eexpr = TFunction fd } ->
-						print ctx "if(!isset($this->%s)) $this->%s = " name name;
-						gen_inline_function ctx fd true e.epos;
-						newline ctx;
-					| _ -> ()
-				) ctx.dynamic_methods;
-				if Codegen.constructor_side_effects e then begin
-					print ctx "if(!%s::$skip_constructor) {" (s_path ctx (["php"],"Boot") false e.epos);
-					(fun() -> print ctx "}")
-				end else
-					(fun() -> ());
-			end) in
-		let remaining = ref (List.length el) in
-		let build e =
-			newline ctx;
-			if (in_block && !remaining = 1) then begin
-				(match e.eexpr with
-				| TIf _
-				| TSwitch _
-				| TThrow _
-				| TWhile _
-				| TFor _
-				| TTry _
-				| TBreak
-				| TBlock _ ->
-					restore_in_block ctx in_block;
-					gen_expr ctx e;
-					unset_locals ctx old_l;
-				| TReturn (Some e1) ->
-					(match e1.eexpr with
-					| TIf _
-					| TSwitch _
-					| TThrow _
-					| TWhile _
-					| TFor _
-					| TTry _
-					| TBlock _ -> ()
-					| _ ->
-						spr ctx "return "
-					);
-					gen_expr ctx e1;
-				| _ ->
-					spr ctx "return ";
-					gen_value ctx e;
-				)
-			end else begin
-				gen_expr ctx e;
-			end;
-			decr remaining;
-		in
-		List.iter build el;
-
-		if ctx.in_loop then begin
-			unset_locals ctx old_l;
-		end;
-		bend();
-		newline ctx;
-
-		cb();
-		print ctx "}";
-		b();
-	| TFunction f ->
-		let old = ctx.in_value, ctx.in_loop in
-		let old_meth = ctx.curmethod in
-		ctx.in_value <- None;
-		ctx.in_loop <- false;
-		ctx.curmethod <- ctx.curmethod ^ "@" ^ string_of_int (Lexer.get_error_line e.epos);
-		gen_inline_function ctx f false e.epos;
-		ctx.curmethod <- old_meth;
-		ctx.in_value <- fst old;
-		ctx.in_loop <- snd old;
-	| TCall (ec,el) ->
-		(match ec.eexpr with
-		| TArray _ ->
-			spr ctx "call_user_func_array(";
-			gen_value ctx ec;
-			spr ctx ", array(";
-			concat ctx ", " (gen_value ctx) el;
-			spr ctx "))";
-		| TField (ef,s) when is_static ef.etype && is_string_expr ef ->
-			gen_string_static_call ctx (field_name s) ef el
-		| TField (ef,s) when is_string_expr ef ->
-			gen_string_call ctx (field_name s) ef el
-		| TField (ef,s) when is_anonym_expr ef && could_be_string_call (field_name s) ->
-			gen_uncertain_string_call ctx (field_name s) ef el
-		| _ ->
-			gen_call ctx ec el);
-	| TArrayDecl el ->
-		spr ctx "(new _hx_array(array(";
-		concat ctx ", " (gen_value ctx) el;
-		spr ctx ")))";
-	| TThrow e ->
-		spr ctx "throw new HException(";
-		gen_value ctx e;
-		spr ctx ")";
-	| TVar (v,eo) ->
-		spr ctx "$";
-		let restore = save_locals ctx in
-		let n = define_local ctx v.v_name in
-		let restore2 = save_locals ctx in
-		restore();
-		(match eo with
-		| None ->
-			print ctx "%s = null" (s_ident_local n)
-		| Some e ->
-			print ctx "%s = " (s_ident_local n);
-			gen_value ctx e);
-		restore2()
-	| TNew (c,_,el) ->
-		(match c.cl_path, el with
-		| ([], "String"), _ ->
-			concat ctx "" (gen_value ctx) el
-		| ([], "Array"), el ->
-			spr ctx "new _hx_array(array(";
-			concat ctx ", " (gen_value ctx) el;
-			spr ctx "))"
-		| (_, _), _ ->
-			print ctx "new %s(" (s_path ctx c.cl_path c.cl_extern e.epos);
-			let count = ref (-1) in
-			concat ctx ", " (fun e ->
-				incr count;
-				match c.cl_constructor with
-				| Some f ->
-					gen_value ctx e;
-				| _ -> ();
-			) el;
-			spr ctx ")")
-	| TIf (cond,e,eelse) ->
-		spr ctx "if";
-		gen_value ctx (parent cond);
-		spr ctx " ";
-		restore_in_block ctx in_block;
-		gen_expr ctx (mk_block e);
-		(match eelse with
-		| None -> ()
-		| Some e when e.eexpr = TConst(TNull) -> ()
-		| Some e ->
-			spr ctx " else ";
-			restore_in_block ctx in_block;
-			gen_expr ctx (mk_block e));
-	| TUnop (op,Ast.Prefix,e) ->
-		(match e.eexpr with
-		| TArray(te1, te2) ->
-			(match op with
-			| Increment ->
-				spr ctx "_hx_array_increment(";
-				gen_value ctx te1;
-				spr ctx ",";
-				gen_value ctx te2;
-				spr ctx ")";
-			| Decrement ->
-				spr ctx "_hx_array_decrement(";
-				gen_value ctx te1;
-				spr ctx ",";
-				gen_value ctx te2;
-				spr ctx ")";
-			| _ ->
-				spr ctx (Ast.s_unop op);
-				gen_value ctx te1;
-				spr ctx "[";
-				gen_value ctx te2;
-				spr ctx "]";
-			);
-		| TField (e1,s) ->
-			spr ctx (Ast.s_unop op);
-			gen_tfield ctx e e1 s
-		| _ ->
-			spr ctx (Ast.s_unop op);
-			gen_value ctx e)
-	| TUnop (op,Ast.Postfix,e) ->
-		(match e.eexpr with
-		| TArray(te1, te2) ->
-			gen_value ctx te1;
-			spr ctx "->a[";
-			gen_value ctx te2;
-			spr ctx "]";
-		| TField (e1,s) ->
-			gen_field_access ctx true e1 (field_name s)
-		| _ ->
-			gen_value ctx e);
-		spr ctx (Ast.s_unop op)
-	| TWhile (cond,e,Ast.NormalWhile) ->
-		let old = save_locals ctx in
-		spr ctx "while";
-		gen_value ctx (parent cond);
-		spr ctx " {";
-		let bend = open_block ctx in
-		gen_while_expr ctx e;
-		bend();
-		newline ctx;
-		spr ctx "}";
-		old()
-	| TWhile (cond,e,Ast.DoWhile) ->
-		let old = save_locals ctx in
-		spr ctx "do {";
-		let bend = open_block ctx in
-		gen_while_expr ctx e;
-		bend();
-		newline ctx;
-		spr ctx "} while";
-		gen_value ctx (parent cond);
-		old()
-	| TObjectDecl fields ->
-		spr ctx "_hx_anonymous(array(";
-		concat ctx ", " (fun (f,e) -> print ctx "\"%s\" => " (escape_bin f); gen_value ctx e) fields;
-		spr ctx "))"
-	| TFor (v,it,e) ->
-		let b = save_locals ctx in
-		let tmp = define_local ctx "__hx__it" in
-		let v = define_local ctx v.v_name in
-		(match it.eexpr with
-		| TCall (e,_) ->
-			(match e.eexpr with
-			| TField (e,f) ->
-				spr ctx "if(null == ";
-				gen_value ctx e;
-				spr ctx ") throw new HException('null iterable')";
-				newline ctx;
-			| _ ->
-				());
-		| _ -> ()
-		);
-		print ctx "$%s = " tmp;
-		gen_value ctx it;
-		newline ctx;
-		print ctx "while($%s->hasNext()) {" tmp;
-		let bend = open_block ctx in
-		newline ctx;
-		(* unset loop variable (issue #2900) *)
-		print ctx "unset($%s)" v;
-		newline ctx;
-		print ctx "$%s = $%s->next()" v tmp;
-		gen_while_expr ctx e;
-		bend();
-		newline ctx;
-		spr ctx "}";
-		b();
-	| TTry (e,catchs) ->
-		spr ctx "try ";
-		restore_in_block ctx in_block;
-		gen_expr ctx (mk_block e);
-		let old = save_locals ctx in
-		let ex = define_local ctx "__hx__e" in
-		print ctx "catch(Exception $%s) {" ex;
-		let bend = open_block ctx in
-		let first = ref true in
-		let catchall = ref false in
-		let evar = define_local ctx "_ex_" in
-		newline ctx;
-		print ctx "$%s = ($%s instanceof HException) && $%s->getCode() == null ? $%s->e : $%s" evar ex ex ex ex;
-		old();
-		List.iter (fun (v,e) ->
-			let ev = define_local ctx v.v_name in
-			newline ctx;
-
-			let b = save_locals ctx in
-			if not !first then spr ctx "else ";
-			(match follow v.v_type with
-			| TEnum (te,_) -> (match te.e_path with
-				| [], "Bool"   -> print ctx "if(is_bool($%s = $%s))" ev evar
-				| _ -> print ctx "if(($%s = $%s) instanceof %s)" ev evar (s_path ctx te.e_path te.e_extern e.epos));
-				restore_in_block ctx in_block;
-				gen_expr ctx (mk_block e);
-			| TInst (tc,_) -> (match tc.cl_path with
-				| [], "Int"	-> print ctx "if(is_int($%s = $%s))"		ev evar
-				| [], "Float"  -> print ctx "if(is_numeric($%s = $%s))"	ev evar
-				| [], "String" -> print ctx "if(is_string($%s = $%s))"	ev evar
-				| [], "Array"  -> print ctx "if(($%s = $%s) instanceof _hx_array)"	ev evar
-				| _ -> print ctx "if(($%s = $%s) instanceof %s)"    ev evar (s_path ctx tc.cl_path tc.cl_extern e.epos));
-				restore_in_block ctx in_block;
-				gen_expr ctx (mk_block e);
-			| TAbstract (ta,_) -> (match ta.a_path with
-				| [], "Int"	-> print ctx "if(is_int($%s = $%s))"		ev evar
-				| [], "Float"  -> print ctx "if(is_numeric($%s = $%s))"	ev evar
-				| [], "Bool"   -> print ctx "if(is_bool($%s = $%s))" ev evar
-				| _ -> print ctx "if(($%s = $%s) instanceof %s)"    ev evar (s_path ctx ta.a_path false e.epos));
-				restore_in_block ctx in_block;
-				gen_expr ctx (mk_block e);
-			| TFun _
-			| TLazy _
-			| TType _
-			| TAnon _ ->
-				assert false
-			| TMono _
-			| TDynamic _ ->
-				catchall := true;
-				if not !first then spr ctx "{ ";
-				print ctx "$%s = $%s" ev evar;
-				newline ctx;
-				restore_in_block ctx in_block;
-				gen_expr ctx (mk_block e);
-				if not !first then spr ctx "}"
-			);
-			b();
-			first := false;
-		) catchs;
-		if not !catchall then
-			print ctx " else throw $%s;" ex;
-		bend();
-		newline ctx;
-		spr ctx "}"
-	| TSwitch (e,cases,def) ->
-		let old_loop = ctx.in_loop in
-		ctx.in_loop <- false;
-		ctx.nested_loops <- ctx.nested_loops + 1;
-		let old = save_locals ctx in
-		spr ctx "switch";
-		gen_value ctx (parent e);
-		spr ctx " {";
-		newline ctx;
-		List.iter (fun (el,e2) ->
-			List.iter (fun e ->
-				spr ctx "case ";
-				gen_value ctx e;
-				spr ctx ":";
-			) el;
-			restore_in_block ctx in_block;
-			gen_expr ctx (mk_block e2);
-			print ctx "break";
-			newline ctx;
-		) cases;
-		(match def with
-		| None -> ()
-		| Some e ->
-			spr ctx "default:";
-			restore_in_block ctx in_block;
-			gen_expr ctx (mk_block e);
-			print ctx "break";
-			newline ctx;
-		);
-		spr ctx "}";
-		ctx.nested_loops <- ctx.nested_loops - 1;
-		ctx.in_loop <- old_loop;
-		old()
-	| TCast (e,None) ->
-		gen_expr ctx e
-	| TCast (e1,Some t) ->
-		let mk_texpr = function
-			| TClassDecl c -> TAnon { a_fields = PMap.empty; a_status = ref (Statics c) }
-			| TEnumDecl e -> TAnon { a_fields = PMap.empty; a_status = ref (EnumStatics e) }
-			| TAbstractDecl a -> TAnon { a_fields = PMap.empty; a_status = ref (AbstractStatics a) }
-			| TTypeDecl _ -> assert false
-		in
-		spr ctx "_hx_cast(";
-		gen_expr ctx e1;
-		spr ctx ", ";
-		gen_expr ctx (mk (TTypeExpr t) (mk_texpr t) e1.epos);
-		spr ctx ")"
-	| TIdent s ->
-		spr ctx s
-
-and argument_list_from_locals include_this in_var l =
-	let lst = ref [] in
-	if (include_this && in_var) then lst := "__hx__this" :: !lst
-	else if include_this then lst := "this" :: !lst;
-	PMap.iter (fun n _ ->
-		lst := !lst @ [n];
-	) l;
-	!lst
-
-and remove_internals args =
-	List.filter (fun a -> a = "__hx__this" || not (start_with a "__hx__")) args;
-
-and inline_block ctx e =
-		let index = ctx.inline_index in
-		ctx.inline_index <- ctx.inline_index + 1;
-		let block = {
-			iname = (s_path ctx ctx.curclass.cl_path ctx.curclass.cl_extern ctx.curclass.cl_pos) ^ "_" ^ string_of_int index;
-			iindex = index;
-			ihasthis = ctx.in_instance_method; (* param this *)
-			iarguments = [];
-			iexpr = e;
-			ilocals = ctx.locals;
-			iin_block = true;
-			iinv_locals = ctx.inv_locals;
-		} in
-
-		print ctx "%s(" block.iname;
-		let in_value = (match ctx.in_value with Some _ -> true | _ -> false) in
-		(match remove_internals (argument_list_from_locals ctx.in_instance_method in_value ctx.locals) with
-		| [] -> ()
-		| l -> print ctx "$%s" (String.concat ", $" l)
-		);
-		spr ctx ")";
-
-		ctx.inline_methods <- ctx.inline_methods @ [block]
-
-and inline_function ctx args hasthis used_args e =
-		let index = ctx.inline_index in
-		ctx.inline_index <- ctx.inline_index + 1;
-		let block = {
-			iname = (s_path ctx ctx.curclass.cl_path ctx.curclass.cl_extern ctx.curclass.cl_pos) ^ "_" ^ string_of_int index;
-			iindex = index;
-			ihasthis = hasthis; (* param this *)
-			iarguments = args;
-			iexpr = e;
-			ilocals = used_args;
-			iin_block = false;
-			iinv_locals = used_args;
-		} in
-
-		ctx.inline_methods <- ctx.inline_methods @ [block];
-		block.iname
-
-and canbe_ternary_param e =
-	match e.eexpr with
-	| TTypeExpr _
-	| TConst _
-	| TLocal _
-	| TField (_,FEnum _)
-	| TParenthesis _
-	| TMeta _
-	| TObjectDecl _
-	| TArrayDecl _
-	| TCall _
-	| TUnop _
-	| TNew _
-	| TCast (_, _)
-	| TBlock [_] ->
-		true
-	| TIf (_,e,eelse) ->
-		cangen_ternary e eelse
-	| _ ->
-		false
-
-and cangen_ternary e eelse =
-	match eelse with
-	| Some other ->
-		(canbe_ternary_param e) && (canbe_ternary_param other)
-	| _ ->
-		false
-
-and gen_value ctx e =
-	match e.eexpr with
-	| TTypeExpr _
-	| TConst _
-	| TLocal _
-	| TArray _
-	| TBinop _
-	| TEnumParameter _
-	| TEnumIndex _
-	| TField _
-	| TParenthesis _
-	| TObjectDecl _
-	| TArrayDecl _
-	| TCall _
-	| TUnop _
-	| TNew _
-	| TFunction _
-	| TIdent _ ->
-		gen_expr ctx e
-	| TMeta (_,e1) ->
-		gen_value ctx e1
-	| TBlock [] ->
-		()
-	| TCast (_, Some _) ->
-		gen_expr ctx e
-	| TCast (e, None)
-	| TBlock [e] ->
-		gen_value ctx e
-	| TIf (cond,e,eelse) when (cangen_ternary e eelse) ->
-		spr ctx "(";
-		gen_value ctx cond;
-		spr ctx " ? ";
-		gen_value ctx e;
-
-		(match eelse with
-		| Some e ->
-			spr ctx " : ";
-			gen_value ctx e
-		| _ ->());
-		spr ctx ")";
-
-(*
-	| TIf (cond,e,eelse) ->
-		spr ctx "if";
-		gen_value ctx (parent cond);
-		spr ctx " ";
-		restore_in_block ctx in_block;
-		gen_expr ctx (mk_block e);
-		(match eelse with
-		| None -> ()
-		| Some e when e.eexpr = TConst(TNull) -> ()
-		| Some e ->
-			spr ctx " else ";
-			restore_in_block ctx in_block;
-			gen_expr ctx (mk_block e));
-*)
-	| TBlock _
-	| TBreak
-	| TContinue
-	| TVar _
-	| TReturn _
-	| TWhile _
-	| TThrow _
-	| TSwitch _
-	| TFor _
-	| TIf _
-	| TTry _ ->
-		inline_block ctx e
-
-let rec is_instance_method_defined cls m =
-	if PMap.exists m cls.cl_fields then
-		true
-	else
-		match cls.cl_super with
-		| Some (scls, _) ->
-			is_instance_method_defined scls m
-		| None ->
-			false
-
-let is_method_defined ctx m static =
-	if static then
-		PMap.exists m ctx.curclass.cl_statics
-	else
-		is_instance_method_defined ctx.curclass m
-
-let generate_self_method ctx rights m static setter =
-	if setter then (
-		if static then
-			print ctx "%s function %s($v) { return call_user_func(self::$%s, $v); }" rights (s_ident m) (s_ident m)
-		else
-			print ctx "%s function %s($v) { return call_user_func($this->%s, $v); }" rights (s_ident m) (s_ident m)
-	) else (
-		if static then
-			print ctx "%s function %s() { return call_user_func(self::$%s); }" rights (s_ident m) (s_ident m)
-		else
-			print ctx "%s function %s() { return call_user_func($this->%s); }" rights (s_ident m) (s_ident m)
-	);
-	newline ctx
-
-let gen_assigned_value ctx eo =	match eo with
-	| Some ({eexpr = TConst _} as e) ->
-		print ctx " = ";
-		gen_value ctx e
-	| _ ->
-		()
-
-let generate_field ctx static f =
-	if is_physical_field f then
-		newline ctx;
-	ctx.locals <- PMap.empty;
-	ctx.inv_locals <- PMap.empty;
-	ctx.in_instance_method <- not static;
-	let rights = if static then "static" else "public" in
-	let p = ctx.curclass.cl_pos in
-	match f.cf_expr with
-	| Some { eexpr = TFunction fd } ->
-		if f.cf_name = "__construct" then
-			ctx.curmethod <- "new"
-		else
-			ctx.curmethod <- f.cf_name;
-		spr ctx (rights ^ " ");
-		if is_dynamic_method f then
-			gen_dynamic_function ctx static (s_ident f.cf_name) fd f.cf_params p
-		else
-			gen_function ctx (s_ident f.cf_name) fd f.cf_params p
-	| _ ->
-		if not (is_physical_field f) then
-			()
-		else if ctx.curclass.cl_interface then
-			match follow f.cf_type, f.cf_kind with
-			| TFun (args,r), Method _ ->
-				print ctx "function %s(" (s_ident f.cf_name);
-				concat ctx ", " (fun (arg,o,t) ->
-					s_funarg ctx arg t p o;
-				) args;
-				print ctx ")";
-			| _ -> spr ctx "//"; ()
-		else if
-			(match f.cf_kind with
-			| Var v ->
-				(match v.v_read, v.v_write with
-				| AccCall, AccCall ->
-					let m1 = "get_" ^ f.cf_name in
-					let m2 = "set_" ^ f.cf_name in
-					if not (is_method_defined ctx m1 static) then (
-						generate_self_method ctx rights m1 static false;
-						print ctx "%s $%s" rights (s_ident m1);
-						if not (is_method_defined ctx m2 static) then
-							newline ctx);
-					if not (is_method_defined ctx m2 static) then (
-						generate_self_method ctx rights m2 static true;
-						print ctx "%s $%s" rights (s_ident m2);
-						newline ctx);
-					false
-				| AccCall, _ ->
-					let m = "get_" ^ f.cf_name in
-					if not (is_method_defined ctx m static) then generate_self_method ctx rights m static false;
-					print ctx "%s $%s" rights (s_ident f.cf_name);
-					gen_assigned_value ctx f.cf_expr;
-					true
-				| _, AccCall ->
-					let m = "set_" ^ f.cf_name in
-					if not (is_method_defined ctx m static) then generate_self_method ctx rights m static true;
-					print ctx "%s $%s" rights (s_ident f.cf_name);
-					gen_assigned_value ctx f.cf_expr;
-					true
-				| _ ->
-					false)
-			| _ -> false) then
-				()
-		else begin
-			let name = if static then s_ident f.cf_name else f.cf_name in
-			if static then
-				(match f.cf_kind with
-				| Var _ ->
-					(match follow f.cf_type with
-					| TFun _
-					| TDynamic _ ->
-						print ctx "static function %s() { $args = func_get_args(); return call_user_func_array(self::$%s, $args); }" name name;
-						newline ctx;
-					| _ ->
-						()
-					)
-				| _ ->
-					()
-				);
-			print ctx "%s $%s" rights name;
-			gen_assigned_value ctx f.cf_expr
-		end
-
-let generate_static_field_assign ctx path f =
-	let p = ctx.curclass.cl_pos in
-	if not ctx.curclass.cl_interface then
-		(match f.cf_expr with
-		| None -> ()
-		| Some e ->
-			match e.eexpr with
-			| TConst _ -> ()
-			| TFunction fd ->
-				(match f.cf_kind with
-				| Var _ when
-						(match follow f.cf_type with
-						| TFun _
-						| TDynamic _ ->
-							true;
-						| _ ->
-							false) ->
-					newline ctx;
-					print ctx "%s::$%s = " (s_path ctx path false p) (s_ident f.cf_name);
-					gen_value ctx e
-				| Method MethDynamic ->
-					newline ctx;
-					print ctx "%s::$%s = " (s_path ctx path false p) (s_ident f.cf_name);
-					gen_value ctx e
-				| _ -> ())
-			| _ when not (is_physical_field f) ->
-				()
-			| _ ->
-				newline ctx;
-				print ctx "%s::$%s = " (s_path ctx path false p) (s_ident f.cf_name);
-				gen_value ctx e)
-
-let rec super_has_dynamic c =
-	match c.cl_super with
-	| None -> false
-	| Some (csup, _) -> (match csup.cl_dynamic with
-		| Some _ -> true
-		| _ -> super_has_dynamic csup)
-
-let generate_inline_method ctx c m =
-	(match ctx.inline_methods with
-	| [] -> ()
-	| h :: t -> ctx.inline_methods <- t
-	);
-	ctx.curclass <- c;
-
-	let old = save_locals ctx in
-	ctx.in_value <- Some m.iname;
-	ctx.in_block <- m.iin_block;
-	ctx.in_loop <- false;
-	ctx.locals <- m.ilocals;
-	ctx.inv_locals <- m.iinv_locals;
-
-	newline ctx;
-	print ctx "function %s(" m.iname;
-	(* arguments *)
-	let in_value = (match ctx.in_value with Some _ -> true | _ -> false) in
-	let arguments = remove_internals (argument_list_from_locals m.ihasthis in_value ctx.locals) in
-	let arguments = match arguments with
-	| [h] when h = "this" -> ["__hx__this"]
-	| h :: t when h = "this" -> "__hx__this" :: t
-	| _ -> arguments
-	in
-
-	let marguments = List.map (define_local ctx) m.iarguments in
-	let arguments =  (List.map (fun a -> "&$" ^ a) arguments) @ (List.map (fun a -> "$" ^ a) marguments) in
-
-	(match arguments with
-	| [] -> ()
-	| l  -> spr ctx (String.concat ", " arguments)
-	);
-	spr ctx ") {";
-	ctx.nested_loops <- ctx.nested_loops - 1;
-	let block = open_block ctx in
-	newline ctx;
-
-	gen_expr ctx m.iexpr;
-	block();
-	old();
-	ctx.nested_loops <- ctx.nested_loops + 1;
-	newline ctx;
-	spr ctx "}"
-
-let generate_class ctx c =
-	let requires_constructor = ref true in
-	ctx.curclass <- c;
-	ctx.local_types <- List.map snd c.cl_params;
-
-	print ctx "%s %s " (if c.cl_interface then "interface" else "class") (s_path ctx c.cl_path c.cl_extern c.cl_pos);
-	(match c.cl_super with
-	| None -> ()
-	| Some (csup,_) ->
-		requires_constructor := false;
-		print ctx "extends %s " (s_path ctx csup.cl_path csup.cl_extern c.cl_pos));
-	(* Do not add interfaces which are implemented through other interfaces inheritance *)
-	let unique = List.filter
-		(fun (iface, _) ->
-			not (List.exists
-				(fun (probably_descendant, _) ->
-					if probably_descendant == iface then
-						false
-					else
-						is_parent iface probably_descendant
-				)
-				c.cl_implements
-			)
-		)
-		c.cl_implements
-	in
-	let implements = ExtList.List.unique ~cmp:(fun a b -> (fst a).cl_path = (fst b).cl_path) unique in
-	(match implements with
-	| [] -> ()
-	| l ->
-		spr ctx (if c.cl_interface then "extends " else "implements ");
-		concat ctx ", " (fun (i,_) ->
-		print ctx "%s" (s_path ctx i.cl_path i.cl_extern c.cl_pos)) l);
-	spr ctx "{";
-
-	let get_dynamic_methods = List.filter is_dynamic_method c.cl_ordered_fields in
-
-	if not ctx.curclass.cl_interface then ctx.dynamic_methods <- get_dynamic_methods;
-
-	let cl = open_block ctx in
-	(match c.cl_constructor with
-	| None ->
-		if !requires_constructor && not c.cl_interface then begin
-			newline ctx;
-			spr ctx "public function __construct(){}"
-		end;
-	| Some f ->
-		let f = { f with
-			cf_name = "__construct";
-			cf_public = true;
-		} in
-		ctx.constructor_block <- true;
-		generate_field ctx false f;
-		ctx.constructor_block <- false;
-	);
-
-	List.iter (generate_field ctx false) c.cl_ordered_fields;
-
-	(match c.cl_dynamic with
-		| Some _ when not c.cl_interface && not (super_has_dynamic c) ->
-			newline ctx;
-			spr ctx "public $__dynamics = array();\n\tpublic function __get($n) {\n\t\tif(isset($this->__dynamics[$n]))\n\t\t\treturn $this->__dynamics[$n];\n\t}\n\tpublic function __set($n, $v) {\n\t\t$this->__dynamics[$n] = $v;\n\t}\n\tpublic function __call($n, $a) {\n\t\tif(isset($this->__dynamics[$n]) && is_callable($this->__dynamics[$n]))\n\t\t\treturn call_user_func_array($this->__dynamics[$n], $a);\n\t\tif('toString' == $n)\n\t\t\treturn $this->__toString();\n\t\tthrow new HException(\"Unable to call <\".$n.\">\");\n\t}"
-		| Some _
-		| _ ->
-			if List.length ctx.dynamic_methods > 0 then begin
-				newline ctx;
-				spr ctx "public function __call($m, $a) {\n\t\tif(isset($this->$m) && is_callable($this->$m))\n\t\t\treturn call_user_func_array($this->$m, $a);\n\t\telse if(isset($this->__dynamics[$m]) && is_callable($this->__dynamics[$m]))\n\t\t\treturn call_user_func_array($this->__dynamics[$m], $a);\n\t\telse if('toString' == $m)\n\t\t\treturn $this->__toString();\n\t\telse\n\t\t\tthrow new HException('Unable to call <'.$m.'>');\n\t}";
-			end;
-	);
-
-	List.iter (generate_field ctx true) c.cl_ordered_statics;
-
-	let gen_props props =
-		String.concat "," (List.map (fun (p,v) -> "\"" ^ p ^ "\" => \"" ^ v ^ "\"") props)
-	in
-
-	let rec fields c =
-		let list = Codegen.get_properties (c.cl_ordered_statics @ c.cl_ordered_fields) in
-		match c.cl_super with
-		| Some (csup, _) ->
-			list @ fields csup
-		| None ->
-			list
-	in
-
-	if not c.cl_interface then (match fields c with
-		| [] ->
-			()
-		| props ->
-			newline ctx;
-			print ctx "static $__properties__ = array(%s)" (gen_props props);
-		);
-
-
-	cl();
-	newline ctx;
-
-	if PMap.exists "__toString" c.cl_fields then
-		()
-	else if PMap.exists "toString" c.cl_fields && (not c.cl_interface) && (not c.cl_extern) then begin
-		print ctx "\tfunction __toString() { return $this->toString(); }";
-		newline ctx
-	end else if (not c.cl_interface) && (not c.cl_extern) then begin
-		print ctx "\tfunction __toString() { return '%s'; }" (s_path_haxe c.cl_path) ;
-		newline ctx
-	end;
-
-	print ctx "}"
-
-
-let createmain com e =
-	let filename = match com.php_front with None -> "index.php" | Some n -> n in
-	let ctx = {
-		com = com;
-		stack = stack_init com false;
-		tabs = "";
-		ch = open_out (com.file ^ "/" ^ filename);
-		path = ([], "");
-		buf = Buffer.create (1 lsl 14);
-		in_value = None;
-		in_loop = false;
-		in_instance_method = false;
-		imports = Hashtbl.create 0;
-		extern_required_paths = [];
-		extern_classes_with_init = [];
-		curclass = null_class;
-		curmethod = "";
-		locals = PMap.empty;
-		inv_locals = PMap.empty;
-		local_types = [];
-		inits = [];
-		constructor_block = false;
-		dynamic_methods = [];
-		all_dynamic_methods = [];
-		is_call = false;
-		cwd = "";
-		inline_methods = [];
-		nested_loops = 0;
-		inline_index = 0;
-		in_block = false;
-		lib_path = match com.php_lib with None -> "lib" | Some s -> s;
-	} in
-
-	spr ctx "if(version_compare(PHP_VERSION, '5.1.0', '<')) {
-    exit('Your current PHP version is: ' . PHP_VERSION . '. Haxe/PHP generates code for version 5.1.0 or later');
-} else if(version_compare(PHP_VERSION, '5.4.0', '<')) {
-	trigger_error('Your current PHP version is: ' . PHP_VERSION . '. Code generated by Haxe/PHP might not work for versions < 5.4.0', E_USER_WARNING);
-}";
-	newline ctx;
-	newline ctx;
-	spr ctx ("require_once dirname(__FILE__).'/" ^ ctx.lib_path ^ "/php/" ^ (prefix_class com "Boot.class.php';\n\n"));
-	gen_expr ctx e;
-	newline ctx;
-	spr ctx "\n?>";
-	close ctx
-
-let generate_main ctx c =
-	(match c.cl_ordered_statics with
-	| [{ cf_expr = Some e }] ->
-		gen_value ctx e;
-	| _ -> assert false);
-		newline ctx
-
-let generate_enum ctx e =
-	ctx.local_types <- List.map snd e.e_params;
-	let pack = open_block ctx in
-	let ename = s_path ctx e.e_path e.e_extern e.e_pos in
-
-	print ctx "class %s extends Enum {" ename;
-	PMap.iter (fun _ c ->
-		newline ctx;
-		match c.ef_type with
-		| TFun (args,_) ->
-			print ctx "public static function %s($" (s_ident c.ef_name);
-			concat ctx ", $" (fun (a,o,t) ->
-				spr ctx a;
-				if o then spr ctx " = null";
-			) args;
-			spr ctx ") {";
-			print ctx " return new %s(\"%s\", %d, array($" ename (s_ident c.ef_name) c.ef_index;
-			concat ctx ", $" (fun (a,_,_) -> spr ctx a) args;
-			print ctx ")); }";
-		| _ ->
-			print ctx "public static $%s" (s_ident c.ef_name);
-	) e.e_constrs;
-	newline ctx;
-
-	spr ctx "public static $__constructors = array(";
-
-	let first = ref true in
-	PMap.iter (fun _ c ->
-		if not !first then spr ctx ", ";
-		print ctx "%d => '%s'" c.ef_index (s_ident c.ef_name);
-		first := false;
-	) e.e_constrs;
-
-	spr ctx ")";
-
-	newline ctx;
-
-	(match Codegen.build_metadata ctx.com (TEnumDecl e) with
-	| None -> ()
-	| Some _ ->
-		spr ctx "public static $__meta__";
-		newline ctx);
-
-	pack();
-
-	print ctx "}";
-
-	PMap.iter (fun _ c ->
-		match c.ef_type with
-		| TFun (args,_) ->
-			();
-		| _ ->
-			newline ctx;
-			print ctx "%s::$%s = new %s(\"%s\", %d)" ename (s_ident c.ef_name) ename c.ef_name c.ef_index;
-	) e.e_constrs;
-
-	newline ctx;
-
-	match Codegen.build_metadata ctx.com (TEnumDecl e) with
-	| None -> ()
-	| Some e ->
-		print ctx "%s::$__meta__ = " ename;
-		gen_expr ctx e;
-		newline ctx
-
-let generate com =
-	let all_dynamic_methods = ref [] in
-	let extern_classes_with_init = ref [] in
-	let php_lib_path = (match com.php_lib with None -> "lib" | Some n -> n) in
- 	create_directory com (Str.split (Str.regexp "/")  php_lib_path);
-	(* check for methods with the same name but different case *)
-	let check_class_fields c =
-		let lc_names = ref [] in
-		let special_cases = ["toString"] in
-		let loop c lst static =
-			let in_special_cases name =
-				(List.exists (fun n -> String.lowercase n = name) (special_cases @ List.map (fun f -> f.cf_name) c.cl_overrides))
-			in
-			List.iter(fun cf ->
-				let name = String.lowercase cf.cf_name in
-				let prefixed_name s = (if s then "s_" else "i_") ^ name in
-				match cf.cf_kind, cf.cf_expr with
-				| (Method _, Some e) when not (in_special_cases name) ->
-					(try
-						let lc = List.find (fun n ->
-							let n = snd n in
-							if static then
-								(n = (prefixed_name false))
-							else
-								((n = (prefixed_name false)) || (n = (prefixed_name true)))
-						) !lc_names in
-						unsupported ("method '" ^ (Globals.s_type_path c.cl_path) ^ "." ^ cf.cf_name ^ "' already exists here '" ^ (fst lc) ^ "' (different case?)") c.cl_pos
-					with Not_found ->
-						lc_names := ((Globals.s_type_path c.cl_path) ^ "." ^ cf.cf_name, prefixed_name static) :: !lc_names)
-				| _ ->
-					()
-			) lst
-		in
-		let rec _check_class_fields cl =
-			(match cl.cl_super with
-			| Some (s,_) -> _check_class_fields s
-			| _ -> ());
-			loop cl cl.cl_ordered_statics true;
-			loop cl cl.cl_ordered_fields false
-		in
-		_check_class_fields c
-	in
-	List.iter (fun t ->
-		(match t with
-		| TClassDecl c ->
-			check_class_fields c
-		| TEnumDecl e ->
-			let e_names = ref [] in
-			List.iter(fun en -> (
-				if List.exists (fun n -> n = String.lowercase en) !e_names then
-					unsupported ("'" ^ en ^ "' constructor exists with different case") e.e_pos
-				else
-					e_names := (String.lowercase en) :: !e_names
-			)) (e.e_names)
-		| _ -> ())
-	) com.types;
-	List.iter (fun t ->
-		(match t with
-		| TClassDecl c ->
-			let dynamic_methods_names lst =
-				List.map (fun fd -> {
-					mpath = c.cl_path;
-					mname = fd.cf_name;
-				}) (List.filter is_dynamic_method lst)
-			in
-			all_dynamic_methods := dynamic_methods_names c.cl_ordered_fields @ !all_dynamic_methods;
-
-			if c.cl_extern then
-				(match c.cl_init with
-				| Some _ ->
-					extern_classes_with_init := c.cl_path :: !extern_classes_with_init;
-				| _ ->
-					())
-			else
-				all_dynamic_methods := dynamic_methods_names c.cl_ordered_statics @ !all_dynamic_methods;
-		| _ -> ())
-	) com.types;
-	List.iter (Codegen.fix_abstract_inheritance com) com.types;
-	List.iter (fun t ->
-		(match t with
-		| TClassDecl c ->
-			if c.cl_extern then begin
-				(match c.cl_init with
-				| None -> ()
-				| Some e ->
-					let ctx = init com php_lib_path c.cl_path 3 in
-					gen_expr ctx e;
-					newline ctx;
-					close ctx;
-					);
-			end else
-				let ctx = init com php_lib_path c.cl_path (if c.cl_interface then 2 else 0) in
-				ctx.extern_classes_with_init <- !extern_classes_with_init;
-				ctx.all_dynamic_methods <- !all_dynamic_methods;
-
-				generate_class ctx c;
-
-				(match c.cl_init with
-				| None -> ()
-				| Some e ->
-					newline ctx;
-					gen_expr ctx e);
-				List.iter (generate_static_field_assign ctx c.cl_path) c.cl_ordered_statics;
-				if c.cl_path = (["php"], "Boot") && com.debug then begin
-					newline ctx;
-					print ctx "$%s = new _hx_array(array())" ctx.stack.Codegen.stack_var;
-					newline ctx;
-					print ctx "$%s = new _hx_array(array())" ctx.stack.Codegen.stack_exc_var;
-				end;
-
-				let rec loop l =
-					match l with
-					| [] -> ()
-					| h :: _ ->
-						generate_inline_method ctx c h;
-						loop ctx.inline_methods
-				in
-				loop ctx.inline_methods;
-				newline ctx;
-				close ctx
-		| TEnumDecl e ->
-			if e.e_extern then
-				()
-			else
-				let ctx = init com php_lib_path e.e_path 1 in
-			generate_enum ctx e;
-			close ctx
-		| TTypeDecl _ | TAbstractDecl _ ->
-			());
-	) com.types;
-	(match com.main with
-	| None -> ()
-	| Some e -> createmain com e);
-	Hashtbl.iter (fun name data ->
-		write_resource com.file name data
-	) com.resources;

+ 1 - 1
src/generators/genphp7.ml

@@ -1,5 +1,5 @@
 (**
-	Compatible with PHP 7+
+	Compatible with PHP 7.0+
 *)
 
 open Ast

+ 3 - 14
src/optimization/analyzerTexpr.ml

@@ -125,7 +125,6 @@ let rec can_be_used_as_value com e =
 		(* | TCall _ | TNew _ when (match com.platform with Cpp | Php -> true | _ -> false) -> raise Exit *)
 		| TReturn _ | TThrow _ | TBreak | TContinue -> raise Exit
 		| TUnop((Increment | Decrement),_,_) when not (target_handles_unops com) -> raise Exit
-		| TNew _ when com.platform = Php && not (Common.is_php7 com) -> raise Exit
 		| TFunction _ -> ()
 		| _ -> Type.iter loop e
 	in
@@ -715,7 +714,6 @@ module Fusion = struct
 				can_be_used_as_value com e1 &&
 				not (ExtType.is_void e1.etype) &&
 				(match com.platform with
-					| Php when not (Common.is_php7 com) -> false
 					| Cpp when not (Common.defined com Define.Cppia) -> false
 					| _ -> true)
 				->
@@ -816,17 +814,8 @@ module Fusion = struct
 							let el = List.map replace el in
 							let e2 = replace e2 in
 							e2,el
-						| Php | Cpp  when not (Common.defined com Define.Cppia) && not (Common.is_php7 com) ->
-							let is_php_safe e1 =
-								let rec loop e = match e.eexpr with
-									| TCall _ -> raise Exit
-									| TCast(e1,_) | TParenthesis e1 | TMeta(_,e1) -> loop e1
-									| _ -> ()
-								in
-								try loop e1; true with Exit -> false
-							in
-							(* PHP5 doesn't like call()() expressions. *)
-							let e2 = if com.platform = Php && not (is_php_safe e1) then explore e2 else replace e2 in
+						| Cpp ->
+							let e2 = replace e2 in
 							let el = handle_el el in
 							e2,el
 						| _ ->
@@ -928,7 +917,7 @@ module Fusion = struct
 							let e3 = replace e3 in
 							if not !found && has_state_read ir then raise Exit;
 							{e with eexpr = TBinop(OpAssign,{ea with eexpr = TArray(e1,e2)},e3)}
-						| TBinop(op,e1,e2) when (match com.platform with Cpp | Php when not (Common.is_php7 com) -> true | _ -> false) ->
+						| TBinop(op,e1,e2) when (match com.platform with Cpp -> true | _ -> false) ->
 							let e1 = replace e1 in
 							let temp_found = !found in
 							found := false;

+ 0 - 1
src/optimization/filters.ml

@@ -695,7 +695,6 @@ let add_meta_field ctx t = match t with
 			cf.cf_expr <- Some e;
 			let can_deal_with_interface_metadata () = match ctx.com.platform with
 				| Flash when Common.defined ctx.com Define.As3 -> false
-				| Php when not (Common.is_php7 ctx.com) -> false
 				| Cs | Java -> false
 				| _ -> true
 			in

+ 1 - 1
src/typing/typeload.ml

@@ -222,7 +222,7 @@ let module_pass_1 ctx m tdecls loadp =
 				(match !decls with
 				| (TClassDecl c,_) :: _ ->
 					List.iter (fun m -> match m with
-						| ((Meta.Build | Meta.CoreApi | Meta.Allow | Meta.Access | Meta.Enum | Meta.Dce | Meta.Native | Meta.JsRequire | Meta.PythonImport | Meta.Expose | Meta.Deprecated | Meta.PhpConstants | Meta.PhpGlobal),_,_) ->
+						| ((Meta.Build | Meta.CoreApi | Meta.Allow | Meta.Access | Meta.Enum | Meta.Dce | Meta.Native | Meta.JsRequire | Meta.PythonImport | Meta.Expose | Meta.Deprecated | Meta.PhpGlobal),_,_) ->
 							c.cl_meta <- m :: c.cl_meta;
 						| _ ->
 							()

+ 1 - 1
src/typing/typer.ml

@@ -944,7 +944,7 @@ let error_require r p =
 		error "This field is not available with the current compilation flags" p
 	else
 	let r = if r = "sys" then
-		"a system platform (php,php7,neko,cpp,etc.)"
+		"a system platform (php,neko,cpp,etc.)"
 	else try
 		if String.sub r 0 5 <> "flash" then raise Exit;
 		let _, v = ExtString.String.replace (String.sub r 5 (String.length r - 5)) "_" "." in

+ 0 - 4
std/Math.hx

@@ -73,10 +73,6 @@ extern class Math
 		result is unspecified.
 
 		In order to test if a value is `NaN`, you should use `Math.isNaN()` function.
-
-		@php In PHP versions prior to 5.3.1 VC 9 there may be unexpected
-		results when performing arithmetic operations with `NaN` on Windows,
-		see <https://bugs.php.net/bug.php?id=42143>
 	**/
 	static var NaN(default, null) : Float;
 

+ 0 - 14
std/haxe/CallStack.hx

@@ -88,8 +88,6 @@ class CallStack {
 			var a = makeStack( new flash.errors.Error().getStackTrace() );
 			a.shift(); // remove Stack.callStack()
 			return a;
-		#elseif php
-			return makeStack("%s");
 		#elseif cpp
 			var s:Array<String> = untyped __global__.__hxcpp_get_call_stack(true);
 			return makeStack(s);
@@ -188,8 +186,6 @@ class CallStack {
 				i--;
 			}
 			return a;
-		#elseif php
-			return makeStack("%e");
 		#elseif cpp
 			var s:Array<String> = untyped __global__.__hxcpp_get_exception_stack();
 			return makeStack(s);
@@ -306,16 +302,6 @@ class CallStack {
 				s = r.matchedRight();
 			}
 			return a;
-		#elseif php
-			if (!untyped __call__("isset", __var__("GLOBALS", s)))
-				return [];
-			var a : Array<String> = untyped __var__("GLOBALS", s);
-			var m = [];
-			for( i in 0...a.length - ((s == "%s") ? 2 : 0)) {
-				var d = a[i].split("::");
-				m.unshift(Method(d[0],d[1]));
-			}
-			return m;
 		#elseif cpp
 			var stack : Array<String> = s;
 			var m = new Array<StackItem>();

+ 1 - 1
std/haxe/Int32.hx

@@ -230,7 +230,7 @@ abstract Int32(Int) from Int to Int {
 	}
 
 	#if php
-	static var extraBits : Int = untyped __php__("PHP_INT_SIZE") * 8 - 32;
+	static var extraBits : Int = php.Const.PHP_INT_SIZE * 8 - 32;
 	#end
 
 

+ 0 - 2
std/haxe/Resource.hx

@@ -84,8 +84,6 @@ class Resource {
 		#if neko
 		var tmp = untyped __resources__();
 		content = untyped Array.new1(tmp,__dollar__asize(tmp));
-		#elseif php
-		content = null;
 		#elseif as3
 		null;
 		#else

+ 2 - 4
std/haxe/Serializer.hx

@@ -378,7 +378,7 @@ class Serializer {
 				#end
 			default:
 				if( useCache ) cache.pop();
-				if( #if flash try v.hxSerialize != null catch( e : Dynamic ) false #elseif (cs || java || python) Reflect.hasField(v, "hxSerialize") #elseif (php && php7) php.Global.method_exists(v, 'hxSerialize') #else v.hxSerialize != null #end  ) {
+				if( #if flash try v.hxSerialize != null catch( e : Dynamic ) false #elseif (cs || java || python) Reflect.hasField(v, "hxSerialize") #elseif php php.Global.method_exists(v, 'hxSerialize') #else v.hxSerialize != null #end  ) {
 					buf.add("C");
 					serializeString(Type.getClassName(c));
 					if( useCache ) cache.push(v);
@@ -478,10 +478,8 @@ class Serializer {
 			else {
 				buf.add(l);
 				for( i in 0...l ) {
-					#if (php && php7)
+					#if php
 					serialize(v.params[i]);
-					#elseif php
-					serialize(untyped __field__(v, __php__("params"), i));
 					#end
 				}
 			}

+ 3 - 7
std/haxe/crypto/Md5.hx

@@ -29,8 +29,6 @@ class Md5 {
 	public static function encode( s : String ) : String {
 		#if neko
 			return untyped new String(base_encode(make_md5(s.__s),"0123456789abcdef".__s));
-		#elseif php
-			return untyped __call__("md5", s);
 		#else
 			var m = new Md5();
 			var h = m.doEncode(str2blks(s));
@@ -41,8 +39,6 @@ class Md5 {
 	public static function make( b : haxe.io.Bytes ) : haxe.io.Bytes {
 		#if neko
 			return haxe.io.Bytes.ofData(make_md5(b.getData()));
-		#elseif php
-			return haxe.io.Bytes.ofData( haxe.io.BytesData.ofString(untyped __call__("md5", b.getData().toString(), true)));
 		#else
 			var h = new Md5().doEncode(bytes2blks(b));
 			var out = haxe.io.Bytes.alloc(16);
@@ -60,7 +56,7 @@ class Md5 {
 	#if neko
 	static var base_encode = neko.Lib.load("std","base_encode",2);
 	static var make_md5 = neko.Lib.load("std","make_md5",1);
-	#elseif !php
+	#else
 
 /*
  * A JavaScript implementation of the RSA Data Security, Inc. MD5 Message
@@ -137,7 +133,7 @@ class Md5 {
 	}
 
 	static function str2blks( str : String ){
-#if !(neko || cpp || php)
+#if !(neko || cpp)
 		var str = haxe.io.Bytes.ofString(str);
 #end
 		var nblk = ((str.length + 8) >> 6) + 1;
@@ -157,7 +153,7 @@ class Md5 {
 		var max = str.length;
 		var l = max * 8;
 		while( i < max ) {
-			blks[i >> 2] |= #if !(neko || cpp || php) str.get(i) #else StringTools.fastCodeAt(str, i) #end << (((l + i) % 4) * 8);
+			blks[i >> 2] |= #if !(neko || cpp) str.get(i) #else StringTools.fastCodeAt(str, i) #end << (((l + i) % 4) * 8);
 			i++;
 		}
 		blks[i >> 2] |= 0x80 << (((l + i) % 4) * 8);

+ 2 - 15
std/haxe/crypto/Sha1.hx

@@ -27,19 +27,12 @@ package haxe.crypto;
 class Sha1 {
 
 	public static function encode( s:String ) : String {
-		#if php
-		return untyped __call__("sha1", s);
-		#else
 		var sh = new Sha1();
 		var h = sh.doEncode(str2blks(s));
 		return sh.hex(h);
-		#end
 	}
 
 	public static function make( b : haxe.io.Bytes ) : haxe.io.Bytes {
-		#if php
-		return haxe.io.Bytes.ofData(haxe.io.BytesData.ofString(untyped __call__("sha1", b.getData().toString(), true)));
-		#else
 		var h = new Sha1().doEncode(bytes2blks(b));
 		var out = haxe.io.Bytes.alloc(20);
 		var p = 0;
@@ -50,11 +43,8 @@ class Sha1 {
 			out.set(p++,h[i]&0xFF);
 		}
 		return out;
-		#end
 	}
 
-	#if !php
-
 	function new() {
 	}
 
@@ -105,7 +95,7 @@ class Sha1 {
 		Append padding bits and the length, as described in the SHA1 standard.
 	 */
 	static function str2blks( s :String ) : Array<Int> {
-#if !(neko || cpp || php)
+#if !(neko || cpp)
 		var s = haxe.io.Bytes.ofString(s);
 #end
 		var nblk = ((s.length + 8) >> 6) + 1;
@@ -115,7 +105,7 @@ class Sha1 {
 			blks[i] = 0;
 		for (i in 0...s.length){
 			var p = i >> 2;
-			blks[p] |= #if !(neko || cpp || php) s.get(i) #else StringTools.fastCodeAt(s,i) #end << (24 - ((i & 3) << 3));
+			blks[p] |= #if !(neko || cpp) s.get(i) #else StringTools.fastCodeAt(s,i) #end << (24 - ((i & 3) << 3));
 		}
 		var i = s.length;
 		var p = i >> 2;
@@ -178,7 +168,4 @@ class Sha1 {
 		}
 		return str.toLowerCase();
 	}
-
-	#end
-
 }

+ 0 - 8
std/haxe/crypto/Sha224.hx

@@ -27,19 +27,12 @@ package haxe.crypto;
 class Sha224 {
 
     public static function encode( s:String ) : String {
-        #if php
-        return untyped __call__("hash", "sha224", s);
-        #else
         var sh = new Sha224();
         var h = sh.doEncode(s, s.length*8);
         return sh.hex(h);
-        #end
     }
 
     public static function make( b : haxe.io.Bytes ) : haxe.io.Bytes {
-        #if php
-        return haxe.io.Bytes.ofData(haxe.io.BytesData.ofString(untyped __call__("hash", "sha224", b.getData().toString(), true)));
-        #else
         var h = new Sha224().doEncode(b.toString(), b.length*8);
         var out = haxe.io.Bytes.alloc(28);
         var p = 0;
@@ -50,7 +43,6 @@ class Sha224 {
             out.set(p++,h[i]&0xFF);
         }
         return out;
-        #end
     }
 
     public function new() {

+ 2 - 10
std/haxe/crypto/Sha256.hx

@@ -27,19 +27,12 @@ package haxe.crypto;
 class Sha256 {
 
 	public static function encode( s:String ) : String {
-		#if php
-		return untyped __call__("hash", "sha256", s);
-		#else
 		var sh = new Sha256();
 		var h = sh.doEncode(str2blks(s), s.length*8);
 		return sh.hex(h);
-		#end
 	}
 
 	public static function make( b : haxe.io.Bytes ) : haxe.io.Bytes {
-		#if php
-		return haxe.io.Bytes.ofData(haxe.io.BytesData.ofString(untyped __call__("hash", "sha256", b.getData().toString(), true)));
-		#else
 		var h = new Sha256().doEncode(bytes2blks(b), b.length*8);
 		var out = haxe.io.Bytes.alloc(32);
 		var p = 0;
@@ -50,7 +43,6 @@ class Sha256 {
 			out.set(p++,h[i]&0xFF);
 		}
 		return out;
-		#end
 	}
 
 	public function new() {
@@ -113,7 +105,7 @@ class Sha256 {
 		Append padding bits and the length, as described in the SHA1 standard.
 	 */
 	static function str2blks( s :String ) : Array<Int> {
-#if !(neko || cpp || php)
+#if !(neko || cpp)
 		var s = haxe.io.Bytes.ofString(s);
 #end
 		var nblk = ((s.length + 8) >> 6) + 1;
@@ -123,7 +115,7 @@ class Sha256 {
 			blks[i] = 0;
 		for (i in 0...s.length){
 			var p = i >> 2;
-			blks[p] |= #if !(neko || cpp || php) s.get(i) #else s.charCodeAt(i) #end << (24 - ((i & 3) << 3));
+			blks[p] |= #if !(neko || cpp) s.get(i) #else s.charCodeAt(i) #end << (24 - ((i & 3) << 3));
 		}
 		var i = s.length;
 		var p = i >> 2;

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

@@ -43,8 +43,6 @@ class Bytes {
 		return untyped $sget(b,pos);
 		#elseif flash
 		return b[pos];
-		#elseif php
-		return b.get(pos);
 		#elseif cpp
 		return untyped b[pos];
 		#elseif java
@@ -61,8 +59,6 @@ class Bytes {
 		untyped $sset(b,pos,v);
 		#elseif flash
 		b[pos] = v;
-		#elseif php
-		b.set(pos, v);
 		#elseif cpp
 		untyped b[pos] = v;
 		#elseif java
@@ -82,8 +78,6 @@ class Bytes {
 		#end
 		#if neko
 		try untyped $sblit(b,pos,src.b,srcpos,len) catch( e : Dynamic ) throw Error.OutsideBounds;
-		#elseif php
-		b.blit(pos, src.b, srcpos, len);
 		#elseif flash
 		b.position = pos;
 		if( len > 0 ) b.writeBytes(src.b,srcpos,len);
@@ -141,8 +135,6 @@ class Bytes {
 		var b2 = new flash.utils.ByteArray();
 		b.readBytes(b2,0,len);
 		return new Bytes(len,b2);
-		#elseif php
-		return new Bytes(len, b.sub(pos, len));
 		#elseif java
 		var newarr = new java.NativeArray(len);
 		java.lang.System.arraycopy(b, pos, newarr, 0, len);
@@ -187,8 +179,6 @@ class Bytes {
 		b1.endian = flash.utils.Endian.LITTLE_ENDIAN;
 		b2.endian = flash.utils.Endian.LITTLE_ENDIAN;
 		return length - other.length;
-		#elseif php
-		return b.compare(other.b);
 		//#elseif cs
 		//TODO: memcmp if unsafe flag is on
 		#elseif cpp
@@ -316,7 +306,7 @@ class Bytes {
 	public inline function getInt32( pos : Int ) : Int {
 		#if neko_v21
 		return untyped $sget32(b, pos, false);
-		#elseif (php || python)
+		#elseif python
 		var v = get(pos) | (get(pos + 1) << 8) | (get(pos + 2) << 16) | (get(pos+3) << 24);
 		return if( v & 0x80000000 != 0 ) v | 0x80000000 else v;
 		#elseif lua
@@ -365,8 +355,6 @@ class Bytes {
 		#elseif flash
 		b.position = pos;
 		return b.readUTFBytes(len);
-		#elseif php
-		return b.getString(pos, len);
 		#elseif cpp
 		var result:String="";
 		untyped __global__.__hxcpp_string_of_bytes(b,result,pos,len);
@@ -425,8 +413,6 @@ class Bytes {
 		#elseif flash
 		b.position = 0;
 		return b.toString();
-		#elseif php
-		return b.toString();
 		#elseif cs
 		return cs.system.text.Encoding.UTF8.GetString(b, 0, length);
 		#elseif java
@@ -465,8 +451,6 @@ class Bytes {
 		var b = new flash.utils.ByteArray();
 		b.length = length;
 		return new Bytes(length,b);
-		#elseif php
-		return new Bytes(length, BytesData.alloc(length));
 		#elseif cpp
 		var a = new BytesData();
 		if (length>0) cpp.NativeArray.setSize(a, length);
@@ -493,9 +477,6 @@ class Bytes {
 		var b = new flash.utils.ByteArray();
 		b.writeUTFBytes(s);
 		return new Bytes(b.length,b);
-		#elseif php
-		var x = BytesData.ofString(s);
-		return new Bytes(x.length, x);
 		#elseif cpp
 		var a = new BytesData();
 		untyped __global__.__hxcpp_bytes_of_string(a,s);
@@ -552,8 +533,6 @@ class Bytes {
 		return new Bytes(b.length,b);
 		#elseif neko
 		return new Bytes(untyped __dollar__ssize(b),b);
-		#elseif php
-		return new Bytes(b.length, b);
 		#elseif cs
 		return new Bytes(b.Length,b);
 		#else
@@ -570,8 +549,6 @@ class Bytes {
 		return untyped __dollar__sget(b,pos);
 		#elseif flash
 		return b[pos];
-		#elseif php
-		return b.get(pos);
 		#elseif cpp
 		return untyped b.unsafeGet(pos);
 		#elseif java

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

@@ -27,8 +27,6 @@ class BytesBuffer {
 	var b : Dynamic; // neko string buffer
 	#elseif flash
 	var b : flash.utils.ByteArray;
-	#elseif php
-	var b : String;
 	#elseif cpp
 	var b : BytesData;
 	#elseif cs
@@ -48,8 +46,6 @@ class BytesBuffer {
 		#elseif flash
 		b = new flash.utils.ByteArray();
 		b.endian = flash.utils.Endian.LITTLE_ENDIAN;
-		#elseif php
-		b = "";
 		#elseif cpp
 		b = new BytesData();
 		#elseif cs
@@ -78,8 +74,6 @@ class BytesBuffer {
 		untyped StringBuf.__add_char(b,byte);
 		#elseif flash
 		b.writeByte(byte);
-		#elseif php
-		b += untyped __call__("chr", byte);
 		#elseif cpp
 		b.push(untyped byte);
 		#elseif cs
@@ -96,8 +90,6 @@ class BytesBuffer {
 		untyped StringBuf.__add(b,src.getData());
 		#elseif flash
 		b.writeBytes(src.getData());
-		#elseif php
-		b += src.getData().toString();
 		#elseif cs
 		b.Write(src.getData(), 0, src.length);
 		#elseif java
@@ -165,8 +157,6 @@ class BytesBuffer {
 		try untyped StringBuf.__add_sub(b,src.getData(),pos,len) catch( e : Dynamic ) throw Error.OutsideBounds;
 		#elseif flash
 		if( len > 0 ) b.writeBytes(src.getData(),pos,len);
-		#elseif php
-		b += src.getData().sub(pos, len).toString() ;
 		#elseif cs
 		b.Write(src.getData(), pos, len);
 		#elseif java
@@ -195,8 +185,6 @@ class BytesBuffer {
 		#elseif flash
 		var bytes = new Bytes(b.length,b);
 		b.position = 0;
-		#elseif php
-		var bytes = new Bytes(b.length, BytesData.ofString(b));
 		#elseif cs
 		var buf = b.GetBuffer();
 		var bytes = new Bytes(cast b.Length, buf);

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

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

+ 0 - 4
std/haxe/io/BytesInput.hx

@@ -96,8 +96,6 @@ class BytesInput extends Input {
 			len--;
 			#if neko
 			return untyped __dollar__sget(b,pos++);
-			#elseif php
-			return b.get(pos++);
 			#elseif cpp
 			return untyped b[pos++];
 			#elseif java
@@ -140,8 +138,6 @@ class BytesInput extends Input {
 				len = this.len;
 			#if neko
 			try untyped __dollar__sblit(buf.getData(),pos,b,this.pos,len) catch( e : Dynamic ) throw Error.OutsideBounds;
-			#elseif php
-			buf.getData().blit(pos, b, this.pos, len);
 			#elseif hl
 			@:privateAccess buf.b.blit(pos, b, this.pos, len);
 			#else

+ 0 - 16
std/haxe/io/FPHelper.hx

@@ -52,8 +52,6 @@ class FPHelper {
 			b.endian = flash.utils.Endian.LITTLE_ENDIAN;
 			b;
 		}
-	#elseif php
-		static var isLittleEndian : Bool = untyped __call__('unpack','S','\x01\x00')[1] == 1;
 	#elseif js
 		static var helper = new js.html.DataView(new js.html.ArrayBuffer(8));
 	#else
@@ -89,8 +87,6 @@ class FPHelper {
 			return helper.f;
 		#elseif java
 			return java.lang.Float.FloatClass.intBitsToFloat(i);
-		#elseif php
-			return untyped  __call__('unpack', 'f', __call__('pack', 'l', i))[1];
 		#elseif flash
 			var helper = helper;
 			helper.position = 0;
@@ -138,8 +134,6 @@ class FPHelper {
 			helper.writeFloat(f);
 			helper.position = 0;
 			return helper.readUnsignedInt();
-		#elseif php
-			return untyped __call__('unpack','l',__call__('pack', 'f', f))[1];
 		#elseif js
 			helper.setFloat32(0, f, true);
 			return helper.getInt32(0,true);
@@ -200,8 +194,6 @@ class FPHelper {
 			helper.writeUnsignedInt(high);
 			helper.position = 0;
 			return helper.readDouble();
-		#elseif php
-			return untyped  __call__('unpack', 'd', __call__('pack', 'ii', isLittleEndian ? low : high, isLittleEndian ? high : low))[1];
 		#elseif js
 			helper.setInt32(0, low , true);
 			helper.setInt32(4, high, true);
@@ -284,14 +276,6 @@ class FPHelper {
 				i64.set_high(cast helper.readUnsignedInt());
 			}
 			return i64;
-		#elseif php
-			var a = untyped __call__('unpack',isLittleEndian ? 'V2' : 'N2',__call__('pack', 'd', v));
-			var i64 = i64tmp;
-			@:privateAccess {
-				i64.set_low(a[isLittleEndian ? 1 : 2]);
-				i64.set_high(a[isLittleEndian ? 2 : 1]);
-			}
-			return i64;
 		#elseif js
 			var i64 = i64tmp;
 			helper.setFloat64(0, v, true);

+ 20 - 26
std/haxe/rtti/Meta.hx

@@ -46,43 +46,37 @@ class Meta {
 	private static function isInterface(t:Dynamic):Bool {
 		#if java
 			return java.Lib.toNativeType(t).isInterface();
-	#elseif cs
+		#elseif cs
 			return cs.Lib.toNativeType(t).IsInterface;
 		#elseif (flash && as3)
 			return untyped flash.Lib.describeType(t).factory.extendsClass.length() == 0;
-		#elseif (php && !php7)
-			return untyped __php__("{0} instanceof _hx_interface", t);
 		#else
 			throw "Something went wrong";
 		#end
 	}
 
-	private static function getMeta(t:Dynamic):MetaObject
-	{
-#if (php && php7)
-		return php.Boot.getMeta(t.phpClassName);
-#elseif (java || cs || php || (flash && as3))
+	private static function getMeta(t:Dynamic):MetaObject {
 		#if php
-		t.__ensureMeta__();
-		#end
-		var ret = Reflect.field(t, "__meta__");
-		if (ret == null && Std.is(t,Class))
-		{
-			if (isInterface(t))
+			return php.Boot.getMeta(t.phpClassName);
+		#elseif (java || cs || (flash && as3))
+			var ret = Reflect.field(t, "__meta__");
+			if (ret == null && Std.is(t,Class))
 			{
-				var name = Type.getClassName(t),
-				    cls = Type.resolveClass(name + '_HxMeta');
-				if (cls != null)
-					return Reflect.field(cls, "__meta__");
+				if (isInterface(t))
+				{
+					var name = Type.getClassName(t),
+						cls = Type.resolveClass(name + '_HxMeta');
+					if (cls != null)
+						return Reflect.field(cls, "__meta__");
+				}
 			}
-		}
-		return ret;
-#elseif hl
-		var t : hl.BaseType = t;
-		return t.__meta__;
-#else
-		return untyped t.__meta__;
-#end
+			return ret;
+		#elseif hl
+			var t : hl.BaseType = t;
+			return t.__meta__;
+		#else
+			return untyped t.__meta__;
+		#end
 	}
 
 	/**

+ 0 - 0
std/php7/ArrayAccess.hx → std/php/ArrayAccess.hx


+ 731 - 800
std/php/Boot.hx

@@ -21,966 +21,897 @@
  */
 package php;
 
-@:dox(hide)
+import haxe.PosInfos;
+
+using php.Global;
+
+/**
+	Various Haxe->PHP compatibility utilities.
+	You should not use this class directly.
+**/
 @:keep
+@:dox(hide)
 class Boot {
-	static var qtypes;
-	static var ttypes;
-	static var tpaths;
-	static var skip_constructor = false;
-	static function __init__() : Void {
-		var _hx_class_prefix = untyped __prefix__();
-		untyped __php__("
-function _hx_add($a, $b) {
-	if (!_hx_is_numeric($a) || !_hx_is_numeric($b)) {
-		return _hx_string_or_null($a) . _hx_string_or_null($b);
-	} else {
-		return $a + $b;
+	/** List of Haxe classes registered by their PHP class names  */
+	@:protected static var aliases = new NativeAssocArray<String>();
+	/** Cache of HxClass instances */
+	@:protected static var classes = new NativeAssocArray<HxClass>();
+	/** List of getters (for Reflect) */
+	@:protected static var getters = new NativeAssocArray<NativeAssocArray<Bool>>();
+	/** List of setters (for Reflect) */
+	@:protected static var setters = new NativeAssocArray<NativeAssocArray<Bool>>();
+	/** Metadata storage */
+	@:protected static var meta = new NativeAssocArray<{}>();
+
+	/**
+		Initialization stuff.
+		This method is called once before invoking any Haxe-generated user code.
+	**/
+	static function __init__() {
+		if (!Global.defined('HAXE_CUSTOM_ERROR_HANDLER') || !Const.HAXE_CUSTOM_ERROR_HANDLER) {
+			var previousLevel = Global.error_reporting(Const.E_ALL);
+			var previousHandler = Global.set_error_handler(
+				function (errno:Int, errstr:String, errfile:String, errline:Int) {
+					if (Global.error_reporting() & errno == 0) {
+						return false;
+					}
+					throw new ErrorException(errstr, 0, errno, errfile, errline);
+				}
+			);
+			//Already had user-defined handler. Return it.
+			if (previousHandler != null) {
+				Global.error_reporting(previousLevel);
+				Global.set_error_handler(previousHandler);
+			}
+		}
 	}
-}
 
-function _hx_anonymous($arr = array()) {
-	$o = new _hx_anonymous();
-	foreach($arr as $k => $v)
-		$o->$k = $v;
-	return $o;
-}
-
-class _hx_array implements ArrayAccess, IteratorAggregate {
-	var $a;
-	var $length;
-	function __construct($a = array()) {
-		$this->a = $a;
-		$this->length = count($a);
+	/**
+		Returns root namespace based on a value of `--php-prefix` compiler flag.
+		Returns empty string if no `--php-prefix` provided.
+	**/
+	public static inline function getPrefix() : String {
+		return untyped __php__('self::PHP_PREFIX');
 	}
 
-	function concat($a) {
-		return new _hx_array(array_merge($this->a, $a->a));
+	/**
+		Register list of getters to be able to call getters using reflection
+	**/
+	public static function registerGetters( phpClassName:String, list:NativeAssocArray<Bool> ) : Void {
+		getters[phpClassName] = list;
 	}
 
-	function copy() {
-		return new _hx_array($this->a);
+	/**
+		Register list of setters to be able to call getters using reflection
+	**/
+	public static function registerSetters( phpClassName:String, list:NativeAssocArray<Bool> ) : Void {
+		setters[phpClassName] = list;
 	}
 
-	function &get($index) {
-		if(isset($this->a[$index])) return $this->a[$index];
-		return null;
-	}
+	/**
+		Check if specified property has getter
+	**/
+	public static function hasGetter( phpClassName:String, property:String ) : Bool {
+		ensureLoaded(phpClassName);
 
-	function insert($pos, $x) {
-		array_splice($this->a, $pos, 0, array($x));
-		$this->length++;
+		var has = false;
+		var phpClassName:haxe.extern.EitherType<Bool,String> = phpClassName;
+		do {
+			has = Global.isset(getters[phpClassName][property]);
+			phpClassName = Global.get_parent_class(phpClassName);
+		} while (!has && phpClassName != false && Global.class_exists(phpClassName));
+
+		return has;
 	}
 
-	function iterator() {
-		return new _hx_array_iterator($this->a);
+	/**
+		Check if specified property has setter
+	**/
+	public static function hasSetter( phpClassName:String, property:String ) : Bool {
+		ensureLoaded(phpClassName);
+
+		var has = false;
+		var phpClassName:haxe.extern.EitherType<Bool,String> = phpClassName;
+		do {
+			has = Global.isset(setters[phpClassName][property]);
+			phpClassName = Global.get_parent_class(phpClassName);
+		} while (!has && phpClassName != false && Global.class_exists(phpClassName));
+
+		return has;
 	}
 
-	function getIterator() {
-		return $this->iterator();
+	/**
+		Save metadata for specified class
+	**/
+	public static function registerMeta( phpClassName:String, data:Dynamic ) : Void {
+		meta[phpClassName] = data;
 	}
 
-	function join($sep) {
-		return implode($sep, array_map('_hx_string_rec',$this->a,array()));
+	/**
+		Retrieve metadata for specified class
+	**/
+	public static function getMeta( phpClassName:String ) : Null<Dynamic> {
+		ensureLoaded(phpClassName);
+		return Global.isset(meta[phpClassName]) ? meta[phpClassName] : null;
 	}
 
-	function pop() {
-		$r = array_pop($this->a);
-		$this->length = count($this->a);
-		return $r;
+	/**
+		Associate PHP class name with Haxe class name
+	**/
+	public static function registerClass( phpClassName:String, haxeClassName:String ) : Void {
+		aliases[phpClassName] = haxeClassName;
 	}
 
-	function push($x) {
-		$this->a[] = $x;
-		return ++$this->length;
+	/**
+		Returns a list of currently loaded haxe-generated classes.
+	**/
+	public static function getRegisteredClasses():Array<Class<Dynamic>> {
+		var result = [];
+		Syntax.foreach(aliases, function(phpName, haxeName) {
+			result.push(cast getClass(phpName));
+		});
+		return result;
 	}
 
-	function remove($x) {
-		foreach($this->a as $i => $val)
-			if($val === $x) {
-				unset($this->a[$i]);
-				$this->a = array_values($this->a);
-				$this->length--;
-				return true;
-			}
-		return false;
+	/**
+		Returns a list of phpName=>haxeName for currently loaded haxe-generated classes.
+	**/
+	public static function getRegisteredAliases():NativeAssocArray<String> {
+		return aliases;
 	}
 
-	function indexOf($x, $fromIndex) {
-		$i = ($fromIndex === null) ? 0 : $fromIndex;
-		$len = $this->length;
-		$a = $this->a;
-		if ($i < 0) {
-			$i += $len;
-			if ($i < 0) $i = 0;
+	/**
+		Get Class<T> instance for PHP fully qualified class name (E.g. '\some\pack\MyClass')
+		It's always the same instance for the same `phpClassName`
+	**/
+	public static function getClass( phpClassName:String ) : HxClass {
+		if (phpClassName.charAt(0) == '\\') {
+			phpClassName = phpClassName.substr(1);
 		}
-		while ($i < $len) {
-			if ($a[$i] === $x)
-				return $i;
-			$i++;
+		if (!Global.isset(classes[phpClassName])) {
+			classes[phpClassName] = new HxClass(phpClassName);
 		}
-		return -1;
-	}
 
-	function lastIndexOf($x, $fromIndex) {
-		$len = $this->length;
-		$i = ($fromIndex === null) ? $len - 1 : $fromIndex;
-		$a = $this->a;
-		if ($i >= $len)
-			$i = $len - 1;
-		else if ($i < 0)
-			$i += $len;
-		while ($i >= 0) {
-			if ($a[$i] === $x)
-				return $i;
-			$i--;
+		return classes[phpClassName];
+	}
+
+	/**
+		Returns Class<HxAnon>
+	**/
+	public static inline function getHxAnon() : HxClass {
+		return cast HxAnon;
+	}
+
+	/**
+		Returns Class<HxClass>
+	**/
+	public static inline function getHxClass() : HxClass {
+		return cast HxClass;
+	}
+
+	/**
+		Returns either Haxe class name for specified `phpClassName` or (if no such Haxe class registered) `phpClassName`.
+	**/
+	public static function getClassName( phpClassName:String ) : String {
+		var hxClass = getClass(phpClassName);
+		var name = getHaxeName(hxClass);
+		return (name == null ? hxClass.phpClassName : name);
+	}
+
+	/**
+		Returns original Haxe fully qualified class name for this type (if exists)
+	**/
+	public static function getHaxeName( hxClass:HxClass) : Null<String> {
+		switch (hxClass.phpClassName) {
+			case 'Int': return 'Int';
+			case 'String': return 'String';
+			case 'Bool': return 'Bool';
+			case 'Float': return 'Float';
+			case 'Class': return 'Class';
+			case 'Enum': return 'Enum';
+			case 'Dynamic': return 'Dynamic';
+			case _:
 		}
-		return -1;
-	}
-
-	function removeAt($pos) {
-		if(array_key_exists($pos, $this->a)) {
-			unset($this->a[$pos]);
-			$this->length--;
-			return true;
-		} else
-			return false;
-	}
 
-	function reverse() {
-		$this->a = array_reverse($this->a, false);
-	}
-
-	function shift() {
-		$r = array_shift($this->a);
-		$this->length = count($this->a);
-		return $r;
-	}
+		inline function exists() return Global.isset(aliases[hxClass.phpClassName]);
 
-	function slice($pos, $end) {
-		if($end === null)
-			return new _hx_array(array_slice($this->a, $pos));
-		else
-			return new _hx_array(array_slice($this->a, $pos, $end-$pos));
-	}
+		if (exists()) {
+			return aliases[hxClass.phpClassName];
+		} else if (Global.class_exists(hxClass.phpClassName) && exists()) {
+			return aliases[hxClass.phpClassName];
+		} else if (Global.interface_exists(hxClass.phpClassName) && exists()) {
+			return aliases[hxClass.phpClassName];
+		}
 
-	function sort($f) {
-		usort($this->a, $f);
+		return null;
 	}
 
-	function splice($pos, $len) {
-		if($len < 0) $len = 0;
-		$nh = new _hx_array(array_splice($this->a, $pos, $len));
-		$this->length = count($this->a);
-		return $nh;
-	}
+	/**
+		Find corresponding PHP class name.
+		Returns `null` if specified class does not exist.
+	**/
+	public static function getPhpName( haxeName:String ) : Null<String> {
+		var prefix = getPrefix();
+		var phpParts = (prefix.length == 0 ? [] : [prefix]);
+
+		var haxeParts = haxeName.split('.');
+		for (part in haxeParts) {
+			switch (part.toLowerCase()) {
+				case "__halt_compiler" | "abstract" | "and" | "array" | "as" | "break" | "callable" | "case" | "catch" | "class"
+					| "clone" | "const" | "continue" | "declare" | "default" | "die" | "do" | "echo" | "else" | "elseif" | "empty"
+					| "enddeclare" | "endfor" | "endforeach" | "endif" | "endswitch" | "endwhile" | "eval" | "exit" | "extends"
+					| "final" | "finally" | "for" | "foreach" | "function" | "global" | "goto" | "if" | "implements" | "include"
+					| "include_once" | "instanceof" | "insteadof" | "interface" | "isset" | "list" | "namespace" | "new" | "or"
+					| "print" | "private" | "protected" | "public" | "require" | "require_once" | "return" | "static" | "switch"
+					| "throw" | "trait" | "try" | "unset" | "use" | "var" | "while" | "xor" | "yield" | "__class__" | "__dir__"
+					| "__file__" | "__function__" | "__line__" | "__method__" | "__trait__" | "__namespace__" | "int" | "float"
+					| "bool" | "string" | "true" | "false" | "null" | "parent" | "void" | "iterable":
+						part += '_hx';
+				case _:
+			}
+			phpParts.push(part);
+		}
 
-	function toString() {
-		return '['.implode(',', array_map('_hx_string_rec',$this->a,array())).']';
+		return phpParts.join('\\');
 	}
 
-	function __toString() {
-		return $this->toString();
+	/**
+		Creates Haxe-compatible closure.
+		@param type `this` for instance methods; full php class name for static methods
+		@param func Method name
+	**/
+	public static inline function closure( target:Dynamic, func:Dynamic ) : HxClosure {
+		return new HxClosure(target, func);
 	}
 
-	function unshift($x) {
-		array_unshift($this->a, $x);
-		$this->length++;
+	/**
+		Unsafe cast to HxClosure
+	**/
+	public static inline function castClosure(value:Dynamic) : HxClosure {
+		return value;
 	}
 
-	function map($f) {
-		return new _hx_array(array_map($f, $this->a));
+	/**
+		Unsafe cast to HxClass
+	**/
+	public static inline function castClass(cls:Class<Dynamic>) : HxClass {
+		return cast cls;
 	}
 
-	function filter($f) {
-		return new _hx_array(array_values(array_filter($this->a,$f)));
+	/**
+		Returns `Class<T>` for `HxClosure`
+	**/
+	public static inline function closureHxClass() : HxClass {
+		return cast HxClosure;
 	}
 
-	// ArrayAccess methods:
-	function offsetExists($offset) {
-		return isset($this->a[$offset]);
+	/**
+		Implementation for `cast(value, Class<Dynamic>)`
+		@throws HxException if `value` cannot be casted to this type
+	**/
+	public static function typedCast( hxClass:HxClass, value:Dynamic ) : Dynamic {
+		switch (hxClass.phpClassName) {
+			case 'Int':
+				if (Boot.isNumber(value)) {
+					return Global.intval(value);
+				}
+			case 'Float':
+				if (Boot.isNumber(value)) {
+					return value.floatval();
+				}
+			case 'Bool':
+				if (value.is_bool()) {
+					return value;
+				}
+			case 'String':
+				if (value.is_string()) {
+					return value;
+				}
+			case 'php\\NativeArray':
+				if (value.is_array()) {
+					return value;
+				}
+			case _:
+				if (value.is_object() && Std.is(value, cast hxClass)) {
+					return value;
+				}
+		}
+		throw 'Cannot cast ' + Std.string(value) + ' to ' + getClassName(hxClass.phpClassName);
 	}
 
-	function offsetGet($offset) {
-		if(isset($this->a[$offset])) return $this->a[$offset];
-		return null;
+	/**
+		`trace()` implementation
+	**/
+	public static function trace( value:Dynamic, infos:PosInfos ) : Void {
+		if (infos != null) {
+			Global.echo('${infos.fileName}:${infos.lineNumber}: ');
+		}
+		Global.echo(stringify(value));
+		if (infos.customParams != null) {
+			for (value in infos.customParams) {
+				Global.echo(',' + stringify(value));
+			}
+		}
+		Global.echo('\n');
 	}
 
-	function offsetSet($offset, $value) {
-		if($this->length <= $offset) {
-			$this->a = array_merge($this->a, array_fill(0, $offset+1-$this->length, null));
-			$this->length = $offset+1;
+	/**
+		Returns string representation of `value`
+	**/
+	public static function stringify( value : Dynamic ) : String {
+		if (value == null) {
+			return 'null';
+		}
+		if (value.is_string()) {
+			return value;
+		}
+		if (value.is_int() || value.is_float()) {
+			return Syntax.string(value);
+		}
+		if (value.is_bool()) {
+			return value ? 'true' : 'false';
+		}
+		if (value.is_array()) {
+			var strings = Syntax.arrayDecl();
+			Syntax.foreach(value, function(key:Dynamic, item:Dynamic) {
+				Global.array_push(strings, (key:String) + ' => ' + stringify(item));
+			});
+			return '[' + Global.implode(', ', strings) + ']';
 		}
-		return $this->a[$offset] = $value;
+		if (value.is_object()) {
+			if (value.method_exists('toString')) {
+				return value.toString();
+			}
+			if (value.method_exists('__toString')) {
+				return value.__toString();
+			}
+			if (Std.is(value, StdClass)) {
+				if (Global.isset(Syntax.getField(value, 'toString')) && value.toString.is_callable()) {
+					return value.toString();
+				}
+				var result = new NativeIndexedArray<String>();
+				var data = Global.get_object_vars(value);
+				for (key in data.array_keys()) {
+					result.array_push('$key : ' + stringify(data[key]));
+				}
+				return '{ ' + Global.implode(', ', result) + ' }';
+			}
+			if (isFunction(value)) {
+				return '<function>';
+			}
+			if (Std.is(value, HxClass)) {
+				return '[class ' + getClassName((value:HxClass).phpClassName) + ']';
+			} else {
+				return '[object ' + getClassName(Global.get_class(value)) + ']';
+			}
+		}
+		throw "Unable to stringify value";
 	}
 
-	function offsetUnset($offset) {
-		return $this->removeAt($offset);
+	static public inline function isNumber( value:Dynamic ) {
+		return value.is_int() || value.is_float();
 	}
-}
 
-class _hx_array_iterator implements Iterator {
-	private $a;
-	private $i;
-	public function __construct($a) {
-		$this->a = $a;
-		$this->i = 0;
+	/**
+		Check if specified values are equal
+	**/
+	public static function equal( left:Dynamic, right:Dynamic ) : Bool {
+		if (isNumber(left) && isNumber(right)) {
+			return Syntax.binop(left, '==', right);
+		}
+		return Syntax.binop(left, '===', right);
 	}
 
-	public function next() {
-		if(!$this->hasNext()) return null;
-		return $this->a[$this->i++];
+	/**
+		Concat `left` and `right` if both are strings or string and null.
+		Otherwise return sum of `left` and `right`.
+	**/
+	public static function addOrConcat( left:Dynamic, right:Dynamic ) : Dynamic {
+		if (left.is_string() || right.is_string()) {
+			return (left:String) + (right:String);
+		}
+		return Syntax.binop(left, '+', right);
 	}
 
-	public function hasNext() {
-		return $this->i < count($this->a);
-	}
+	/**
+		`Std.is()` implementation
+	**/
+	public static function is( value:Dynamic, type:HxClass ) : Bool {
+		if (type == null) return false;
 
-	public function current() {
-		if (!$this->hasNext()) return false;
-		return $this->a[$this->i];
+		var phpType = type.phpClassName;
+		switch (phpType) {
+			case 'Dynamic':
+				return true;
+			case 'Int':
+				return (
+						value.is_int()
+						|| (
+							value.is_float()
+							&& Syntax.binop(Syntax.int(value), '==', value)
+							&& !Global.is_nan(value)
+						)
+					)
+					&& Global.abs(value) <= 2147483648;
+			case 'Float':
+				return value.is_float() || value.is_int();
+			case 'Bool':
+				return value.is_bool();
+			case 'String':
+				return value.is_string();
+			case 'php\\NativeArray', 'php\\_NativeArray\\NativeArray_Impl_':
+				return value.is_array();
+			case 'Enum', 'Class':
+				if (Std.is(value, HxClass)) {
+					var valuePhpClass = (cast value:HxClass).phpClassName;
+					var enumPhpClass = (cast HxEnum:HxClass).phpClassName;
+					var isEnumType = Global.is_subclass_of(valuePhpClass, enumPhpClass);
+					return (phpType == 'Enum' ? isEnumType : !isEnumType);
+				}
+			case _:
+				if (value.is_object()) {
+					var type:Class<Dynamic> = cast type;
+					return Syntax.instanceof(value, type);
+				}
+		}
+		return false;
 	}
 
-	public function key() {
-		return $this->i;
+	/**
+		Check if `value` is a `Class<T>`
+	**/
+	public static inline function isClass(value:Dynamic) : Bool {
+		return Std.is(value, HxClass);
 	}
 
-	public function valid() {
-		return $this->current() !== false;
+	/**
+		Check if `value` is an enum constructor instance
+	**/
+	public static inline function isEnumValue(value:Dynamic) : Bool {
+		return Std.is(value, HxEnum);
 	}
 
-	public function rewind() {
-		$this->i = 0;
-	}
-	public function size() {
-		return count($this->a);
+	/**
+		Check if `value` is a function
+	**/
+	public static inline function isFunction(value:Dynamic) : Bool {
+		return Std.is(value, Closure) || Std.is(value, HxClosure);
 	}
-}
 
-function _hx_array_get($a, $pos) { return $a[$pos]; }
-
-function _hx_array_increment($a, $pos) { return $a[$pos] += 1; }
-function _hx_array_decrement($a, $pos) { return $a[$pos] -= 1; }
-
-function _hx_array_assign($a, $i, $v) { return $a[$i] = $v; }
-
-class _hx_break_exception extends Exception {}
-
-function _hx_cast($v, $type) {
-	if(_hx_instanceof($v, $type)) {
-		return $v;
-	} else {
-		throw new HException('Class cast error');
+	/**
+		Check if `value` is an instance of `HxClosure`
+	**/
+	public static inline function isHxClosure(value:Dynamic) : Bool {
+		return Std.is(value, HxClosure);
 	}
-}
-
-function _hx_char_at($o, $i) {
-	if ($i < 0)
-		return '';
-	$c = substr($o, $i, 1);
-	return FALSE === $c ? '' : $c;
-}
 
-function _hx_char_code_at($s, $pos) {
-	if($pos < 0 || $pos >= strlen($s)) return null;
-	return ord($s{$pos});
-}
-
-function _hx_deref($o) { return $o; }
-
-function _hx_equal($x, $y) {
-	if(is_null($x)) {
-		return is_null($y);
-	} else {
-		if(is_null($y)) {
-			return false;
+	/**
+		Performs `left >>> right` operation
+	**/
+	public static function shiftRightUnsigned( left:Int, right:Int ) : Int {
+		if (right == 0) {
+			return left;
+		} else if (left >= 0) {
+			return (left >> right);
 		} else {
-			if((is_float($x) || is_int($x)) && (is_float($y) || is_int($y))) {
-				return $x == $y;
-			} else {
-				return $x === $y;
-			}
+			return (left >> right) & (0x7fffffff >> (right - 1));
 		}
 	}
-}
 
-function _hx_mod($x, $y) {
-	if (is_int($x) && is_int($y)) {
-		if ($y == 0) return 0;
-		return $x % $y;
+	/**
+		Helper method to avoid "Cannot use temporary expression in write context" error for expressions like this:
+		```
+		(new MyClass()).fieldName = 'value';
+		```
+	**/
+	static public function deref( value:Dynamic ) : Dynamic {
+		return value;
 	}
-	if (!is_nan($x) && !is_nan($y) && !is_finite($y) && is_finite($x)) {
-		return $x;
-	}
-	return fmod($x, $y);
-}
 
-function _hx_error_handler($errno, $errmsg, $filename, $linenum, $vars) {
-	if (!(error_reporting() & $errno)) {
-		return false;
+	/**
+		Create Haxe-compatible anonymous structure of `data` associative array
+	**/
+	static public inline function createAnon( data:NativeArray ) : Dynamic {
+		return new HxAnon(data);
 	}
-	$msg = $errmsg . ' (errno: ' . $errno . ')';
-	$e = new HException($msg, '', $errno, _hx_anonymous(array('fileName' => 'Boot.hx', 'lineNumber' => __LINE__, 'className' => 'php.Boot', 'methodName' => '_hx_error_handler')));
-	$e->setFile($filename);
-	$e->setLine($linenum);
-	throw $e;
-	return null;
-}
 
-function _hx_exception_handler($e) {
-	if(0 == strncasecmp(PHP_SAPI, 'cli', 3)) {
-		$msg   = $e-> getMessage();
-		$nl    = \"\\n\";
-		$pre   = '';
-		$post  = '';
-	} else {
-		$msg   = '<b>' . $e-> getMessage() . '</b>';
-		$nl    = \"<br />\";
-		$pre   = '<pre>';
-		$post  = '</pre>';
-	}
-	if(isset($GLOBALS['%s'])) {
-		$stack = '';
-		$i = $GLOBALS['%s']->length;
-		while(--$i >= 0)
-			$stack .= 'Called from '.$GLOBALS['%s'][$i].$nl;
-		echo $pre.'uncaught exception: '.$msg.$nl.$nl.$stack.$post;
-	} else
-		echo $pre.'uncaught exception: '.$msg.$nl.$nl.'in file: '.$e->getFile().' line '.$e->getLine().$nl.$e->getTraceAsString().$post;
-	exit(1);
-}
-
-function _hx_explode($delimiter, $s) {
-	if($delimiter == '')
-		return new _hx_array(str_split($s, 1));
-	return new _hx_array(explode($delimiter, $s));
-}
-
-function _hx_explode2($s, $delimiter) {
-	if($delimiter == '')
-		return new _hx_array(str_split($s, 1));
-	return new _hx_array(explode($delimiter, $s));
-}
+	/**
+		Make sure specified class is loaded
+	**/
+	static public inline function ensureLoaded( phpClassName:String ) : Bool {
+		return Global.class_exists(phpClassName) || Global.interface_exists(phpClassName);
+	}
 
-function _hx_field($o, $field) {
-	if(_hx_has_field($o, $field)) {
-		if($o instanceof _hx_type) {
-			if(is_callable($c = array($o->__tname__, $field)) && !property_exists($o->__tname__, $field)) {
-				return $c;
-			} else {
-				$name = $o->__tname__;
-				return eval('return '.$name.'::$'.$field.';');
-			}
-		} else {
-			if(is_string($o)) {
-				if($field == 'length') {
-					return strlen($o);
-				} else {
-					switch($field) {
-						case 'charAt'     : return array(new _hx_lambda(array(&$o), '_hx_char_at'), 'execute');
-						case 'charCodeAt' : return array(new _hx_lambda(array(&$o), '_hx_char_code_at'), 'execute');
-						case 'indexOf'    : return array(new _hx_lambda(array(&$o), '_hx_index_of'), 'execute');
-						case 'lastIndexOf': return array(new _hx_lambda(array(&$o), '_hx_last_index_of'), 'execute');
-						case 'split'      : return array(new _hx_lambda(array(&$o), '_hx_explode2'), 'execute');
-						case 'substr'     : return array(new _hx_lambda(array(&$o), '_hx_substr'), 'execute');
-						case 'toUpperCase': return array(new _hx_lambda(array(&$o), 'strtoupper'), 'execute');
-						case 'toLowerCase': return array(new _hx_lambda(array(&$o), 'strtolower'), 'execute');
-						case 'toString'   : return array(new _hx_lambda(array(&$o), '_hx_deref'), 'execute');
-					}
-					return null;
-				}
-			} else {
-				if(property_exists($o, $field)) {
-					if(is_array($o->$field) && is_callable($o->$field)) {
-						return $o->$field;
-					} else {
-						if(is_string($o->$field) && _hx_is_lambda($o->$field)) {
-							return array($o, $field);
-						} else {
-							return $o->$field;
-						}
-					}
-				} else if(isset($o->__dynamics) && isset($o->__dynamics[$field])) {
-					return $o->__dynamics[$field];
-				} else {
-					return array($o, $field);
-				}
-			}
+	/**
+		Get `field` of a dynamic `value` in a safe manner (avoid exceptions on trying to get a method)
+	**/
+	static public function dynamicField( value:Dynamic, field:String ) : Dynamic {
+		if(Global.method_exists(value, field)) {
+			return closure(value, field);
 		}
-	} else {
-		return null;
+		if(Global.is_string(value)) {
+			value = @:privateAccess new HxDynamicStr(value);
+		}
+		return Syntax.getField(value, field);
 	}
-}
-
-function _hx_get_object_vars($o) {
-	$a = array_keys(get_object_vars($o));
-	if(isset($o->__dynamics))
-		$a = array_merge($a, array_keys($o->__dynamics));
-	$arr = array();
-	foreach($a as $val)
-		$arr[] = '' . $val;
-	return $arr;
-}
-
-function _hx_has_field($o, $field) {
-	return
-		(is_object($o) && (method_exists($o, $field) || isset($o->$field) || property_exists($o, $field) || isset($o->__dynamics[$field])))
-		||
-		(is_string($o) && (in_array($field, array('toUpperCase', 'toLowerCase', 'charAt', 'charCodeAt', 'indexOf', 'lastIndexOf', 'split', 'substr', 'toString', 'length'))))
-	;
-}
 
-function _hx_index_of($s, $value, $startIndex = null) {
-	$x = strpos($s, $value, $startIndex);
-	if($x === false)
-		return -1;
-	else
-		return $x;
-}
-
-function _hx_instanceof($v, $t) {
-	if($t === null) {
-		return false;
-	}
-	switch($t->__tname__) {
-		case 'Array'  : return is_array($v);
-		case 'String' : return is_string($v) && !_hx_is_lambda($v);
-		case 'Bool'   : return is_bool($v);
-		case 'Int'    : return (is_int($v) || (is_float($v) && intval($v) == $v && !is_nan($v))) && abs($v) <= 0x80000000;
-		case 'Float'  : return is_float($v) || is_int($v);
-		case 'Dynamic': return true;
-		case 'Class'  : return ($v instanceof _hx_class || $v instanceof _hx_interface) && $v->__tname__ != 'Enum';
-		case 'Enum'   : return $v instanceof _hx_enum;
-		case 'php.NativeArray': return is_array($v);
-		default       : return is_a($v, $t->__tname__);
+	public static function dynamicString( str:String ) : HxDynamicStr {
+		return @:privateAccess new HxDynamicStr(str);
 	}
 }
 
-function _hx_is_lambda($s) {
-	return (is_string($s) && substr($s, 0, 8) == chr(0).'lambda_') || (is_array($s) && count($s) > 0 && (is_a($s[0], '_hx_lambda') || is_a($s[0], '_hx_lambda2')));
-}
-
-function _hx_is_numeric($v)
-{
-	return is_numeric($v) && !is_string($v);
-}
 
-function _hx_last_index_of($s, $value, $startIndex = null) {
-	$x = strrpos($s, $value, $startIndex === null ? 0 : $startIndex-strlen($s));
-	if($x === false)
-		return -1;
-	else
-		return $x;
-}
+/**
+	Class<T> implementation for Haxe->PHP internals.
+**/
+@:keep
+@:dox(hide)
+private class HxClass {
 
-function _hx_len($o) {
-	return is_string($o) ? strlen($o) : $o->length;
-}
+	public var phpClassName (default,null) : String;
 
-class _hx_list_iterator implements Iterator {
-	private $h;
-	private $list;
-	private $counter;
-	public function __construct($list) {
-		$this->list = $list;
-		$this->rewind();
+	public function new( phpClassName:String ) : Void {
+		this.phpClassName = phpClassName;
 	}
 
-	public function next() {
-		if($this->h == null) return null;
-		$this->counter++;
-		$x = $this->h[0];
-		$this->h = $this->h[1];
-		return $x;
+	/**
+		Magic method to call static methods of this class, when `HxClass` instance is in a `Dynamic` variable.
+	**/
+	@:phpMagic
+	function __call( method:String, args:NativeArray ) : Dynamic {
+		var callback = (phpClassName == 'String' ? (cast HxString:HxClass).phpClassName : phpClassName) + '::' + method;
+		return Global.call_user_func_array(callback, args);
 	}
 
-	public function hasNext() {
-		return $this->h != null;
+	/**
+		Magic method to get static vars of this class, when `HxClass` instance is in a `Dynamic` variable.
+	**/
+	@:phpMagic
+	function __get( property:String ) : Dynamic {
+		if (Boot.hasGetter(phpClassName, property)) {
+			return Syntax.staticCall(phpClassName, 'get_$property');
+		} else {
+			return Syntax.getStaticField(phpClassName, property);
+		}
 	}
 
-	public function current() {
-		if (!$this->hasNext()) return null;
-		return $this->h[0];
+	/**
+		Magic method to set static vars of this class, when `HxClass` instance is in a `Dynamic` variable.
+	**/
+	@:phpMagic
+	function __set( property:String, value:Dynamic ) : Void {
+		if (Boot.hasSetter(phpClassName, property)) {
+			Syntax.staticCall(phpClassName, 'set_$property', value);
+		} else {
+			Syntax.setStaticField(phpClassName, property, value);
+		}
 	}
+}
 
-	public function key() {
-		return $this->counter;
-	}
 
-	public function valid() {
-		return $this->current() !== null;
-	}
+/**
+	Base class for enum types
+**/
+@:keep
+@:dox(hide)
+private class HxEnum {
+	static var singletons = new Map<String,HxEnum>();
+
+	var tag : String;
+	var index : Int;
+	var params : NativeArray;
+
+	/**
+		Returns instances of constructors without arguments
+	**/
+	public static function singleton( enumClass:String, tag:String, index:Int ) : HxEnum {
+		var key = '$enumClass::$tag';
+
+		var instance = singletons.get(key);
+		if (instance == null) {
+			instance = Syntax.construct(enumClass, tag, index);
+			singletons.set(key, instance);
+		}
 
-	public function rewind() {
-		$this->counter = -1;
-		$this->h = $this->list->h;
+		return instance;
 	}
 
-	public function size() {
-		return $this->list->length;
+	public function new( tag:String, index:Int, arguments:NativeArray = null ) : Void {
+		this.tag = tag;
+		this.index = index;
+		params = (arguments == null ? new NativeArray() : arguments);
 	}
-}
-
-function _hx_null() { return null; }
-
-class _hx_nullob {
-	function _throw()       { throw new HException('Null object'); }
-	function __call($f, $a) { $this->_throw(); }
-	function __get($f)      { $this->_throw(); }
-	function __set($f, $v)  { $this->_throw(); }
-	function __isset($f)    { $this->_throw(); }
-	function __unset($f)    { $this->_throw(); }
-	function __toString()   { return 'null'; }
-	static $inst;
-}
 
-_hx_nullob::$inst = new _hx_nullob();
-
-function _hx_nullob() { return _hx_nullob::$inst; }
-
-function _hx_qtype($n) {
-	if(!isset(php_Boot::$qtypes[$n])) {
-		php_Boot::$qtypes[$n] = new _hx_type($n, null);
+	/**
+		Get string representation of this `Class`
+	**/
+	public function toString() : String {
+		return __toString();
 	}
 
-	return php_Boot::$qtypes[$n];
-}
-
-function _hx_register_type($t) {
-	php_Boot::$qtypes[$t->__qname__] = $t;
-	php_Boot::$ttypes[$t->__tname__] = $t;
-	if($t->__path__ !== null)
-		php_Boot::$tpaths[$t->__tname__] = $t->__path__;
+	/**
+		PHP magic method to get string representation of this `Class`
+	**/
+	@:phpMagic
+	public function __toString() : String {
+		var result = tag;
+		if (Global.count(params) > 0) {
+			var strings = Global.array_map(function (item) return Boot.stringify(item), params);
+			result += '(' + Global.implode(',', strings) + ')';
+		}
+		return result;
+	}
 }
 
-function _hx_set_method($o, $field, $func) {
-	$value[0]->scope = $o;
-	$o->$field = $func;
-}
 
-function _hx_shift_right($v, $n) {
-	return ($n == 0) ? $v : ($v >= 0) ? ($v >> $n) : ($v >> $n) & (0x7fffffff >> ($n-1));
-}
+/**
+	`String` implementation
+**/
+@:keep
+@:dox(hide)
+private class HxString {
 
-function _hx_string_call($s, $method, $params) {
-	if(!is_string($s)) return call_user_func_array(array($s, $method), $params);
-	switch($method) {
-		case 'toUpperCase': return strtoupper($s);
-		case 'toLowerCase': return strtolower($s);
-		case 'charAt'     : return substr($s, $params[0], 1);
-		case 'charCodeAt' : return _hx_char_code_at($s, $params[0]);
-		case 'indexOf'    : return _hx_index_of($s, $params[0], (count($params) > 1 ? $params[1] : null));
-		case 'lastIndexOf': return _hx_last_index_of($s, $params[0], (count($params) > 1 ? $params[1] : null));
-		case 'split'      : return _hx_explode($params[0], $s);
-		case 'substr'     : return _hx_substr($s, $params[0], (count($params) > 1 ? $params[1] : null));
-		case 'toString'   : return $s;
-		default           : throw new HException('Invalid Operation: ' . $method);
+	public static function toUpperCase( str:String ) : String {
+		return Global.strtoupper(str);
 	}
-}
 
-function _hx_string_or_null($s) {
-	return $s === null ? 'null' : $s;
-}
+	public static function toLowerCase( str:String ) : String {
+		return Global.strtolower(str);
+	}
 
-function _hx_string_rec($o, $s) {
-	if($o === null)                return 'null';
-	if(strlen($s) >= 5)            return '<...>';
-	if(is_int($o) || is_float($o)) return '' . $o;
-	if(is_bool($o))                return $o ? 'true' : 'false';
-	if(is_object($o)) {
-		$c = get_class($o);
-		if($o instanceof Enum) {
-			$b = $o->tag;
-			if(!empty($o->params)) {
-				$s .= \"\t\";
-				$b .= '(';
-				foreach($o->params as $i => $val) {
-					if($i > 0)
-						$b .= ',' . _hx_string_rec($val, $s);
-					else
-						$b .= _hx_string_rec($val, $s);
-				}
-				$b .= ')';
-			}
-			return $b;
+	public static function charAt( str:String, index:Int) : String {
+		if (index < 0 || index >= str.length) {
+			return '';
 		} else {
-			if ($o instanceof _hx_anonymous) {
-				if ($o->toString && is_callable($o->toString)) {
-					return call_user_func($o->toString);
-				}
-				$rfl = new ReflectionObject($o);
-				$b2 = \"{\n\";
-				$s .= \"\t\";
-				$properties = $rfl->getProperties();
-
-				foreach($properties as $i => $prop) {
-					$f = $prop->getName();
-					if($i > 0)
-						$b2 .= \", \n\";
-					$b2 .= $s . $f . ' : ' . _hx_string_rec($o->$f, $s);
-				}
-				$s = substr($s, 1);
-				$b2 .= \"\n\" . $s . '}';
-				return $b2;
-			} else {
-				if($o instanceof _hx_type)
-					return $o->__qname__;
-				else {
-					if(is_callable(array($o, 'toString')))
-						return $o->toString();
-					else {
-						if(is_callable(array($o, '__toString')))
-							return $o->__toString();
-						else
-							return '[' . _hx_ttype($c) . ']';
-					}
-				}
-			}
+			return (str:NativeString)[index];
 		}
 	}
-	if(is_string($o)) {
-		if(_hx_is_lambda($o)) return '<function>';
-//		if(strlen($s) > 0)    return '\"' . str_replace('\"', '\\\"', $o) . '\"';
-		else                  return $o;
-	}
-	if(is_array($o)) {
-		if(is_callable($o)) return '<function>';
-		$str = '[';
-		$s .= \"\t\";
-		$first = true;
-		$assoc = true;
-		foreach($o as $k => $v)
-		{
-			if ($first && $k === 0)
-				$assoc = false;
-			$str .= ($first ? '' : ',') . ($assoc
-				? _hx_string_rec($k, $s) . '=>' . _hx_string_rec($o[$k], $s)
-				: _hx_string_rec($o[$k], $s)
-			);
-			$first = false;
+
+	public static function charCodeAt( str:String, index:Int) : Null<Int> {
+		if (index < 0 || index >= str.length) {
+			return null;
+		} else {
+			return Global.ord((str:NativeString)[index]);
 		}
-		$str .= ']';
-		return $str;
 	}
-	return '';
-}
-
-function _hx_substr($s, $pos, $len) {
-	if($pos !== null && $pos !== 0 && $len !== null && $len < 0) return '';
-	if($len === null) $len = strlen($s);
-	if($pos < 0) {
-		$pos = strlen($s) + $pos;
-		if($pos < 0) $pos = 0;
-	} else if($len < 0 )
-		$len = strlen($s) + $len - $pos;
-	$s = substr($s, $pos, $len);
-	if($s === false)
-		return '';
-	else
-		return $s;
-}
-
-function _hx_substring($s, $startIndex, $endIndex) {
-	$len = strlen($s);
-	if ($endIndex === null)
-		$endIndex = $len;
-	else if ($endIndex < 0)
-		$endIndex = 0;
-	else if ($endIndex > $len)
-		$endIndex  = $len;
-
-	if ($startIndex < 0)
-		$startIndex = 0;
-	else if ($startIndex > $len)
-		$startIndex = $len;
-
-	if ($startIndex > $endIndex) {
-		$tmp = $startIndex;
-		$startIndex = $endIndex;
-		$endIndex = $tmp;
-	}
-	return _hx_substr($s, $startIndex, $endIndex - $startIndex);
-}
 
-function _hx_trace($v, $i) {
-	$msg = $i !== null ? $i->fileName.':'.$i->lineNumber.': ' : '';
-	echo $msg._hx_string_rec($v, '').\"\n\";
-}
-
-function _hx_ttype($n) {
-	return isset(php_Boot::$ttypes[$n]) ? php_Boot::$ttypes[$n] : null;
-}
-
-function _hx_make_var_args() {
-	$args = func_get_args();
-	$f = array_shift($args);
-	return call_user_func($f, new _hx_array($args));
-}
-
-class _hx_anonymous extends stdClass {
-	public function __call($m, $a) {
-		return call_user_func_array($this->$m, $a);
+	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 function __set($n, $v) {
-		$this->$n = $v;
+	public static function lastIndexOf( str:String, search:String, startIndex:Int = null ) : Int {
+		var index = Global.strrpos(str, search, (startIndex == null ? 0 : startIndex - str.length));
+		if (index == false) {
+			return -1;
+		} else {
+			return index;
+		}
 	}
 
-	public function &__get($n) {
-		if(isset($this->$n))
-			return $this->$n;
-		$null = null;
-		return $null;
+	public static function split( str:String, delimiter:String ) : Array<String> {
+		if (delimiter == '') {
+			return @:privateAccess Array.wrap(Global.str_split(str));
+		} else {
+			return @:privateAccess Array.wrap(Global.explode(delimiter, str));
+		}
 	}
 
-	public function __isset($n) {
-		return isset($this->$n);
+	public static function substr( str:String, pos:Int, ?len:Int ) : String {
+		if (pos < -str.length) {
+			pos = 0;
+		} else if (pos >= str.length) {
+			return '';
+		}
+		if (len == null) {
+			return Global.substr(str, pos);
+		} else {
+			var result = Global.substr(str, pos, len);
+			return (result == false ? '' : result);
+		}
 	}
 
-	public function __unset($n) {
-		unset($this->$n);
+	public static function substring( str:String, startIndex:Int, ?endIndex:Int ) : String {
+		if (endIndex == null) {
+			endIndex = str.length;
+		} else if (endIndex < 0) {
+			endIndex = 0;
+		}
+		if (startIndex < 0) startIndex = 0;
+		if (startIndex > endIndex) {
+			var tmp = endIndex;
+			endIndex = startIndex;
+			startIndex = tmp;
+		}
+		var result = Global.substr(str, startIndex, endIndex - startIndex);
+		return (result == false ? '' : result);
 	}
 
-	public function __toString() {
-		$rfl = new ReflectionObject($this);
-		$b = '{ ';
-		$properties = $rfl->getProperties();
-		$first = true;
-		while(list(, $prop) = each($properties)) {
-			if($first)
-				$first = false;
-			else
-				$b .= ', ';
-			$f = $prop->getName();
-			$b .= $f . ' => ' . $this->$f;
-		}
-		$b .= ' }';
-		return $b;
+	public static function toString( str:String ) : String {
+		return str;
 	}
-}
 
-class _hx_type {
-	public $__tname__;
-	public $__qname__;
-	public $__path__;
-	public function __construct($cn, $qn, $path = null) {
-		$this->__tname__ = $cn;
-		$this->__qname__ = $qn;
-		$this->__path__ = $path;
-		if(property_exists($cn, '__meta__'))
-			$this->__meta__ =  eval($cn.'::$__meta__');
+	public static function fromCharCode( code:Int ) : String {
+		return Global.chr(code);
 	}
+}
 
-	public function __ensureMeta__() {
-		if(property_exists($this->__tname__, '__meta__') && !$this->__meta__) {
-			$this->__meta__ =  eval($this->__tname__.'::$__meta__');
+/**
+	For Dynamic access which looks like String.
+	Instances of this class should not be saved anywhere.
+	Instead it should be used to immediately invoke a String field right after instance creation one time only.
+**/
+@:dox(hide)
+@:keep
+private class HxDynamicStr extends HxClosure {
+	static var hxString : String = (cast HxString:HxClass).phpClassName;
+
+	/**
+		Returns HxDynamicStr instance if `value` is a string.
+		Otherwise returns `value` as-is.
+	**/
+	static function wrap( value:Dynamic ) : Dynamic {
+		if (value.is_string()) {
+			return new HxDynamicStr(value);
+		} else {
+			return value;
 		}
 	}
 
-	public function toString()   { return $this->__toString(); }
+	static inline function invoke( str:String, method:String, args:NativeArray ) : Dynamic {
+		Global.array_unshift(args, str);
+		return Global.call_user_func_array(hxString + '::' + method, args);
+	}
 
-	public function __toString() {
-		return $this->__qname__;
+	function new( str:String ) {
+		super(str, null);
 	}
 
-	private $rfl = false;
-	public function __rfl__() {
-		if($this->rfl !== false) return $this->rfl;
-		if(class_exists($this->__tname__) || interface_exists($this->__tname__))
-			$this->rfl = new ReflectionClass($this->__tname__);
-		else
-			$this->rfl = null;
-		return $this->rfl;
+	@:phpMagic
+	function __get( field:String ) : Dynamic {
+		switch (field) {
+			case 'length':
+				return (target:String).length;
+			case _:
+				func = field;
+				return this;
+		}
 	}
 
-	public function __call($n, $a) {
-		return call_user_func_array(array($this->__tname__, $n), $a);
+	@:phpMagic
+	function __call( method:String, args:NativeArray ) : Dynamic {
+		return invoke(target, method, args);
 	}
 
-	public function __get($n) {
-		if(($r = $this->__rfl__())==null) return null;
-		if($r->hasProperty($n)) {
-			try {
-				return $r->getStaticPropertyValue($n);
-			} catch(Exception $e) {
-				return null;
-			}
-		} else if($r->hasMethod($n))
-			return array($r->name, $n);
-		else
-			return null;
+	/**
+		@see http://php.net/manual/en/language.oop5.magic.php#object.invoke
+	**/
+	@:phpMagic
+	override public function __invoke() {
+		return invoke(target, func, Global.func_get_args());
 	}
 
-	public function __set($n, $v) {
-		if(($r = $this->__rfl__())==null) return null;
-		return $r->setStaticPropertyValue($n, $v);
+	/**
+		Generates callable value for PHP
+	**/
+	override public function getCallback(eThis:Dynamic = null) : NativeIndexedArray<Dynamic> {
+		if (eThis == null) {
+			return Syntax.arrayDecl((this:Dynamic), func);
+		}
+		return Syntax.arrayDecl((new HxDynamicStr(eThis):Dynamic), func);
 	}
 
-	public function __isset($n) {
-		if(($r = $this->__rfl__())==null) return null;
-		return array_key_exists($n, $r->getStaticProperties()) || $r->hasMethod($n);
+	/**
+		Invoke this closure with `newThis` instead of `this`
+	**/
+	override public function callWith( newThis:Dynamic, args:NativeArray ) : Dynamic {
+		if (newThis == null) {
+			newThis = target;
+		}
+		return invoke(newThis, func, args);
 	}
 }
 
-class _hx_class extends _hx_type {}
-
-class _hx_enum extends _hx_type {}
 
-class _hx_interface extends _hx_type {}
+/**
+	Anonymous objects implementation
+**/
+@:keep
+@:dox(hide)
+private class HxAnon extends StdClass {
 
-class HException extends Exception {
-	public function __construct($e, $message = null, $code = null, $p = null) {
-		$message = _hx_string_rec($e, '') . $message;
-		parent::__construct($message,$code);
-		$this->e = $e;
-		$this->p = $p;
-	}
-	public $e;
-	public $p;
-	public function setLine($l) {
-		$this->line = $l;
-	}
-	public function setFile($f) {
-		$this->file = $f;
+	public function new( fields:NativeArray = null ) {
+		super();
+		if (fields != null) {
+			Syntax.foreach(fields, function(name, value) Syntax.setField(this, name, value));
+		}
 	}
-}
 
-class _hx_lambda {
-	public function __construct($locals, $func) {
-		$this->locals = $locals;
-		$this->func = $func;
+	@:phpMagic
+	function __get( name:String ) {
+		return null;
 	}
-	public $locals;
-	public $func;
 
-	public function execute() {
-		// if use $this->locals directly in array_merge it works only if I make the assignement loop,
-		// so I've decided to reference $arr
-		$arr = array();
-		foreach($this->locals as $i => $val)
-			$arr[] = & $this->locals[$i];
-		$args = func_get_args();
-		return call_user_func_array($this->func, array_merge($arr, $args));
+	@:phpMagic
+	function __call( name:String, args:NativeArray ) : Dynamic {
+		var method = Syntax.getField(this, name);
+		Syntax.keepVar(method);
+		return method(Syntax.splat(args));
 	}
 }
 
-class Enum {
-	public function __construct($tag, $index, $params = null) { $this->tag = $tag; $this->index = $index; $this->params = $params; }
-	public $tag;
-	public $index;
-	public $params;
-
-	public function __toString() {
-		return $this->tag;
+/**
+	Closures implementation
+**/
+@:keep
+@:dox(hide)
+private class HxClosure {
+	/** `this` for instance methods; php class name for static methods */
+	var target : Dynamic;
+	/** Method name for methods */
+	var func : String;
+
+	public function new( target:Dynamic, func:String ) : Void {
+		this.target = target;
+		this.func = func;
+		//Force runtime error if trying to create a closure of an instance which happen to be `null`
+		if (target.is_null()) {
+			throw "Unable to create closure on `null`";
+		}
 	}
-}
 
-error_reporting(E_ALL & ~E_STRICT);
-set_error_handler('_hx_error_handler', E_ALL & ~E_STRICT);
-set_exception_handler('_hx_exception_handler');
-
-php_Boot::$qtypes = array();
-php_Boot::$ttypes = array();
-php_Boot::$tpaths = array();
-
-_hx_register_type(new _hx_class('String',  'String'));
-_hx_register_type(new _hx_class('_hx_array', 'Array'));
-_hx_register_type(new _hx_class('Int',     'Int'));
-_hx_register_type(new _hx_class('Float',   'Float'));
-_hx_register_type(new _hx_class('Class',   'Class'));
-_hx_register_type(new _hx_class('Enum',    'Enum'));
-_hx_register_type(new _hx_class('Dynamic', 'Dynamic'));
-_hx_register_type(new _hx_enum('Bool',     'Bool'));
-_hx_register_type(new _hx_enum('Void',     'Void'));
-
-
-$_hx_libdir = dirname(__FILE__) . '/..';
-$_hx_autload_cache_file = $_hx_libdir . '/../cache/haxe_autoload.php';
-if(!file_exists($_hx_autload_cache_file)) {
-	function _hx_build_paths($d, &$_hx_types_array, $pack, $prefix) {
-		$h = opendir($d);
-		while(false !== ($f = readdir($h))) {
-			$p = $d.'/'.$f;
-			if($f == '.' || $f == '..')
-				continue;
-				if (is_file($p) && substr($f, -4) == '.php') {
-				$bn = basename($f, '.php');
-				if ($prefix)
-				{
-					if ($prefix != substr($bn, 0, $lenprefix = strlen($prefix)))
-						continue;
-					$bn = substr($bn, $lenprefix);
-				}
-				if(substr($bn, -6) == '.class') {
-					$bn = substr($bn, 0, -6);
-					$t = 0;
-				} else if(substr($bn, -5) == '.enum') {
-					$bn = substr($bn, 0, -5);
-					$t = 1;
-				} else if(substr($bn, -10) == '.interface') {
-					$bn = substr($bn, 0, -10);
-					$t = 2;
-				} else if(substr($bn, -7) == '.extern') {
-					$bn = substr($bn, 0, -7);
-					$t = 3;
-				} else
-					continue;
-				$qname = ($bn == 'HList' && empty($pack)) ? 'List' : join(array_merge($pack, array($bn)), '.');
-				$_hx_types_array[] = array(
-					'path' => $p,
-					'name' => $prefix . $bn,
-					'type' => $t,
-					'qname' => $qname,
-					'phpname' => join(array_merge($pack, array($prefix . $bn)), '_')
-				);
-			} else if(is_dir($p))
-				_hx_build_paths($p, $_hx_types_array, array_merge($pack, array($f)), $prefix);
-		}
-		closedir($h);
-	}
-
-	$_hx_cache_content = '<?php\n\n';
-	$_hx_types_array = array();
-
-	_hx_build_paths($_hx_libdir, $_hx_types_array, array(), $_hx_class_prefix);
-
-	foreach($_hx_types_array as $val) {
-		$_hx_cache_content .= '_hx_register_type(new ';
-		$t = null;
-		if($val['type'] == 0) {
-			$t = new _hx_class($val['phpname'], $val['qname'], $val['path']);
-			$_hx_cache_content .= '_hx_class';
-		} else if($val['type'] == 1) {
-			$t = new _hx_enum($val['phpname'], $val['qname'], $val['path']);
-			$_hx_cache_content .= '_hx_enum';
-		} else if($val['type'] == 2) {
-			$t = new _hx_interface($val['phpname'], $val['qname'], $val['path']);
-			$_hx_cache_content .= '_hx_interface';
-		} else if($val['type'] == 3) {
-			$t = new _hx_class($val['name'], $val['qname'], $val['path']);
-			$_hx_cache_content .= '_hx_class';
-		}
-		_hx_register_type($t);
-		$_hx_cache_content .= '(\\''.($val['type'] == 3 ? $val['name'] : $val['phpname']).'\\', \\''.$val['qname'].'\\', \\''.$val['path'].'\\'));\n';
-	}
-	try {
-		file_put_contents($_hx_autload_cache_file, $_hx_cache_content);
-	} catch(Exception $e) {}
-	unset($_hx_types_array);
-	unset($_hx_cache_content);
-} else {
-	require($_hx_autload_cache_file);
-}
+	/**
+		@see http://php.net/manual/en/language.oop5.magic.php#object.invoke
+	**/
+	@:phpMagic
+	public function __invoke() {
+		return Global.call_user_func_array(getCallback(), Global.func_get_args());
+	}
 
-function _hx_autoload($name) {
-	if(!isset(php_Boot::$tpaths[$name])) return false;
-	require_once(php_Boot::$tpaths[$name]);
-	return true;
-}
+	/**
+		Generates callable value for PHP
+	**/
+	public function getCallback(eThis:Dynamic = null) : NativeIndexedArray<Dynamic> {
+		if (eThis == null) {
+			eThis = target;
+		}
+		if (Std.is(eThis, StdClass)) {
+			if (Std.is(eThis, HxAnon)) {
+				return Syntax.getField(eThis, func);
+			}
+		}
+		return Syntax.arrayDecl(eThis, func);
+	}
 
-if(!ini_get('date.timezone'))
-	date_default_timezone_set('UTC');
+	/**
+		Check if this is the same closure
+	**/
+	public function equals( closure:HxClosure ) : Bool {
+		return (target == closure.target && func == closure.func);
+	}
 
-spl_autoload_register('_hx_autoload')");
+	/**
+		Invoke this closure with `newThis` instead of `this`
+	**/
+	public function callWith( newThis:Dynamic, args:NativeArray ) : Dynamic {
+		return Global.call_user_func_array(getCallback(newThis), args);
 	}
 }
+
+/**
+	Special exception which is used to wrap non-throwable values
+**/
+@:keep
+@:dox(hide)
+private class HxException extends Exception {
+  var e : Dynamic;
+  public function new( e:Dynamic ) : Void {
+	  this.e = e;
+	  super(Boot.stringify(e));
+  }
+}

+ 0 - 94
std/php/BytesData.hx

@@ -1,94 +0,0 @@
-/*
- * 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;
-
-
-
-private class Wrapper {
-	public var s : NativeString;
-	public inline function new (s:NativeString) {
-		this.s = s;
-	}
-}
-
-abstract BytesData(Wrapper) {
-
-	inline function new (x:Wrapper) this = x;
-
-	inline function str ():php.NativeString return this.s;
-
-	inline function setNativeString (val:NativeString):Void {
-		this.s = val;
-	}
-
-	inline function get_length ():Int {
-		return untyped __call__("strlen", str());
-	}
-
-	static inline function wrap (s:NativeString):Wrapper {
-		return new Wrapper(s);
-	}
-
-	static inline function ofNativeString (s:NativeString) {
-		return new BytesData( wrap(s));
-	}
-
-	public inline function set (index:Int, val:Int):Void {
-		untyped __php__("{0}->s[{1}] = chr({2})", this, index, val);
-	}
-
-	public var length(get, never):Int;
-
-	public inline function compare (other:BytesData):Int {
-		return untyped __php__("{0} < {1} ? -1 : ({0} == {1} ? 0 : 1)", str(), other.str());
-	}
-
-	public inline function get (pos:Int):Int {
-		return untyped __call__("ord", str()[pos]);
-	}
-
-	public inline function copy ():BytesData {
-		return ofNativeString(str());
-	}
-
-	public inline function getString (pos:Int, len:Int):String {
-		return untyped __call__("substr", str(), pos, len);
-	}
-
-	public inline function sub (pos:Int, len:Int):BytesData {
-		return ofString(untyped __call__("substr", str(), pos, len));
-	}
-
-	public inline function blit (pos : Int, src : BytesData, srcpos : Int, len : Int):Void {
-		setNativeString(untyped __php__("substr({0}, 0, {2}) . substr({1}, {3}, {4}) . substr({0}, {2}+{4})", str(), src.str(), pos, srcpos, len));
-	}
-
-	public inline function toString():String return cast str();
-
-	public static inline function ofString (s:String) {
-		return ofNativeString(cast s);
-	}
-
-	public static inline function alloc (length:Int) {
-		return ofNativeString(untyped __call__("str_repeat", __call__("chr", 0), length));
-	}
-}

+ 0 - 0
std/php7/Closure.hx → std/php/Closure.hx


+ 0 - 0
std/php7/Const.hx → std/php/Const.hx


+ 0 - 0
std/php7/Error.hx → std/php/Error.hx


+ 0 - 0
std/php7/ErrorException.hx → std/php/ErrorException.hx


+ 14 - 16
std/php/Exception.hx

@@ -21,24 +21,22 @@
  */
 package php;
 
-extern class Exception {
-    @:overload(function():Void { } )
-    @:overload(function(message : String):Void { } )
-    @:overload(function(message : String, code : Int):Void { } )
-	public function new(message : String, code : Int, previous:Exception) : Void;
-	
+@:native('Exception')
+extern class Exception implements Throwable {
+	public function new(?message : String, ?code : Int, ?previous:Throwable) : Void;
+
 	private var message : String;
 	private var code : Int;
 	private var file : String;
 	private var line : Int;
-	
-	public function getMessage() : String;       // message of the exception
-	public function getPrevious() : Exception;   // last exception
-	public function getCode() : Dynamic;             // code of the exception
-	public function getFile() : String;          // source filename
-	public function getLine() : Int;             // source line
-	public function getTrace() : NativeArray;  // an array of the backtrace()
-	public function getTraceAsString() : String; // formated string of trace
-	
-	public function __toString() : String;       // formated string for display
+
+	@:final
+	function getPrevious() : Throwable;   // Returns previous Throwable
+    function getMessage() : String;       // message of the exception
+    function getCode() : Int;             // code of the exception
+    function getFile() : String;          // source filename
+    function getLine() : Int;             // source line
+    function getTrace() : NativeIndexedArray<NativeAssocArray<Dynamic>>;  // an array of the backtrace
+    function getTraceAsString() : String; // formated string of trace
+	@:phpMagic function __toString() : String;       // formated string for display
 }

+ 0 - 0
std/php7/Global.hx → std/php/Global.hx


+ 0 - 30
std/php/HException.hx

@@ -1,30 +0,0 @@
-/*
- * 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;
-
-extern class HException extends Exception {
-  public var e : Dynamic;
-  public var p : haxe.PosInfos;
-  public function new(e : Dynamic, ?message : String, ?code : Int, ?p : haxe.PosInfos) : Void;
-  public function setLine(l:Int) : Void;
-  public function setFile(f:String) : Void;
-}

+ 1 - 0
std/php/IteratorAggregate.hx

@@ -21,6 +21,7 @@
  */
 package php;
 
+@:native('IteratorAggregate')
 extern interface IteratorAggregate<T> {
 	/**
 		This method is not public to not induce Haxe users to use it ;)

+ 79 - 97
std/php/Lib.hx

@@ -21,21 +21,25 @@
  */
 package php;
 
+import haxe.ds.StringMap;
+import php.*;
+import php.reflection.ReflectionClass;
+
 /**
-	Platform-specific PHP Library. Provides some platform-specific functions 
-	for the PHP target, such as conversion from Haxe types to native types 
+	Platform-specific PHP Library. Provides some platform-specific functions
+	for the PHP target, such as conversion from Haxe types to native types
 	and vice-versa.
 **/
 class Lib {
 	/**
 		Print the specified value on the default output.
 	**/
-	public static function print( v : Dynamic ) : Void {
-		untyped __call__("echo", Std.string(v));
+	public static inline function print( v : Dynamic ) : Void {
+		Global.echo(Std.string(v));
 	}
 
 	/**
-		Print the specified value on the default output followed by 
+		Print the specified value on the default output followed by
 		a newline character.
 	**/
 	public static function println( v : Dynamic ) : Void {
@@ -44,74 +48,71 @@ class Lib {
 	}
 
 	/**
-		Displays structured information about one or more expressions 
-		that includes its type and value. Arrays and objects are 
+		Displays structured information about one or more expressions
+		that includes its type and value. Arrays and objects are
 		explored recursively with values indented to show structure.
 	*/
-	public static function dump(v : Dynamic) : Void {
-		untyped __call__("var_dump", v);
+	public static inline function dump(v : Dynamic) : Void {
+		Global.var_dump(v);
 	}
 
 	/**
-		Serialize using native PHP serialization. This will return a binary 
+		Serialize using native PHP serialization. This will return a binary
 		`String` that can be stored for long term usage.
 	**/
-	public static function serialize( v : Dynamic ) : String {
-		return untyped __call__("serialize", v);
+	public static inline function serialize( v : Dynamic ) : String {
+		return Global.serialize(v);
 	}
 
 	/**
 		Unserialize a `String` using native PHP serialization. See `php.Lib.serialize()`.
 	**/
-	public static function unserialize( s : String ) : Dynamic {
-		return untyped __call__("unserialize", s);
+	public static inline function unserialize( s : String ) : Dynamic {
+		return Global.unserialize(s);
 	}
 
 	/**
 		Find out whether an extension is loaded.
 	*/
-	public static function extensionLoaded(name : String) {
-		return untyped __call__("extension_loaded", name);
+	public static inline function extensionLoaded(name : String) {
+		return Global.extension_loaded(name);
 	}
 
-	public static function isCli() : Bool {
-		return untyped __php__("(0 == strncasecmp(PHP_SAPI, 'cli', 3))");
+	public static inline function isCli() : Bool {
+		return 0 == Global.strncasecmp(Const.PHP_SAPI, 'cli', 3);
 	}
 
 	/**
 		Output file content from the given file name.
 	*/
-	public static function printFile(file : String) {
-		return untyped __call__("fpassthru", __call__("fopen", file,  "r"));
+	public static inline function printFile(file : String) {
+		return Global.fpassthru(Global.fopen(file,  "r"));
 	}
 
-	public static function toPhpArray(a : Array<Dynamic>) : NativeArray {
-		return untyped __field__(a, 'a');
+	public static inline function toPhpArray(a : Array<Dynamic>) : NativeArray {
+		return @:privateAccess a.arr;
 	}
 
 	public static inline function toHaxeArray(a : NativeArray) : Array<Dynamic> {
-		return untyped __call__("new _hx_array", a);
+		return @:privateAccess Array.wrap(a);
 	}
 
-	public static function hashOfAssociativeArray<T>(arr : NativeArray) : Map<String,T> {
-		var h = new haxe.ds.StringMap<T>();
-		untyped h.h = arr;
-		return h;
+	public static function hashOfAssociativeArray<T>(arr : NativeAssocArray<T>) : Map<String,T> {
+		var result = new StringMap();
+		@:privateAccess result.data = arr;
+		return result;
 	}
 
-	public static function associativeArrayOfHash(hash : haxe.ds.StringMap<Dynamic>) : NativeArray {
-		return untyped hash.h;
+	public static inline function associativeArrayOfHash(hash : haxe.ds.StringMap<Dynamic>) : NativeArray {
+		return @:privateAccess hash.data;
 	}
 
-	public static function objectOfAssociativeArray(arr : NativeArray) : Dynamic {
-		untyped __php__("foreach($arr as $key => $value){
-			if(is_array($value)) $arr[$key] = php_Lib::objectOfAssociativeArray($value);
-		}");
-		return untyped __call__("_hx_anonymous", arr);
+	public static inline function objectOfAssociativeArray(arr : NativeArray) : Dynamic {
+		return Boot.createAnon(arr);
 	}
 
-	public static function associativeArrayOfObject(ob : Dynamic) : NativeArray {
-		return untyped __php__("(array) $ob");
+	public static inline function associativeArrayOfObject(ob : Dynamic) : NativeArray {
+		return Syntax.array(ob);
 	}
 
 	/**
@@ -123,77 +124,58 @@ class Lib {
 	 * @param	?additionalHeaders
 	 * @param	?additionalParameters
 	 */
-	public static function mail(to : String, subject : String, message : String, ?additionalHeaders : String, ?additionalParameters : String) : Bool
-	{
-		if(null != additionalParameters)
-			return untyped __call__("mail", to, subject, message, additionalHeaders, additionalParameters);
-		else if(null != additionalHeaders)
-			return untyped __call__("mail", to, subject, message, additionalHeaders);
-		else
-			return untyped __call__("mail", to, subject, message);
+	public static inline function mail(to : String, subject : String, message : String, ?additionalHeaders : String, ?additionalParameters : String) : Bool {
+		return Global.mail(to, subject, message, additionalHeaders, additionalParameters);
 	}
 
 	/**
 		For neko compatibility only.
 	**/
-	public static function rethrow( e : Dynamic ) {
-		if(Std.is(e, Exception)) {
-			var __rtex__ = e;
-			untyped __php__("throw $__rtex__");
-		}
-		else throw e;
+	public static inline function rethrow( e : Dynamic ) {
+		throw e;
 	}
 
-	static function appendType(o : Dynamic, path : Array<String>, t : Dynamic) {
-		var name = path.shift();
-		if(path.length == 0)
-			untyped __php__("$o->$name = $t");
-		else {
-			var so = untyped __call__("isset", __php__("$o->$name")) ? __php__("$o->$name") : {};
-			appendType(so, path, t);
-			untyped __php__("$o->$name = $so");
+	/**
+		Tries to load all compiled php files and returns list of tpes.
+	**/
+	public static function getClasses():Dynamic {
+		if(!loaded) {
+			loaded = true;
+			var reflection = new ReflectionClass(Boot.getPhpName('php.Boot'));
+			loadLib(Global.dirname(reflection.getFileName(), 2));
 		}
-	}
 
-	public static function getClasses() {
-		var path : String = null;
-		var o = {};
-		untyped __call__('reset', php.Boot.qtypes);
-		while((path = untyped __call__('key', php.Boot.qtypes)) != null) {
-			appendType(o, path.split('.'), untyped php.Boot.qtypes[path]);
-			untyped __call__('next',php.Boot.qtypes);
-		}
-		return o;
+		var result:Dynamic = {};
+		Syntax.foreach(Boot.getRegisteredAliases(), function(phpName:String, haxeName:String) {
+			var parts = haxeName.split('.');
+			var obj = result;
+			while(parts.length > 1) {
+				var pack = parts.shift();
+				if(Syntax.getField(obj, pack) == null) {
+					Syntax.setField(obj, pack, {});
+				}
+				obj = Syntax.getField(obj, pack);
+			}
+			Syntax.setField(obj, parts[0], Boot.getClass(phpName));
+		});
+
+		return result;
 	}
+	static var loaded:Bool = false;
 
 	/**
-	*  Loads types defined in the specified directory.
- 	*/
- 	public static function loadLib(pathToLib : String) : Void
- 	{
-		var prefix = untyped __prefix__();
-		untyped __php__("$_hx_types_array = array();
- 		$_hx_cache_content = '';
- 		//Calling this function will put all types present in the specified types in the $_hx_types_array
- 		_hx_build_paths($pathToLib, $_hx_types_array, array(), $prefix);
-
- 		foreach($_hx_types_array as $val) {
- 			//For every type that has been found, create its description
- 			$t = null;
- 			if($val['type'] == 0) {
- 				$t = new _hx_class($val['phpname'], $val['qname'], $val['path']);
- 			} else if($val['type'] == 1) {
- 				$t = new _hx_enum($val['phpname'], $val['qname'], $val['path']);
- 			} else if($val['type'] == 2) {
- 				$t = new _hx_interface($val['phpname'], $val['qname'], $val['path']);
- 			} else if($val['type'] == 3) {
- 				$t = new _hx_class($val['name'], $val['qname'], $val['path']);
- 			}
- 			//Register the type
- 			if(!array_key_exists($t->__qname__, php_Boot::$qtypes)) {
- 				_hx_register_type($t);
- 			}
- 		}
- ");
- 	}
+		Loads types defined in the specified directory.
+	**/
+	public static function loadLib(pathToLib : String) : Void {
+		var absolutePath = Global.realpath(pathToLib);
+		if(absolutePath == false) throw 'Failed to read path: $pathToLib';
+		Syntax.foreach(Global.glob('$absolutePath/*.php'), function(_, fileName) {
+			if(!Global.is_dir(fileName)) {
+				Global.require_once(fileName);
+			}
+		});
+		Syntax.foreach(Global.glob('$absolutePath/*', Const.GLOB_ONLYDIR), function(_, dirName) {
+			loadLib(dirName);
+		});
+	}
 }

+ 43 - 2
std/php/NativeArray.hx

@@ -21,6 +21,47 @@
  */
 package php;
 
-extern class NativeArray implements ArrayAccess<Dynamic> {
+using php.Global;
 
-}
+/**
+	Native PHP array.
+**/
+@:coreType @:runtimeValue abstract NativeArray {
+	public inline function new()
+		this = Syntax.arrayDecl();
+
+	@:arrayAccess function getByInt(key:Int):Dynamic;
+	@:arrayAccess function setByInt(key:Int, val:Dynamic):Dynamic;
+	@:arrayAccess function getByFloat(key:Float):Dynamic;
+	@:arrayAccess function setByFloat(key:Float, val:Dynamic):Dynamic;
+	@:arrayAccess function getByString(key:String):Dynamic;
+	@:arrayAccess function setByString(key:String, val:Dynamic):Dynamic;
+	@:arrayAccess function getByBool(key:Bool):Dynamic;
+	@:arrayAccess function setByBool(key:Bool, val:Dynamic):Dynamic;
+
+	public inline function iterator()
+		return new NativeArrayIterator(this);
+}
+
+/**
+	Allows iterating over native PHP array with Haxe for-loop
+**/
+private class NativeArrayIterator {
+	var arr:NativeArray;
+	var hasMore:Bool;
+
+	public inline function new( a:NativeArray ) {
+		arr = a;
+		hasMore = (arr.reset() != false);
+	}
+
+	public inline function hasNext() : Bool {
+		return hasMore;
+	}
+
+	public inline function next() : Dynamic {
+		var result = arr.current();
+		hasMore = (arr.next() != false);
+		return result;
+	}
+}

+ 0 - 0
std/php7/NativeAssocArray.hx → std/php/NativeAssocArray.hx


+ 0 - 0
std/php7/NativeIndexedArray.hx → std/php/NativeIndexedArray.hx


+ 6 - 1
std/php/NativeString.hx

@@ -21,6 +21,11 @@
  */
 package php;
 
-extern class NativeString implements ArrayAccess<String> {
+/**
+	Native PHP string.
+**/
+@:coreType @:runtimeValue abstract NativeString from String to String {
 
+	@:arrayAccess function get(key:Int):String;
+	@:arrayAccess function set(key:Int, val:String):String;
 }

+ 0 - 0
std/php7/NativeStructArray.hx → std/php/NativeStructArray.hx


+ 0 - 364
std/php/NativeXml.hx

@@ -1,364 +0,0 @@
-/*
- * 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;
-
-import php.Lib;
-
-enum XmlType {
-}
-
-typedef NativeXml = Xml;
-
-class Xml {
-
-	public static var Element(default,null) : XmlType;
-	public static var PCData(default,null) : XmlType;
-	public static var CData(default,null) : XmlType;
-	public static var Comment(default,null) : XmlType;
-	public static var DocType(default,null) : XmlType;
-	public static var ProcessingInstruction(default,null) : XmlType;
-	public static var Document(default,null) : XmlType;
-
-	public var nodeType(default,null) : XmlType;
-	public var nodeName(get,set) : String;
-	public var nodeValue(get,set) : String;
-	public var parent(get,null) : Xml;
-
-	var _nodeName : String;
-	var _nodeValue : String;
-	var _attributes : haxe.ds.StringMap<String>;
-	var _children : Array<Xml>;
-	var _parent : Xml;
-	var _fromCustomParser:Bool;
-
-	private static var build : Xml;
-	private static function __start_element_handler(parser : Dynamic, name : String, attribs : ArrayAccess<String>) : Void {
-		var node = createElement(name);
-		untyped __php__("foreach($attribs as $k => $v) $node->set($k, $v)");
-		build.addChild(node);
-		build = node;
-	}
-
-	private static function __end_element_handler(parser : Dynamic, name : String) : Void {
-		build = build.parent;
-	}
-
-	private static function __decodeattr(value : String) : String
-	{
-		return untyped __call__("str_replace", "'", '&apos;', __call__("htmlspecialchars", value, __php__('ENT_COMPAT'), 'UTF-8'));
-	}
-
-	private static function __decodeent(value : String) : String
-	{
-		return untyped __call__("str_replace", "'", '&apos;', __call__("htmlentities", value, __php__('ENT_COMPAT'), 'UTF-8'));
-	}
-
-	private static function __character_data_handler(parser : Dynamic, data : String) : Void {
-		var d = __decodeent(data);
-		if ((untyped __call__("strlen", data) == 1 && d != data) || d == data) {
-			var last = build._children[build._children.length - 1];
-			if (null != last && last.nodeType == Xml.PCData)
-			{
-				last.nodeValue += d;
-			} else
-				build.addChild(createPCData(d));
-		} else {
-			build.addChild(createCData(data));
-		}
-	}
-
-	private static function __default_handler(parser : Dynamic, data : String) : Void {
-		//On some PHP setups (seems to happen when libexpat is used) we may get called for such "entities" although character_data will correctly be called afterward.
-		if(data == "<![CDATA[")
-			return;
-		if(data == "]]>")
-			return;
-		if ("<!--" == data.substr(0, 4))
-			build.addChild(createComment(data.substr(4, data.length-7)));
-		else
-			build.addChild(createPCData(data));
-	}
-
-	static var reHeader = ~/\s*(?:<\?(.+?)\?>)?(?:<!DOCTYPE ([^>]+)>)?/mi;
-
-	public static function parse( str : String ) : Xml {
-		build = createDocument();
-		var xml_parser = untyped __call__("xml_parser_create");
-		untyped __call__("xml_set_element_handler", xml_parser, __start_element_handler, __end_element_handler);
-		untyped __call__("xml_set_character_data_handler", xml_parser, __character_data_handler);
-		untyped __call__("xml_set_default_handler", xml_parser, __default_handler);
-		untyped __call__("xml_parser_set_option", xml_parser, __php__("XML_OPTION_CASE_FOLDING"), 0);
-		untyped __call__("xml_parser_set_option", xml_parser, __php__("XML_OPTION_SKIP_WHITE"), 0);
-
-		reHeader.match(str);
-
-		str = "<doc>"+reHeader.matchedRight()+"</doc>";
-
-		if(1 != untyped __call__("xml_parse", xml_parser, str, true)) {
-			throw "Xml parse error ("+untyped __call__("xml_error_string", __call__("xml_get_error_code", xml_parser)) + ") line #" + __call__("xml_get_current_line_number", xml_parser);
-		}
-
-		untyped __call__("xml_parser_free", xml_parser);
-
-		build = build._children[0];
-		build._parent = null;
-		build._nodeName = null;
-		build.nodeType = Document;
-
-		var doctype = reHeader.matched(2);
-		if (null != doctype)
-			build.insertChild(createDocType(doctype), 0);
-
-		var ProcessingInstruction = reHeader.matched(1);
-		if (null != ProcessingInstruction)
-			build.insertChild(createProcessingInstruction(ProcessingInstruction), 0);
-
-		return build;
-	}
-
-	private function new(fromCustomParser:Bool = false) : Void {
-		_fromCustomParser = fromCustomParser;
-	}
-
-	@:allow(haxe.xml.Parser)
-	static function createPCDataFromCustomParser( data : String ) : Xml {
-		var r = new Xml(true);
-		r.nodeType = Xml.PCData;
-		r.set_nodeValue( data );
-		return r;
-	}
-
-	public static function createElement( name : String ) : Xml {
-		var r = new Xml();
-		r.nodeType = Xml.Element;
-		r._children = new Array();
-		r._attributes = new haxe.ds.StringMap();
-		r.set_nodeName( name );
-		return r;
-	}
-
-	public static function createPCData( data : String ) : Xml {
-		var r = new Xml();
-		r.nodeType = Xml.PCData;
-		r.set_nodeValue( data );
-		return r;
-	}
-
-	public static function createCData( data : String ) : Xml {
-		var r = new Xml();
-		r.nodeType = Xml.CData;
-		r.set_nodeValue( data );
-		return r;
-	}
-
-	public static function createComment( data : String ) : Xml {
-		var r = new Xml();
-		r.nodeType = Xml.Comment;
-		r.set_nodeValue( data );
-		return r;
-	}
-
-	public static function createDocType( data : String ) : Xml {
-		var r = new Xml();
-		r.nodeType = Xml.DocType;
-		r.set_nodeValue( data );
-		return r;
-	}
-
-	public static function createProcessingInstruction( data : String ) : Xml {
-		var r = new Xml();
-		r.nodeType = Xml.ProcessingInstruction;
-		r.set_nodeValue( data );
-		return r;
-	}
-
-	public static function createDocument() : Xml {
-		var r = new Xml();
-		r.nodeType = Xml.Document;
-		r._children = new Array();
-		return r;
-	}
-
-	private function get_nodeName() : String {
-		if( nodeType != Xml.Element )
-			throw "bad nodeType";
-		return _nodeName;
-	}
-
-	private function set_nodeName( n : String ) : String {
-		if( nodeType != Xml.Element )
-			throw "bad nodeType";
-		return _nodeName = n;
-	}
-
-	private function get_nodeValue() : String {
-		if( nodeType == Xml.Element || nodeType == Xml.Document )
-			throw "bad nodeType";
-		return _nodeValue;
-	}
-
-	private function set_nodeValue( v : String ) : String {
-		if( nodeType == Xml.Element || nodeType == Xml.Document )
-			throw "bad nodeType";
-		return _nodeValue = v;
-	}
-
-	private inline function get_parent() : Xml {
-		return _parent;
-	}
-
-	public function get( att : String ) : String {
-		if( nodeType != Xml.Element )
-			throw "bad nodeType";
-		return _attributes.get( att );
-	}
-
-	// TODO: check correct transform function
-	@:ifFeature("Xml.parse")
-	public function set( att : String, value : String ) : Void {
-		if( nodeType != Xml.Element )
-			throw "bad nodeType";
-		_attributes.set( att, __decodeattr(value) );
-	}
-
-	public function remove( att : String ) : Void{
-		if( nodeType != Xml.Element )
-			throw "bad nodeType";
-		_attributes.remove( att );
-	}
-
-	public function exists( att : String ) : Bool {
-		if( nodeType != Xml.Element )
-			throw "bad nodeType";
-		return _attributes.exists( att );
-	}
-
-	public function attributes() : Iterator<String> {
-		if( nodeType != Xml.Element )
-			throw "bad nodeType";
-		return _attributes.keys();
-	}
-
-	public function iterator() : Iterator<Xml> {
-		if( _children == null ) throw "bad nodetype";
-		return _children.iterator();
-	}
-
-	public function elements() : Iterator<Xml> {
-		if( _children == null ) throw "bad nodetype";
-		return Lambda.filter(_children, function(child) return child.nodeType == Xml.Element).iterator();
-	}
-
-	public function elementsNamed( name : String ) : Iterator<Xml> {
-		if( _children == null ) throw "bad nodetype";
-		return Lambda.filter(_children, function(child) return child.nodeType == Xml.Element && child.nodeName == name).iterator();
-	}
-
-	public function firstChild() : Xml {
-		if( _children == null ) throw "bad nodetype";
-		if( _children.length == 0 ) return null;
-		return _children[0];
-	}
-
-	public function firstElement() : Xml {
-		if( _children == null ) throw "bad nodetype";
-		for (child in _children)
-			if (child.nodeType == Xml.Element)
-				return child;
-		return null;
-	}
-
-	public function addChild( x : Xml ) : Void {
-		if( _children == null ) throw "bad nodetype";
-		if( x._parent != null ) x._parent._children.remove(x);
-		x._parent = this;
-		_children.push( x );
-	}
-
-	public function removeChild( x : Xml ) : Bool {
-		if( _children == null ) throw "bad nodetype";
-		var b = _children.remove( x );
-		if( b )
-			x._parent = null;
-		return b;
-	}
-
-	public function insertChild( x : Xml, pos : Int ) : Void {
-		if( _children == null ) throw "bad nodetype";
-		if( x._parent != null ) x._parent._children.remove(x);
-		x._parent = this;
-		_children.insert( pos, x );
-	}
-
-	public function toString() : String {
-		if( nodeType == Xml.PCData )
-			return _fromCustomParser ? StringTools.htmlEscape(_nodeValue) : _nodeValue;
-
-		var s = "";
-
-		if( nodeType == Xml.Element ) {
-			s += "<";
-			s += _nodeName;
-			for( k in _attributes.keys() ){
-				s += " ";
-				s += k;
-				s += "=\""; // \"
-				s += _attributes.get(k);
-				s += "\""; // \"
-			}
-			if( _children.length == 0 ) {
-				s += "/>";
-				return s;
-			}
-			s += ">";
-		} else if( nodeType == Xml.CData )
-			return "<![CDATA["+_nodeValue+"]]>";
-		else if( nodeType == Xml.Comment )
-			return "<!--"+_nodeValue+"-->";
-		else if( nodeType == Xml.DocType )
-			return "<!DOCTYPE "+_nodeValue+">";
-		else if ( nodeType == Xml.ProcessingInstruction )
-			return "<?"+_nodeValue+"?>";
-
-
-		for( x in iterator() )
-			s += x.toString();
-
-		if( nodeType == Xml.Element ) {
-			s += "</";
-			s += _nodeName;
-			s += ">";
-		}
-		return s;
-	}
-
-	static function __init__() : Void untyped {
-		Xml.Element = "element";
-		Xml.PCData = "pcdata";
-		Xml.CData = "cdata";
-		Xml.Comment = "comment";
-		Xml.DocType = "doctype";
-		Xml.ProcessingInstruction = "processingInstruction";
-		Xml.Document = "document";
-	}
-
-}

+ 0 - 0
std/php7/Ref.hx → std/php/Ref.hx


+ 9 - 0
std/php/Resource.hx

@@ -0,0 +1,9 @@
+package php;
+
+/**
+	PHP native `resource` type
+	@see http://php.net/manual/en/language.types.resource.php
+**/
+abstract Resource(Dynamic) {
+
+}

+ 2 - 25
std/php/RuntimeException.hx

@@ -1,27 +1,4 @@
-/*
- * Copyright (C)2005-2012 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;
-import php.Exception;
 
-extern class RuntimeException extends Exception {
-	
-}
+@:native('RuntimeException')
+extern class RuntimeException extends Exception {}

+ 0 - 0
std/php7/Scalar.hx → std/php/Scalar.hx


+ 34 - 31
std/php/Session.hx

@@ -21,13 +21,17 @@
  */
 package php;
 
+import php.Boot;
+import php.Global.*;
+import php.SuperGlobal.*;
+
 /**
-	Session consists of a way to preserve certain data across 
+	Session consists of a way to preserve certain data across
 	subsequent accesses.
 */
 class Session {
 	public static function getCacheLimiter() {
-		switch(untyped __call__("session_cache_limiter")) {
+		switch(session_cache_limiter()) {
 			case "public":
 				return Public;
 			case "private":
@@ -44,119 +48,118 @@ class Session {
 		if(started) throw "You can't set the cache limiter while the session is already in use";
 		switch(l) {
 			case Public:
-				untyped __call__("session_cache_limiter", "public");
+				session_cache_limiter("public");
 			case Private:
-				untyped __call__("session_cache_limiter", "private");
+				session_cache_limiter("private");
 			case NoCache:
-				untyped __call__("session_cache_limiter", "nocache");
+				session_cache_limiter("nocache");
 			case PrivateNoExpire:
-				untyped __call__("session_cache_limiter", "private_no_expire");
+				session_cache_limiter("private_no_expire");
 		}
 	}
 
 	public static function getCacheExpire() : Int {
-		return untyped __call__("session_cache_expire");
+		return session_cache_expire();
 	}
 
 	public static function setCacheExpire(minutes : Int) {
 		if(started) throw "You can't set the cache expire time while the session is already in use";
-		untyped __call__("session_cache_expire", minutes);
+		session_cache_expire(minutes);
 	}
 
 	public static function setName(name : String) {
 		if(started) throw "You can't set the name while the session is already in use";
-		untyped __call__("session_name", name);
+		session_name(name);
 	}
 
 	public static function getName() : String {
-		return untyped __call__("session_name");
+		return session_name();
 	}
 
 	public static function getId() : String {
-		return untyped __call__("session_id");
+		return session_id();
 	}
 
 	public static function setId(id : String) {
 		if(started) throw "You can't set the session id while the session is already in use";
-		untyped __call__("session_id", id);
+		session_id(id);
 	}
 
 	public static function getSavePath() : String {
-		return untyped __call__("session_save_path");
+		return session_save_path();
 	}
 
 	public static function setSavePath(path : String) {
 		if(started) throw "You can't set the save path while the session is already in use";
-		untyped __call__("session_save_path", path);
+		session_save_path(path);
 	}
 
 	public static function getModule() : String {
-		return untyped __call__("session_module_name");
+		return session_module_name();
 	}
 
 	public static function setModule(module : String) {
 		if(started) throw "You can't set the module while the session is already in use";
-		untyped __call__("session_module_name", module);
+		session_module_name(module);
 	}
 
 	public static function regenerateId(?deleteold : Bool) : Bool {
-		return untyped __call__("session_regenerate_id", deleteold);
+		return session_regenerate_id(deleteold);
 	}
 
 	public static function get(name : String) : Dynamic {
 		start();
-		if(!untyped __call__('isset', __var__("_SESSION", name))) return null;
-		return untyped __var__("_SESSION", name);
+		if(!isset(_SESSION[name])) return null;
+		return _SESSION[name];
 	}
 
 	public static function set(name : String, value : Dynamic) {
 		start();
-		return untyped __set__("_SESSION", name, value);
+		return _SESSION[name] = value;
 	}
 
 	public static function setCookieParams(?lifetime : Int, ?path : String, ?domain : String, ?secure : Bool, ?httponly : Bool) {
 		if(started) throw "You can't set the cookie params while the session is already in use";
-		untyped __call__("session_set_cookie_params", lifetime, path, domain, secure, httponly);
+		session_set_cookie_params(lifetime, path, domain, secure, httponly);
 	}
 
 	public static function getCookieParams() : { lifetime : Int, path : String, domain : String, secure : Bool, httponly : Bool} {
-		return untyped __call__("_hx_anonymous", untyped __call__("session_get_cookie_params"));
+		return Boot.createAnon(session_get_cookie_params());
 	}
 
 	// TODO: completely untested
 	public static function setSaveHandler(open : String -> String -> Bool, close : Void -> Bool, read : String -> String, write : String -> String -> Bool, destroy, gc) : Bool {
-		return untyped __call__("session_set_save_handler", open, close, read, write, destroy, gc);
+		return session_set_save_handler(open, close, read, write, destroy, gc);
 	}
 
 	public static function exists(name : String) {
 		start();
-		return untyped __call__("array_key_exists", name, __var__("_SESSION"));
+		return array_key_exists(name, _SESSION);
 	}
 
 	public static function remove(name : String) {
 		start();
-		untyped __call__("unset", __var__("_SESSION", name));
+		unset(_SESSION[name]);
 	}
 
 	public static var started(default, null) : Bool;
 	public static function start() {
 		if(started) return;
 		started = true;
-		untyped __call__("session_start");
+		session_start();
 	}
 
 	public static function clear() {
-		untyped __call__("session_unset");
+		session_unset();
 	}
 
 	public static function close() {
-		untyped __call__("session_write_close");
+		session_write_close();
 		started = false; // TODO: not sure this useful; test if a closed session can be re-opened (I doubt)
 	}
 
-	static function __init__()
-	{
-		started = untyped __call__("isset", __var__("_SESSION"));
+	static function __init__() {
+		started = isset(_SESSION);
 	}
 }
 

+ 0 - 0
std/php7/SessionHandlerInterface.hx → std/php/SessionHandlerInterface.hx


+ 0 - 0
std/php7/StdClass.hx → std/php/StdClass.hx


+ 0 - 0
std/php7/SuperGlobal.hx → std/php/SuperGlobal.hx


+ 0 - 0
std/php7/Syntax.hx → std/php/Syntax.hx


+ 0 - 0
std/php7/Throwable.hx → std/php/Throwable.hx


+ 0 - 0
std/php7/Traversable.hx → std/php/Traversable.hx


+ 102 - 85
std/php/Web.hx

@@ -22,6 +22,9 @@
 package php;
 
 import haxe.io.Bytes;
+import php.Syntax.*;
+import php.Global.*;
+import php.SuperGlobal.*;
 
 /**
 	This class is used for accessing the local Web server and the current
@@ -34,10 +37,7 @@ class Web {
 	**/
 	public static function getParams() : Map<String,String> {
 		#if force_std_separator
-		var a : NativeArray = untyped __php__("$_POST");
-		if(untyped __call__("get_magic_quotes_gpc"))
-			untyped __php__("reset($a); while(list($k, $v) = each($a)) $a[$k] = stripslashes((string)$v)");
-		var h = Lib.hashOfAssociativeArray(a);
+		var h = Lib.hashOfAssociativeArray(_POST);
 		var params = getParamsString();
 		if( params == "" )
 			return h;
@@ -48,10 +48,7 @@ class Web {
 		}
 		return h;
 		#else
-		var a : NativeArray = untyped __php__("array_merge($_GET, $_POST)");
-		if(untyped __call__("get_magic_quotes_gpc"))
-			untyped __php__("reset($a); while(list($k, $v) = each($a)) $a[$k] = stripslashes((string)$v)");
-		return Lib.hashOfAssociativeArray(a);
+		return Lib.hashOfAssociativeArray(array_merge(_GET, _POST));
 		#end
 	}
 
@@ -80,16 +77,15 @@ class Web {
 		explore(StringTools.replace(getParamsString(), ";", "&"));
 		explore(getPostData());
 
-        if (res.length == 0) {
-            var post:haxe.ds.StringMap<Dynamic> = Lib.hashOfAssociativeArray(untyped __php__("$_POST"));
-            var data = post.get(param);
-            var k = 0, v = "";
-            if (untyped __call__("is_array", data)) {
-                untyped __php__(" reset($data); while(list($k, $v) = each($data)) { ");
-                res[k] = v;
-                untyped __php__(" } ");
-            }
-        }
+		if (res.length == 0) {
+			var post:haxe.ds.StringMap<Dynamic> = Lib.hashOfAssociativeArray(_POST);
+			var data = post.get(param);
+			if (is_array(data)) {
+				foreach(data, function(key:Int, value:String) {
+					res[key] = value;
+				});
+			}
+		}
 
 		if (res.length == 0)
 			return null;
@@ -100,21 +96,21 @@ class Web {
 		Returns the local server host name.
 	**/
 	public static inline function getHostName() : String {
-		return untyped __php__("$_SERVER['SERVER_NAME']");
+		return _SERVER['SERVER_NAME'];
 	}
 
 	/**
 		Surprisingly returns the client IP address.
 	**/
 	public static inline function getClientIP() : String {
-		return untyped __php__("$_SERVER['REMOTE_ADDR']");
+		return _SERVER['REMOTE_ADDR'];
 	}
 
 	/**
 		Returns the original request URL (before any server internal redirections).
 	**/
 	public static function getURI() : String {
-		var s : String = untyped __php__("$_SERVER['REQUEST_URI']");
+		var s : String = _SERVER['REQUEST_URI'];
 		return s.split("?")[0];
 	}
 
@@ -122,7 +118,7 @@ class Web {
 		Tell the client to redirect to the given url ("Location" header).
 	**/
 	public static function redirect( url : String ) {
-		untyped __call__('header', "Location: " + url);
+		header("Location: " + url);
 	}
 
 	/**
@@ -130,7 +126,7 @@ class Web {
 		already been sent so this will raise an exception.
 	**/
 	public static inline function setHeader( h : String, v : String ) {
-		untyped __call__('header', h+": "+v);
+		header('$h: $v');
 	}
 
 	/**
@@ -182,57 +178,81 @@ class Web {
 			case 505: code = "505 HTTP Version Not Supported";
 			default: code = Std.string(r);
 		}
-		untyped __call__('header', "HTTP/1.1 " + code, true, r);
+		header("HTTP/1.1 " + code, true, r);
 	}
 
 	/**
 		Retrieve a client header value sent with the request.
 	**/
 	public static function getClientHeader( k : String ) : String {
-		var k = StringTools.replace(k.toUpperCase(),"-","_");
-		for(i in getClientHeaders()) {
-			if(i.header == k)
-				return i.value;
-		}
-		return null;
+		return loadClientHeaders().get(k);
 	}
 
 
-	private static var _client_headers : List<{header : String, value : String}>;
+	private static var _clientHeaders : Map<String,String>;
 	/**
-		Retrieve all the client headers.
+		Based on https://github.com/ralouphie/getallheaders
 	**/
-	public static function getClientHeaders() {
-		if(_client_headers == null) {
-			_client_headers = new List();
-			var h = Lib.hashOfAssociativeArray(untyped __php__("$_SERVER"));
-			for(k in h.keys()) {
-				if(k.substr(0,5) == "HTTP_") {
-					_client_headers.add({ header : k.substr(5), value : h.get(k)});
-				// this is also a valid prefix (issue #1883)
-				} else if(k.substr(0,8) == "CONTENT_") {
-					_client_headers.add({ header : k, value : h.get(k)});
+	static function loadClientHeaders():Map<String,String> {
+		if(_clientHeaders != null) return _clientHeaders;
+
+		_clientHeaders = new Map();
+
+		if(function_exists('getallheaders')) {
+			foreach(getallheaders(), function(key:String, value:Dynamic) {
+				_clientHeaders.set(key, Std.string(value));
+			});
+			return _clientHeaders;
+		}
+
+		var copyServer = [
+			'CONTENT_TYPE'   => 'Content-Type',
+			'CONTENT_LENGTH' => 'Content-Length',
+			'CONTENT_MD5'    => 'Content-Md5'
+		];
+		foreach(_SERVER, function(key:String, value:Dynamic) {
+			if((substr(key, 0, 5):String) == 'HTTP_') {
+				key = substr(key, 5);
+				if(!copyServer.exists(key) || !isset(_SERVER[key])) {
+					key = str_replace(' ', '-', ucwords(strtolower(str_replace('_', ' ', key))));
+					_clientHeaders[key] = Std.string(value);
 				}
+			} else if(copyServer[key] != null) {
+				_clientHeaders[copyServer[key]] = Std.string(value);
 			}
-			// and these(issue #5270)
-			if(untyped __php__("isset($_SERVER['REDIRECT_HTTP_AUTHORIZATION'])")) {
-				_client_headers.add({header: 'AUTHORIZATION', value: untyped __php__("(string)$_SERVER['REDIRECT_HTTP_AUTHORIZATION']")});
-			} else if(untyped __php__("isset($_SERVER['PHP_AUTH_USER'])")) {
-				var basic_pass = untyped __php__("isset($_SERVER['PHP_AUTH_PW']) ? (string)$_SERVER['PHP_AUTH_PW'] : ''");
-				_client_headers.add({header: 'AUTHORIZATION', value: 'Basic ' + untyped __php__("base64_encode($_SERVER['PHP_AUTH_USER'] + ':' + $basic_pass)")});
-			} else if(untyped __php__("isset($_SERVER['PHP_AUTH_DIGEST'])")) {
-				_client_headers.add({header: 'AUTHORIZATION', value: untyped __php__("(string)$_SERVER['PHP_AUTH_DIGEST']")});
+		});
+		if(!_clientHeaders.exists('Authorization')) {
+			if(isset(_SERVER['REDIRECT_HTTP_AUTHORIZATION'])) {
+				_clientHeaders['Authorization'] = Std.string(_SERVER['REDIRECT_HTTP_AUTHORIZATION']);
+			} else if(isset(_SERVER['PHP_AUTH_USER'])) {
+				var basic_pass = isset(_SERVER['PHP_AUTH_PW']) ? Std.string(_SERVER['PHP_AUTH_PW']) : '';
+				_clientHeaders['Authorization'] = 'Basic ' + base64_encode(_SERVER['PHP_AUTH_USER'] + ':' + basic_pass);
+			} else if(isset(_SERVER['PHP_AUTH_DIGEST'])) {
+				_clientHeaders['Authorization'] = Std.string(_SERVER['PHP_AUTH_DIGEST']);
 			}
 		}
-		return _client_headers;
+
+		return _clientHeaders;
+	}
+
+	/**
+		Retrieve all the client headers.
+	**/
+	public static function getClientHeaders():List<{value:String, header:String}> {
+		var headers = loadClientHeaders();
+		var result = new List();
+		for(key in headers.keys()) {
+			result.push({value:headers.get(key), header:key});
+		}
+		return result;
 	}
 
 	/**
 		Returns all the GET parameters `String`
 	**/
 	public static function getParamsString() : String {
-		if(untyped __call__("isset", __var__("_SERVER", "QUERY_STRING")))
-			return untyped __var__("_SERVER", "QUERY_STRING");
+		if(isset(_SERVER['QUERY_STRING']))
+			return _SERVER['QUERY_STRING'];
 		else
 			return "";
 	}
@@ -246,16 +266,16 @@ class Web {
 		`php.Web.parseMultipart()` methods.
 	**/
 	public static function getPostData() : Null<String> {
-		var h = untyped __call__("fopen", "php://input", "r");
+		var h = 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 __php__('{0} . fread({1}, {2})', data, h, bsize);
+		while (!feof(h) && counter < max) {
+			data = Syntax.binop(data, ' . ', fread(h, bsize));
 			counter++;
 		}
-		untyped __call__("fclose", h);
+		fclose(h);
 		return data;
 	}
 
@@ -265,7 +285,7 @@ class Web {
 		instead.
 	**/
 	public static function getCookies():Map<String,String> {
-		return Lib.hashOfAssociativeArray(untyped __php__("$_COOKIE"));
+		return Lib.hashOfAssociativeArray(_COOKIE);
 	}
 
 
@@ -278,23 +298,23 @@ class Web {
 		if(domain == null) domain = '';
 		if(secure == null) secure = false;
 		if(httpOnly == null) httpOnly = false;
-		untyped __call__("setcookie", key, value, t, path, domain, secure, httpOnly);
+		setcookie(key, value, t, path, domain, secure, httpOnly);
 	}
 
 	/**
 		Returns an object with the authorization sent by the client (Basic scheme only).
 	**/
 	public static function getAuthorization() : { user : String, pass : String } {
-		if(!untyped __php__("isset($_SERVER['PHP_AUTH_USER'])"))
+		if(!isset(_SERVER['PHP_AUTH_USER']))
 			return null;
-		return untyped {user: __php__("$_SERVER['PHP_AUTH_USER']"), pass: __php__("$_SERVER['PHP_AUTH_PW']")};
+		return {user: _SERVER['PHP_AUTH_USER'], pass: _SERVER['PHP_AUTH_PW']};
 	}
 
 	/**
 		Get the current script directory in the local filesystem.
 	**/
 	public static inline function getCwd() : String {
-		return untyped __php__("dirname($_SERVER[\"SCRIPT_FILENAME\"])") + "/";
+		return dirname(_SERVER['SCRIPT_FILENAME']) + "/";
 	}
 
 	/**
@@ -327,34 +347,31 @@ class Web {
 	/**
 		Parse the multipart data. Call `onPart` when a new part is found
 		with the part name and the filename if present
-		and `onData` when some part data is read. You can this way
+		and `onData` when some part data is readed. You can this way
 		directly save the data on hard drive in the case of a file upload.
 	**/
 	public static function parseMultipart( onPart : String -> String -> Void, onData : Bytes -> Int -> Int -> Void ) : Void {
-		var a : NativeArray = untyped __var__("_POST");
-		if(untyped __call__("get_magic_quotes_gpc"))
-			untyped __php__("reset($a); while(list($k, $v) = each($a)) $a[$k] = stripslashes((string)$v)");
-		var post = Lib.hashOfAssociativeArray(a);
+		var post = Lib.hashOfAssociativeArray(_POST);
 
 		for (key in post.keys())
 		{
 			onPart(key, "");
 			var v = post.get(key);
-			onData(Bytes.ofString(v), 0, untyped __call__("strlen", v));
+			onData(Bytes.ofString(v), 0, strlen(v));
 		}
 
-		if(!untyped __call__("isset", __php__("$_FILES"))) return;
-		var parts : Array<String> = untyped __call__("new _hx_array",__call__("array_keys", __php__("$_FILES")));
+		if(!isset(_FILES)) return;
+		var parts : Array<String> = @:privateAccess Array.wrap(array_keys(_FILES));
 		for(part in parts) {
-			var info : Dynamic = untyped __php__("$_FILES[$part]");
-			var tmp : String = untyped info['tmp_name'];
-			var file : String = untyped info['name'];
-			var err : Int = untyped info['error'];
+			var info : NativeAssocArray<Dynamic> = _FILES[part];
+			var tmp : String = info['tmp_name'];
+			var file : String = info['name'];
+			var err : Int = info['error'];
 
 			if(err > 0) {
 				switch(err) {
-					case 1: throw "The uploaded file exceeds the max size of " + untyped __call__('ini_get', 'upload_max_filesize');
-					case 2: throw "The uploaded file exceeds the max file size directive specified in the HTML form (max is" + untyped __call__('ini_get', 'post_max_size') + ")";
+					case 1: throw "The uploaded file exceeds the max size of " + ini_get('upload_max_filesize');
+					case 2: throw "The uploaded file exceeds the max file size directive specified in the HTML form (max is" + ini_get('post_max_size') + ")";
 					case 3: throw "The uploaded file was only partially uploaded";
 					case 4: continue; // No file was uploaded
 					case 6: throw "Missing a temporary folder";
@@ -365,14 +382,14 @@ class Web {
 			onPart(part, file);
 			if ("" != file)
 			{
-				var h = untyped __call__("fopen", tmp, "r");
+				var h = fopen(tmp, "r");
 				var bsize = 8192;
-				while (!untyped __call__("feof", h)) {
-					var buf : String = untyped __call__("fread", h, bsize);
-					var size : Int = untyped __call__("strlen", buf);
+				while (!feof(h)) {
+					var buf : String = fread(h, bsize);
+					var size : Int = strlen(buf);
 					onData(Bytes.ofString(buf), 0, size);
 				}
-				untyped __call__("fclose", h);
+				fclose(h);
 			}
 		}
 	}
@@ -382,15 +399,15 @@ class Web {
 		this can be useful for displaying some long operation progress.
 	**/
 	public static inline function flush() : Void {
-		untyped __call__("flush");
+		flush();
 	}
 
 	/**
 		Get the HTTP method used by the client.
 	**/
 	public static function getMethod() : String {
-		if(untyped __php__("isset($_SERVER['REQUEST_METHOD'])"))
-			return untyped __php__("$_SERVER['REQUEST_METHOD']");
+		if(isset(_SERVER['REQUEST_METHOD']))
+			return _SERVER['REQUEST_METHOD'];
 		else
 			return null;
 	}
@@ -398,6 +415,6 @@ class Web {
 	public static var isModNeko(default,null) : Bool;
 
 	static function __init__() {
-		isModNeko = !php.Lib.isCli();
+		isModNeko = !Lib.isCli();
 	}
 }

+ 0 - 0
std/php7/_std/Array.hx → std/php/_std/Array.hx


+ 18 - 14
std/php/_std/Date.hx

@@ -19,16 +19,20 @@
  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * DEALINGS IN THE SOFTWARE.
  */
+
+import php.Global.*;
+import php.Syntax.*;
+
 @:coreApi @:final class Date
 {
 	private var __t : Float;
 
 	public function new(year : Int, month : Int, day : Int, hour : Int, min : Int, sec : Int ) : Void {
-		__t = untyped __call__("mktime", hour, min, sec, month+1, day, year);
+		__t = mktime(hour, min, sec, month + 1, day, year);
 	}
 
 	public function getTime() : Float {
-		return __t * 1000;
+		return __t * 1000.0;
 	}
 
 	private function getPhpTime() : Float {
@@ -36,56 +40,56 @@
 	}
 
 	public function getFullYear() : Int {
-		return untyped __call__("intval", __call__("date", "Y", this.__t));
+		return int(date("Y", int(__t)));
 	}
 
 	public function getMonth() : Int {
-		var m : Int = untyped __call__("intval", __call__("date", "n", this.__t));
+		var m : Int = int(date("n", int(__t)));
 		return -1 + m;
 	}
 
 	public function getDate() : Int {
-		return untyped __call__("intval", __call__("date", "j", this.__t));
+		return int(date("j", int(__t)));
 	}
 
 	public function getHours() : Int {
-		return untyped __call__("intval", __call__("date", "G", this.__t));
+		return int(date("G", int(__t)));
 	}
 
 	public function getMinutes() : Int {
-		return untyped __call__("intval", __call__("date", "i", this.__t));
+		return int(date("i", int(__t)));
 	}
 
 	public function getSeconds() : Int {
-		return untyped __call__("intval", __call__("date", "s", this.__t));
+		return int(date("s", int(__t)));
 	}
 
 	public function getDay() : Int {
-		return untyped __call__("intval", __call__("date", "w", this.__t));
+		return int(date("w", int(__t)));
 	}
 
 	public function toString():String {
-		return untyped __call__("date", "Y-m-d H:i:s", this.__t);
+		return date("Y-m-d H:i:s", int(__t));
 	}
 
 	public static function now() : Date {
-		return fromPhpTime(untyped __call__("round", __call__("microtime", true), 3));
+		return fromPhpTime(round(microtime(true), 3));
 	}
 
 	static function fromPhpTime( t : Float ) : Date {
-		var d = new Date(2000,1,1,0,0,0);
+		var d = new Date(2000, 1, 1, 0, 0, 0);
 		d.__t = t;
 		return d;
 	}
 
 	public static function fromTime( t : Float ) : Date {
-		var d = new Date(2000,1,1,0,0,0);
+		var d = new Date(2000, 1, 1, 0, 0, 0);
 		d.__t = t / 1000;
 		return d;
 	}
 
 	public static function fromString( s : String ) : Date {
-		return fromPhpTime(untyped __call__("strtotime", s));
+		return fromPhpTime(strtotime(s));
 	}
 }
 

+ 44 - 28
std/php/_std/EReg.hx

@@ -19,6 +19,10 @@
  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * DEALINGS IN THE SOFTWARE.
  */
+
+import haxe.extern.EitherType;
+import php.*;
+
 @:coreApi @:final class EReg {
 
 	var r : Dynamic;
@@ -27,80 +31,90 @@
 	var pattern : String;
 	var options : String;
 	var re : String;
-	var matches : ArrayAccess<Dynamic>;
+	var matches : NativeIndexedArray<NativeIndexedArray<EitherType<Int,String>>>;
 
 	public function new( r : String, opt : String ) : Void {
 		this.pattern = r;
 		var a = opt.split("g");
 		global = a.length > 1;
-		if( global )
+		if (global) {
 			opt = a.join("");
+		}
 		this.options = opt;
-		this.re = untyped __php__("'\"' . str_replace('\"','\\\\\"',$r) . '\"' . $opt");
+		this.re = '"' + Global.str_replace('"', '\\"', r) + '"' + opt;
 	}
 
 	public function match( s : String ) : Bool {
-		var p : Int = untyped __call__("preg_match", re, s, matches, __php__("PREG_OFFSET_CAPTURE"));
+		var p : Int = Global.preg_match(re, s, matches, Const.PREG_OFFSET_CAPTURE);
 
-		if(p > 0)
+		if (p > 0) {
 			last = s;
-		else
+		} else {
 			last = null;
+		}
 		return p > 0;
 	}
 
 	public function matched( n : Int ) : String {
-		if (matches == null ||  n < 0 ) throw "EReg::matched";
+		if (matches == null ||  n < 0) throw "EReg::matched";
 		// we can't differenciate between optional groups at the end of a match
 		// that have not been matched and invalid groups
-		if( n >= untyped __call__("count", matches)) return null;
-		if(untyped __php__("$this->matches[$n][1] < 0")) return null;
-		return untyped __php__("$this->matches[$n][0]");
+		if (n >= Global.count(matches)) return null;
+		if ((matches[n][1]:Int) < 0) return null;
+		return matches[n][0];
 	}
 
 	public function matchedLeft() : String {
-		if( untyped __call__("count", matches) == 0 ) throw "No string matched";
-		return last.substr(0, untyped __php__("$this->matches[0][1]"));
+		if (Global.count(matches) == 0) throw "No string matched";
+		return last.substr(0, matches[0][1]);
 	}
 
 	public function matchedRight() : String {
-		if( untyped __call__("count", matches) == 0 ) throw "No string matched";
-		var x : Int = untyped __php__("$this->matches[0][1]") + __call__("strlen",__php__("$this->matches[0][0]"));
+		if (Global.count(matches) == 0) throw "No string matched";
+		var x : Int = (matches[0][1]:Int) + Global.strlen(matches[0][0]);
 		return last.substr(x);
 	}
 
 	public function matchedPos() : { pos : Int, len : Int } {
-		return untyped { pos : __php__("$this->matches[0][1]"), len : __call__("strlen",__php__("$this->matches[0][0]")) };
+		return {
+			pos : matches[0][1],
+			len : Global.strlen(matches[0][0])
+		};
 	}
 
 	public function matchSub( s : String, pos : Int, len : Int = -1):Bool {
-		var p : Int = untyped __call__("preg_match", re, len < 0 ? s : s.substr(0,pos + len), matches, __php__("PREG_OFFSET_CAPTURE"), pos);
+		var subject = len < 0 ? s : s.substr(0,pos + len);
+		var p : Int = Global.preg_match(re, subject, matches, Const.PREG_OFFSET_CAPTURE, pos);
 		if(p > 0) {
 			last = s;
 		}
-		else
+		else {
 			last = null;
+		}
 		return p > 0;
 	}
 
 	public function split( s : String ) : Array<String> {
-		return untyped __php__("new _hx_array(preg_split($this->re, $s, $this->{\"global\"} ? -1 : 2))");
+		var parts:NativeArray = Global.preg_split(re, s, (global ? -1 : 2));
+		return @:privateAccess Array.wrap(parts);
 	}
 
 	public function replace( s : String, by : String ) : String {
-		by = untyped __call__("str_replace", "\\$", "\\\\$", by);
-		by = untyped __call__("str_replace", "$$", "\\$", by);
-		untyped __php__("if(!preg_match('/\\\\([^?].*?\\\\)/', $this->re)) $by = preg_replace('/\\$(\\d+)/', '\\\\\\$\\1', $by)");
-		return untyped __call__("preg_replace", re, by, s, global ? -1 : 1);
+		by = Global.str_replace("\\$", "\\\\$", by);
+		by = Global.str_replace("$$", "\\$", by);
+		if (!Global.preg_match('/\\\\([^?].*?\\\\)/', re)) {
+			by = Global.preg_replace('/\\$(\\d+)/', '\\$\\1', by);
+		}
+		return Global.preg_replace(re, by, s, global ? -1 : 1);
 	}
 
 	public function map( s : String, f : EReg -> String ) : String {
 		var offset = 0;
 		var buf = new StringBuf();
 		do {
-			if (offset >= s.length)
+			if (offset >= s.length) {
 				break;
-			else if (!matchSub(s, offset)) {
+			} else if (!matchSub(s, offset)) {
 				buf.add(s.substr(offset));
 				break;
 			}
@@ -111,15 +125,17 @@
 				buf.add(s.substr(p.pos, 1));
 				offset = p.pos + 1;
 			}
-			else
+			else {
 				offset = p.pos + p.len;
+			}
 		} while (global);
-		if (!global && offset > 0 && offset < s.length)
+		if (!global && offset > 0 && offset < s.length) {
 			buf.add(s.substr(offset));
+		}
 		return buf.toString();
 	}
 
-	public static function escape( s : String ) : String {
-		return untyped __call__("preg_quote", s);
+	public static inline function escape( s : String ) : String {
+		return Global.preg_quote(s);
 	}
 }

+ 31 - 44
std/php/_std/Math.hx

@@ -19,54 +19,41 @@
  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * DEALINGS IN THE SOFTWARE.
  */
-@:coreApi class Math
-{
-	public static var PI(default,null) : Float;
-	public static var NaN(default,null) : Float;
-	public static var POSITIVE_INFINITY(default,null) : Float;
-	public static var NEGATIVE_INFINITY(default,null) : Float;
 
-	public static function abs(v : Float) : Float      { return untyped __call__("abs", v); }
-	public static function min(a : Float,b : Float) : Float    { return untyped !isNaN(a) ? __call__("min", a, b) : NaN; }
-	public static function max(a : Float,b : Float) : Float    { return untyped !isNaN(b) ? __call__("max", a, b) : NaN; }
-	public static function sin(v : Float) : Float      { return untyped __call__("sin", v); }
-	public static function cos(v : Float) : Float      { return untyped __call__("cos", v); }
-	public static function atan2(y : Float,x : Float) : Float  { return untyped __call__("atan2", y, x); }
-	public static function tan(v : Float) : Float      { return untyped __call__("tan", v); }
-	public static function exp(v : Float) : Float      {
-		if(isNaN(v))
-			return NaN;
-		if(untyped __call__("is_finite", v))
-			return untyped __call__("exp", v);
-		else if(v == POSITIVE_INFINITY)
-			return POSITIVE_INFINITY;
-		else
-			return 0.0;
-	}
-	public static function log(v : Float) : Float      { return untyped __call__("log", v); }
-	public static function sqrt(v : Float) : Float     { return untyped __call__("sqrt", v); }
-	public static function round(v : Float) : Int      { return untyped __call__("(int) floor", v + 0.5); }
-	public static function floor(v : Float) : Int      { return untyped __call__("(int) floor", v); }
-	public static function ceil(v : Float) : Int       { return untyped __call__("(int) ceil", v); }
-	public static function atan(v : Float) : Float     { return untyped __call__("atan", v); }
-	public static function asin(v : Float) : Float     { return untyped __call__("asin", v); }
-	public static function acos(v : Float) : Float     { return untyped __call__("acos", v); }
-	public static function pow(v : Float,exp : Float) : Float    { return untyped __call__("pow", v, exp); }
-	public static function random() : Float    { return untyped __call__("mt_rand") / __call__("mt_getrandmax"); }
-	public static function isNaN(f : Float) : Bool     { return untyped __call__("is_nan", f); }
-	public static function isFinite(f : Float) : Bool  { return untyped __call__("is_finite", f); }
+import php.Global;
+import php.Const;
+import php.Syntax.*;
 
-	public static function fround(v : Float) : Float      { return untyped __call__("floor", v + 0.5); }
-	public static function ffloor(v : Float) : Float      { return untyped __call__("floor", v); }
-	public static function fceil(v : Float) : Float       { return untyped __call__("ceil", v); }
+@:coreApi class Math {
+	public static var PI(default,null) : Float = Const.M_PI;
+	public static var NaN(default,null) : Float = Const.NAN;
+	public static var POSITIVE_INFINITY(default,null) : Float = Const.INF;
+	public static var NEGATIVE_INFINITY(default,null) : Float = -Const.INF;
 
-	static function __init__() : Void {
-	 	PI = untyped __php__("M_PI");
-	 	NaN = untyped __php__("acos(1.01)");
-	 	NEGATIVE_INFINITY = untyped __php__("log(0)");
-	 	POSITIVE_INFINITY = -NEGATIVE_INFINITY;
-	}
+	public static inline function abs( v:Float ) : Float return Global.abs(v);
+	public static inline function min( a:Float, b:Float ) : Float return isNaN(a) ? NaN : Global.min(a, b);
+	public static inline function max( a:Float, b:Float ) : Float return isNaN(b) ? NaN : Global.max(a, b);
+	public static inline function sin( v:Float ) : Float return Global.sin(v);
+	public static inline function cos( v:Float ) : Float return Global.cos(v);
+	public static inline function atan2( y:Float, x:Float ) : Float return Global.atan2(y, x);
+	public static inline function tan( v:Float ) : Float return Global.tan(v);
+	public static inline function exp( v:Float ) : Float return Global.exp(v);
+	public static inline function log( v:Float ) : Float return Global.log(v);
+	public static inline function sqrt( v:Float ) : Float return Global.sqrt(v);
+	public static inline function round( v:Float ) : Int return int(Global.floor(v + 0.5));
+	public static inline function floor( v:Float ) : Int return int(Global.floor(v));
+	public static inline function ceil( v:Float ) : Int return int(Global.ceil(v));
+	public static inline function atan( v:Float ) : Float return Global.atan(v);
+	public static inline function asin( v:Float ) : Float return Global.asin(v);
+	public static inline function acos( v:Float ) : Float return Global.acos(v);
+	public static inline function pow( v:Float, exp:Float ) : Float return Global.pow(v, exp);
+	public static inline function random() : Float return Global.mt_rand() / Global.mt_getrandmax();
+	public static inline function isNaN( f:Float ) : Bool return Global.is_nan(f);
+	public static inline function isFinite( f:Float ) : Bool return Global.is_finite(f);
 
+	public static inline function fround( v:Float ) : Float return Global.floor(v + 0.5);
+	public static inline function ffloor( v:Float ) : Float return Global.floor(v);
+	public static inline function fceil( v:Float ) : Float return Global.ceil(v);
 }
 
 

+ 109 - 53
std/php/_std/Reflect.hx

@@ -19,101 +19,157 @@
  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * DEALINGS IN THE SOFTWARE.
  */
+
+import php.Boot;
+import php.Syntax;
+import php.Closure;
+import haxe.Constraints;
+
+using php.Global;
+
 @:coreApi class Reflect {
 
-	public inline static function hasField( o : Dynamic, field : String ) : Bool {
-		return untyped __call__("_hx_has_field", o, field);
+	public static function hasField( o : Dynamic, field : String ) : Bool {
+		if (!o.is_object()) return false;
+		if (o.property_exists(field)) return true;
+
+		if (Boot.isClass(o)) {
+			var phpClassName = Boot.castClass(o).phpClassName;
+			return Global.property_exists(phpClassName, field) || Global.method_exists(phpClassName, field);
+		}
+
+		return false;
 	}
 
 	public static function field( o : Dynamic, field : String ) : Dynamic {
-		return untyped __call__("_hx_field", o, field);
+		if (o.is_string()) {
+			return Syntax.getField(Boot.dynamicString(o), field);
+		}
+		if (!o.is_object()) return null;
+
+		if (o.property_exists(field)) {
+			return Syntax.getField(o, field);
+		}
+		if (o.method_exists(field)) {
+			return Boot.closure(o, field);
+		}
+
+		if (Boot.isClass(o)) {
+			var phpClassName = Boot.castClass(o).phpClassName;
+			if (Global.property_exists(phpClassName, field)) {
+				return Syntax.getField(o, field);
+			}
+			if (Global.method_exists(phpClassName, field)) {
+				return Boot.closure(phpClassName, field);
+			}
+		}
+
+		return null;
 	}
 
-	public inline static function setField( o : Dynamic, field : String, value : Dynamic ) : Void {
-		untyped __setfield__(o, field, value);
+	public static function setField( o : Dynamic, field : String, value : Dynamic ) : Void {
+		Syntax.setField(o, field, value);
 	}
 
 	public static function getProperty( o : Dynamic, field : String ) : Dynamic {
-		if (null == o) return null;
-		var cls : String = Std.is(o, Class) ? untyped __php__("$o->__tname__") : untyped __call__("get_class", o);
-		var cls_vars : php.NativeArray = untyped __call__("get_class_vars", cls);
-		if (untyped __php__("isset($cls_vars['__properties__']) && isset($cls_vars['__properties__']['get_'.$field]) && ($field = $cls_vars['__properties__']['get_'.$field])"))
-			return untyped __php__("$o->$field()");
-		else
-			return untyped __call__("_hx_field", o, field);
+		if (o.is_object()) {
+			if (Boot.isClass(o)) {
+				var phpClassName = Boot.castClass(o).phpClassName;
+				if (Boot.hasGetter(phpClassName, field)) {
+					return Syntax.staticCall(phpClassName, 'get_$field');
+				}
+			} else if (Boot.hasGetter(Global.get_class(o), field)) {
+				return Syntax.call(o, 'get_$field');
+			}
+		}
+
+		return Reflect.field(o, field);
 	}
 
 	public static function setProperty( o : Dynamic, field : String, value : Dynamic ) : Void {
-		if (null == o) return null;
-		var cls : String = Std.is(o, Class) ? untyped __php__("$o->__tname__") : untyped __call__("get_class", o);
-		var cls_vars : php.NativeArray = untyped __call__("get_class_vars", cls);
-		if (untyped __php__("isset($cls_vars['__properties__']) && isset($cls_vars['__properties__']['set_'.$field]) && ($field = $cls_vars['__properties__']['set_'.$field])"))
-			untyped __php__("$o->$field($value)");
-		else
-			untyped __setfield__(o, field, value);
+		if (o.is_object()) {
+			if (Boot.hasSetter(Global.get_class(o), field)) {
+				Syntax.call(o, 'set_$field', value);
+			} else {
+				Syntax.setField(o, field, value);
+			}
+		}
 	}
 
-	public static function callMethod( o : Dynamic, func : haxe.Constraints.Function, args : Array<Dynamic> ) : Dynamic untyped {
-		return __call__("call_user_func_array", __call__("is_callable", func) ? func : __call__("array", o, func), (null == args ? __call__("array") : __field__(args, "a")));
+	public static function callMethod( o : Dynamic, func : Function, args : Array<Dynamic> ) : Dynamic {
+		if (Std.is(func, Closure)) {
+			if (o != null) {
+				func = cast cast(func, Closure).bindTo(o);
+			}
+			return Global.call_user_func_array(func, @:privateAccess args.arr);
+		} else {
+			return Boot.castClosure(func).callWith(o, @:privateAccess args.arr);
+		}
 	}
 
 	public static function fields( o : Dynamic ) : Array<String> {
-		if( o == null ) return new Array();
-		return untyped __php__("$o instanceof _hx_array")
-				? __php__("new _hx_array(array('concat','copy','insert','iterator','length','join','pop','push','remove','reverse','shift','slice','sort','splice','toString','unshift'))")
-				: (__call__('is_string', o)
-					? __php__("new _hx_array(array('charAt','charCodeAt','indexOf','lastIndexOf','length','split','substr','toLowerCase','toString','toUpperCase'))")
-					: __php__("new _hx_array(_hx_get_object_vars($o))"));
+		if (Global.is_object(o)) {
+			return @:privateAccess Array.wrap(Global.get_object_vars(o).array_keys());
+		}
+		return [];
 	}
 
-	public static function isFunction( f : Dynamic ) : Bool {
-		return untyped __php__("(is_array($f) && is_callable($f)) || _hx_is_lambda($f)") || (__php__("is_array($f)") && hasField(__php__("$f[0]"), __php__("$f[1]")) && __php__("$f[1]") != "length");
+	public static inline function isFunction( f : Dynamic ) : Bool {
+		return Boot.isFunction(f);
 	}
 
 	public static function compare<T>( a : T, b : T ) : Int {
-		return ( a == b ) ? 0 : untyped __php__("is_string($a)") ? untyped __php__("strcmp($a, $b)") : (((cast a) > (cast b)) ? 1 : -1);
+		if (a == b) return 0;
+		if (Global.is_string(a)){
+			return Global.strcmp(cast a, cast b);
+		} else {
+			return ((cast a) > (cast b) ? 1 : -1);
+		}
 	}
 
 	public static function compareMethods( f1 : Dynamic, f2 : Dynamic ) : Bool {
-		if(untyped __call__("is_array", f1) && untyped __call__("is_array", f1))
-			return untyped __php__("$f1[0] === $f2[0] && $f1[1] == $f2[1]");
-		if(untyped __call__("is_string", f1) && untyped __call__("is_string", f2))
+		if (Boot.isHxClosure(f1) && Boot.isHxClosure(f2)) {
+			return f1.equals(f2);
+		} else {
 			return f1 == f2;
-		return false;
+		}
 	}
 
 	public static function isObject( v : Dynamic ) : Bool {
-		if( v == null )
+		if (Boot.isEnumValue(v)) {
 			return false;
-		if(untyped __call__("is_object", v))
-			return untyped __php__("$v instanceof _hx_anonymous") || Type.getClass(v) != null
-			  || untyped __php__("$v instanceof _hx_class")
-			  || untyped __php__("$v instanceof _hx_enum");
-		return untyped __php__("is_string($v) && !_hx_is_lambda($v)");
+		} else {
+			return v.is_object() || v.is_string();
+		}
 	}
 
-	public static function isEnumValue( v : Dynamic ) : Bool {
-		return untyped __php__("$v instanceof Enum");
+	public static inline function isEnumValue( v : Dynamic ) : Bool {
+		return Boot.isEnumValue(v);
 	}
 
 	public static function deleteField( o : Dynamic, field : String ) : Bool {
-		if(!hasField(o,field)) return false;
-		untyped __php__("if(isset($o->__dynamics[$field])) unset($o->__dynamics[$field]); else if($o instanceof _hx_anonymous) unset($o->$field); else $o->$field = null");
-		return true;
+		if (hasField(o, field)) {
+			Global.unset(Syntax.getField(o, field));
+			return true;
+		} else {
+			return false;
+		}
 	}
 
 	public static function copy<T>( o : T ) : T {
-		if (untyped __call__("is_string", o)) return o;
-		var o2 : Dynamic = {};
-		for( f in Reflect.fields(o) )
-			Reflect.setField(o2,f,Reflect.field(o,f));
-		return o2;
+		if (Global.is_object(o)) {
+			var fields = Global.get_object_vars(cast o);
+			var hxAnon = Boot.getHxAnon().phpClassName;
+			return Syntax.construct(hxAnon, fields);
+		} else {
+			return null;
+		}
 	}
 
 	@:overload(function( f : Array<Dynamic> -> Void ) : Dynamic {})
 	public static function makeVarArgs( f : Array<Dynamic> -> Dynamic ) : Dynamic {
-		return untyped __php__("array(new _hx_lambda(array(&$f), '_hx_make_var_args'), 'execute')");
+		return function () {
+			return Global.call_user_func(f, @:privateAccess Array.wrap(Global.func_get_args()));
+		}
 	}
-
-
 }

+ 36 - 26
std/php/_std/Std.hx

@@ -1,3 +1,5 @@
+import php.Boot;
+
 /*
  * Copyright (C)2005-2017 Haxe Foundation
  *
@@ -19,47 +21,54 @@
  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * DEALINGS IN THE SOFTWARE.
  */
+
+import php.Global;
+import php.Const;
+import php.Syntax;
+
+@:keep
 @:coreApi class Std {
 
-	public static function is( v : Dynamic, t : Dynamic ) : Bool {
-		return untyped __call__("_hx_instanceof", v,t);
+	public static inline function is( v : Dynamic, t : Dynamic ) : Bool {
+		return Boot.is(v, t);
 	}
 
-	public static function instance<T:{},S:T>( value : T, c : Class<S> ) : S {
-		return Std.is(value, c) ? cast value : null;
+	public static inline function instance<T:{},S:T>( value : T, c : Class<S> ) : S {
+		return Boot.is(value, cast c) ? cast value : null;
 	}
 
 	public static function string( s : Dynamic ) : String {
-		return untyped __call__("_hx_string_rec", s, '');
+		return Boot.stringify(s);
 	}
 
-	public static function int( x : Float ) : Int {
-		var i : Int = untyped __call__("fmod", x, 0x80000000) & 0xffffffff;
-		if (untyped i & 0x80000000)
-        	i = -((~i & 0xffffffff) + 1);
-        return i;
+	public static inline function int( x : Float ) : Int {
+		return Syntax.int(x);
 	}
 
 	public static function parseInt( x : String ) : Null<Int> {
-		x = untyped __call__("ltrim", x);
-		var firstCharIndex = (x.charAt(0) == '-' ? 1 : 0);
-		var firstCharCode = x.charCodeAt(firstCharIndex);
-		if (!isDigitCode(firstCharCode)) {
-			return null;
-		}
-		var secondChar = x.charAt(firstCharIndex + 1);
-		if (secondChar == 'x' || secondChar == 'X') {
-			return untyped __call__("intval", x, 0);
+		if (Global.is_numeric(x)) {
+			return Global.intval(x, 10);
 		} else {
-			return untyped __call__("intval", x, 10);
+			x = Global.ltrim(x);
+			var firstCharIndex = (x.charAt(0) == '-' ? 1 : 0);
+			var firstCharCode = x.charCodeAt(firstCharIndex);
+			if (!isDigitCode(firstCharCode)) {
+				return null;
+			}
+			var secondChar = x.charAt(firstCharIndex + 1);
+			if (secondChar == 'x' || secondChar == 'X') {
+				return Global.intval(x, 0);
+			} else {
+				return Global.intval(x, 10);
+			}
 		}
 	}
 
 	public static function parseFloat( x : String ) : Float {
-		var result = untyped __call__("floatval", x);
-		if (untyped __php__("$result != 0")) return result;
+		var result = Global.floatval(x);
+		if (result != 0) return result;
 
-		x = untyped __call__("ltrim", x);
+		x = Global.ltrim(x);
 		var firstCharIndex = (x.charAt(0) == '-' ? 1 : 0);
 		var charCode = x.charCodeAt(firstCharIndex);
 
@@ -70,15 +79,16 @@
 		if (isDigitCode(charCode)) {
 			return 0.0;
 		} else {
-			return Math.NaN;
+			return Const.NAN;
 		}
 	}
 
-	public static function random( x : Int ) : Int {
-		return untyped x <= 0 ? 0 : __call__("mt_rand", 0, x-1);
+	public static inline function random( x : Int ) : Int {
+		return x <= 1 ? 0 : Global.mt_rand(0, x - 1);
 	}
 
 	static inline function isDigitCode( charCode:Null<Int> ) : Bool {
 		return charCode != null && charCode >= '0'.code && charCode <= '9'.code;
 	}
+
 }

+ 0 - 0
std/php7/_std/String.hx → std/php/_std/String.hx


+ 13 - 2
std/php/_std/StringBuf.hx

@@ -19,6 +19,10 @@
  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * DEALINGS IN THE SOFTWARE.
  */
+
+import php.Global;
+import php.Syntax;
+
 @:coreApi class StringBuf {
 	private var b : String;
 
@@ -33,8 +37,15 @@
 	}
 
 	public function add<T>( x : T ) : Void {
-		untyped if( __call__('is_null',x) ) x = cast 'null' else if( __call__('is_bool',x) ) x = cast (x?'true':'false');
-		b += x;
+		if( x == null ) {
+			b = Syntax.binop(b, '.', 'null');
+		} else if( Global.is_bool(x) ) {
+			b = Syntax.binop(b, '.', ((x:Dynamic) ? 'true' : 'false'));
+		} else if( Global.is_string(x) ) {
+			b = Syntax.binop(b, '.', x);
+		} else {
+			b += x;
+		}
 	}
 
 	public inline function addSub( s : String, pos : Int, ?len : Int ) : Void {

+ 33 - 26
std/php/_std/StringTools.hx

@@ -19,33 +19,33 @@
  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * DEALINGS IN THE SOFTWARE.
  */
+
+import php.*;
+
 @:coreApi class StringTools {
 
-	public inline static function urlEncode( s : String ) : String untyped {
-		return __call__("rawurlencode", s);
+	public inline static function urlEncode( s : String ) : String {
+		return Global.rawurlencode(s);
 	}
 
-	public inline static function urlDecode( s : String ) : String untyped {
-		return __call__("urldecode", s);
+	public inline static function urlDecode( s : String ) : String {
+		return Global.urldecode(s);
 	}
 
-	public static function htmlEscape( s : String, ?quotes : Bool ) : String {
-		s = s.split("&").join("&amp;").split("<").join("&lt;").split(">").join("&gt;");
-		return quotes ? s.split('"').join("&quot;").split("'").join("&#039;") : s;
+	public inline static function htmlEscape( s : String, ?quotes : Bool ) : String {
+		return Global.htmlspecialchars(s, (quotes ? Const.ENT_QUOTES | Const.ENT_HTML401 : Const.ENT_NOQUOTES));
 	}
 
 	public inline static function htmlUnescape( s : String ) : String {
-		return untyped __call__("htmlspecialchars_decode", s ,__php__("ENT_QUOTES"));
+		return Global.htmlspecialchars_decode(s, Const.ENT_QUOTES);
 	}
 
 	public static function startsWith( s : String, start : String ) : Bool {
-		return( s.length >= start.length && s.substr(0,start.length) == start );
+		return start == '' || Global.strpos(s, start) == 0;
 	}
 
 	public static function endsWith( s : String, end : String ) : Bool {
-		var elen = end.length;
-		var slen = s.length;
-		return( slen >= elen && s.substr(slen-elen,elen) == end );
+		return end == '' || Global.substr(s, -end.length) == end;
 	}
 
 	public static function isSpace( s : String, pos : Int ) : Bool {
@@ -54,32 +54,39 @@
 	}
 
 	public inline static function ltrim( s : String ) : String {
-		return untyped __call__("ltrim", s);
+		return Global.ltrim(s);
 	}
 
 	public inline static function rtrim( s : String ) : String {
-		return untyped __call__("rtrim", s);
+		return Global.rtrim(s);
 	}
 
 	public inline static function trim( s : String ) : String {
-		return untyped __call__("trim", s);
+		return Global.trim(s);
 	}
 
-	public inline static function rpad( s : String, c : String, l : Int ) : String {
-		return c.length == 0 || s.length >= l ? s : untyped __call__("str_pad", s, Math.ceil((l-s.length) / c.length) * c.length + s.length , c, __php__("STR_PAD_RIGHT"));
+	public static function rpad( s : String, c : String, l : Int ) : String {
+		if (c.length == 0 || s.length >= l) return s;
+		var padLength = Math.ceil((l - s.length) / c.length) * c.length + s.length;
+		return Global.str_pad(s, padLength, c, Const.STR_PAD_RIGHT);
 	}
 
-	public inline static function lpad( s : String, c : String, l : Int ) : String {
-		return c.length == 0 || s.length >= l ? s : untyped __call__("str_pad", s, Math.ceil((l-s.length) / c.length) * c.length + s.length , c, __php__("STR_PAD_LEFT"));
+	public static function lpad( s : String, c : String, l : Int ) : String {
+		if (c.length == 0 || s.length >= l) return s;
+		var padLength = Math.ceil((l - s.length) / c.length) * c.length + s.length;
+		return Global.str_pad(s, padLength, c, Const.STR_PAD_LEFT);
 	}
 
-	public inline static function replace( s : String, sub : String, by : String ) : String {
-		return untyped sub=="" ? __call__("implode", __call__("str_split ", s) , by) : __call__("str_replace", sub, by, s);
+	public static function replace( s : String, sub : String, by : String ) : String {
+		if (sub == '') {
+			return Global.implode(by, Global.str_split(s));
+		}
+		return Global.str_replace(sub, by, s);
 	}
 
 	public static function hex( n : Int, ?digits : Int ) : String {
-		var s : String = untyped __call__("dechex", n),
-			len = 8;
+		var s = Global.dechex(n);
+		var len = 8;
 		if (s.length > (null == digits ? len : (len = digits > len ? digits : len)))
 			s = s.substr(-len);
 		else if ( digits != null )
@@ -88,11 +95,11 @@
 	}
 
 	public static inline function fastCodeAt( s : String, index : Int ) : Int {
-		return untyped s.cca(index);
+		return (s.length == index ? 0 : Global.ord((s:NativeString)[index]));
 	}
 
 	public static inline function isEof( c : Int ) : Bool {
-		return untyped __physeq__(c, 0);
+		return c == 0;
 	}
 
 	/**
@@ -159,7 +166,7 @@
 						result.add(bs);
 						bs_buf = new StringBuf();
 						result.add('\\"');
-					case c:
+					case var c:
 						// Normal char
 						if (bs_buf.length > 0) {
 							result.add(bs_buf.toString());

+ 53 - 43
std/php/_std/Sys.hx

@@ -19,10 +19,15 @@
  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * DEALINGS IN THE SOFTWARE.
  */
+
+import php.*;
+import sys.io.FileOutput;
+import sys.io.FileInput;
+
 @:coreApi class Sys {
 
-	public static function print( v : Dynamic ) : Void {
-		untyped __call__("echo", Std.string(v));
+	public static inline function print( v : Dynamic ) : Void {
+		Global.echo(Std.string(v));
 	}
 
 	public static function println( v : Dynamic ) : Void {
@@ -31,43 +36,45 @@
 	}
 
 	public static function args() : Array<String> {
-		return untyped __call__('array_key_exists', 'argv', __var__('_SERVER')) ? __call__('new _hx_array', __call__('array_slice', __var__('_SERVER', 'argv'), 1)) : [];
+		if (Global.array_key_exists('argv', SuperGlobal._SERVER)) {
+			return @:privateAccess Array.wrap(Global.array_slice(SuperGlobal._SERVER['argv'], 1));
+		} else {
+			return [];
+		}
 	}
 
 	public static function getEnv( s : String ) : String {
-		var ret:Dynamic = untyped __call__("getenv", s);
-		return ret == false ? null : ret;
+		var value = Global.getenv(s);
+		return value == false ? null : value;
 	}
 
-	public static function putEnv( s : String, v : String ) : Void {
-		return untyped __call__("putenv", s + "=" + v);
+	public static inline function putEnv( s : String, v : String ) : Void {
+		Global.putenv('$s=$v');
 	}
 
-	public static function sleep( seconds : Float ) : Void {
-		return untyped __call__("usleep", seconds*1000000);
+	public static inline function sleep( seconds : Float ) : Void {
+		return Global.usleep(Std.int(seconds * 1000000));
 	}
 
-	public static function setTimeLocale( loc : String ) : Bool {
-		return untyped __call__("setlocale", __php__("LC_TIME"), loc) != false;
+	public static inline function setTimeLocale( loc : String ) : Bool {
+		return Global.setlocale(Const.LC_TIME, loc) != false;
 	}
 
 	public static function getCwd() : String {
-		var cwd : String = untyped __call__("getcwd");
-		var l = cwd.substr(-1);
-		return cwd + (l == '/' || l == '\\' ? '' : '/');
+		var cwd = Global.getcwd();
+		if (cwd == false) return null;
+		var l = (cwd:String).substr(-1);
+		return (cwd:String) + (l == '/' || l == '\\' ? '' : '/');
 	}
 
-	public static function setCwd( s : String ) : Void {
-		untyped __call__("chdir", s);
+	public static inline function setCwd( s : String ) : Void {
+		Global.chdir(s);
 	}
 
 	public static function systemName() : String {
-		var s : String = untyped __call__("php_uname", "s");
-		var p : Int;
-		if((p = s.indexOf(" ")) >= 0)
-			return s.substr(0, p);
-		else
-			return s;
+		var s = Global.php_uname('s');
+		var p = s.indexOf(" ");
+		return (p >= 0 ? s.substr(0, p) : s);
 	}
 
 	public static function command( cmd : String, ?args : Array<String> ) : Int {
@@ -82,57 +89,60 @@
 					cmd = [cmd].concat(args).map(StringTools.quoteUnixArg).join(" ");
 			}
 		}
-		var result = 0;
-		untyped __call__("system", cmd, result);
+		var result = Boot.deref(0);
+		Global.system(cmd, result);
 		return result;
 	}
 
-	public static function exit( code : Int ) : Void {
-		untyped __call__("exit", code);
+	public static inline function exit( code : Int ) : Void {
+		Global.exit(code);
 	}
 
-	public static function time() : Float {
-		return untyped __call__("microtime", true);
+	public static inline function time() : Float {
+		return Global.microtime(true);
 	}
 
 	public static function cpuTime() : Float {
-		return untyped __call__("microtime", true) - __php__("$_SERVER['REQUEST_TIME']");
+		return time() - SuperGlobal._SERVER['REQUEST_TIME'];
 	}
 
-	@:deprecated("Use programPath instead") public static function executablePath() : String {
-		return untyped __php__("$_SERVER['SCRIPT_FILENAME']");
+	@:deprecated("Use programPath instead") public static inline function executablePath() : String {
+		return SuperGlobal._SERVER['SCRIPT_FILENAME'];
 	}
 
 	// It has to be initialized before any call to Sys.setCwd()...
-	static var _programPath = sys.FileSystem.fullPath(untyped __php__("$_SERVER['SCRIPT_FILENAME']"));
+	static var _programPath = sys.FileSystem.fullPath(SuperGlobal._SERVER['SCRIPT_FILENAME']);
 	public static function programPath() : String {
 		return _programPath;
 	}
 
 	public static function environment() : Map<String,String> {
-		return php.Lib.hashOfAssociativeArray(untyped __php__("$_SERVER"));
+		return php.Lib.hashOfAssociativeArray(SuperGlobal._SERVER);
 	}
 
 	public static function stdin() : haxe.io.Input {
-		var p = untyped __php__("defined('STDIN') ? STDIN : fopen('php://stdin', 'r')");
-		return untyped new sys.io.FileInput(p);
+		var p = Global.defined('STDIN') ? Const.STDIN : Global.fopen('php://stdin', 'r');
+		return @:privateAccess new FileInput(p);
 	}
 
 	public static function stdout() : haxe.io.Output {
-		var p = untyped __php__("defined('STDOUT') ? STDOUT : fopen('php://stdout', 'w')");
-		return untyped new sys.io.FileOutput(p);
+		var p = Global.defined('STDOUT') ? Const.STDOUT : Global.fopen('php://stdout', 'w');
+		return @:privateAccess new FileOutput(p);
 	}
 
 	public static function stderr() : haxe.io.Output {
-		var p = untyped __php__("defined('STDERR') ? STDERR : fopen('php://stderr', 'w')");
-		return untyped new sys.io.FileOutput(p);
+		var p = Global.defined('STDERR') ? Const.STDERR : Global.fopen('php://stderr', 'w');
+		return @:privateAccess new FileOutput(p);
 	}
 
 	public static function getChar( echo : Bool ) : Int {
-		var v : Int = untyped __call__("fgetc", __php__("STDIN"));
-		if(echo)
-			untyped __call__('echo', v);
-		return v;
+		var c = Global.fgetc(Const.STDIN);
+		if (c == false) {
+			return 0;
+		} else {
+			if(echo) Global.echo(c);
+			return Global.ord(c);
+		}
 	}
 
 }

+ 252 - 158
std/php/_std/Type.hx

@@ -20,6 +20,12 @@
  * DEALINGS IN THE SOFTWARE.
  */
 
+import php.*;
+import php.reflection.*;
+import haxe.extern.EitherType;
+
+using php.Global;
+
 enum ValueType {
 	TNull;
 	TInt;
@@ -34,218 +40,283 @@ enum ValueType {
 
 @:coreApi class Type {
 
-	public static function getClass<T>( o : T ) : Class<T> untyped {
-		if(o == null) return null;
-		untyped if(__call__("is_array",  o)) {
-			if(__call__("count", o) == 2 && __call__("is_callable", o)) return null;
-			return __call__("_hx_ttype", 'Array');
-		}
-		if(untyped __call__("is_string", o)) {
-			if(__call__("_hx_is_lambda", untyped o)) return null;
-			return __call__("_hx_ttype", 'String');
-		}
-		if(!untyped __call__("is_object", o)) {
+	public static function getClass<T>( o : T ) : Class<T> {
+		if(Global.is_object(o) && !Boot.isClass(o) && !Boot.isEnumValue(o)) {
+			var cls = Boot.getClass(Global.get_class(cast o));
+			return (cls == Boot.getHxAnon() ? null : cast cls);
+		} else if(Global.is_string(o)) {
+			return cast String;
+		} else {
 			return null;
 		}
-		var c = __call__("get_class", o);
-		if(c == false || c == '_hx_anonymous' || __call__("is_subclass_of", c, "enum"))
-			return null;
-		else
-			return __call__("_hx_ttype", c);
 	}
 
-	public static function getEnum( o : EnumValue ) : Enum<Dynamic> untyped {
-		if(!__php__("$o instanceof Enum"))
-			return null;
-		else
-			return __php__("_hx_ttype(get_class($o))");
+	public static function getEnum( o : EnumValue ) : Enum<Dynamic> {
+		if(o == null) return null;
+		return cast Boot.getClass(Global.get_class(cast o));
 	}
 
 	public static function getSuperClass( c : Class<Dynamic> ) : Class<Dynamic> {
-		var s = untyped __call__("get_parent_class", c.__tname__);
-		if(s == false)
-			return null;
-		else
-			return untyped __call__("_hx_ttype", s);
+		if(c == null) return null;
+		var parentClass = Global.get_parent_class((cast c).phpClassName);
+		if(!parentClass) return null;
+		return cast Boot.getClass(parentClass);
 	}
 
 	public static function getClassName( c : Class<Dynamic> ) : String {
-		if( c == null )
-			return null;
-		return untyped c.__qname__;
+		if(c == null) return null;
+		return Boot.getHaxeName(cast c);
 	}
 
 	public static function getEnumName( e : Enum<Dynamic> ) : String {
-		return untyped e.__qname__;
+		return getClassName(cast e);
 	}
 
-	public static function resolveClass( name : String ) : Class<Dynamic> untyped {
-		var c = untyped __call__("_hx_qtype", name);
-		if(__php__("$c instanceof _hx_class || $c instanceof _hx_interface"))
-			return c;
-		else
-			return null;
+	public static function resolveClass( name : String ) : Class<Dynamic> {
+		if (name == null) return null;
+		switch(name) {
+			case 'Dynamic': return cast Dynamic;
+			case 'Int': return cast Int;
+			case 'Float': return cast Float;
+			case 'Bool':  return cast Bool;
+			case 'String': return String;
+			case 'Class': return cast Class;
+			case 'Enum': return cast Enum;
+		}
+
+		var phpClass = Boot.getPhpName(name);
+		if (!Global.class_exists(phpClass) && !Global.interface_exists(phpClass)) return null;
+
+		var hxClass = Boot.getClass(phpClass);
+
+		return cast hxClass;
 	}
 
 	public static function resolveEnum( name : String ) : Enum<Dynamic> {
-		var e = untyped __call__("_hx_qtype", name);
-		if(untyped __php__("$e instanceof _hx_enum"))
-			return e;
-		else
-			return null;
+		if (name == null) return null;
+		if (name == 'Bool') return cast Bool;
+
+		var phpClass = Boot.getPhpName(name);
+		if (!Global.class_exists(phpClass)) return null;
+
+		var hxClass = Boot.getClass(phpClass);
+
+		return cast hxClass;
 	}
 
-	public static function createInstance<T>( cl : Class<T>, args : Array<Dynamic> ) : T untyped {
-		if(cl.__qname__ == 'Array') return [];
-		if(cl.__qname__ == 'String') return args[0];
-		var c = cl.__rfl__();
-		if(c == null) return null;
-		return __php__("$inst = $c->getConstructor() ? $c->newInstanceArgs($args->a) : $c->newInstanceArgs()");
+	public static function createInstance<T>( cl : Class<T>, args : Array<Dynamic> ) : T {
+		if (String == cast cl) return args[0];
+
+		var phpName = getPhpName(cl);
+		if (phpName == null) return null;
+		var nativeArgs:NativeArray = @:privateAccess args.arr;
+		return Syntax.construct(phpName, Syntax.splat(nativeArgs));
 	}
 
-	public static function createEmptyInstance<T>( cl : Class<T> ) : T untyped {
-		if(cl.__qname__ == 'Array') return [];
-		if(cl.__qname__ == 'String') return '';
-		try {
-			__php__("php_Boot::$skip_constructor = true");
-			var rfl = cl.__rfl__();
-			if(rfl == null) return null;
-			var m = __php__("$rfl->getConstructor()");
-			var nargs : Int = m.getNumberOfRequiredParameters();
-			var i;
-			if(nargs > 0) {
-				var args = __call__("array_fill", 0, m.getNumberOfRequiredParameters(), null);
-				i = __php__("$rfl->newInstanceArgs($args)");
-			} else {
-				i = __php__("$rfl->newInstanceArgs(array())");
-			}
-			__php__("php_Boot::$skip_constructor = false");
-			return i;
-		} catch( e : Dynamic ) {
-			__php__("php_Boot::$skip_constructor = false");
-			throw "Unable to instantiate " + Std.string(cl);
-		}
-		return null;
+	public static function createEmptyInstance<T>( cl : Class<T> ) : T {
+		if (String == cast cl) return cast '';
+		if (Array == cast cl) return cast [];
+
+		var phpName = getPhpName(cl);
+		if (phpName == null) return null;
+
+		var reflection = new ReflectionClass(phpName);
+		return reflection.newInstanceWithoutConstructor();
 	}
 
 	public static function createEnum<T>( e : Enum<T>, constr : String, ?params : Array<Dynamic> ) : T {
-		var f:Dynamic = Reflect.field(e,constr);
-		if( f == null ) throw "No such constructor "+constr;
-		if( Reflect.isFunction(f) ) {
-			if( params == null ) throw "Constructor "+constr+" need parameters";
-			return Reflect.callMethod(e,f,params);
+		if (e == null || constr == null) return null;
+
+		var phpName = getPhpName(e);
+		if (phpName == null) return null;
+
+		if (!Global.in_array(constr, Syntax.staticCall(phpName, "__hx__list"))) {
+			throw 'No such constructor $constr';
+		}
+
+		var paramsCounts:NativeAssocArray<Int> = Syntax.staticCall(phpName, "__hx__paramsCount");
+		if ((params == null && paramsCounts[constr] != 0) || (params != null && params.length != paramsCounts[constr])) {
+			throw 'Provided parameters count does not match expected parameters count';
+		}
+
+		if (params == null) {
+			return Syntax.staticCall(phpName, constr);
+		} else {
+			var nativeArgs:NativeArray = @:privateAccess params.arr;
+			return Syntax.staticCall(phpName, constr, Syntax.splat(nativeArgs));
 		}
-		if( params != null && params.length != 0 )
-			throw "Constructor "+constr+" does not need parameters";
-		return f;
 	}
 
 	public static function createEnumIndex<T>( e : Enum<T>, index : Int, ?params : Array<Dynamic> ) : T {
-		var c = Type.getEnumConstructs(e)[index];
-		if( c == null ) throw index+" is not a valid enum constructor index";
-		return createEnum(e,c,params);
+		if (e == null || index == null) return null;
+
+		var phpName = getPhpName(e);
+		if (phpName == null) return null;
+
+		var constructors:NativeIndexedArray<String> = Syntax.staticCall(phpName, "__hx__list");
+		if (index < 0 || index >= Global.count(constructors)) {
+			throw '$index is not a valid enum constructor index';
+		}
+
+		var constr = constructors[index];
+		var paramsCounts:NativeAssocArray<Int> = Syntax.staticCall(phpName, "__hx__paramsCount");
+		if ((params == null && paramsCounts[constr] != 0) || (params != null && params.length != paramsCounts[constr])) {
+			throw 'Provided parameters count does not match expected parameters count';
+		}
+
+		if (params == null) {
+			return Syntax.staticCall(phpName, constr);
+		} else {
+			var nativeArgs:NativeArray = @:privateAccess params.arr;
+			return Syntax.staticCall(phpName, constr, Syntax.splat(nativeArgs));
+		}
 	}
 
 	public static function getInstanceFields( c : Class<Dynamic> ) : Array<String> {
-		if(untyped c.__qname__ == 'String') return ['substr', 'charAt', 'charCodeAt', 'indexOf', 'lastIndexOf', 'split', 'toLowerCase', 'toUpperCase', 'toString', 'length'];
-		if(untyped c.__qname__ == 'Array') return  ['push', 'concat', 'join', 'pop', 'reverse', 'shift', 'slice', 'sort', 'splice', 'toString', 'copy', 'unshift', 'insert', 'remove', 'iterator', 'length'];
-		untyped __php__("
-		$rfl = $c->__rfl__();
-		if($rfl === null) return new _hx_array(array());
-		$r = array();
-		$internals = array('__construct', '__call', '__get', '__set', '__isset', '__unset', '__toString');
-		$ms = $rfl->getMethods();
-		while(list(, $m) = each($ms)) {
-			$n = $m->getName();
-			if(!$m->isStatic() && !in_array($n, $internals)) $r[] = $n;
+		if (c == null) return null;
+		if (c == String) {
+			return [
+				'substr', 'charAt', 'charCodeAt', 'indexOf',
+				'lastIndexOf', 'split', 'toLowerCase',
+				'toUpperCase', 'toString', 'length'
+			];
+		}
+
+		var phpName = getPhpName(c);
+		if (phpName == null) return null;
+
+		var reflection = new ReflectionClass(phpName);
+
+		var methods = new NativeArray();
+		for (m in reflection.getMethods()) {
+			var method:ReflectionMethod = m;
+			if (!method.isStatic()) {
+				var name = method.getName();
+				if (!isServiceFieldName(name)) {
+					methods.array_push(name);
+				}
+			}
+		}
+
+		var properties = new NativeArray();
+		for (p in reflection.getProperties()) {
+			var property:ReflectionProperty = p;
+			if (!property.isStatic()) {
+				var name = property.getName();
+				if (!isServiceFieldName(name)) {
+					properties.array_push(name);
+				}
+			}
 		}
-		$ps = $rfl->getProperties();
-		while(list(, $p) = each($ps))
-			if(!$p->isStatic() && ($name = $p->getName()) !== '__dynamics') $r[] = $name;
-		");
-		return untyped __php__("new _hx_array(array_values(array_unique($r)))");
+		properties = Global.array_diff(properties, methods);
+
+		var fields = Global.array_merge(properties, methods);
+
+		return @:privateAccess Array.wrap(fields);
 	}
 
 	public static function getClassFields( c : Class<Dynamic> ) : Array<String> {
-		if(untyped c.__qname__ == 'String') return ['fromCharCode'];
-		if(untyped c.__qname__ == 'Array')  return [];
-		untyped __php__("
-		$rfl = $c->__rfl__();
-		if($rfl === null) return new _hx_array(array());
-		$ms = $rfl->getMethods(ReflectionMethod::IS_STATIC);
-		$r = array();
-		while(list(, $m) = each($ms)) {
-			$cls = $m->getDeclaringClass();
-			if($cls->getName() == $c->__tname__) $r[] = $m->getName();
+		if (c == null) return null;
+		if (c == String) return ['fromCharCode'];
+
+		var phpName = getPhpName(c);
+		if (phpName == null) return null;
+
+		var reflection = new ReflectionClass(phpName);
+
+		var methods = new NativeArray();
+		for (m in reflection.getMethods(ReflectionMethod.IS_STATIC)) {
+			//TODO: report an issue on invalid type inference for iteration over `NativeIndexedArray`
+			var m:ReflectionMethod = m;
+			var name = m.getName();
+			if (!isServiceFieldName(name) && phpName == m.getDeclaringClass().getName()) {
+				methods.array_push(name);
+			}
 		}
-		$ps = $rfl->getProperties(ReflectionMethod::IS_STATIC);
-		while(list(, $p) = each($ps)) {
-			$cls = $p->getDeclaringClass();
-			if($cls->getName() == $c->__tname__ && ($name = $p->getName()) !== '__properties__') $r[] = $name;
+
+		var properties = new NativeArray();
+		for (p in reflection.getProperties(ReflectionProperty.IS_STATIC)) {
+			var p:ReflectionMethod = p;
+			var name = p.getName();
+			if (!isServiceFieldName(name) && phpName == p.getDeclaringClass().getName()) {
+				properties.array_push(name);
+			}
 		}
-		");
-		return untyped __php__("new _hx_array(array_values(array_unique($r)))");
+		properties = Global.array_diff(properties, methods);
+		var fields = Global.array_merge(properties, methods);
+
+		return @:privateAccess Array.wrap(fields);
 	}
 
-	public static function getEnumConstructs( e : Enum<Dynamic> ) : Array<String> untyped {
-		if (__php__("$e->__tname__ == 'Bool'")) return ['true', 'false'];
-		if (__php__("$e->__tname__ == 'Void'")) return [];
-		return __call__("new _hx_array", e.__constructors);
+	public static function getEnumConstructs( e : Enum<Dynamic> ) : Array<String> {
+		if (e == null) return null;
+		return @:privateAccess Array.wrap(untyped e.__hx__list());
 	}
 
-	public static function typeof( v : Dynamic ) : ValueType untyped {
-		if(v == null) return TNull;
-		if(__call__("is_array", v)) {
-			if(__call__("is_callable", v)) return TFunction;
-			return TClass(Array);
-		}
-		if(__call__("is_string", v)) {
-			if(__call__("_hx_is_lambda", v)) return TFunction;
-			return TClass(String);
+	public static function typeof( v : Dynamic ) : ValueType {
+		if (v == null) return TNull;
+
+		if (v.is_object()) {
+			if (Reflect.isFunction(v)) return TFunction;
+			if (Std.is(v, StdClass)) return TObject;
+			if (Boot.isClass(v)) return TObject;
+
+			var hxClass = Boot.getClass(Global.get_class(v));
+			if (Boot.isEnumValue(v)) return TEnum(cast hxClass);
+			return TClass(cast hxClass);
 		}
-		if(__call__("is_bool", v)) return TBool;
-		if(__call__("is_int", v)) return TInt;
-		if(__call__("is_float", v)) return TFloat;
-		if(__php__("$v instanceof _hx_anonymous"))  return TObject;
-		if(__php__("$v instanceof _hx_enum"))  return TObject;
-		if(__php__("$v instanceof _hx_class"))  return TObject;
 
-		var c = __php__("_hx_ttype(get_class($v))");
+		if (v.is_bool()) return TBool;
+		if (v.is_int()) return TInt;
+		if (v.is_float()) return TFloat;
+		if (v.is_string()) return TClass(String);
 
-		if(__php__("$c instanceof _hx_enum"))  return TEnum(cast c);
-		if(__php__("$c instanceof _hx_class")) return TClass(cast c);
 		return TUnknown;
 	}
 
-	public static function enumEq<T>( a : T, b : T ) : Bool untyped {
-		if( a == b )
-			return true;
+	public static function enumEq<T:EnumValue>( a : T, b : T ) : Bool {
+		if (a == b) return true;
+		if (a == null || b == null) return false;
+
 		try {
-			if( a.index != b.index )
-				return false;
-			for( i in 0...__call__("count", a.params))
-				if(getEnum(untyped __php__("$a->params[$i]")) != null) {
-					if(!untyped enumEq(__php__("$a->params[$i]"),__php__("$b->params[$i]")))
+			if (Global.get_class(cast a) != Global.get_class(cast b)) return false;
+			if (enumIndex(a) != enumIndex(b)) return false;
+
+			var aParams:NativeIndexedArray<Dynamic> = untyped a.params;
+			var bParams:NativeIndexedArray<Dynamic> = untyped b.params;
+			for (i in 0...Global.count(aParams)) {
+				//enums
+				if (Boot.isEnumValue(aParams[i])) {
+					if (!enumEq(aParams[i], bParams[i])) {
 						return false;
-				} else {
-					if(!untyped __call__("_hx_equal", __php__("$a->params[$i]"),__php__("$b->params[$i]")))
+					}
+					continue;
+				}
+				//functions
+				if (Reflect.isFunction(aParams[i])) {
+					if (!Reflect.compareMethods(aParams[i], bParams[i])) {
 						return false;
+					}
+					continue;
+				}
+				//everything else
+				if (aParams[i] != bParams[i]) {
+					return false;
 				}
-		} catch( e : Dynamic ) {
+			}
+
+			return true;
+		} catch (e:Dynamic) {
 			return false;
 		}
-		return true;
 	}
 
 	public static function enumConstructor( e : EnumValue ) : String {
 		return untyped e.tag;
 	}
 
-	public static function enumParameters( e : EnumValue ) : Array<Dynamic> untyped {
-		if(e.params == null)
-			return [];
-		else
-			return __php__("new _hx_array($e->params)");
+	public inline static function enumParameters( e : EnumValue ) : Array<Dynamic> {
+		return @:privateAccess Array.wrap(untyped e.params);
 	}
 
 	public inline static function enumIndex( e : EnumValue ) : Int {
@@ -253,15 +324,38 @@ enum ValueType {
 	}
 
 	public static function allEnums<T>( e : Enum<T> ) : Array<T> {
-		var all = [];
-		for( c in getEnumConstructs(e) ) {
-			var v = Reflect.field(e,c);
-			if( !Reflect.isFunction(v) )
-				all.push(v);
+		if (e == null) return null;
+
+		var phpName = getPhpName(e);
+		if (phpName == null) return null;
+
+		var result = [];
+
+		for (name in getEnumConstructs(e)) {
+			var reflection = new ReflectionMethod(phpName, name);
+			if (reflection.getNumberOfParameters() == 0) {
+				result.push(reflection.invoke(null));
+			}
 		}
-		return all;
+
+		return result;
 	}
 
+	/**
+		Get corresponding PHP name for specified `type`.
+		Returns `null` if `type` does not exist.
+	**/
+	static function getPhpName( type:EitherType<Class<Dynamic>,Enum<Dynamic>> ) : Null<String> {
+		var haxeName = Boot.getHaxeName(cast type);
+
+		return (haxeName == null ? null : Boot.getPhpName(haxeName));
+	}
 
+	/**
+		check if specified `name` is a special field name generated by compiler.
+	 **/
+	static inline function isServiceFieldName(name:String) : Bool {
+		return (name == '__construct' || name.indexOf('__hx__') == 0);
+	}
 }
 

+ 0 - 0
std/php7/_std/haxe/CallStack.hx → std/php/_std/haxe/CallStack.hx


+ 63 - 51
std/php/_std/haxe/Json.hx

@@ -21,82 +21,94 @@
  */
 package haxe;
 
+import php.*;
+import haxe.format.JsonPrinter;
+
 @:coreApi
 class Json {
 
 	public static inline function parse( text : String ) : Dynamic {
-		#if !haxeJSON
-		return phpJsonDecode(text);
+		#if haxeJSON
+			return haxe.format.JsonParser.parse(text);
 		#else
-		return haxe.format.JsonParser.parse(text);
+			return phpJsonDecode(text);
 		#end
 	}
 
 	public static inline function stringify( value : Dynamic, ?replacer:Dynamic -> Dynamic -> Dynamic, ?space:String ) : String {
-		#if !haxeJSON
-		return phpJsonEncode(value, replacer, space);
+		#if haxeJSON
+			return JsonPrinter.print(value, replacer, space);
 		#else
-		return haxe.format.JsonPrinter.print(value, replacer, space);
+			return phpJsonEncode(value, replacer, space);
 		#end
 	}
 
 	static function phpJsonDecode(json:String):Dynamic {
-		var val = untyped __call__("json_decode", json);
-		if (val == null && untyped __php__("json_last_error() != JSON_ERROR_NONE")) {
-			throw untyped __call__("json_last_error_msg");
+		var value = Global.json_decode(json);
+		if (value == null && Global.json_last_error() != Const.JSON_ERROR_NONE) {
+			throw Global.json_last_error_msg();
 		}
-		return convertAfterDecode(val);
+		return convertAfterDecode(value);
 	}
 
-	static function convertAfterDecode(val:Dynamic):Dynamic {
-		var arr:php.NativeArray;
-		if (untyped __call__("is_object", val)) {
-			arr = phpMapArray(php.Lib.associativeArrayOfObject(val), convertAfterDecode);
-			return untyped __call__("_hx_anonymous", arr);
+	static function convertAfterDecode(value:Dynamic):Dynamic {
+		if (Global.is_object(value)) {
+			var result = new NativeAssocArray();
+			var data = Syntax.array(value);
+			Syntax.foreach(data, function(fieldName:String, fieldValue:Dynamic) {
+				result[fieldName] = convertAfterDecode(fieldValue);
+			});
+
+			return Boot.createAnon(result);
 		}
-		else if (untyped __call__("is_array", val)) {
-			arr = phpMapArray(val, convertAfterDecode);
-			return php.Lib.toHaxeArray(arr);
+
+		if (Global.is_array(value)) {
+			var result = new NativeIndexedArray();
+			Syntax.foreach(value, function(index:Int, item:Dynamic) {
+				result[index] = convertAfterDecode(item);
+			});
+
+			return @:privateAccess Array.wrap(result);
 		}
-		else
-			return val;
-	}
 
-	static function phpJsonEncode(val:Dynamic, ?replacer:Dynamic -> Dynamic -> Dynamic, ?space:String):String {
-		if(null != replacer || null != space)
-			return haxe.format.JsonPrinter.print(val, replacer, space);
-		var json = untyped __call__("json_encode", convertBeforeEncode(val));
-		if (untyped __physeq__(json, false))
-			return throw "invalid json";
-		else
-			return json;
+		return value;
 	}
 
-	static function convertBeforeEncode(val:Dynamic):Dynamic {
-		var arr:php.NativeArray;
-		if (untyped __call__("is_object", val)) {
-			switch (untyped __call__("get_class", val)) {
-				case "_hx_anonymous", "stdClass" :
-					arr = php.Lib.associativeArrayOfObject(val);
-					if(untyped __php__('!{0}', arr)) return {};
-				case "_hx_array" : arr = php.Lib.toPhpArray(val);
-				case "Date" : return Std.string(val); //.split(" ").join("T"); //better with "T"?
-				case "HList" : arr = php.Lib.toPhpArray(Lambda.array(val)); //convert List to array?
-				case "_hx_enum" : return Type.enumIndex(val);
-				case "StringMap", "IntMap" : arr = php.Lib.associativeArrayOfHash(val);
-				default : arr = php.Lib.associativeArrayOfObject(val);
-			}
+	static function phpJsonEncode(value:Dynamic, ?replacer:Dynamic -> Dynamic -> Dynamic, ?space:String):String {
+		if(null != replacer || null != space) {
+			return JsonPrinter.print(value, replacer, space);
 		}
-		else if (untyped __call__("is_array", val)) arr = val;
-		else {
-			if (untyped __call__("is_float",val) && !__call__("is_finite",val)) val = null;
-			return val;
+
+		var json = Global.json_encode(convertBeforeEncode(value));
+		if (Global.json_last_error() != Const.JSON_ERROR_NONE) {
+			return throw Global.json_last_error_msg();
 		}
-		return phpMapArray(arr, convertBeforeEncode);
+		return json;
 	}
 
-	inline static function phpMapArray(arr:php.NativeArray, func:Dynamic->Dynamic):php.NativeArray {
-		return untyped __call__("array_map", func, arr);
-	}
+	static function convertBeforeEncode(value:Dynamic):Dynamic {
+		if (Std.is(value, Array)) {
+			var result = new NativeIndexedArray();
+			Syntax.foreach(value.arr, function(index:Int, item:Dynamic) {
+				result[index] = convertBeforeEncode(item);
+			});
 
+			return result;
+		}
+
+		if (Global.is_object(value)) {
+			var result = {};
+			Syntax.foreach(value, function(fieldName:String, fieldValue:Dynamic) {
+				Syntax.setField(result, fieldName, convertBeforeEncode(fieldValue));
+			});
+
+			return result;
+		}
+
+		if (Global.is_float(value) && !Global.is_finite(value)) {
+			return null;
+		}
+
+		return value;
+	}
 }

+ 1 - 8
std/php/_std/haxe/Log.hx

@@ -23,13 +23,6 @@ package haxe;
 
 @:coreApi class Log {
 	public static dynamic function trace( v : Dynamic, ?infos : PosInfos ) : Void {
-		if (infos!=null && infos.customParams!=null) {
-			var extra:String = "";
-			for( v in infos.customParams )
-				extra += "," + v;
-			untyped __call__('_hx_trace', v + extra, infos);
-		}
-		else
-			untyped __call__('_hx_trace', v, infos);
+		php.Boot.trace(v, infos);
 	}
 }

+ 2 - 1
std/php/_std/haxe/Resource.hx

@@ -21,6 +21,7 @@
  */
 package haxe;
 
+import php.*;
 import haxe.io.Bytes;
 import haxe.crypto.Base64;
 
@@ -32,7 +33,7 @@ class Resource {
 	}
 
 	static function getDir() : String {
-		return untyped __call__('dirname', __php__('__FILE__'))+"/../../res";
+		return Global.dirname(Const.__FILE__) + "/../../res";
 	}
 
 	@:access(haxe.io.Path.escape)

+ 13 - 10
std/php/_std/haxe/Utf8.hx

@@ -21,6 +21,8 @@
  */
 package haxe;
 
+import php.Global;
+
 @:coreApi
 class Utf8 {
 
@@ -39,17 +41,18 @@ class Utf8 {
 	}
 
 	public static function encode( s : String ) : String {
-		return untyped __call__("utf8_encode", s);
+		return Global.utf8_encode(s);
 	}
 
 	public static function decode( s : String ) : String {
-		return untyped __call__("utf8_decode", s);
+		return Global.utf8_decode(s);
 	}
 
 	public static function iter(s : String, chars : Int -> Void ) : Void {
 		var len = length(s);
-		for(i in 0...len)
+		for(i in 0...len) {
 			chars(charCodeAt(s, i));
+		}
 	}
 
 	public static function charCodeAt( s : String, index : Int ) : Int {
@@ -57,28 +60,28 @@ class Utf8 {
 	}
 
 	static function uchr(i : Int) : String {
-		return untyped __php__("mb_convert_encoding(pack('N',$i), 'UTF-8', 'UCS-4BE')");
+		return Global.mb_convert_encoding(Global.pack('N', i), 'UTF-8', 'UCS-4BE');
 	}
 
-	static function uord(s : String) : Int untyped {
-		var c : Array<Int> = untyped __php__("unpack('N', mb_convert_encoding($s, 'UCS-4BE', 'UTF-8'))");
+	static function uord(s : String) : Int {
+		var c = Global.unpack('N', Global.mb_convert_encoding(s, 'UCS-4BE', 'UTF-8'));
 		return c[1];
 	}
 
 	public static function validate( s : String ) : Bool {
-		return untyped __call__("mb_check_encoding", s, enc);
+		return Global.mb_check_encoding(s, enc);
 	}
 
 	public static function length( s : String ) : Int {
-		return untyped __call__("mb_strlen", s, enc);
+		return Global.mb_strlen(s, enc);
 	}
 
 	public static function compare( a : String, b : String ) : Int {
-		return untyped __call__("strcmp", a, b);
+		return Global.strcmp(a, b);
 	}
 
 	public static function sub( s : String, pos : Int, len : Int ) : String {
-		return untyped __call__("mb_substr", s, pos, len, enc);
+		return Global.mb_substr(s, pos, len, enc);
 	}
 
 	private static inline var enc = "UTF-8";

+ 0 - 0
std/php7/_std/haxe/crypto/Md5.hx → std/php/_std/haxe/crypto/Md5.hx


+ 0 - 0
std/php7/_std/haxe/crypto/Sha1.hx → std/php/_std/haxe/crypto/Sha1.hx


+ 0 - 0
std/php7/_std/haxe/crypto/Sha224.hx → std/php/_std/haxe/crypto/Sha224.hx


+ 0 - 0
std/php7/_std/haxe/crypto/Sha256.hx → std/php/_std/haxe/crypto/Sha256.hx


+ 55 - 41
std/php/_std/haxe/ds/IntMap.hx

@@ -21,70 +21,84 @@
  */
 package haxe.ds;
 
-@:coreApi class IntMap<T> implements php.IteratorAggregate<T> implements haxe.Constraints.IMap<Int,T> {
-	@:analyzer(no_simplification)
-	private var h : ArrayAccess<Int>;
+import php.Syntax;
+import php.Global;
+import php.NativeArray;
+import php.NativeIndexedArray;
 
+@:coreApi class IntMap<T> implements haxe.Constraints.IMap<Int,T> {
+
+	var data:NativeIndexedArray<T>;
+
+	/**
+		Creates a new IntMap.
+	**/
 	public function new() : Void {
-		h = untyped __call__('array');
+		data = new NativeIndexedArray();
 	}
 
-	public function set( key : Int, value : T ) : Void {
-		untyped h[key] = value;
+	/**
+		See `Map.set`
+	**/
+	public inline function set( key : Int, value : T ) : Void {
+		data[key] = value;
 	}
 
-	public function get( key : Int ) : Null<T> {
-		if (untyped __call__("array_key_exists", key, h))
-			return untyped h[key];
-		else
-			return null;
+	/**
+		See `Map.get`
+	**/
+	public inline function get( key : Int ) : Null<T> {
+		return Syntax.binop(data[key], '??', null);
 	}
 
-	public function exists( key : Int ) : Bool {
-		return untyped __call__("array_key_exists", key, h);
+	/**
+		See `Map.exists`
+	**/
+	public inline function exists( key : Int ) : Bool {
+		return Global.array_key_exists(key, data);
 	}
 
+	/**
+		See `Map.remove`
+	**/
 	public function remove( key : Int ) : Bool {
-		if (untyped __call__("array_key_exists", key, h)) {
-			untyped __call__("unset", h[key]);
+		if (Global.array_key_exists(key, data)) {
+			Global.unset(data[key]);
 			return true;
-		} else
-			return false;
+		}
+
+		return false;
 	}
 
-	public function keys() : Iterator<Int> {
-		return untyped __call__("new _hx_array_iterator", __call__("array_keys", h));
+	/**
+		See `Map.keys`
+	**/
+	public inline function keys() : Iterator<Int> {
+		return Global.array_keys(data).iterator();
 	}
 
-	public function iterator() : Iterator<T> {
-		return untyped __call__("new _hx_array_iterator", __call__("array_values", h));
+	/**
+		See `Map.iterator`
+	**/
+	public inline function iterator() : Iterator<T> {
+		return Global.array_values(data).iterator();
 	}
-	
+
 	public function copy() : IntMap<T> {
 		var copied = new IntMap();
-		copied.h = h;
+		copied.data = data;
 		return copied;
 	}
 
-	public function toString() : String {
-		var s = "{";
-		var it = keys();
-		for( i in it ) {
-			s += i;
-			s += " => ";
-			s += Std.string(get(i));
-			if( it.hasNext() )
-				s += ", ";
-		}
-		return s + "}";
-	}
-
 	/**
-		Implement IteratorAggregate for native php iteration
+		See `Map.toString`
 	**/
-	#if php
-	function getIterator() : Iterator<T> {
-		return iterator();
+	public function toString() : String {
+		var parts = new NativeArray();
+		Syntax.foreach(data, function(key:Int, value:T) {
+			Global.array_push(parts, '$key => ' + Std.string(value));
+		});
+
+		return '{' + Global.implode(', ', parts) + '}';
 	}
-	#end
 }

+ 0 - 167
std/php/_std/haxe/ds/List.hx

@@ -1,167 +0,0 @@
-/*
- * 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 haxe.ds;
-
-@:coreApi class List<T> implements php.IteratorAggregate<T> {
-
-	@:ifFeature("List.iterator") private var h : ArrayAccess<Dynamic>;
-	@:ifFeature("List.iterator") private var q : ArrayAccess<Dynamic>;
-
-	public var length(default,null) : Int;
-
-	public function new() : Void {
-		length = 0;
-	}
-
-	public function add( item : T ) : Void {
-		var x = untyped __call__('array', item, null);
-		if( h == null )
-			untyped __php__("$this->h =& $x");
-		else
-			untyped __php__("$this->q[1] =& $x");
-		untyped __php__("$this->q =& $x");
-		length++;
-	}
-
-	public function push( item : T ) : Void {
-		var x = untyped __call__('array', item, __php__("&$this->h"));
-		untyped __php__("$this->h =& $x");
-		if( q == null )
-			untyped __php__("$this->q =& $x");
-		length++;
-	}
-
-	public function first() : Null<T> {
-		return if( h == null ) null else h[0];
-	}
-
-	public function last() : Null<T> {
-		return if( q == null ) null else q[0];
-	}
-
-	public function pop() : Null<T> {
-		if( h == null )
-			return null;
-		var x = h[0];
-		h = h[1];
-		if( h == null )
-			q = null;
-		length--;
-		return x;
-	}
-
-	public function isEmpty() : Bool {
-		return (h == null);
-	}
-
-	public function clear() : Void {
-		h = null;
-		q = null;
-		length = 0;
-	}
-
-	public function remove( v : T ) : Bool {
-		var prev = null;
-		var l = untyped __php__("& $this->h");
-		while( l != null ) {
-			if(untyped __php__("$l[0] === $v")) {
-				if( prev == null )
-					untyped __php__("$this->h =& $l[1]");
-				else
-					untyped __php__("$prev[1] =& $l[1]");
-				if(untyped __physeq__(q, l))
-					untyped __php__("$this->q =& $prev");
-				length--;
-				return true;
-			}
-			untyped __php__("$prev =& $l");
-			untyped __php__("$l =& $l[1]");
-		}
-		return false;
-	}
-
-	public function iterator() : ListIterator<T> {
-		return untyped __call__("new _hx_list_iterator", this);
-	}
-
-	public function toString() : String {
-		var s = "";
-		var first = true;
-		var l = h;
-		while( l != null ) {
-			if( first )
-				first = false;
-			else
-				s += ", ";
-			s += Std.string(l[0]);
-			l = l[1];
-		}
-		return "{" + s + "}";
-	}
-
-	public function join(sep : String) : String {
-		var s = "";
-		var first = true;
-		var l = h;
-		while( l != null ) {
-			if( first )
-				first = false;
-			else
-				s += sep;
-			s += l[0];
-			l = l[1];
-		}
-		return s;
-	}
-
-	public function filter( f : T -> Bool ) : List<T> {
-		var l2 = new List();
-		var l = h;
-		while( l != null ) {
-			var v = l[0];
-			l = l[1];
-			if( f(v) )
-				l2.add(v);
-		}
-		return l2;
-	}
-
-	public function map<X>(f : T -> X) : List<X> {
-		var b = new List();
-		var l = h;
-		while( l != null ) {
-			var v = l[0];
-			l = l[1];
-			b.add(f(v));
-		}
-		return b;
-	}
-
-	function getIterator() : Iterator<T> {
-		return iterator();
-	}
-}
-
-@:coreType private extern class ListIterator<T> {
-	function hasNext():Bool;
-	function next():T;
-}

+ 22 - 29
std/php/_std/haxe/ds/ObjectMap.hx

@@ -22,62 +22,55 @@
 
 package haxe.ds;
 
+import php.*;
+
 @:coreApi
 class ObjectMap <K:{ }, V> implements haxe.Constraints.IMap<K,V> {
-	static function getId(key: { } ):String {
-		return untyped __php__("spl_object_hash($key)");
-	}
-
-	@:analyzer(no_simplification)
-	var h : ArrayAccess<V>;
-	@:analyzer(no_simplification)
-	var hk : ArrayAccess<K>;
+	var _keys:NativeAssocArray<K>;
+	var _values:NativeAssocArray<V>;
 
 	public function new():Void {
-		h = untyped __call__('array');
-		hk = untyped __call__('array');
+		_keys = new NativeAssocArray();
+		_values = new NativeAssocArray();
 	}
 
-	public function set(key:K, value:V):Void untyped {
-		var id = getId(key);
-		untyped h[id] = value;
-		untyped hk[id] = key;
+	public function set(key:K, value:V):Void {
+		var id = Global.spl_object_hash(key);
+		_keys[id] = key;
+		_values[id] = value;
 	}
 
 	public function get(key:K):Null<V> {
-		var id = getId(key);
-		if (untyped __call__("array_key_exists", id, h))
-			return untyped h[id];
-		else
-			return null;
+		var id = Global.spl_object_hash(key);
+		return Global.isset(_values[id]) ? _values[id] : null;
 	}
 
 	public function exists(key:K):Bool {
-		return untyped __call__("array_key_exists", getId(key), h);
+		return Global.array_key_exists(Global.spl_object_hash(key), _values);
 	}
 
 	public function remove( key : K ) : Bool {
-		var id = getId(key);
-		if (untyped __call__("array_key_exists", id, h)) {
-			untyped __call__("unset", h[id]);
-			untyped __call__("unset", hk[id]);
+		var id = Global.spl_object_hash(key);
+		if (Global.array_key_exists(id, _values)) {
+			Global.unset(_keys[id], _values[id]);
 			return true;
-		} else
+		} else {
 			return false;
+		}
 	}
 
 	public inline function keys() : Iterator<K> {
-		return untyped __call__("new _hx_array_iterator", __call__("array_values", hk));
+		return _keys.iterator();
 	}
 
 	public inline function iterator() : Iterator<V> {
-		return untyped __call__("new _hx_array_iterator", __call__("array_values", h));
+		return _values.iterator();
 	}
 	
 	public function copy() : ObjectMap<K,V> {
 		var copied = new ObjectMap();
-		copied.h = h;
-		copied.hk = hk;
+		copied._values = _values;
+		copied._keys = _keys;
 		return copied;
 	}
 

+ 30 - 40
std/php/_std/haxe/ds/StringMap.hx

@@ -21,70 +21,60 @@
  */
 package haxe.ds;
 
-@:coreApi class StringMap<T> implements php.IteratorAggregate<T> implements haxe.Constraints.IMap<String,T> {
-	@:analyzer(no_simplification)
-	private var h : ArrayAccess<T>;
+import php.Syntax;
+import php.Global;
+import php.NativeArray;
+import php.NativeAssocArray;
+import haxe.Constraints;
 
-	public function new() : Void {
-		h = untyped __call__('array');
+@:coreApi class StringMap<T> implements IMap<String,T> {
+	private var data : NativeAssocArray<T>;
+
+	public inline function new() : Void {
+		data = new NativeAssocArray();
 	}
 
-	public function set( key : String, value : T ) : Void {
-		untyped h[key] = value;
+	public inline function set( key : String, value : T ) : Void {
+		data[key] = value;
 	}
 
-	public function get( key : String ) : Null<T> {
-		if (untyped __call__("array_key_exists", key, h))
-			return untyped h[key];
-		else
-			return null;
+	public inline function get( key : String ) : Null<T> {
+		return Syntax.binop(data[key], '??', null);
 	}
 
-	public function exists( key : String ) : Bool {
-		return untyped __call__("array_key_exists", key, h);
+	public inline function exists( key : String ) : Bool {
+		return Global.array_key_exists(key, data);
 	}
 
 	public function remove( key : String ) : Bool {
-		if (untyped __call__("array_key_exists", key, h)) {
-			untyped __call__("unset", h[key]);
+		if (Global.array_key_exists(key, data)) {
+			Global.unset(data[key]);
 			return true;
-		} else
+		} else {
 			return false;
+		}
 	}
 
-	public function keys() : Iterator<String> {
-		return untyped __call__("new _hx_array_iterator", __call__("array_map", "strval", __call__("array_keys", h)));
+	public inline function keys() : Iterator<String> {
+		return Global.array_map('strval', Global.array_keys(data)).iterator();
 	}
 
-	public function iterator() : Iterator<T> {
-		return untyped __call__("new _hx_array_iterator", __call__("array_values", h));
+	public inline function iterator() : Iterator<T> {
+		return data.iterator();
 	}
 	
 	public function copy() : StringMap<T> {
 		var copied = new StringMap();
-		copied.h = h;
+		copied.data = data;
 		return copied;
 	}
 
 	public function toString() : String {
-		var s = "{";
-		var it = keys();
-		for( i in it ) {
-			s += i;
-			s += " => ";
-			s += Std.string(get(i));
-			if( it.hasNext() )
-				s += ", ";
-		}
-		return s + "}";
-	}
+		var parts = new NativeArray();
+		Syntax.foreach(data, function(key:String, value:T) {
+			Global.array_push(parts, '$key => ' + Std.string(value));
+		});
 
-	/**
-		Implement IteratorAggregate for native php iteration
-	**/
-	#if php
-	function getIterator() : Iterator<T> {
-		return iterator();
+		return '{' + Global.implode(', ', parts) + '}';
 	}
-	#end
 }

+ 0 - 0
std/php7/_std/haxe/io/Bytes.hx → std/php/_std/haxe/io/Bytes.hx


+ 0 - 0
std/php7/_std/haxe/io/BytesBuffer.hx → std/php/_std/haxe/io/BytesBuffer.hx


+ 0 - 0
std/php7/_std/haxe/io/BytesData.hx → std/php/_std/haxe/io/BytesData.hx


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


+ 0 - 0
std/php7/_std/haxe/io/BytesOutput.hx → std/php/_std/haxe/io/BytesOutput.hx


+ 0 - 0
std/php7/_std/haxe/io/FPHelper.hx → std/php/_std/haxe/io/FPHelper.hx


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

@@ -21,6 +21,9 @@
  */
 package sys;
 
+import php.*;
+import haxe.io.Path;
+
 private enum FileKind {
 	kdir;
 	kfile;
@@ -31,83 +34,80 @@ private enum FileKind {
 class FileSystem {
 
 	public static inline function exists( path : String ) : Bool {
-		return untyped __call__("file_exists", path);
+		return Global.file_exists(path);
 	}
 
 	public static inline function rename( path : String, newPath : String ) : Void {
-		untyped __call__("rename", path, newPath);
+		Global.rename(path, newPath);
 	}
 
 	public static function stat( path : String ) : FileStat {
-		untyped __php__("$fstat = stat($path);");
-		return untyped {
-			gid   : __php__("$fstat['gid']"),
-			uid   : __php__("$fstat['uid']"),
-			atime : Date.fromTime(__php__("$fstat['atime']")*1000),
-			mtime : Date.fromTime(__php__("$fstat['mtime']")*1000),
-			ctime : Date.fromTime(__php__("$fstat['ctime']")*1000),
-			dev   : __php__("$fstat['dev']"),
-			ino   : __php__("$fstat['ino']"),
-			nlink : __php__("$fstat['nlink']"),
-			rdev  : __php__("$fstat['rdev']"),
-			size  : __php__("$fstat['size']"),
-			mode  : __php__("$fstat['mode']")
+		var info = Global.stat(path);
+		if (info == false) throw 'Unable to stat $path';
+		var info:NativeArray = info;
+
+		return {
+			gid   : info['gid'],
+			uid   : info['uid'],
+			atime : Date.fromTime(info['atime'] * 1000),
+			mtime : Date.fromTime(info['mtime'] * 1000),
+			ctime : Date.fromTime(info['ctime'] * 1000),
+			dev   : info['dev'],
+			ino   : info['ino'],
+			nlink : info['nlink'],
+			rdev  : info['rdev'],
+			size  : info['size'],
+			mode  : info['mode']
 		};
 	}
 
 	public static inline function fullPath( relPath : String ) : String {
-		var p = untyped __call__("realpath", relPath);
-		if (untyped __physeq__(p, false))
-			return null;
-		else
-			return p;
+		return (Syntax.binop(Global.realpath(relPath), "?:", null));
 	}
 
 	public static function absolutePath ( relPath : String ) : String {
-		if (haxe.io.Path.isAbsolute(relPath)) return relPath;
-		return haxe.io.Path.join([Sys.getCwd(), relPath]);
+		if (Path.isAbsolute(relPath)) return relPath;
+		return Path.join([Sys.getCwd(), relPath]);
 	}
 
 	static function kind( path : String ) : FileKind {
-		var k = untyped __call__("filetype", path);
-		switch(k) {
+		var kind = Global.filetype(path);
+		if (kind == false) throw 'Failed to check file type $path';
+
+		switch(kind) {
 			case "file": return kfile;
 			case "dir": return kdir;
-			default: return kother(k);
+			default: return kother(kind);
 		}
 	}
 
 	public static inline function isDirectory( path : String ) : Bool {
-		return untyped __call__("is_dir", path);
+		return Global.is_dir(path);
 	}
 
 	public static inline function createDirectory( path : String ) : Void {
-		var path = haxe.io.Path.addTrailingSlash(path);
-		var _p = null;
-		var parts = [];
-		while (path != (_p = haxe.io.Path.directory(path))) {
-			parts.unshift(path);
-			path = _p;
-		}
-		for (part in parts) {
-			if (part.charCodeAt(part.length - 1) != ":".code && !exists(part))
-				untyped __call__("@mkdir", part, 493); // php default is 0777, neko is 0755
-		}
+		if (!Global.is_dir(path))
+			Global.mkdir(path, 493, true);
 	}
 
 	public static inline function deleteFile( path : String ) : Void {
-		untyped __call__("unlink", path);
+		Global.unlink(path);
 	}
 
 	public static inline function deleteDirectory( path : String ) : Void {
-		untyped __call__("rmdir", path);
+		Global.rmdir(path);
 	}
 
 	public static function readDirectory( path : String ) : Array<String> {
-		var l = untyped __call__("array");
-		untyped __php__("$dh = opendir($path);
-        while (($file = readdir($dh)) !== false) if(\".\" != $file && \"..\" != $file) $l[] = $file;
-        closedir($dh);");
-		return untyped __call__("new _hx_array", l);
+		var list = [];
+		var dir = Global.opendir(path);
+		var file;
+		while ((file = Global.readdir(dir)) != false) {
+			if (file != '.' && file != '..') {
+				list.push(file);
+			}
+		}
+		Global.closedir(dir);
+        return list;
 	}
 }

+ 210 - 21
std/php/_std/sys/db/Mysql.hx

@@ -21,32 +21,221 @@
  */
 package sys.db;
 
-import sys.db.Connection;
+import php.*;
+import sys.db.*;
+import php.db.*;
+import php.db.Mysqli_result;
 
 @:coreApi class Mysql {
+	public static function connect(
+		params : {
+			host : String,
+			?port : Int,
+			user : String,
+			pass : String,
+			?socket : String,
+			?database : String
+		}
+	) : Connection {
+		return new MysqlConnection(params);
+	}
+}
+
+private class MysqlConnection implements Connection {
+	var db : Mysqli;
+
+	public function new(
+		params : {
+			host : String,
+			?port : Int,
+			user : String,
+			pass : String,
+			?socket : String,
+			?database : String
+		}
+	) : Void {
+		if (params.port == null) params.port = Std.parseInt(Global.ini_get('mysqli.default_port'));
+		if (params.socket == null) params.socket = Global.ini_get('mysqli.default_socket');
+		if (params.database == null) params.database = "";
+
+		db = new Mysqli(params.host, params.user, params.pass, params.database, params.port, params.socket);
+	}
+
+	public function request( s : String ) : ResultSet {
+		var result = db.query(s);
+		if (result == false) throw 'Failed to perform db query: ' + db.error;
+		if (result == true) return null;
+
+		return new MysqlResultSet(result);
+	}
+
+	public function close() : Void {
+		db.close();
+	}
+
+	public function escape( s : String ) : String {
+		return db.escape_string(s);
+	}
+
+	public function quote( s : String ) : String {
+		if (s.indexOf("\000") >= 0) return "x'" + Global.bin2hex(s) + "'";
+		return "'" + db.escape_string(s) + "'";
+	}
+
+	public function addValue( s : StringBuf, v : Dynamic ) : Void {
+		if (Global.is_int(v)
+		|| Global.is_null(v)) {
+			s.add(v);
+		} else if (Global.is_bool(v)) {
+			s.add(v ? 1 : 0);
+		} else {
+			s.add(quote(Std.string(v)));
+		}
+	}
+
+	public function lastInsertId() : Int {
+		return db.insert_id;
+	}
+
+	public function dbName() : String {
+		return 'MySQL';
+	}
+
+	public function startTransaction() : Void {
+		var success = db.begin_transaction();
+		if (!success) throw 'Failed to start transaction: ' + db.error;
+	}
+
+	public function commit() : Void {
+		var success = db.commit();
+		if (!success) throw 'Failed to commit transaction: ' + db.error;
+	}
+
+	public function rollback() : Void {
+		var success = db.rollback();
+		if (!success) throw 'Failed to rollback transaction: ' + db.error;
+	}
+
+}
+
+private class MysqlResultSet implements ResultSet {
+	static var hxAnonClassName = Boot.getHxAnon().phpClassName;
+
+	public var length(get,null) : Int;
+	public var nfields(get,null) : Int;
+
+	var result:Mysqli_result;
+	var fetchedRow:NativeAssocArray<Scalar>;
+	var fieldsInfo:NativeAssocArray<MysqliFieldInfo>;
+
+	public function new( result:Mysqli_result ) {
+		this.result = result;
+	}
+
+	public function hasNext() : Bool {
+		if (fetchedRow == null) fetchNext();
+		return fetchedRow != null;
+	}
+
+	public function next() : Dynamic {
+		if (fetchedRow == null) fetchNext();
+		return withdrawFetched();
+	}
+
+	public function results() : List<Dynamic> {
+		var list = new List();
+
+		result.data_seek(0);
+		var row = result.fetch_object(hxAnonClassName);
+		while (row != null) {
+			row = correctObjectTypes(row);
+			list.add(row);
+			row = result.fetch_object(hxAnonClassName);
+		}
+
+		return list;
+	}
+
+	public function getResult( n : Int ) : String {
+		if (fetchedRow == null) fetchNext();
+		return Global.array_values(fetchedRow)[n];
+	}
+
+	public function getIntResult( n : Int ) : Int {
+		return Syntax.int(getResult(n));
+	}
+
+	public function getFloatResult( n : Int ) : Float {
+		return Syntax.float(getResult(n));
+	}
+
+	public function getFieldsNames() : Null<Array<String>> {
+		var fields = result.fetch_fields();
+		return [for (field in fields) field.name];
+	}
+
+	function fetchNext() {
+		var row = result.fetch_assoc();
+		if (row != null) fetchedRow = correctArrayTypes(row);
+	}
+
+	function withdrawFetched() : Dynamic {
+		if (fetchedRow == null) return null;
+		var row = fetchedRow;
+		fetchedRow = null;
+		return Boot.createAnon(row);
+	}
+
+	function correctArrayTypes(row:NativeAssocArray<String>):NativeAssocArray<Scalar> {
+		var fieldsInfo = getFieldsInfo();
+		Syntax.foreach(row, function(field:String, value:String) {
+			row[field] = correctType(value, fieldsInfo[field].type);
+		});
+		return cast row;
+	}
+
+	function correctObjectTypes(row:{}):{} {
+		var fieldsInfo = getFieldsInfo();
+		Syntax.foreach(row, function(field:String, value:String) {
+			value = correctType(value, fieldsInfo[field].type);
+			Syntax.setField(row, field, value);
+		});
+		return row;
+	}
+
+	inline function getFieldsInfo():NativeAssocArray<MysqliFieldInfo> {
+		if (fieldsInfo == null) {
+			fieldsInfo = cast Syntax.arrayDecl();
+			Syntax.foreach(result.fetch_fields(), function(_, info) {
+				fieldsInfo[info.name] = info;
+			});
+		}
+		return fieldsInfo;
+	}
 
-	public static function connect( params : {
-		host : String,
-		?port : Int,
-		user : String,
-		pass : String,
-		?socket : String,
-		?database : String
-	} ) : sys.db.Connection {
-		var dsn = "mysql:";
-        
-		if (params.socket !=null)
-			dsn+="unix_socket="+params.socket+";";
-		else{
-			dsn+="host="+params.host+";";
-			if (params.port!=null)
-				dsn+='port='+params.port+";";
+	function correctType(value:String, type:Int):Scalar {
+		if (value == null) return null;
+		if (
+			type == Const.MYSQLI_TYPE_BIT
+			|| type == Const.MYSQLI_TYPE_TINY
+			|| type == Const.MYSQLI_TYPE_SHORT
+			|| type == Const.MYSQLI_TYPE_LONG
+			|| type == Const.MYSQLI_TYPE_INT24
+			|| type == Const.MYSQLI_TYPE_CHAR
+		) {
+			return Syntax.int(value);
 		}
-		if (params.database != null) {
-			dsn+="dbname="+params.database;
+		if (
+			type == Const.MYSQLI_TYPE_DECIMAL
+			|| type == Const.MYSQLI_TYPE_NEWDECIMAL
+			|| type == Const.MYSQLI_TYPE_FLOAT
+			|| type == Const.MYSQLI_TYPE_DOUBLE
+		) {
+			return Syntax.float(value);
 		}
-		
-		return php.db.PDO.open(dsn,params.user,params.pass);
+		return value;
 	}
 
+	function get_length() return result.num_rows;
+	function get_nfields() return result.field_count;
 }

+ 164 - 2
std/php/_std/sys/db/Sqlite.hx

@@ -21,10 +21,172 @@
  */
 package sys.db;
 
+import php.*;
+import php.db.*;
+import sys.db.*;
+
 @:coreApi class Sqlite {
+	public static function open( file:String ) : Connection {
+		return new SQLiteConnection(file);
+	}
+}
+
+private class SQLiteConnection implements Connection {
+	var db:SQLite3;
+
+	public function new( file:String ) {
+		db = new SQLite3('sqlite:$file');
+		db.enableExceptions(true);
+	}
+
+	public function request( s : String ) : ResultSet {
+		var result = db.query(s);
+		return new SQLiteResultSet(result);
+	}
+
+	public function close() : Void {
+		db.close();
+	}
+
+	public function escape( s : String ) : String {
+		return SQLite3.escapeString(s);
+	}
+
+	public function quote( s : String ) : String {
+		if (s.indexOf("\000") >= 0) return "x'" + Global.bin2hex(s) + "'";
+		return "'" + SQLite3.escapeString(s) + "'";
+	}
+
+	public function addValue( s : StringBuf, v : Dynamic ) : Void {
+		if (Global.is_int(v) || Global.is_null(v)) {
+			s.add(v);
+		} else if (Global.is_bool(v)) {
+			s.add(v ? 1 : 0);
+		} else {
+			s.add(quote(Std.string(v)));
+		}
+	}
+
+	public function lastInsertId() : Int {
+		return Syntax.int(db.lastInsertRowID());
+	}
+
+	public function dbName() : String {
+		return 'SQLite';
+	}
+
+	public function startTransaction() : Void {
+		db.query('BEGIN TRANSACTION');
+	}
+
+	public function commit() : Void {
+		db.query('COMMIT');
+	}
+
+	public function rollback() : Void {
+		db.query('ROLLBACK');
+	}
+}
+
+private class SQLiteResultSet implements ResultSet {
+	public var length(get,null) : Int;
+	public var nfields(get,null) : Int;
+
+	var _length : Int = 0;
+	var _nfields : Int = 0;
+
+	var loaded:Bool = false;
+	var currentIndex:Int = 0;
+	var rows:NativeIndexedArray<NativeAssocArray<Scalar>>;
+	var result:SQLite3Result;
+	var fetchedRow:NativeArray;
+	var fieldsInfo:NativeAssocArray<Int>;
+
+	public function new( result:SQLite3Result ) {
+		this.result = result;
+	}
+
+	public function hasNext() : Bool {
+		if (!loaded) load();
+		return currentIndex < _length;
+	}
+
+	public function next() : Dynamic {
+		if (!loaded) load();
+		var next:Dynamic = rows[currentIndex++];
+		return Boot.createAnon(correctArrayTypes(next));
+	}
+
+	public function results() : List<Dynamic> {
+		if (!loaded) load();
+		var list = new List();
+		Syntax.foreach(rows, function(_, row) list.add(Boot.createAnon(correctArrayTypes(row))));
+		return list;
+	}
+
+	public function getResult( n : Int ) : String {
+		if (!loaded) load();
+		if (!hasNext()) return null;
+		return Global.array_values(rows[currentIndex])[n];
+	}
+
+	public function getIntResult( n : Int ) : Int {
+		return Syntax.int(getResult(n));
+	}
+
+	public function getFloatResult( n : Int ) : Float {
+		return Syntax.float(getResult(n));
+	}
+
+	public function getFieldsNames() : Null<Array<String>> {
+		var fieldsInfo = getFieldsInfo();
+		return Global.array_keys(fieldsInfo);
+	}
+
+	function correctArrayTypes(row:NativeAssocArray<String>):NativeAssocArray<Scalar> {
+		var fieldsInfo = getFieldsInfo();
+		Syntax.foreach(row, function(field:String, value:String) {
+			row[field] = correctType(value, fieldsInfo[field]);
+		});
+		return cast row;
+	}
+
+	inline function getFieldsInfo():NativeAssocArray<Int> {
+		if (fieldsInfo == null) {
+			fieldsInfo = cast Syntax.arrayDecl();
+			for(i in 0...nfields) {
+				fieldsInfo[result.columnName(i)] = result.columnType(i);
+			}
+		}
+		return fieldsInfo;
+	}
+
+	function load() {
+		loaded = true;
+		_nfields = result.numColumns();
+		getFieldsInfo();
+		fetchAll();
+	}
+
+	function correctType(value:String, type:Int):Scalar {
+		if (value == null) return null;
+		if (type == Const.SQLITE3_INTEGER) return Syntax.int(value);
+		if (type == Const.SQLITE3_FLOAT) return Syntax.float(value);
+		return value;
+	}
 
-	public static function open( file : String ) : Connection {
-		return php.db.PDO.open("sqlite:"+file);
+	function fetchAll() {
+		rows = Syntax.arrayDecl();
+		var index = 0;
+		var row = result.fetchArray(Const.SQLITE3_ASSOC);
+		while(row != false) {
+			rows[index] = correctArrayTypes(row);
+			row = result.fetchArray(Const.SQLITE3_ASSOC);
+			index++;
+		}
+		_length = index;
 	}
 
+	function get_length() return _length;
+	function get_nfields() return _nfields;
 }

+ 9 - 9
std/php/_std/sys/io/File.hx

@@ -21,21 +21,21 @@
  */
 package sys.io;
 
-enum FileHandle {
-}
+import php.Global.*;
+import php.Global;
 
 @:coreApi class File {
 
 	public static function getContent( path : String ) : String {
-		return untyped __call__("file_get_contents", path);
+		return file_get_contents(path);
 	}
 
 	public static function getBytes( path : String ) : haxe.io.Bytes {
-		return haxe.io.Bytes.ofString(getContent(path));
+		return haxe.io.Bytes.ofString(file_get_contents(path));
 	}
 
 	public static function saveContent( path : String, content : String) : Void {
-		untyped __call__("file_put_contents", path, content);
+		file_put_contents(path, content);
 	}
 
 	public static function saveBytes( path : String, bytes : haxe.io.Bytes ) : Void {
@@ -45,19 +45,19 @@ enum FileHandle {
 	}
 
 	public static function read( path : String, binary : Bool = true ) : FileInput {
-		return untyped new FileInput(__call__('fopen', path, binary ? "rb" : "r"));
+		return @:privateAccess new FileInput(fopen(path, binary ? "rb" : "r"));
 	}
 
 	public static function write( path : String, binary : Bool = true ) : FileOutput {
-		return untyped new FileOutput(untyped __call__('fopen', path, binary ? "wb" : "w"));
+		return untyped new FileOutput(fopen(path, binary ? "wb" : "w"));
 	}
 
 	public static function append( path : String, binary : Bool = true ) : FileOutput {
-		return untyped new FileOutput(untyped __call__('fopen', path, binary ? "ab" : "a"));
+		return untyped new FileOutput(fopen(path, binary ? "ab" : "a"));
 	}
 
 	public static function copy( srcPath : String, dstPath : String ) : Void {
-		untyped __call__("copy", srcPath, dstPath);
+		Global.copy(srcPath, dstPath);
 	}
 
 }

+ 31 - 26
std/php/_std/sys/io/FileInput.hx

@@ -20,63 +20,68 @@
  * DEALINGS IN THE SOFTWARE.
  */
 package sys.io;
+
 import haxe.io.Eof;
+import haxe.io.Error;
+import haxe.io.Bytes;
+import php.*;
+import php.Global.*;
+import php.Const.*;
 
 @:coreApi
 class FileInput extends haxe.io.Input {
 
-	private var __f : File.FileHandle;
+	private var __f : Resource;
 
-	function new(f:File.FileHandle) : Void {
+	function new(f:Resource) : Void {
 		__f = f;
 	}
 
 	public override function readByte() : Int {
-		var r = untyped __call__('fread', __f, 1);
-		if(untyped __call__('feof', __f)) return throw new haxe.io.Eof();
-		if(untyped __physeq__(r, false)) return throw haxe.io.Error.Custom('An error occurred');
-		return untyped __call__('ord', r);
+		var r = fread(__f, 1);
+		if(feof(__f)) throw new Eof();
+		if(r == false) throw Custom('An error occurred');
+		return ord(r);
 	}
 
-	public override function readBytes( s : haxe.io.Bytes, p : Int, l : Int ) : Int {
-		if(untyped __call__('feof', __f)) return throw new haxe.io.Eof();
-		var r : String = untyped __call__('fread', __f, l);
-		if(untyped __physeq__(r, false)) return throw haxe.io.Error.Custom('An error occurred');
-		var b = haxe.io.Bytes.ofString(r);
-		s.blit(p, b, 0, r.length);
-		return r.length;
+	public override function readBytes( s : Bytes, p : Int, l : Int ) : Int {
+		if(feof(__f)) throw new Eof();
+		var r = fread(__f, l);
+		if(r == false) throw Custom('An error occurred');
+		var b = Bytes.ofString(r);
+		s.blit(p, b, 0, (r:String).length);
+		return (r:String).length;
 	}
 
 	public override function close() : Void {
 		super.close();
-		if(__f != null)	untyped __call__('fclose', __f);
+		if(__f != null)	fclose(__f);
 	}
 
 	public function seek( p : Int, pos : FileSeek ) : Void {
 		var w;
 		switch( pos ) {
-			case SeekBegin: w = untyped __php__('SEEK_SET');
-			case SeekCur  : w = untyped __php__('SEEK_CUR');
-			case SeekEnd  : w = untyped __php__('SEEK_END');
+			case SeekBegin: w = SEEK_SET;
+			case SeekCur  : w = SEEK_CUR;
+			case SeekEnd  : w = SEEK_END;
 		}
-		var r = untyped __call__('fseek', __f, p, w);
-		if(untyped __physeq__(r, false)) throw haxe.io.Error.Custom('An error occurred');
+		var r = fseek(__f, p, w);
+		if(r == false) throw Custom('An error occurred');
 	}
 
 	public function tell() : Int {
-		var r = untyped __call__('ftell', __f);
-		if(untyped __physeq__(r, false)) return throw haxe.io.Error.Custom('An error occurred');
+		var r = ftell(__f);
+		if(r == false) throw Custom('An error occurred');
 		return cast r;
 	}
 
 	public function eof() : Bool {
-		return untyped __call__('feof', __f);
+		return feof(__f);
 	}
 
 	override function readLine() : String {
-		var r : String = untyped __call__('fgets', __f);
-		if (untyped __physeq__(false, r))
-			throw new Eof();
-		return untyped __call__("rtrim", r, "\r\n");
+		var r = fgets(__f);
+		if (false == r) throw new Eof();
+		return rtrim(r, "\r\n");
 	}
 }

+ 22 - 18
std/php/_std/sys/io/FileOutput.hx

@@ -21,52 +21,56 @@
  */
 package sys.io;
 
+import php.*;
+import php.Global.*;
+import php.Const.*;
+
 @:coreApi
 class FileOutput extends haxe.io.Output {
-	private var __f : File.FileHandle;
+	private var __f : Resource;
 
-	function new(f:File.FileHandle) : Void {
+	function new(f:Resource) : Void {
 		__f = f;
 	}
 
 	public override function writeByte( c : Int ) : Void {
-		var r = untyped __call__('fwrite', __f, __call__('chr', c));
-		if(untyped __physeq__(r, false)) throw haxe.io.Error.Custom('An error occurred');
+		var r = fwrite(__f, chr(c));
+		if(r == false) throw haxe.io.Error.Custom('An error occurred');
 	}
 
 	public override function writeBytes( b : haxe.io.Bytes, p : Int, l : Int ) : Int {
 		var s = b.getString(p, l);
-		if(untyped __call__('feof', __f)) return throw new haxe.io.Eof();
-		var r = untyped __call__('fwrite', __f, s, l);
-		if(untyped __physeq__(r, false)) return throw haxe.io.Error.Custom('An error occurred');
+		if(feof(__f)) throw new haxe.io.Eof();
+		var r = fwrite(__f, s, l);
+		if(r == false) throw haxe.io.Error.Custom('An error occurred');
 		return r;
 	}
 
 	public override function flush() : Void {
-		var r = untyped __call__('fflush', __f);
-		if(untyped __physeq__(r, false)) throw haxe.io.Error.Custom('An error occurred');
+		var r = fflush(__f);
+		if(r == false) throw haxe.io.Error.Custom('An error occurred');
 	}
 
 	public override function close() : Void {
 		super.close();
-		if(__f != null)	untyped __call__('fclose', __f);
+		if(__f != null)	fclose(__f);
 	}
 
 	public function seek( p : Int, pos : FileSeek ) : Void {
 		var w;
 		switch( pos ) {
-			case SeekBegin: w = untyped __php__('SEEK_SET');
-			case SeekCur  : w = untyped __php__('SEEK_CUR');
-			case SeekEnd  : w = untyped __php__('SEEK_END');
+			case SeekBegin: w = SEEK_SET;
+			case SeekCur  : w = SEEK_CUR;
+			case SeekEnd  : w = SEEK_END;
 		}
-		var r = untyped __call__('fseek', __f, p, w);
-		if(untyped __physeq__(r, false)) throw haxe.io.Error.Custom('An error occurred');
+		var r = fseek(__f, p, w);
+		if(r == false) throw haxe.io.Error.Custom('An error occurred');
 	}
 
 	public function tell() : Int {
-		var r = untyped __call__('ftell', __f);
-		if(untyped __physeq__(r, false)) return throw haxe.io.Error.Custom('An error occurred');
-		return cast r;
+		var r = ftell(__f);
+		if(r == false) throw haxe.io.Error.Custom('An error occurred');
+		return r;
 	}
 
 }

+ 153 - 96
std/php/_std/sys/io/Process.hx

@@ -20,138 +20,195 @@
  * DEALINGS IN THE SOFTWARE.
  */
 package sys.io;
-import php.NativeArray;
 
-private class Stdin extends haxe.io.Output {
-	var p : Dynamic;
-	var buf : haxe.io.Bytes;
+import php.*;
+import haxe.io.*;
 
-	public function new(p:Dynamic) {
-		this.p = p;
-		buf = haxe.io.Bytes.alloc(1);
+using StringTools;
+using php.Global;
+
+@:forward(iterator)
+private abstract ProcessPipes(NativeIndexedArray<Resource>) from NativeIndexedArray<Resource> to NativeIndexedArray<Resource> {
+	public var stdin (get,never) : Resource;
+	public var stdout (get,never) : Resource;
+	public var stderr (get,never) : Resource;
+
+	inline function get_stdin() return this[0];
+	inline function get_stdout() return this[1];
+	inline function get_stderr() return this[2];
+}
+
+private class ReadablePipe extends Input {
+	var pipe : Resource;
+	var tmpBytes : Bytes;
+
+	public function new(pipe:Resource) {
+		this.pipe = pipe;
+		tmpBytes = Bytes.alloc(1);
 	}
 
-	public override function close() {
-		super.close();
-		untyped __call__('fclose', p);
+	override public function close() : Void {
+		pipe.fclose();
 	}
 
-	public override function writeByte(c) {
-		buf.set(0,c);
-		writeBytes(buf,0,1);
+	override public function readByte() : Int {
+		if (readBytes(tmpBytes, 0, 1) == 0) throw Error.Blocked;
+		return tmpBytes.get(0);
 	}
 
-	public override function writeBytes( b : haxe.io.Bytes, pos : Int, l : Int ) : Int {
-		var s = b.getString(pos, l);
-		if(untyped __call__('feof', p)) return throw new haxe.io.Eof();
-		var r = untyped __call__('fwrite', p, s, l);
-		if(untyped __physeq__(r, false)) return throw haxe.io.Error.Custom('An error occurred');
-		return r;
+	override public function readBytes( s:Bytes, pos:Int, len:Int ) : Int {
+		if(pipe.feof()) throw new Eof();
+
+		var result = pipe.fread(len);
+		if(result == "") throw new Eof();
+		if(result == false) return throw Error.Custom('Failed to read process output');
+		var result:String = result;
+
+		var bytes = Bytes.ofString(result);
+		s.blit(pos, bytes, 0, result.length);
+		return result.length;
 	}
 }
 
-private class Stdout extends haxe.io.Input {
-	var p : Dynamic;
-	var buf : haxe.io.Bytes;
+private class WritablePipe extends Output {
+	var pipe : Resource;
+	var tmpBytes : Bytes;
 
-	public function new(p:Dynamic) {
-		this.p = p;
-		buf = haxe.io.Bytes.alloc(1);
+	public function new(pipe:Resource) {
+		this.pipe = pipe;
+		tmpBytes = Bytes.alloc(1);
 	}
 
-	public override function readByte() {
-		if( readBytes(buf,0,1) == 0 )
-			throw haxe.io.Error.Blocked;
-		return buf.get(0);
+	override public function close() : Void {
+		pipe.fclose();
 	}
 
-	public override function readBytes( str : haxe.io.Bytes, pos : Int, l : Int ) : Int {
-		if(untyped __call__('feof', p)) return throw new haxe.io.Eof();
-		var r : String = untyped __call__('fread', p, l);
-		if(untyped __physeq__(r, "")) return throw new haxe.io.Eof();
-		if(untyped __physeq__(r, false)) return throw haxe.io.Error.Custom('An error occurred');
-		var b = haxe.io.Bytes.ofString(r);
-		str.blit(pos, b, 0, r.length);
-		return r.length;
+	override public function writeByte(c:Int) : Void {
+		tmpBytes.set(0, c);
+		writeBytes(tmpBytes, 0, 1);
+	}
+
+	override public function writeBytes( b : Bytes, pos : Int, l : Int ) : Int {
+		var s = b.getString(pos, l);
+		if(pipe.feof()) throw new Eof();
+
+		var result = Global.fwrite(pipe, s, l);
+		if(result == false) throw Error.Custom('Failed to write to process input');
+		return result;
 	}
 }
 
-@:coreApi
 class Process {
-	var p : Dynamic;
-	var st : NativeArray;
-	var cl : Int;
-	public var stdout(default,null) : haxe.io.Input;
-	public var stderr(default,null) : haxe.io.Input;
-	public var stdin(default,null) : haxe.io.Output;
+	/**
+		Standard output. The output stream where a process writes its output data.
+	**/
+	public var stdout(default, null) : Input;
+
+	/**
+		Standard error. The output stream to output error messages or diagnostics.
+	**/
+	public var stderr(default, null) : Input;
+
+	/**
+		Standard input. The stream data going into a process.
+	**/
+	public var stdin(default, null) : Output;
+
+	var process : Resource;
+	var pipes : ProcessPipes;
+	var pid : Int = -1;
+	var running : Bool = true;
+	var _exitCode : Int = -1;
+
+	/**
+		Construct a `Process` object, which run the given command immediately.
 
+		Command arguments can be passed in two ways: 1. using `args`, 2. appending to `cmd` and leaving `args` as `null`.
+
+		 1. When using `args` to pass command arguments, each argument will be automatically quoted, and shell meta-characters will be escaped if needed.
+		`cmd` should be an executable name that can be located in the `PATH` environment variable, or a path to an executable.
+
+		 2. When `args` is not given or is `null`, command arguments can be appended to `cmd`. No automatic quoting/escaping will be performed. `cmd` should be formatted exactly as it would be when typed at the command line.
+		It can run executables, as well as shell commands that are not executables (e.g. on Windows: `dir`, `cd`, `echo` etc).
+
+		`close()` should be called when the `Process` is no longer used.
+	*/
 	public function new( cmd : String, ?args : Array<String>, ?detached : Bool ) : Void {
 		if( detached ) throw "Detached process is not supported on this platform";
-		var pipes = untyped __call__("array");
-		var descriptorspec = untyped __php__("array(
-			array('pipe', 'r'),
-			array('pipe', 'w'),
-			array('pipe', 'w')
-		)");
-		if (args != null) {
-			switch (Sys.systemName()) {
-				case "Windows":
-					cmd = [
-						for (a in [StringTools.replace(cmd, "/", "\\")].concat(args))
-						StringTools.quoteWinArg(a, true)
-					].join(" ");
-				case _:
-					cmd = [cmd].concat(args).map(StringTools.quoteUnixArg).join(" ");
-			}
+		var descriptors = Syntax.arrayDecl(
+			Syntax.arrayDecl('pipe', 'r'),
+			Syntax.arrayDecl('pipe', 'w'),
+			Syntax.arrayDecl('pipe', 'w')
+		);
+		var result = buildCmd(cmd, args).proc_open(descriptors, pipes);
+		if (result == false) throw Error.Custom('Failed to start process: $cmd');
+		process = result;
+
+		updateStatus();
+
+		stdin = new WritablePipe(pipes.stdin);
+		stdout = new ReadablePipe(pipes.stdout);
+		stderr = new ReadablePipe(pipes.stderr);
+	}
+
+	/**
+		Return the process ID.
+	*/
+	public function getPid() : Int {
+		return pid;
+	}
+
+	public function exitCode( block : Bool = true ) : Null<Int> {
+		if(!block) {
+			updateStatus();
+			return (running ? null : _exitCode);
+		}
+		while (running) {
+			var arr = Syntax.arrayDecl(process);
+			Syntax.suppress(Global.stream_select(arr, arr, arr, null));
+			updateStatus();
 		}
-		p = untyped __call__('proc_open', cmd, descriptorspec, pipes);
-		if(untyped __physeq__(p, false)) throw "Process creation failure : "+cmd;
-		stdin  = new Stdin( pipes[0]);
-		stdout = new Stdout(pipes[1]);
-		stderr = new Stdout(pipes[2]);
+		return _exitCode;
 	}
 
+	/**
+		Close the process handle and release the associated resources.
+		All `Process` fields should not be used after `close()` is called.
+	*/
 	public function close() : Void {
-		if(null == st)
-			st = untyped __call__('proc_get_status', p);
-		replaceStream(stderr);
-		replaceStream(stdout);
-		if(null == cl)
-			cl = untyped __call__('proc_close', p);
-	}
+		if (!running) return;
 
-	public function getPid() : Int {
-		var r = untyped __call__('proc_get_status', p);
-		return r[untyped 'pid'];
+		for (pipe in pipes) Global.fclose(pipe);
+		process.proc_close();
 	}
 
+	/**
+		Kill the process.
+	*/
 	public function kill() : Void {
-		untyped __call__('proc_terminate',p);
+		process.proc_terminate();
 	}
 
-	function replaceStream(input : haxe.io.Input) : Void {
-		var fp = untyped __call__("fopen", "php://memory", "r+");
-		while(true) {
-			var s = untyped __call__("fread", untyped input.p, 8192);
-			if(untyped __physeq__(s, false) || s == null || s == '') break;
-			untyped __call__("fwrite", fp, s);
+	function buildCmd( cmd:String, ?args:Array<String> ) : String {
+		if (args == null) return cmd;
+
+		return switch (Sys.systemName()) {
+			case "Windows":
+				[cmd.replace("/", "\\")].concat(args).map(StringTools.quoteWinArg.bind(_, true)).join(" ");
+			case _:
+				[cmd].concat(args).map(StringTools.quoteUnixArg).join(" ");
 		}
-		untyped __call__("rewind", fp);
-		untyped input.p = fp;
 	}
 
-	public function exitCode( block : Bool = true ) : Null<Int> {
-		if (null == cl)
-		{
-			st = untyped __call__('proc_get_status', p);
-			while(st[untyped 'running']) {
-				if( block == false ) return null;
-				Sys.sleep(0.01);
-				st = untyped __call__('proc_get_status', p);
-			}
-			close();
-		}
-		return (cast st[untyped 'exitcode']) < 0 ? cl : cast st[untyped 'exitcode'];
+	function updateStatus() : Void {
+		if (!running) return;
+
+		var status = process.proc_get_status();
+		if (status == false) throw Error.Custom('Failed to obtain process status');
+		var status:NativeAssocArray<Scalar> = status;
 
+		pid = status['pid'];
+		running = status['running'];
+		_exitCode = status['exitcode'];
 	}
 }

+ 7 - 4
std/php/_std/sys/net/Host.hx

@@ -21,6 +21,9 @@
  */
 package sys.net;
 
+import php.Global.*;
+import php.SuperGlobal.*;
+
 @:coreApi
 class Host {
 
@@ -34,14 +37,14 @@ class Host {
 		if(~/^(\d{1,3}\.){3}\d{1,3}$/.match(name)) {
 		  _ip = name;
 		} else {
-			_ip = untyped __call__('gethostbyname', name);
+			_ip = gethostbyname(name);
 			if(_ip == name) {
 				ip = 0;
 				return;
 			}
 		}
 		var p = _ip.split('.');
-		ip = untyped __call__('intval', __call__('sprintf', '%02X%02X%02X%02X', p[3], p[2], p[1], p[0]), 16);
+		ip = intval(sprintf('%02X%02X%02X%02X', p[3], p[2], p[1], p[0]), 16);
 	}
 
 	public function toString() : String {
@@ -49,10 +52,10 @@ class Host {
 	}
 
 	public function reverse() : String {
-		return untyped __call__('gethostbyaddr', _ip);
+		return gethostbyaddr(_ip);
 	}
 
 	public static function localhost() : String {
-		return untyped __var__('_SERVER', 'HTTP_HOST');
+		return _SERVER['HTTP_HOST'];
 	}
 }

+ 42 - 40
std/php/_std/sys/net/Socket.hx

@@ -21,90 +21,92 @@
  */
 package sys.net;
 
-import sys.io.File;
+import php.*;
+import php.Global.*;
+import php.Const.*;
+import sys.io.FileInput;
+import sys.io.FileOutput;
 
 @:coreApi
 class Socket {
 
-	private var __s : FileHandle;
+	private var __s : Resource;
 	private var protocol : String;
 	public var input(default,null) : haxe.io.Input;
 	public var output(default,null) : haxe.io.Output;
 	public var custom : Dynamic;
 
 	public function new() : Void {
-		input = untyped new sys.io.FileInput(null);
-		output = untyped new sys.io.FileOutput(null);
+		input = @:privateAccess new sys.io.FileInput(null);
+		output = @:privateAccess new sys.io.FileOutput(null);
 		protocol = "tcp";
 	}
 
 	private function assignHandler() : Void {
-		untyped input.__f = __s;
-		untyped output.__f = __s;
+		@:privateAccess (cast input:FileInput).__f = __s;
+		@:privateAccess (cast output:FileOutput).__f = __s;
 	}
 
 	public function close() : Void {
-		untyped __call__('fclose', __s);
-		untyped {
-			input.__f = null;
-			output.__f = null;
-		}
+		fclose(__s);
+		@:privateAccess (cast input:FileInput).__f = null;
+		@:privateAccess (cast output:FileOutput).__f = null;
 		input.close();
 		output.close();
 	}
 
 	public function read() : String {
 		var b = '';
-		untyped __php__("while (!feof($this->__s)) $b .= fgets($this->__s)");
+		while(!feof(__s)) b += fgets(__s);
 		return b;
 	}
 
 	public function write( content : String ) : Void {
-		return untyped __call__('fwrite', __s, content);
+		fwrite(__s, content);
 	}
 
 	public function connect(host : Host, port : Int) : Void {
 		var errs = null;
 		var errn = null;
-		var r = untyped __call__('stream_socket_client', protocol + '://' +host.host + ':' + port, errn, errs);
+		var r = stream_socket_client(protocol + '://' + host.host + ':' + port, errn, errs);
 		Socket.checkError(r, errn, errs);
-		__s = cast r;
+		__s = r;
 		assignHandler();
 	}
 
 	public function listen(connections : Int) : Void {
 		throw "Not implemented";
 /* TODO: ??????
-		var r = untyped __call__('socket_listen', __s, connections);
+		var r = socket_listen(__s, connections);
 		checkError(r);
 */
 	}
 
 	public function shutdown( read : Bool, write : Bool ) : Void {
-		var r;
-		if(untyped __call__("function_exists", "stream_socket_shutdown")) {
-			var rw = read && write ? 2 : (write ? 1 : (read ? 0 : 2));
-			r = untyped __call__('stream_socket_shutdown', __s, rw);
-		} else {
-			r = untyped __call__('fclose', __s);
-		}
+		var rw = read && write ? 2 : (write ? 1 : (read ? 0 : 2));
+		var r = stream_socket_shutdown(__s, rw);
 		checkError(r, 0, 'Unable to Shutdown');
 	}
 
 	public function bind(host : Host, port : Int) : Void {
-		var errs = null;
-		var errn = null;
-		var r = untyped __call__('stream_socket_server', protocol + '://' +host._ip + ':' + port, errn, errs, (protocol=="udp") ? __php__('STREAM_SERVER_BIND') : __php__('STREAM_SERVER_BIND | STREAM_SERVER_LISTEN'));
+		var errs = Boot.deref(null);
+		var errn = Boot.deref(null);
+		var r = stream_socket_server(
+			protocol + '://' + host.ip + ':' + port,
+			errn,
+			errs,
+			(protocol == "udp" ? STREAM_SERVER_BIND : STREAM_SERVER_BIND | STREAM_SERVER_LISTEN)
+		);
 		Socket.checkError(r, errn, errs);
 		__s = cast r;
 		assignHandler();
 	}
 
 	public function accept() : Socket {
-		var r = untyped __call__('stream_socket_accept', __s);
+		var r = stream_socket_accept(__s);
 		checkError(r, 0, 'Unable to accept connections on socket');
 		var s = new Socket();
-		s.__s = cast r;
+		s.__s = r;
 		s.assignHandler();
 		return s;
 	}
@@ -119,26 +121,26 @@ class Socket {
 	}
 
 	public function peer() : { host : Host, port : Int } {
-		var r : String = untyped __call__('stream_socket_get_name', __s, true);
-		checkError(cast r, 0, 'Unable to retrieve the peer name');
+		var r = stream_socket_get_name(__s, true);
+		checkError(r, 0, 'Unable to retrieve the peer name');
 		return hpOfString(r);
 	}
 
 	public function host() : { host : Host, port : Int } {
-		var r : String = untyped __call__('stream_socket_get_name', __s, false);
-		checkError(cast r, 0, 'Unable to retrieve the host name');
+		var r = stream_socket_get_name(__s, false);
+		checkError(r, 0, 'Unable to retrieve the host name');
 		return hpOfString(r);
 	}
 
 	public function setTimeout( timeout : Float ) : Void {
 		var s = Std.int(timeout);
-		var ms = Std.int((timeout-s)*1000000);
-		var r = untyped __call__('stream_set_timeout', __s, s, ms);
+		var ms = Std.int((timeout - s) * 1000000);
+		var r = stream_set_timeout(__s, s, ms);
 		checkError(r, 0, 'Unable to set timeout');
 	}
 
 	public function setBlocking( b : Bool ) : Void {
-		var r = untyped __call__('stream_set_blocking', __s, b);
+		var r = stream_set_blocking(__s, b);
 		checkError(r, 0, 'Unable to block');
 	}
 
@@ -147,20 +149,20 @@ class Socket {
 	}
 
 	public function waitForRead() : Void {
-		select([this],null,null);
+		select([this], null, null);
 	}
 
 	private static function checkError(r : Bool, code : Int, msg : String) : Void {
-		if(!untyped __physeq__(r, false)) return;
-		throw haxe.io.Error.Custom('Error ['+code+']: ' +msg);
+		if(r != false) return;
+		throw haxe.io.Error.Custom('Error [$code]: $msg');
 	}
 
 	private static function getType(isUdp : Bool) : Int {
-		return isUdp ? untyped __php__('SOCK_DGRAM') : untyped __php__('SOCK_STREAM');
+		return isUdp ? SOCK_DGRAM : SOCK_STREAM;
 	}
 
 	private static function getProtocol(protocol : String) : Int {
-		return untyped __call__('getprotobyname', protocol);
+		return getprotobyname(protocol);
  	}
 
 	public static function select(read : Array<Socket>, write : Array<Socket>, others : Array<Socket>, ?timeout : Float) : { read: Array<Socket>,write: Array<Socket>,others: Array<Socket> }

+ 0 - 0
std/php7/db/Mysqli.hx → std/php/db/Mysqli.hx


+ 0 - 0
std/php7/db/Mysqli_driver.hx → std/php/db/Mysqli_driver.hx


Niektoré súbory nie sú zobrazené, pretože je v týchto rozdielových dátach zmenené mnoho súborov