Explorar o código

Merge remote-tracking branch 'upstream/master' into intmap_iterator

SmerkyG %!s(int64=10) %!d(string=hai) anos
pai
achega
f4e2449fd3
Modificáronse 100 ficheiros con 6413 adicións e 4033 borrados
  1. 3 3
      .travis.yml
  2. 11 0
      CONTRIBUTING.md
  3. 11 13
      Makefile
  4. 1 1
      Makefile.win
  5. 10 8
      README.md
  6. 333 109
      analyzer.ml
  7. 4 5
      appveyor.yml
  8. 23 2
      ast.ml
  9. 127 32
      codegen.ml
  10. 70 43
      common.ml
  11. 150 15
      dce.ml
  12. 48 4
      extra/CHANGES.txt
  13. 0 4
      extra/ImportAll.hx
  14. 0 7
      extra/all.hxml
  15. 2 2
      extra/extract.hxml
  16. 1 1
      extra/haxelib_src
  17. 20 7
      extra/release-checklist.txt
  18. 1 1
      extra/release.neko
  19. 113 32
      filters.ml
  20. 14 2
      genas3.ml
  21. 318 138
      gencommon.ml
  22. 308 133
      gencpp.ml
  23. 437 192
      gencs.ml
  24. 377 175
      genjava.ml
  25. 48 34
      genjs.ml
  26. 12 2
      genneko.ml
  27. 1 9
      genphp.ml
  28. 396 217
      genpy.ml
  29. 3 35
      genswf.ml
  30. 0 1590
      genswf8.ml
  31. 36 12
      genswf9.ml
  32. 11 3
      genxml.ml
  33. 7 0
      haxe.hxproj
  34. 115 66
      interp.ml
  35. 1 1
      libs
  36. 96 49
      main.ml
  37. 11 7
      matcher.ml
  38. 151 52
      optimizer.ml
  39. 108 44
      parser.ml
  40. 1 17
      std/Date.hx
  41. 1 1
      std/EReg.hx
  42. 4 10
      std/Math.hx
  43. 6 3
      std/StdTypes.hx
  44. 6 14
      std/StringTools.hx
  45. 33 24
      std/UInt.hx
  46. 5 0
      std/cpp/Callable.hx
  47. 13 0
      std/cpp/CastCharStar.hx
  48. 13 0
      std/cpp/ConstCharStar.hx
  49. 8 9
      std/cpp/Function.hx
  50. 32 5
      std/cpp/Lib.hx
  51. 424 0
      std/cpp/NativeXml.hx
  52. 0 15
      std/cpp/_std/Reflect.hx
  53. 356 0
      std/cpp/_std/haxe/Int64.hx
  54. 1 1
      std/cpp/_std/sys/FileSystem.hx
  55. 4 0
      std/cpp/abi/Abi.hx
  56. 4 0
      std/cpp/abi/CDecl.hx
  57. 4 0
      std/cpp/abi/FastCall.hx
  58. 4 0
      std/cpp/abi/StdCall.hx
  59. 4 0
      std/cpp/abi/ThisCall.hx
  60. 4 0
      std/cpp/abi/Winapi.hx
  61. 28 0
      std/cpp/cppia/Host.hx
  62. 229 0
      std/cpp/cppia/HostClasses.hx
  63. 1 1
      std/cpp/vm/Gc.hx
  64. 2 0
      std/cs/Boot.hx
  65. 100 0
      std/cs/Flags.hx
  66. 38 5
      std/cs/Lib.hx
  67. 49 3
      std/cs/NativeArray.hx
  68. 11 1
      std/cs/StdTypes.hx
  69. 37 29
      std/cs/_std/Array.hx
  70. 73 107
      std/cs/_std/Reflect.hx
  71. 32 86
      std/cs/_std/Std.hx
  72. 1 25
      std/cs/_std/Sys.hx
  73. 101 164
      std/cs/_std/Type.hx
  74. 163 89
      std/cs/_std/haxe/Int64.hx
  75. 4 0
      std/cs/_std/haxe/Resource.hx
  76. 9 2
      std/cs/_std/haxe/ds/IntMap.hx
  77. 10 3
      std/cs/_std/haxe/ds/ObjectMap.hx
  78. 10 4
      std/cs/_std/haxe/ds/StringMap.hx
  79. 17 10
      std/cs/_std/haxe/ds/WeakMap.hx2
  80. 1 1
      std/cs/_std/sys/FileSystem.hx
  81. 4 4
      std/cs/_std/sys/io/File.hx
  82. 217 12
      std/cs/internal/FieldLookup.hx
  83. 16 2
      std/cs/internal/Function.hx
  84. 55 15
      std/cs/internal/HxObject.hx
  85. 317 198
      std/cs/internal/Runtime.hx
  86. 93 112
      std/cs/internal/StringExt.hx
  87. 15 6
      std/cs/io/NativeInput.hx
  88. 0 1
      std/flash/Boot.hx
  89. 421 0
      std/flash/NativeXml.hx
  90. 2 2
      std/flash/_std/haxe/ds/StringMap.hx
  91. 1 0
      std/flash/display/Stage.hx
  92. 8 1
      std/flash/display3D/Context3D.hx
  93. 1 1
      std/flash/display3D/Context3DBufferUsage.hx
  94. 6 0
      std/flash/display3D/Context3DFillMode.hx
  95. 1 0
      std/flash/display3D/Context3DProfile.hx
  96. 9 0
      std/flash/display3D/textures/VideoTexture.hx
  97. 8 0
      std/flash/events/AVDictionaryDataEvent.hx
  98. 9 0
      std/flash/events/AVHTTPStatusEvent.hx
  99. 7 0
      std/flash/events/AVPauseAtPeriodEndEvent.hx
  100. 2 0
      std/flash/events/AVStatusEvent.hx

+ 3 - 3
.travis.yml

@@ -31,13 +31,13 @@ before_script:
 
 install:
   - if [ -z "${TRAVIS_OS_NAME}" ]; then export TRAVIS_OS_NAME=linux; fi; # for our forks that do not have mult-os enabled.
-  - if [ "${TRAVIS_OS_NAME}" = "linux" ]; then travis_retry sudo apt-get update -qq; travis_retry sudo apt-get install ocaml zlib1g-dev libgc-dev -qq; fi
-  - if [ "${TRAVIS_OS_NAME}" = "osx" ]; then travis_retry brew update; travis_retry brew install phinze/cask/brew-cask; travis_retry brew install ocaml camlp4; fi
+  - if [ "${TRAVIS_OS_NAME}" = "linux" ]; then travis_retry sudo apt-get update -qq; travis_retry sudo apt-get install ocaml-native-compilers zlib1g-dev libgc-dev -qq; fi
+  - if [ "${TRAVIS_OS_NAME}" = "osx" ]; then travis_retry brew update; travis_retry brew install caskroom/cask/brew-cask; travis_retry brew install ocaml camlp4; fi
   - if [ "${TRAVIS_OS_NAME}" = "linux" ]; then travis_retry git clone https://github.com/HaxeFoundation/neko.git ~/neko && cd ~/neko && make os=${TRAVIS_OS_NAME} -s && sudo make install -s && cd $TRAVIS_BUILD_DIR; fi
   - if [ "${TRAVIS_OS_NAME}" = "osx" ]; then travis_retry brew install neko --HEAD; fi
 
 script:
-  - make -s
+  - make OCAMLOPT=ocamlopt.opt -s
   - make tools -s
   - sudo make install -s
   - cd tests/

+ 11 - 0
CONTRIBUTING.md

@@ -0,0 +1,11 @@
+Things to check before/while filing an issue:
+
+- Reduce your code to a minimal example (see http://sscce.org/). In particular avoid library dependencies: If you cannot reproduce your issue without using a specific library, it might not be a Haxe issue to begin with.
+- Check if your problems are already resolved in the Haxe development version (for builds see http://builds.haxe.org/).
+- Most targets produce readable code. If you suspect the generated code to be wrong, try checking the output. Note that you can add `-D dump=pretty` to your compilation parameters and find the code which is passed to the generators in a `dump` sub directory.
+
+Other remarks:
+
+- Sometimes people try to be particularly helpful by not only including broken parts in their code, but also "similar" code which is working. More often than not this is more distracting than helpful. If you want to highlight something like this, consider adding the working code commented out.
+- We do not require a classic "What do you see/what do you expect?" form, but in some cases it is hard to figure out where you think the actual problem is otherwise.
+- We're keeping this page quite short so there's a higher chance that people actually read it.

+ 11 - 13
Makefile

@@ -26,7 +26,7 @@ LIBS=unix str libs/extlib/extLib libs/xml-light/xml-light libs/swflib/swflib \
 	libs/extc/extc libs/neko/neko libs/javalib/java libs/ziplib/zip \
 	libs/ttflib/ttf libs/ilib/il libs/objsize/objsize
 
-NATIVE_LIBS=-cclib libs/extc/extc_stubs.o -cclib -lz -cclib libs/objsize/c_objsize.o
+NATIVE_LIBS=-cclib libs/extc/extc_stubs.o -cclib libs/extc/process_stubs.o -cclib -lz -cclib libs/objsize/c_objsize.o
 
 ifeq ($(BYTECODE),1)
 	TARGET_FLAG = bytecode
@@ -48,7 +48,7 @@ CC_PARSER_CMD = $(COMPILER) -pp camlp4o $(CFLAGS) -c parser.ml
 RELDIR=../../..
 
 MODULES=ast type lexer common genxml parser typecore optimizer typeload \
-	codegen gencommon genas3 gencpp genjs genneko genphp genswf8 \
+	codegen gencommon genas3 gencpp genjs genneko genphp \
 	genswf9 genswf genjava gencs genpy interp dce analyzer filters typer matcher version main
 
 ADD_REVISION=0
@@ -120,7 +120,7 @@ analyzer.$(MODULE_EXT): ast.$(MODULE_EXT) type.$(MODULE_EXT) common.$(MODULE_EXT
 
 codegen.$(MODULE_EXT): optimizer.$(MODULE_EXT) typeload.$(MODULE_EXT) typecore.$(MODULE_EXT) type.$(MODULE_EXT) genxml.$(MODULE_EXT) common.$(MODULE_EXT) ast.$(MODULE_EXT)
 
-common.$(MODULE_EXT): type.$(MODULE_EXT) ast.$(MODULE_EXT)
+common.$(MODULE_EXT): type.$(MODULE_EXT) ast.$(MODULE_EXT) libs/ilib/il.$(LIB_EXT)
 
 dce.$(MODULE_EXT): ast.$(MODULE_EXT) common.$(MODULE_EXT) codegen.$(MODULE_EXT) type.$(MODULE_EXT)
 
@@ -128,11 +128,11 @@ filters.$(MODULE_EXT): ast.$(MODULE_EXT) analyzer.$(MODULE_EXT) common.$(MODULE_
 
 genas3.$(MODULE_EXT): type.$(MODULE_EXT) common.$(MODULE_EXT) codegen.$(MODULE_EXT) ast.$(MODULE_EXT)
 
-gencommon.$(MODULE_EXT): type.$(MODULE_EXT) common.$(MODULE_EXT) codegen.$(MODULE_EXT) ast.$(MODULE_EXT)
+gencommon.$(MODULE_EXT): type.$(MODULE_EXT) common.$(MODULE_EXT) codegen.$(MODULE_EXT) ast.$(MODULE_EXT) libs/ilib/il.$(LIB_EXT)
 
-gencpp.$(MODULE_EXT): type.$(MODULE_EXT) lexer.$(MODULE_EXT) common.$(MODULE_EXT) codegen.$(MODULE_EXT) ast.$(MODULE_EXT)
+gencpp.$(MODULE_EXT): type.$(MODULE_EXT) lexer.$(MODULE_EXT) common.$(MODULE_EXT) codegen.$(MODULE_EXT) ast.$(MODULE_EXT) gencommon.$(MODULE_EXT)
 
-gencs.$(MODULE_EXT): type.$(MODULE_EXT) lexer.$(MODULE_EXT) gencommon.$(MODULE_EXT) common.$(MODULE_EXT) codegen.$(MODULE_EXT) ast.$(MODULE_EXT)
+gencs.$(MODULE_EXT): type.$(MODULE_EXT) lexer.$(MODULE_EXT) gencommon.$(MODULE_EXT) common.$(MODULE_EXT) codegen.$(MODULE_EXT) ast.$(MODULE_EXT) libs/ilib/il.$(LIB_EXT)
 
 genjava.$(MODULE_EXT): type.$(MODULE_EXT) gencommon.$(MODULE_EXT) common.$(MODULE_EXT) codegen.$(MODULE_EXT) ast.$(MODULE_EXT)
 
@@ -144,19 +144,17 @@ genphp.$(MODULE_EXT): type.$(MODULE_EXT) lexer.$(MODULE_EXT) common.$(MODULE_EXT
 
 genpy.$(MODULE_EXT): type.$(MODULE_EXT) lexer.$(MODULE_EXT) common.$(MODULE_EXT) codegen.$(MODULE_EXT) ast.$(MODULE_EXT)
 
-genswf.$(MODULE_EXT): type.$(MODULE_EXT) genswf9.$(MODULE_EXT) genswf8.$(MODULE_EXT) common.$(MODULE_EXT) ast.$(MODULE_EXT)
+genswf.$(MODULE_EXT): type.$(MODULE_EXT) genswf9.$(MODULE_EXT) common.$(MODULE_EXT) ast.$(MODULE_EXT)
 
-genswf8.$(MODULE_EXT): type.$(MODULE_EXT) lexer.$(MODULE_EXT) common.$(MODULE_EXT) codegen.$(MODULE_EXT) ast.$(MODULE_EXT)
-
-genswf9.$(MODULE_EXT): type.$(MODULE_EXT) lexer.$(MODULE_EXT) genswf8.$(MODULE_EXT) common.$(MODULE_EXT) codegen.$(MODULE_EXT) ast.$(MODULE_EXT)
+genswf9.$(MODULE_EXT): type.$(MODULE_EXT) lexer.$(MODULE_EXT) common.$(MODULE_EXT) codegen.$(MODULE_EXT) ast.$(MODULE_EXT)
 
 genxml.$(MODULE_EXT): type.$(MODULE_EXT) lexer.$(MODULE_EXT) common.$(MODULE_EXT) ast.$(MODULE_EXT)
 
-interp.$(MODULE_EXT): typecore.$(MODULE_EXT) type.$(MODULE_EXT) lexer.$(MODULE_EXT) genneko.$(MODULE_EXT) common.$(MODULE_EXT) codegen.$(MODULE_EXT) ast.$(MODULE_EXT) genswf.$(MODULE_EXT) genjava.$(MODULE_EXT) gencs.$(MODULE_EXT) parser.$(MODULE_EXT)
+interp.$(MODULE_EXT): typecore.$(MODULE_EXT) type.$(MODULE_EXT) lexer.$(MODULE_EXT) genneko.$(MODULE_EXT) common.$(MODULE_EXT) codegen.$(MODULE_EXT) ast.$(MODULE_EXT) genswf.$(MODULE_EXT) genjava.$(MODULE_EXT) gencs.$(MODULE_EXT) parser.$(MODULE_EXT) libs/ilib/il.$(LIB_EXT)
 
 matcher.$(MODULE_EXT): optimizer.$(MODULE_EXT) codegen.$(MODULE_EXT) typecore.$(MODULE_EXT) type.$(MODULE_EXT) typer.$(MODULE_EXT) common.$(MODULE_EXT) ast.$(MODULE_EXT)
 
-main.$(MODULE_EXT): filters.$(MODULE_EXT) matcher.$(MODULE_EXT) typer.$(MODULE_EXT) typeload.$(MODULE_EXT) typecore.$(MODULE_EXT) type.$(MODULE_EXT) parser.$(MODULE_EXT) optimizer.$(MODULE_EXT) lexer.$(MODULE_EXT) interp.$(MODULE_EXT) genxml.$(MODULE_EXT) genswf.$(MODULE_EXT) genphp.$(MODULE_EXT) genneko.$(MODULE_EXT) genjs.$(MODULE_EXT) gencpp.$(MODULE_EXT) genas3.$(MODULE_EXT) common.$(MODULE_EXT) codegen.$(MODULE_EXT) ast.$(MODULE_EXT) gencommon.$(MODULE_EXT) genjava.$(MODULE_EXT) gencs.$(MODULE_EXT) genpy.$(MODULE_EXT) version.$(MODULE_EXT)
+main.$(MODULE_EXT): filters.$(MODULE_EXT) matcher.$(MODULE_EXT) typer.$(MODULE_EXT) typeload.$(MODULE_EXT) typecore.$(MODULE_EXT) type.$(MODULE_EXT) parser.$(MODULE_EXT) optimizer.$(MODULE_EXT) lexer.$(MODULE_EXT) interp.$(MODULE_EXT) genxml.$(MODULE_EXT) genswf.$(MODULE_EXT) genphp.$(MODULE_EXT) genneko.$(MODULE_EXT) genjs.$(MODULE_EXT) gencpp.$(MODULE_EXT) genas3.$(MODULE_EXT) common.$(MODULE_EXT) codegen.$(MODULE_EXT) ast.$(MODULE_EXT) gencommon.$(MODULE_EXT) genjava.$(MODULE_EXT) gencs.$(MODULE_EXT) genpy.$(MODULE_EXT) version.$(MODULE_EXT) libs/ilib/il.$(LIB_EXT)
 
 optimizer.$(MODULE_EXT): typecore.$(MODULE_EXT) type.$(MODULE_EXT) parser.$(MODULE_EXT) common.$(MODULE_EXT) ast.$(MODULE_EXT)
 
@@ -169,7 +167,7 @@ typecore.$(MODULE_EXT): type.$(MODULE_EXT) common.$(MODULE_EXT) ast.$(MODULE_EXT
 
 typeload.$(MODULE_EXT): typecore.$(MODULE_EXT) type.$(MODULE_EXT) parser.$(MODULE_EXT) optimizer.$(MODULE_EXT) lexer.$(MODULE_EXT) common.$(MODULE_EXT) ast.$(MODULE_EXT)
 
-typer.$(MODULE_EXT): typeload.$(MODULE_EXT) typecore.$(MODULE_EXT) type.$(MODULE_EXT) parser.$(MODULE_EXT) optimizer.$(MODULE_EXT) lexer.$(MODULE_EXT) interp.$(MODULE_EXT) genneko.$(MODULE_EXT) genjs.$(MODULE_EXT) common.$(MODULE_EXT) codegen.$(MODULE_EXT) ast.$(MODULE_EXT) filters.$(MODULE_EXT)
+typer.$(MODULE_EXT): typeload.$(MODULE_EXT) typecore.$(MODULE_EXT) type.$(MODULE_EXT) parser.$(MODULE_EXT) optimizer.$(MODULE_EXT) lexer.$(MODULE_EXT) interp.$(MODULE_EXT) genneko.$(MODULE_EXT) genjs.$(MODULE_EXT) common.$(MODULE_EXT) codegen.$(MODULE_EXT) ast.$(MODULE_EXT) filters.$(MODULE_EXT) gencommon.$(MODULE_EXT)
 
 lexer.$(MODULE_EXT): lexer.ml
 

+ 1 - 1
Makefile.win

@@ -24,7 +24,7 @@ endif
 # use make MSVC=1 -f Makefile.win to build for OCaml/MSVC
 
 ifeq (${MSVC}, 1)
-NATIVE_LIBS = shell32.lib libs/extc/extc_stubs.obj libs/extc/zlib/zlib.lib libs/objsize/c_objsize.obj
+NATIVE_LIBS = shell32.lib libs/extc/extc_stubs.obj libs/extc/process_stubs.obj libs/extc/zlib/zlib.lib libs/objsize/c_objsize.obj
 endif
 
 ifeq (${MSVC_OUTPUT}, 1)

+ 10 - 8
README.md

@@ -1,7 +1,7 @@
 
 # [<img src="http://haxe.org/img/haxe-logo-horizontal.svg" alt="Haxe logo" width="140">](http://haxe.org) - [The Cross-Platform Toolkit](http://haxe.org)
 [![TravisCI Build Status](https://travis-ci.org/HaxeFoundation/haxe.svg?branch=development)](https://travis-ci.org/HaxeFoundation/haxe)
-[![AppVeyor Build Status](https://ci.appveyor.com/api/projects/status/github/HaxeFoundation/haxe?branch=development&svg=true)](https://ci.appveyor.com/project/Simn/haxe)
+[![AppVeyor Build Status](https://ci.appveyor.com/api/projects/status/github/HaxeFoundation/haxe?branch=development&svg=true)](https://ci.appveyor.com/project/HaxeFoundation/haxe)
 [![SauceLabs Test Status](https://saucelabs.com/buildstatus/haxe)](https://saucelabs.com/u/haxe)
 [![Gitter](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/HaxeFoundation/haxe?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge)
 
@@ -13,6 +13,7 @@ Haxe is an open source toolkit that allows you to easily build cross-platform to
 
 Haxe allows you to compile for the following targets:
 
+ * ActionScript 3
  * C++
  * C#
  * Flash
@@ -20,6 +21,7 @@ Haxe allows you to compile for the following targets:
  * JavaScript
  * NekoVM
  * PHP
+ * Python
 
 You can try Haxe directly from your browser at [try.haxe.org](http://try.haxe.org)!
 
@@ -37,14 +39,14 @@ For the complete Haxe licenses, please see http://haxe.org/foundation/open-sourc
 
 ## Installing Haxe
 
-The latest stable release is [Haxe v3.1.3](http://haxe.org/download). Pre-built binaries are available for your platform:
+The latest stable release is [Haxe 3.2.0-rc1](http://haxe.org/download). Pre-built binaries are available for your platform:
 
- * **[Windows installer](http://haxe.org/file/haxe-3.1.3-win.exe)**
- * **[Windows binaries](http://haxe.org/file/haxe-3.1.3-win.zip)**
- * **[OSX installer](http://haxe.org/file/haxe-3.1.3-osx-installer.pkg)**
- * **[OSX binaries](http://haxe.org/file/haxe-3.1.3-osx.tar.gz)**
- * **[Linux 32-bit binaries](http://haxe.org/file/haxe-3.1.3-linux32.tar.gz)**
- * **[Linux 64-bit binaries](http://haxe.org/file/haxe-3.1.3-linux64.tar.gz)**
+ * **[Windows installer](http://haxe.org/download/file/3.2.0-rc.1/haxe-3.2.0-rc1-win.exe)**
+ * **[Windows binaries](http://haxe.org/download/file/3.2.0-rc.1/haxe-3.2.0-rc1-win.zip)**
+ * **[OSX installer](http://haxe.org/download/file/3.2.0-rc.1/haxe-3.2.0-rc1-osx-installer.pkg)**
+ * **[OSX binaries](http://haxe.org/download/file/3.2.0-rc.1/haxe-3.2.0-rc1-osx.tar.gz)**
+ * **[Linux 32-bit binaries](http://haxe.org/download/file/3.2.0-rc.1/haxe-3.2.0-rc1-linux32.tar.gz)**
+ * **[Linux 64-bit binaries](http://haxe.org/download/file/3.2.0-rc.1/haxe-3.2.0-rc1-linux64.tar.gz)**
 
 Automated development builds are available from [build.haxe.org](http://build.haxe.org).
 

+ 333 - 109
analyzer.ml

@@ -3,8 +3,6 @@ open Type
 open Common
 open Typecore
 
-module IntMap = Map.Make(struct type t = int let compare a b = a - b end)
-
 let s_expr = s_expr (s_type (print_context()))
 let s_expr_pretty = s_expr_pretty "" (s_type (print_context()))
 let debug e = print_endline (s_expr e)
@@ -42,6 +40,29 @@ let has_analyzer_option meta s =
 	with Not_found ->
 		false
 
+let is_ignored meta =
+	try
+		let rec loop ml = match ml with
+			| (Meta.Analyzer,el,_) :: ml ->
+				if List.exists (fun (e,p) ->
+					match e with
+						| EConst(Ident s2) when flag_ignore = s2 -> true
+						| _ -> false
+				) el then
+					true
+				else
+					loop ml
+			| (Meta.HasUntyped,_,_) :: _ ->
+				true
+			| _ :: ml ->
+				loop ml
+			| [] ->
+				false
+		in
+		loop meta
+	with Not_found ->
+		false
+
 let rec get_type_meta t = match t with
 	| TMono r ->
 		begin match !r with
@@ -89,7 +110,7 @@ let rec awkward_get_enum_index com e = match e.eexpr with
 	nodes without worrying about their placement.
 *)
 module Simplifier = struct
-	let mk_block_context com gen_temp =
+	let mk_block_context com =
 		let block_el = ref [] in
 		let push e = block_el := e :: !block_el in
 		let assign ev e =
@@ -138,7 +159,7 @@ module Simplifier = struct
 			loop e
 		in
 		let declare_temp t eo p =
-			let v = gen_temp t in
+			let v = alloc_var "tmp" t in
 			v.v_meta <- [Meta.CompilerGenerated,[],p];
 			let e_v = mk (TLocal v) t p in
 			let declare e_init =
@@ -192,8 +213,8 @@ module Simplifier = struct
 		in
 		block,declare_temp,fun () -> !block_el
 
-	let apply com gen_temp e =
-		let block,declare_temp,close_block = mk_block_context com gen_temp in
+	let apply com e =
+		let block,declare_temp,close_block = mk_block_context com in
 		let skip_binding ?(allow_tlocal=false) e =
 			let rec loop e =
 				match e.eexpr with
@@ -203,6 +224,7 @@ module Simplifier = struct
 				| TField(_,(FStatic(c,cf) | FInstance(c,_,cf))) when has_analyzer_option cf.cf_meta flag_no_simplification || has_analyzer_option c.cl_meta flag_no_simplification -> ()
 				| TField({eexpr = TLocal _},_) when allow_tlocal -> ()
 				| TCall({eexpr = TField(_,(FStatic(c,cf) | FInstance(c,_,cf)))},el) when has_analyzer_option cf.cf_meta flag_no_simplification || has_analyzer_option c.cl_meta flag_no_simplification -> ()
+				| TCall({eexpr =  TLocal { v_name = "__cpp__" } },_) -> ()
 				| TField(_,FEnum _) -> ()
 				| TField(_,FDynamic _) -> ()
 				| _ when (try ignore(awkward_get_enum_index com e); true with Not_found -> false) -> ()
@@ -388,16 +410,30 @@ module Simplifier = struct
 		let rec get_assignment_to v e = match e.eexpr with
 			| TBinop(OpAssign,{eexpr = TLocal v2},e2) when v == v2 -> Some e2
 			| TBlock [e] -> get_assignment_to v e
+			| TIf(e1,e2,Some e3) ->
+				begin match get_assignment_to v e2,get_assignment_to v e3 with
+				| Some e2,Some e3 -> Some ({e with eexpr = TIf(e1,e2,Some e3)})
+				| _ -> None
+				end
 			| _ -> None
 		in
+		let if_or_op e e1 e2 e3 = match e1.eexpr,e3.eexpr with
+			| TUnop(Not,Prefix,e1),TConst (TBool true) -> {e with eexpr = TBinop(OpBoolOr,e1,e2)}
+			| _,TConst (TBool false) -> {e with eexpr = TBinop(OpBoolAnd,e1,e2)}
+			| _ -> {e with eexpr = TIf(e1,e2,Some e3)}
+		in
 		let rec loop e = match e.eexpr with
 			| TBlock el ->
 				let rec loop2 el = match el with
 					| e :: el ->
 						begin match e.eexpr with
 							| TVar(v,Some e1) when Meta.has Meta.CompilerGenerated v.v_meta ->
-								var_map := IntMap.add v.v_id (loop e1) !var_map;
-								loop2 el
+								if el = [] then
+									[loop e1]
+								else begin
+									var_map := IntMap.add v.v_id (loop e1) !var_map;
+									loop2 el
+								end
 							| TVar(v,None) when not (com.platform = Php) ->
 								begin match el with
 									| {eexpr = TBinop(OpAssign,{eexpr = TLocal v2},e2)} :: el when v == v2 ->
@@ -409,7 +445,7 @@ module Simplifier = struct
 										let e3 = loop e3 in
 										begin match get_assignment_to v e2,get_assignment_to v e3 with
 											| Some e2,Some e3 ->
-												let e_if = {e_if with eexpr = TIf(e1,e2,Some e3)} in
+												let e_if = if_or_op e_if (loop e1) (loop e2) (loop e3) in
 												let e = {e with eexpr = TVar(v,Some e_if)} in
 												loop2 (e :: el)
 											| _ ->
@@ -420,6 +456,8 @@ module Simplifier = struct
 										let e = loop e in
 										e :: loop2 el
 								end
+							| TReturn (Some e1) when (match follow e1.etype with TAbstract({a_path=[],"Void"},_) -> true | _ -> false) ->
+								[(loop e1);{e with eexpr = TReturn None}]
 							| _ ->
 								let e = loop e in
 								e :: loop2 el
@@ -448,13 +486,15 @@ module Simplifier = struct
 									let e1 = extract_cond e1 in
 									e1,{e2 with eexpr = TBlock el},NormalWhile
 								| _ ->
-									begin match List.rev el with
+									e1,e2,flag
+									(* issue 3844 *)
+(* 									begin match List.rev el with
 										| {eexpr = TMeta((Meta.Custom ":whileCond",_,_),e1)} :: el ->
 											let e1 = extract_cond e1 in
 											e1,{e2 with eexpr = TBlock (List.rev el)},DoWhile
 										| _ ->
 											e1,e2,flag
-									end
+									end *)
 							end
 						| _ ->
 							e1,e2,flag
@@ -462,6 +502,11 @@ module Simplifier = struct
 						e1,e2,flag
 				in
 				{e with eexpr = TWhile(e1,e2,flag)}
+			| TIf(e1,e2,Some e3) ->
+				let e1 = loop e1 in
+				let e2 = loop e2 in
+				let e3 = loop e3 in
+				if_or_op e e1 e2 e3
 			| _ ->
 				Type.map_expr loop e
 		in
@@ -493,6 +538,7 @@ module Ssa = struct
 		mutable var_conds : (condition list) IntMap.t;
 		mutable loop_stack : (join_node * join_node) list;
 		mutable exception_stack : join_node list;
+		mutable block_depth : int;
 	}
 
 	let s_cond = function
@@ -561,42 +607,70 @@ module Ssa = struct
 			ctx.exception_stack <- List.tl ctx.exception_stack;
 		)
 
-	let get_origin_var v = match v.v_extra with
-		| Some (_,Some {eexpr = TArrayDecl ({eexpr = TLocal v'} :: _)}) -> v'
-		| _ -> raise Not_found
-
-	let set_origin_var v v_origin p =
-		let ev = mk_loc v_origin p in
-		let create tl =
-			let e_extra = mk (TArrayDecl [
-				ev
-			]) t_dynamic p in
-			v.v_extra <- Some (tl,Some e_extra)
-		in
+	let create_v_extra v =
 		match v.v_extra with
-		| Some (tl,Some ({eexpr = TArrayDecl (_ :: el)} as ee)) ->
-			v.v_extra <- Some(tl, Some {ee with eexpr = TArrayDecl (ev :: el)})
+		| Some (_,Some _) ->
+			()
 		| Some (tl,None) ->
-			create tl
+			let e_extra = mk (TObjectDecl []) t_dynamic null_pos in
+			v.v_extra <- Some (tl,Some e_extra)
 		| None ->
-			create []
+			let e_extra = mk (TObjectDecl []) t_dynamic null_pos in
+			v.v_extra <- Some ([],Some e_extra)
+
+	let set_v_extra_value v s e = match v.v_extra with
+		| Some (tl, Some {eexpr = TObjectDecl fl}) ->
+			let rec loop fl = match fl with
+				| (s',_) :: fl when s' = s ->
+					(s,e) :: fl
+				| f1 :: fl ->
+					f1 :: loop fl
+				| [] ->
+					[s,e]
+			in
+			let e_extra = mk (TObjectDecl (loop fl)) t_dynamic null_pos in
+			v.v_extra <- Some (tl, Some e_extra)
 		| _ ->
 			assert false
 
+	let get_origin_var v = match v.v_extra with
+		| Some (_,Some {eexpr = TObjectDecl fl}) ->
+			begin match List.assoc "origin_var" fl with
+				| {eexpr = TLocal v'} -> v'
+				| _ -> raise Not_found
+			end
+		| _ ->
+			raise Not_found
+
+	let set_origin_var v v_origin p =
+		let ev = mk_loc v_origin p in
+		set_v_extra_value v "origin_var" ev
+
 	let get_var_value v = match v.v_extra with
-		| Some (_,Some {eexpr = TArrayDecl (_ :: e :: _)}) -> e
-		| _ -> raise Not_found
+		| Some (_,Some {eexpr = TObjectDecl fl}) ->
+			List.assoc "var_value" fl
+		| _ ->
+			raise Not_found
 
 	let set_var_value v e =
-		match v.v_extra with
-		| Some (tl,Some ({eexpr = TArrayDecl (e1 :: el)} as ee)) ->
-			let el = match el with
-				| [] -> [e]
-				| _ :: el -> e :: el
-			in
-			v.v_extra <- Some (tl,Some {ee with eexpr = TArrayDecl (e1 :: el)})
+		set_v_extra_value v "var_value" e
+
+	let get_var_usage_count v = match v.v_extra with
+		| Some (_,Some {eexpr = TObjectDecl fl}) ->
+			begin try
+				begin match List.assoc "usage_count" fl with
+				| {eexpr = TConst (TInt i32)} -> Int32.to_int i32
+				| _ -> 0
+				end
+			with Not_found ->
+				0
+			end
 		| _ ->
-			assert false
+			raise Not_found
+
+	let set_var_usage_count v i =
+		let e = mk (TConst (TInt (Int32.of_int i))) t_dynamic null_pos in
+		set_v_extra_value v "usage_count" e
 
 	let declare_var ctx v p =
 		let old = v.v_extra in
@@ -604,6 +678,9 @@ module Ssa = struct
 			v.v_extra <- old
 		) :: ctx.cleanup;
 		ctx.cur_data.nd_var_map <- IntMap.add v.v_id v ctx.cur_data.nd_var_map;
+		v.v_meta <- ((Meta.Custom ":blockDepth",[EConst (Int (string_of_int ctx.block_depth)),p],p)) :: v.v_meta;
+		v.v_extra <- None;
+		create_v_extra v;
 		set_origin_var v v p
 
 	let assign_var ctx v e p =
@@ -618,6 +695,7 @@ module Ssa = struct
 					error "Something went wrong" p
 			in
 			let v' = alloc_var (Printf.sprintf "%s<%i>" v.v_name i) v.v_type in
+			create_v_extra v';
 			v'.v_meta <- [(Meta.Custom ":ssa"),[],p];
 			set_origin_var v' v p;
 			ctx.cur_data.nd_var_map <- IntMap.add v.v_id v' ctx.cur_data.nd_var_map;
@@ -630,7 +708,7 @@ module Ssa = struct
 			IntMap.find v.v_id ctx.cur_data.nd_var_map
 		with Not_found ->
 			if not (has_meta Meta.Unbound v.v_meta) then
-				ctx.com.warning (Printf.sprintf "Unbound variable %s" v.v_name) p;
+				error (Printf.sprintf "Unbound variable %s" v.v_name) p;
 			v
 
 	let close_join_node ctx node p =
@@ -697,7 +775,7 @@ module Ssa = struct
 			ctx.var_conds <- IntMap.add v.v_id [cond] ctx.var_conds
 		end
 
-	let apply_cond ctx = function
+(* 	let apply_cond ctx = function
 		| Equal({v_extra = Some(_,Some {eexpr = TLocal v})} as v0,e1) ->
 			let v' = assign_var ctx v (mk_loc v0 e1.epos) e1.epos in
 			append_cond ctx v' (Equal(v',e1)) e1.epos
@@ -707,34 +785,33 @@ module Ssa = struct
 		| _ -> ()
 
 	let apply_not_null_cond ctx v p =
-		apply_cond ctx (NotEqual(v,(mk (TConst TNull) t_dynamic p)))
+		apply_cond ctx (NotEqual(v,(mk (TConst TNull) t_dynamic p))) *)
 
 	let apply com e =
-		let rec handle_if ctx e econd eif eelse =
+		let rec handle_if ctx f econd eif eelse =
 			let econd = loop ctx econd in
-			let cond = eval_cond ctx econd in
+			(* let cond = eval_cond ctx econd in *)
 			let join = mk_join_node() in
 			let close = branch ctx eif.epos in
-			List.iter (apply_cond ctx) cond;
+			(* List.iter (apply_cond ctx) cond; *)
 			let eif = loop ctx eif in
 			close join;
 			let eelse = match eelse with
 				| None ->
-					let cond = invert_conds cond in
-					List.iter (apply_cond ctx) cond;
+					(* let cond = invert_conds cond in *)
+					(* List.iter (apply_cond ctx) cond; *)
 					add_branch join ctx.cur_data e.epos;
 					None
 				| Some e ->
 					let close = branch ctx e.epos in
-					let cond = invert_conds cond in
-					List.iter (apply_cond ctx) cond;
+					(* let cond = invert_conds cond in *)
+					(* List.iter (apply_cond ctx) cond; *)
 					let eelse = loop ctx e in
 					close join;
 					Some eelse
 			in
 			close_join_node ctx join e.epos;
-			let e = {e with eexpr = TIf(econd,eif,eelse)} in
-			e
+			f econd eif eelse
 		and handle_loop_body ctx e =
 			let join_top = mk_join_node() in
 			let join_bottom = mk_join_node() in
@@ -765,9 +842,9 @@ module Ssa = struct
 				let close = branch ctx e.epos in
 				List.iter (fun (v,co) ->
 					declare_var ctx v e.epos;
-					match co with
+(* 					match co with
 						| Some TNull when (match v.v_type with TType({t_path=["haxe"],"PosInfos"},_) -> false | _ -> true) -> ()
-						| _ -> apply_not_null_cond ctx v e.epos
+						| _ -> apply_not_null_cond ctx v e.epos *)
 				) tf.tf_args;
 				let e' = loop ctx tf.tf_expr in
 				close (mk_join_node());
@@ -796,7 +873,8 @@ module Ssa = struct
 				{e with eexpr = TLocal v}
 			(* control flow *)
 			| TIf(econd,eif,eelse) ->
-				handle_if ctx e econd eif eelse
+				let f econd eif eelse = {e with eexpr = TIf(econd,eif,eelse)} in
+				handle_if ctx f econd eif eelse
 			| TSwitch(e1,cases,edef) ->
 				let e1 = loop ctx e1 in
 				let join = mk_join_node() in
@@ -833,7 +911,7 @@ module Ssa = struct
 				e
 			| TFor(v,e1,ebody) ->
 				declare_var ctx v e.epos;
-				apply_not_null_cond ctx v e1.epos;
+				(* apply_not_null_cond ctx v e1.epos; *)
 				let v' = IntMap.find v.v_id ctx.cur_data.nd_var_map in
 				let e1 = loop ctx e1 in
 				let ebody = handle_loop_body ctx ebody in
@@ -849,7 +927,7 @@ module Ssa = struct
 				close_join_node ctx join_ex e.epos;
 				let catches = List.map (fun (v,e) ->
 					declare_var ctx v e.epos;
-					apply_not_null_cond ctx v e.epos;
+					(* apply_not_null_cond ctx v e.epos; *)
 					let close = branch ctx e.epos in
 					let e = loop ctx e in
 					close join_bottom;
@@ -896,7 +974,10 @@ module Ssa = struct
 							let e = loop ctx e in
 							e :: (loop2 el)
 				in
-				{e with eexpr = TBlock(loop2 el)}
+				ctx.block_depth <- ctx.block_depth + 1;
+				let el = loop2 el in
+				ctx.block_depth <- ctx.block_depth - 1;
+				{e with eexpr = TBlock(el)}
 			| _ ->
 				begin match ctx.exception_stack with
 					| join :: _ when can_throw e -> add_branch join ctx.cur_data e.epos
@@ -911,17 +992,20 @@ module Ssa = struct
 			loop_stack = [];
 			exception_stack = [];
 			cleanup = [];
+			block_depth = 0;
 		} in
 		let e = loop ctx e in
 		e,ctx
 
 	let unapply com e =
 		let rec loop e = match e.eexpr with
-			| TFor(({v_extra = Some([],Some {eexpr = TArrayDecl ({eexpr = TLocal v'} :: _)})} as v),e1,e2) when Meta.has (Meta.Custom ":ssa") v.v_meta ->
+			| TFor(v,e1,e2) when Meta.has (Meta.Custom ":ssa") v.v_meta ->
+				let v' = get_origin_var v in
 				let e1 = loop e1 in
 				let e2 = loop e2 in
 				{e with eexpr = TFor(v',e1,e2)}
-			| TLocal ({v_extra = Some([],Some {eexpr = TArrayDecl ({eexpr = TLocal v'} :: _)})} as v) when Meta.has (Meta.Custom ":ssa") v.v_meta ->
+			| TLocal v when Meta.has (Meta.Custom ":ssa") v.v_meta ->
+				let v' = get_origin_var v in
 				{e with eexpr = TLocal v'}
 			| TBlock el ->
 				let rec filter e = match e.eexpr with
@@ -948,7 +1032,16 @@ module ConstPropagation = struct
 		| _ ->
 			false
 
-	let can_be_inlined com e = match e.eexpr with
+	let get_block_depth v = try
+		let i = match Meta.get (Meta.Custom ":blockDepth") v.v_meta with
+			| _,[EConst(Int s),_],_ -> int_of_string s
+			| _ -> raise Not_found
+		in
+		i
+		with Not_found ->
+			-1
+
+	let can_be_inlined com v0 e = type_iseq v0.v_type e.etype && match e.eexpr with
 		| TConst ct ->
 			begin match ct with
 				| TThis | TSuper -> false
@@ -957,6 +1050,19 @@ module ConstPropagation = struct
 				| TNull when (match com.platform with Php | Cpp -> true | _ -> false) -> false
 				| _ -> true
 			end
+		| TLocal v ->
+			not (Meta.has Meta.CompilerGenerated v.v_meta) &&
+			begin try
+				let v' = Ssa.get_origin_var v in
+				begin match v'.v_extra with
+					| Some ([],_) -> get_block_depth v <= get_block_depth v0
+					| _ -> false
+				end
+			with Not_found ->
+				false
+			end
+		| TEnumParameter _ when not (com.platform = Php) ->
+			Ssa.get_var_usage_count v0 <= 1
 		| _ ->
 			false
 
@@ -964,7 +1070,7 @@ module ConstPropagation = struct
 		| TCall({eexpr = TField(_,FEnum _)},el) -> (try List.nth el i with Failure _ -> raise Not_found)
 		| _ -> raise Not_found
 
-	let rec local ssa v e =
+	let rec local ssa force v e =
 		begin try
 			if v.v_capture then raise Not_found;
 			if type_has_analyzer_option v.v_type flag_no_const_propagation then raise Not_found;
@@ -975,7 +1081,7 @@ module ConstPropagation = struct
 			let e = Ssa.get_var_value v in
 			let old = v.v_extra in
 			v.v_extra <- None;
-			let e = value ssa e in
+			let e = value ssa force e in
 			v.v_extra <- old;
 			Ssa.set_var_value v e;
 			e
@@ -983,59 +1089,74 @@ module ConstPropagation = struct
 			e
 		end
 
-	and value ssa e = match e.eexpr with
+	(* force must only be true if the value is not used in the output *)
+	and value ssa force e = match e.eexpr with
 		| TUnop((Increment | Decrement),_,_)
 		| TBinop(OpAssignOp _,_,_)
 		| TBinop(OpAssign,_,_) ->
 			e
 		| TBinop(op,e1,e2) ->
-			let e1 = value ssa e1 in
-			let e2 = value ssa e2 in
+			let e1 = value ssa force e1 in
+			let e2 = value ssa force e2 in
 			let e = {e with eexpr = TBinop(op,e1,e2)} in
 			let e' = Optimizer.optimize_binop e op e1 e2 in
 			if e == e' then
 				e
 			else
-				value ssa e'
+				value ssa force e'
 		| TUnop(op,flag,e1) ->
-			let e1 = value ssa e1 in
+			let e1 = value ssa force e1 in
 			let e = {e with eexpr = TUnop(op,flag,e1)} in
 			let e' = Optimizer.optimize_unop e op flag e1 in
 			if e == e' then
 				e
 			else
-				value ssa e'
-		| TCall (({eexpr = TLocal {v_name = "__ssa_phi__"}}),el) ->
-			let el = List.map (value ssa) el in
+				value ssa force e'
+		| TCall (({eexpr = TLocal {v_name = "__ssa_phi__"}} as ephi),el) ->
+			let el = List.map (value ssa force) el in
 			begin match el with
 				| [] -> assert false
 				| e1 :: el ->
 					if List.for_all (fun e2 -> expr_eq e1 e2) el then
-						value ssa e1
+						value ssa force e1
 					else
-						{e with eexpr = TCall(e1,el)}
+						{e with eexpr = TCall(ephi, e1 :: el)}
 			end
 		| TParenthesis e1 | TMeta(_,e1) ->
-			value ssa e1
+			value ssa force e1
 		| TLocal v ->
-			local ssa v e
+			let e' = local ssa force v e in
+			if force || can_be_inlined ssa.com v e' then
+				e'
+			else
+				e
  		| TEnumParameter(e1,ef,i) ->
-			let ev = value ssa e1 in
-			begin try semi_awkward_enum_value ssa ev i
-			with Not_found -> e end
+			let ev = value ssa true e1 in
+			begin try
+				value ssa force (semi_awkward_enum_value ssa ev i)
+			with Not_found ->
+				e
+			end
 		| _ ->
 			e
 
 	(* TODO: the name is quite accurate *)
 	let awkward_get_enum_index ssa e =
 		let e = awkward_get_enum_index ssa.com e in
-		let ev = (value ssa e) in
+		let ev = (value ssa true e) in
 		match ev.eexpr with
 			| TField(_,FEnum(_,ef)) -> TInt (Int32.of_int ef.ef_index)
 			| TCall({eexpr = TField(_,FEnum(_,ef))},_) -> TInt (Int32.of_int ef.ef_index)
 			| _ -> raise Not_found
 
 	let apply ssa e =
+		let rec loop e = match e.eexpr with
+			| TLocal v when not (Meta.has Meta.Unbound v.v_meta) ->
+				set_var_usage_count v (get_var_usage_count v + 1);
+			| _ ->
+				Type.iter loop e
+		in
+		loop e;
 		let had_function = ref false in
 		let rec loop e = match e.eexpr with
 			| TFunction _ when !had_function ->
@@ -1044,8 +1165,8 @@ module ConstPropagation = struct
 				had_function := true;
 				{e with eexpr = TFunction {tf with tf_expr = loop tf.tf_expr}}
 			| TLocal v ->
-				let e' = local ssa v e in
-				if can_be_inlined ssa.com e' then
+				let e' = local ssa false v e in
+				if can_be_inlined ssa.com v e' then
 					e'
 				else
 					e
@@ -1059,6 +1180,15 @@ module ConstPropagation = struct
 				in
 				let el = Codegen.UnificationCallback.check_call check el e1.etype in
 				{e with eexpr = TCall(e1,el)}
+(* 			| TField(e1,fa) ->
+				let e1' = loop e1 in
+				let fa = if e1' != e1 then
+					begin try quick_field e1'.etype (field_name fa)
+					with Not_found -> fa end
+				else
+					fa
+				in
+				{e with eexpr = TField(e1',fa)} *)
 			| TUnop((Increment | Decrement),_,_) ->
 				e
 			| TBinop(OpAssignOp op,e1,e2) ->
@@ -1137,7 +1267,7 @@ module EffectChecker = struct
 		in
 		let e = if is_var_expression then
 			(* var initialization expressions are like assignments, so let's cheat a bit here *)
-			snd (Simplifier.apply com (alloc_var "tmp") (Codegen.binop OpAssign (mk (TConst TNull) t_dynamic e.epos) e e.etype e.epos))
+			snd (Simplifier.apply com (Codegen.binop OpAssign (mk (TConst TNull) t_dynamic e.epos) e e.etype e.epos))
 		else e
 		in
 		let rec loop e = match e.eexpr with
@@ -1239,15 +1369,96 @@ module Checker = struct
 		loop e;
 end
 
+let rec lrev_iter f el = match el with
+	| e :: el ->
+		lrev_iter f el;
+		f e
+	| [] ->
+		()
+
+let rev_iter f e = match e.eexpr with
+	| TConst _
+	| TLocal _
+	| TBreak
+	| TContinue
+	| TTypeExpr _ ->
+		()
+	| TArray (e1,e2)
+	| TBinop (_,e1,e2)
+	| TFor (_,e1,e2)
+	| TWhile (e1,e2,_) ->
+		f e2;
+		f e1;
+	| TThrow e
+	| TField (e,_)
+	| TEnumParameter (e,_,_)
+	| TParenthesis e
+	| TCast (e,_)
+	| TUnop (_,_,e)
+	| TMeta(_,e) ->
+		f e
+	| TArrayDecl el
+	| TNew (_,_,el)
+	| TBlock el ->
+		lrev_iter f el
+	| TObjectDecl fl ->
+		lrev_iter (fun (_,e) -> f e) fl
+	| TCall (e,el) ->
+		f e;
+		lrev_iter f el
+	| TVar (v,eo) ->
+		(match eo with None -> () | Some e -> f e)
+	| TFunction fu ->
+		f fu.tf_expr
+	| TIf (e,e1,e2) ->
+		(match e2 with None -> () | Some e -> f e);
+		f e1;
+		f e;
+	| TSwitch (e,cases,def) ->
+		(match def with None -> () | Some e -> f e);
+		lrev_iter (fun (el,e2) -> lrev_iter f el; f e2) cases;
+		f e;
+	| TTry (e,catches) ->
+		lrev_iter (fun (_,e) -> f e) catches;
+		f e;
+	| TReturn eo ->
+		(match eo with None -> () | Some e -> f e)
+
 module LocalDce = struct
 	let apply e =
-		let is_used v = Meta.has Meta.Used v.v_meta || type_has_analyzer_option v.v_type flag_no_local_dce in
-		let use v = v.v_meta <- (Meta.Used,[],Ast.null_pos) :: v.v_meta in
-		let has_side_effect e = match e.eexpr with
-			| TVar(v,None) -> is_used v
-			| TVar(v,Some e1) -> is_used v || Optimizer.has_side_effect e1
-			| TBinop(OpAssign,{eexpr = TLocal v},e2) -> is_used v || Optimizer.has_side_effect e2
-			| _ -> Optimizer.has_side_effect e
+		let is_used v = Meta.has Meta.Used v.v_meta || type_has_analyzer_option v.v_type flag_no_local_dce || v.v_capture in
+		let is_ref_type t = match t with
+			| TType({t_path = ["cs"],("Ref" | "Out")},_) -> true
+			| _ -> false
+		in
+		let rec use v =
+			if not (Meta.has Meta.Used v.v_meta) then begin
+				v.v_meta <- (Meta.Used,[],Ast.null_pos) :: v.v_meta;
+				try use (Ssa.get_origin_var v) with Not_found -> ()
+			end
+		in
+		let rec has_side_effect e =
+			let rec loop e =
+				match e.eexpr with
+				| TLocal v when Meta.has Meta.CompilerGenerated v.v_meta -> (try loop (Ssa.get_var_value v) with Not_found -> ())
+				| TBinop((OpAssign | OpAssignOp _),{eexpr = TLocal v},e2) when is_used v || has_side_effect e2 || is_ref_type v.v_type -> raise Exit
+				| TVar(v,None) when is_used v -> raise Exit
+				| TVar(v,Some e1) when is_used v || has_side_effect e1 -> raise Exit
+				| TConst _ | TLocal _ | TTypeExpr _ | TFunction _ -> ()
+				| TCall ({ eexpr = TField(_,FStatic({ cl_path = ([],"Std") },{ cf_name = "string" })) },args) -> Type.iter loop e
+				| TCall (({eexpr = TLocal {v_name = "__ssa_phi__"}}),el) -> ()
+				| TCall ({eexpr = TField(_,FEnum _)},_) -> Type.iter loop e
+				| TNew _ | TCall _ | TBinop ((OpAssignOp _ | OpAssign),_,_) | TUnop ((Increment|Decrement),_,_) -> raise Exit
+				| TReturn _ | TBreak | TContinue | TThrow _ | TCast (_,Some _) -> raise Exit
+				| TFor _ -> raise Exit
+				| TArray _ | TEnumParameter _ | TCast (_,None) | TBinop _ | TUnop _ | TParenthesis _ | TMeta _ | TWhile _
+				| TField _ | TIf _ | TTry _ | TSwitch _ | TArrayDecl _ | TBlock _ | TObjectDecl _ | TVar _ -> Type.iter loop e
+			in
+			try
+				loop e;
+				false
+			with Exit ->
+				true
 		in
 		let rec collect e = match e.eexpr with
 			| TLocal v ->
@@ -1256,49 +1467,65 @@ module LocalDce = struct
 				(* TODO: this is probably dangerous *)
 				()
 			| _ ->
-				Type.iter collect e
+				rev_iter collect e
 		in
-		let rec loop e = match e.eexpr with
+		let rec loop need_val e =
+			match e.eexpr with
 			| TLocal v ->
 				use v;
 				e
 			| TBinop(OpAssign,({eexpr = TLocal v} as e1),e2) ->
-				let e2 = loop e2 in
-				if not (is_used v) then
+				let e2 = loop false e2 in
+				if not (is_used v) && not (is_ref_type v.v_type) then
 					e2
 				else
 					{e with eexpr = TBinop(OpAssign,{e1 with eexpr = TLocal v},e2)}
 			| TVar(v,Some e1) when not (is_used v) ->
-				let e1 = loop e1 in
+				let e1 = if has_side_effect e1 then loop true e1 else e1 in
 				e1
 			| TWhile(e1,e2,flag) ->
 				collect e2;
-				let e2 = loop e2 in
-				let e1 = loop e1 in
+				let e2 = loop false e2 in
+				let e1 = loop false e1 in
 				{e with eexpr = TWhile(e1,e2,flag)}
 			| TFor(v,e1,e2) ->
 				collect e2;
-				let e2 = loop e2 in
-				let e1 = loop e1 in
+				let e2 = loop false e2 in
+				let e1 = loop false e1 in
 				{e with eexpr = TFor(v,e1,e2)}
 			| TBlock el ->
 				let rec block el = match el with
 					| e :: el ->
 						let el = block el in
-						if el <> [] && not (has_side_effect e) then
+						if not need_val && not (has_side_effect e) then
 							el
 						else begin
-							let e = loop e in
+							let e = loop false e in
 							e :: el
 						end
 					| [] ->
 						[]
 				in
 				{e with eexpr = TBlock (block el)}
+			| TCall(e1, el) ->
+				let el = List.rev_map (loop true) (List.rev el) in
+				let e1 = loop false e1 in
+				{e with eexpr = TCall(e1,el)}
+			| TIf(e1,e2,e3) ->
+				let e3 = match e3 with None -> None | Some e -> Some (loop need_val e) in
+				let e2 = loop need_val e2 in
+				let e1 = loop false e1 in
+				{e with eexpr = TIf(e1,e2,e3)}
+			| TArrayDecl el ->
+				let el = List.rev_map (loop true) (List.rev el) in
+				{e with eexpr = TArrayDecl el}
+			| TObjectDecl fl ->
+				let fl = List.rev_map (fun (s,e) -> s,loop true e) (List.rev fl) in
+				{e with eexpr = TObjectDecl fl}
 			| _ ->
-				Type.map_expr loop e
+				Type.map_expr (loop false) e
 		in
-		loop e
+		loop false e
 end
 
 module Config = struct
@@ -1323,7 +1550,7 @@ module Config = struct
 			const_propagation = not (Common.raw_defined com "analyzer-no-const-propagation");
 			check_has_effect = (Common.raw_defined com "analyzer-check-has-effect");
 			check = not (Common.raw_defined com "analyzer-no-check");
-			local_dce = not (Common.raw_defined com "analyzer-no-local-dce");
+			local_dce = not (Common.raw_defined com "analyzer-no-local-dce") && not (Common.defined com Define.As3);
 			ssa_unapply = not (Common.raw_defined com "analyzer-no-ssa-unapply");
 			simplifier_unapply = not (Common.raw_defined com "analyzer-no-simplify-unapply");
 		}
@@ -1360,12 +1587,9 @@ module Run = struct
 	open Config
 
 	let run_on_expr com config is_var_expression e =
-		let rec gen_local t =
-			alloc_var "tmp" t
-		in
 		let do_simplify = (not (Common.defined com Define.NoSimplify) ) && match com.platform with
 			| Cpp when Common.defined com Define.Cppia -> false
-			| Cpp | Flash8 | Python -> true
+			| Cpp | Python -> true
 			| _ -> false
 		in
 		let with_timer s f =
@@ -1376,7 +1600,7 @@ module Run = struct
 		in
 		try
 			let has_unbound,e = if do_simplify || config.analyzer_use then
-				with_timer "analyzer-simplify-apply" (fun () -> Simplifier.apply com gen_local e)
+				with_timer "analyzer-simplify-apply" (fun () -> Simplifier.apply com e)
 			else
 				false,e
 			in
@@ -1385,13 +1609,13 @@ module Run = struct
 					let e,ssa = with_timer "analyzer-ssa-apply" (fun () -> Ssa.apply com e) in
 					let e = if config.const_propagation then with_timer "analyzer-const-propagation" (fun () -> ConstPropagation.apply ssa e) else e in
 					(* let e = if config.check then with_timer "analyzer-checker" (fun () -> Checker.apply ssa e) else e in *)
+					let e = if config.local_dce && config.analyzer_use && not has_unbound && not is_var_expression then with_timer "analyzer-local-dce" (fun () -> LocalDce.apply e) else e in
 					let e = if config.ssa_unapply then with_timer "analyzer-ssa-unapply" (fun () -> Ssa.unapply com e) else e in
 					List.iter (fun f -> f()) ssa.Ssa.cleanup;
 					e
 			end else
 				e
 			in
-			let e = if config.local_dce && config.analyzer_use && not has_unbound && not is_var_expression then with_timer "analyzer-local-dce" (fun () -> LocalDce.apply e) else e in
 			let e = if not do_simplify && not (Common.raw_defined com "analyzer-no-simplify-unapply") then
 				with_timer "analyzer-simplify-unapply" (fun () -> Simplifier.unapply com e)
 			else
@@ -1403,7 +1627,7 @@ module Run = struct
 
 	let run_on_field ctx config cf =
 		match cf.cf_expr with
-		| Some e when not (has_analyzer_option cf.cf_meta flag_ignore) && not (Codegen.is_removable_field ctx cf) ->
+		| Some e when not (is_ignored cf.cf_meta) && not (Codegen.is_removable_field ctx cf) ->
 			let config = update_config_from_meta config cf.cf_meta in
 			let is_var_expression = match cf.cf_kind with
 				| Var _ -> true
@@ -1428,7 +1652,7 @@ module Run = struct
 
 	let run_on_type ctx config t =
 		match t with
-		| TClassDecl c when (has_analyzer_option c.cl_meta flag_ignore) -> ()
+		| TClassDecl c when (is_ignored c.cl_meta) -> ()
 		| TClassDecl c -> run_on_class ctx config c
 		| TEnumDecl _ -> ()
 		| TTypeDecl _ -> ()
@@ -1439,4 +1663,4 @@ module Run = struct
 		let config = get_base_config com in
 		List.iter (run_on_type ctx config) types
 
-end
+end

+ 4 - 5
appveyor.yml

@@ -28,15 +28,14 @@ init:
 install:
     - 'git submodule update --init --recursive'
     # Install ocaml using wodi
-    - '%CYG_ROOT%/setup-%CYG_ARCH%.exe -q -R "%CYG_ROOT%" -P wget -P dos2unix -P diffutils -P cpio -P make -P patch -P mingw64-%MINGW_ARCH%-gcc-core -P mingw64-%MINGW_ARCH%-gcc-g++ >NUL'
+    - '%CYG_ROOT%/setup-%CYG_ARCH%.exe -q -R "%CYG_ROOT%" -P dos2unix -P diffutils -P cpio -P make -P patch -P mingw64-%MINGW_ARCH%-gcc-core -P mingw64-%MINGW_ARCH%-gcc-g++ >NUL'
     - '%CYG_ROOT%/bin/bash -lc "cygcheck -dc cygwin"'
     - '%CYG_ROOT%/bin/bash -lc "wget -q http://ml.ignorelist.com/wodi/8/wodi%WODI_ARCH%.tar.xz -O /tmp/wodi%WODI_ARCH%.tar.xz"'
     - '%CYG_ROOT%/bin/bash -lc "cd /tmp && rm -rf wodi%WODI_ARCH% && tar -xf wodi%WODI_ARCH%.tar.xz && bash wodi%WODI_ARCH%/install.sh"'
     - '%CYG_ROOT%/bin/bash -lc "godi_add godi-zip"'
     - 'set PATH=%PATH%;%CYG_ROOT%/opt/wodi%WODI_ARCH%/bin'
     # Install neko
-    - cinst make
-    - cinst SQLite -version 3.8.5
+    - cinst make -y
     - 'git clone --recursive https://github.com/HaxeFoundation/neko.git %NEKO_ROOT%'
     - 'cd %NEKO_ROOT%'
     - set PATH=%PATH%;%NEKO_ROOT%/bin
@@ -51,8 +50,8 @@ install:
 build_script:
     - 'cd %APPVEYOR_BUILD_FOLDER%'
     - 'set PATH=%PATH%;%APPVEYOR_BUILD_FOLDER%'
-    - '%CYG_ROOT%/bin/bash -lc "cd \"$OLDPWD\" && make -f Makefile.win WODI=wodi%WODI_ARCH%"'
-    - '%CYG_ROOT%/bin/bash -lc "cd \"$OLDPWD\" && make -f Makefile.win WODI=wodi%WODI_ARCH% tools"'
+    - '%CYG_ROOT%/bin/bash -lc "cd \"$OLDPWD\" && make -f Makefile.win WODI=wodi%WODI_ARCH% OCAMLOPT=ocamlopt.opt"'
+    - '%CYG_ROOT%/bin/bash -lc "cd \"$OLDPWD\" && make -f Makefile.win WODI=wodi%WODI_ARCH% OCAMLOPT=ocamlopt.opt tools"'
     - cd %APPVEYOR_BUILD_FOLDER%/tests/
     - mkdir "%HAXELIB_ROOT%"
     - haxelib setup "%HAXELIB_ROOT%"

+ 23 - 2
ast.ml

@@ -26,8 +26,11 @@ type pos = {
 	pmax : int;
 }
 
+module IntMap = Map.Make(struct type t = int let compare a b = a - b end)
+
 module Meta = struct
 	type strict_meta =
+		| Abi
 		| Abstract
 		| Access
 		| Accessor
@@ -50,6 +53,7 @@ module Meta = struct
 		| CoreApi
 		| CoreType
 		| CppFileCode
+		| CppInclude
 		| CppNamespaceCode
 		| CsNative
 		| Dce
@@ -59,6 +63,7 @@ module Meta = struct
 		| Delegate
 		| Depend
 		| Deprecated
+		| DirectlyUsed
 		| DynamicObject
 		| Enum
 		| EnumConstructorParam
@@ -80,14 +85,17 @@ module Meta = struct
 		| GenericInstance
 		| Getter
 		| Hack
+		| HasUntyped
 		| HaxeGeneric
 		| HeaderClassCode
 		| HeaderCode
+		| HeaderInclude
 		| HeaderNamespaceCode
 		| HxGen
 		| IfFeature
 		| Impl
 		| PythonImport
+		| ImplicitCast
 		| Include
 		| InitPackage
 		| Internal
@@ -98,6 +106,7 @@ module Meta = struct
 		| Keep
 		| KeepInit
 		| KeepSub
+		| LibType
 		| Meta
 		| Macro
 		| MaybeUsed
@@ -107,6 +116,7 @@ module Meta = struct
 		| NativeChildren
 		| NativeGen
 		| NativeGeneric
+		| NativeProperty
 		| NoCompletion
 		| NoDebug
 		| NoDoc
@@ -125,8 +135,8 @@ module Meta = struct
 		| Protected
 		| Public
 		| PublicFields
+		| QuotedField
 		| ReadOnly
-		| ReallyUsed
 		| RealPath
 		| Remove
 		| Require
@@ -141,6 +151,9 @@ module Meta = struct
 		| SkipCtor
 		| SkipReflection
 		| Sound
+		| SourceFile
+		| StoredTypedExpr
+		| Strict
 		| Struct
 		| StructAccess
 		| SuppressWarnings
@@ -434,6 +447,8 @@ type type_decl = type_def * pos
 
 type package = string list * type_decl list
 
+exception Error of string * pos
+
 let is_lower_ident i =
 	let rec loop p =
 		match String.unsafe_get i p with
@@ -746,4 +761,10 @@ let get_value_meta meta =
 			| _ -> raise Not_found
 		end
 	with Not_found ->
-		PMap.empty
+		PMap.empty
+
+let rec string_list_of_expr_path_raise (e,p) =
+	match e with
+	| EConst (Ident i) -> [i]
+	| EField (e,f) -> f :: string_list_of_expr_path_raise e
+	| _ -> raise Exit

+ 127 - 32
codegen.ml

@@ -47,6 +47,13 @@ let binop op a b t p =
 let index com e index t p =
 	mk (TArray (e,mk (TConst (TInt (Int32.of_int index))) com.basic.tint p)) t p
 
+let maybe_cast e t =
+	try
+		type_eq EqDoNotFollowNull e.etype t;
+		e
+	with
+		Unify_error _ -> mk (TCast(e,None)) t e.epos
+
 let type_constant com c p =
 	let t = com.basic in
 	match c with
@@ -121,6 +128,15 @@ let is_removable_field ctx f =
 		| Method MethMacro -> not ctx.in_macro
 		| _ -> false)
 
+let escape_res_name name allow_dirs =
+	ExtString.String.replace_chars (fun chr ->
+		if (chr >= 'a' && chr <= 'z') || (chr >= 'A' && chr <= 'Z') || (chr >= '0' && chr <= '9') || chr = '_' || chr = '.' then
+			Char.escaped chr
+		else if chr = '/' && allow_dirs then
+			"/"
+		else
+			"-x" ^ (string_of_int (Char.code chr))) name
+
 (* -------------------------------------------------------------------------- *)
 (* REMOTING PROXYS *)
 
@@ -198,7 +214,7 @@ let extend_remoting ctx c t p async prot =
 		error ("Module " ^ s_type_path path ^ " does not define type " ^ t.tname) p
 	) in
 	match t with
-	| TClassDecl c2 when c2.cl_params = [] -> c2.cl_build(); c.cl_super <- Some (c2,[]);
+	| TClassDecl c2 when c2.cl_params = [] -> ignore(c2.cl_build()); c.cl_super <- Some (c2,[]);
 	| _ -> error "Remoting proxy must be a class without parameters" p
 
 (* -------------------------------------------------------------------------- *)
@@ -295,7 +311,7 @@ let get_short_name =
 	let i = ref (-1) in
 	(fun () ->
 		incr i;
-		Printf.sprintf "__hx_type_%i" !i
+		Printf.sprintf "Hx___short___hx_type_%i" !i
 	)
 
 let rec build_generic ctx c p tl =
@@ -325,7 +341,7 @@ let rec build_generic ctx c p tl =
 	with Error(Module_not_found path,_) when path = (pack,name) ->
 		let m = (try Hashtbl.find ctx.g.modules (Hashtbl.find ctx.g.types_module c.cl_path) with Not_found -> assert false) in
 		let ctx = { ctx with m = { ctx.m with module_types = m.m_types @ ctx.m.module_types } } in
-		c.cl_build(); (* make sure the super class is already setup *)
+		ignore(c.cl_build()); (* make sure the super class is already setup *)
 		let mg = {
 			m_id = alloc_mid();
 			m_path = (pack,name);
@@ -418,7 +434,7 @@ let rec build_generic ctx c p tl =
 						(* extended type parameter: concrete type must have a constructor, but generic base class must not have one *)
 						begin match follow t,c.cl_constructor with
 							| TInst(cs,_),None ->
-								cs.cl_build();
+								ignore(cs.cl_build());
 								begin match cs.cl_constructor with
 									| None -> error ("Cannot use " ^ (s_type_path cs.cl_path) ^ " as type parameter because it is extended and has no constructor") p
 									| _ -> ()
@@ -441,6 +457,7 @@ let rec build_generic ctx c p tl =
 		);
 		Typeload.add_constructor ctx cg false p;
 		cg.cl_kind <- KGenericInstance (c,tl);
+		cg.cl_meta <- (Meta.NoDoc,[],p) :: cg.cl_meta;
 		cg.cl_interface <- c.cl_interface;
 		cg.cl_constructor <- (match cg.cl_constructor, c.cl_constructor, c.cl_super with
 			| _, Some cf, _ -> Some (build_field cf)
@@ -461,8 +478,7 @@ let rec build_generic ctx c p tl =
 		(* In rare cases the class name can become too long, so let's shorten it (issue #3090). *)
 		if String.length (snd cg.cl_path) > 254 then begin
 			let n = get_short_name () in
-			let tp = fst cg.cl_path,n in
-			cg.cl_meta <- (Meta.Native,[EConst(String (s_type_path tp)),p],p) :: cg.cl_meta;
+			cg.cl_meta <- (Meta.Native,[EConst(String (n)),p],p) :: cg.cl_meta;
 		end;
 		TInst (cg,[])
 	end
@@ -544,7 +560,7 @@ let build_metadata com t =
 			if Hashtbl.mem h f then error ("Duplicate metadata '" ^ f ^ "'") p;
 			Hashtbl.add h f ();
 			f, mk (match el with [] -> TConst TNull | _ -> TArrayDecl (List.map (type_constant_value com) el)) (api.tarray t_dynamic) p
-		) ml)) (api.tarray t_dynamic) p
+		) ml)) t_dynamic p
 	in
 	let make_meta l =
 		mk (TObjectDecl (List.map (fun (f,ml) -> f,make_meta_field ml) l)) t_dynamic p
@@ -623,7 +639,7 @@ let build_macro_build ctx c pl cfl p =
 let build_instance ctx mtype p =
 	match mtype with
 	| TClassDecl c ->
-		if ctx.pass > PBuildClass then c.cl_build();
+		if ctx.pass > PBuildClass then ignore(c.cl_build());
 		let build f s =
 			let r = exc_protect ctx (fun r ->
 				let t = mk_mono() in
@@ -690,7 +706,10 @@ module AbstractCast = struct
 			if (Meta.has Meta.MultiType a.a_meta) then
 				mk_cast eright tleft p
 			else match a.a_impl with
-				| Some c -> recurse cf (fun () -> make_static_call ctx c cf a tl [eright] tleft p)
+				| Some c -> recurse cf (fun () ->
+					let ret = make_static_call ctx c cf a tl [eright] tleft p in
+					{ ret with eexpr = TMeta( (Meta.ImplicitCast,[],ret.epos), ret) }
+				)
 				| None -> assert false
 		in
 		if type_iseq tleft eright.etype then
@@ -861,29 +880,50 @@ module AbstractCast = struct
 				end
 			| TCall(e1, el) ->
 				begin try
-					begin match e1.eexpr with
+					let rec find_abstract e = match follow e.etype,e.eexpr with
+						| TAbstract(a,pl),_ when Meta.has Meta.MultiType a.a_meta -> a,pl,e
+						| _,TCast(e1,None) -> find_abstract e1
+						| _ -> raise Not_found
+					in
+					let rec find_field e1 =
+						match e1.eexpr with
+						| TCast(e2,None) ->
+							{e1 with eexpr = TCast(find_field e2,None)}
 						| TField(e2,fa) ->
-							begin match follow e2.etype with
-								| TAbstract(a,pl) when Meta.has Meta.MultiType a.a_meta ->
-									let m = Abstract.get_underlying_type a pl in
-									let fname = field_name fa in
-									let el = List.map (loop ctx) el in
-									begin try
-										let ef = mk (TField({e2 with etype = m},quick_field m fname)) e1.etype e2.epos in
-										make_call ctx ef el e.etype e.epos
-									with Not_found ->
-										(* quick_field raises Not_found if m is an abstract, we have to replicate the 'using' call here *)
-										match follow m with
-										| TAbstract({a_impl = Some c} as a,pl) ->
-											let cf = PMap.find fname c.cl_statics in
-											make_static_call ctx c cf a pl (e2 :: el) e.etype e.epos
-										| _ -> raise Not_found
-									end
+							let a,pl,e2 = find_abstract e2 in
+							let m = Abstract.get_underlying_type a pl in
+							let fname = field_name fa in
+							let el = List.map (loop ctx) el in
+							begin try
+								let fa = quick_field m fname in
+								let get_fun_type t = match follow t with
+									| TFun(_,tr) as tf -> tf,tr
+									| _ -> raise Not_found
+								in
+								let tf,tr = match fa with
+									| FStatic(_,cf) -> get_fun_type cf.cf_type
+									| FInstance(c,tl,cf) -> get_fun_type (apply_params c.cl_params tl cf.cf_type)
+									| FAnon cf -> get_fun_type cf.cf_type
+									| _ -> raise Not_found
+								in
+								let ef = mk (TField({e2 with etype = m},fa)) tf e2.epos in
+								let ecall = make_call ctx ef el tr e.epos in
+								if not (type_iseq ecall.etype e.etype) then
+									mk (TCast(ecall,None)) e.etype e.epos
+								else
+									ecall
+							with Not_found ->
+								(* quick_field raises Not_found if m is an abstract, we have to replicate the 'using' call here *)
+								match follow m with
+								| TAbstract({a_impl = Some c} as a,pl) ->
+									let cf = PMap.find fname c.cl_statics in
+									make_static_call ctx c cf a pl (e2 :: el) e.etype e.epos
 								| _ -> raise Not_found
 							end
 						| _ ->
 							raise Not_found
-					end
+					in
+					find_field e1
 				with Not_found ->
 					Type.map_expr (loop ctx) e
 				end
@@ -930,6 +970,39 @@ module PatternMatchConversion = struct
 			| [] -> cases
 			| tmp -> ((tmp,ldt) :: cases)
 
+	let replace_locals e =
+		let v_known = ref IntMap.empty in
+		let copy v =
+			let v' = alloc_var v.v_name v.v_type in
+			v_known := IntMap.add v.v_id v' !v_known;
+			v'
+		in
+		let rec loop e = match e.eexpr with
+			| TVar(v,e1) ->
+				let v' = copy v in
+				let e1 = match e1 with None -> None | Some e -> Some (loop e) in
+				{e with eexpr = TVar(v',e1)}
+			| TFor(v,e1,e2) ->
+				let v' = copy v in
+				let e1 = loop e1 in
+				let e2 = loop e2 in
+				{e with eexpr = TFor(v',e1,e2)}
+			| TTry(e1,catches) ->
+				let e1 = loop e1 in
+				let catches = List.map (fun (v,e) ->
+					let v' = copy v in
+					let e = loop e in
+					v',e
+				) catches in
+				{e with eexpr = TTry(e1,catches)}
+			| TLocal v ->
+				let v' = try IntMap.find v.v_id !v_known with Not_found -> v in
+				{e with eexpr = TLocal v'}
+			| _ ->
+				Type.map_expr loop e
+		in
+		loop e
+
 	let rec convert_dt cctx dt =
 		match dt with
 		| DTBind (bl,dt) ->
@@ -956,7 +1029,14 @@ module PatternMatchConversion = struct
 		| DTSwitch(e_st,cl,dto) ->
 			let def = match dto with None -> None | Some dt -> Some (convert_dt cctx dt) in
 			let cases = group_cases cl in
-			let cases = List.map (fun (cl,dt) -> cl,convert_dt cctx dt) cases in
+			let cases = List.map (fun (cl,dt) ->
+				let e = convert_dt cctx dt in
+				(* The macro interpreter does not care about unique locals and
+				   we don't run the analyzer on the output, so let's save some
+				   time here (issue #3937) *)
+				let e = if cctx.ctx.in_macro then e else replace_locals e in
+				cl,e
+			) cases in
 			mk (TSwitch(e_st,cases,def)) (mk_mono()) e_st.epos
 
 	let to_typed_ast ctx dt p =
@@ -1513,6 +1593,13 @@ struct
 		List.iter2 (fun f a -> if not (type_iseq f a) then incr acc) tlfun tlarg;
 		!acc
 
+	(**
+		The rate function returns an ( int * int ) type.
+		The smaller the int, the best rated the caller argument is in comparison with the callee.
+
+		The first int refers to how many "conversions" would be necessary to convert from the callee to the caller type, and
+		the second refers to the type parameters.
+	**)
 	let rec rate_conv cacc tfun targ =
 		match simplify_t tfun, simplify_t targ with
 		| TInst({ cl_interface = true } as cf, tlf), TInst(ca, tla) ->
@@ -1604,10 +1691,11 @@ struct
 		| r :: ret ->
 			rm_duplicates (r :: acc) ret
 
-(* 	let s_options rated =
-		String.concat ",\n" (List.map (fun ((_,t),rate) ->
+	let s_options rated =
+		String.concat ",\n" (List.map (fun ((elist,t,_),rate) ->
+			"( " ^ (String.concat "," (List.map (fun(e,_) -> s_expr (s_type (print_context())) e) elist)) ^ " ) => " ^
 			"( " ^ (String.concat "," (List.map (fun (i,i2) -> string_of_int i ^ ":" ^ string_of_int i2) rate)) ^ " ) => " ^ (s_type (print_context()) t)
-		) rated) *)
+		) rated)
 
 	let count_optionals elist =
 		List.fold_left (fun acc (_,is_optional) -> if is_optional then acc + 1 else acc) 0 elist
@@ -1634,7 +1722,14 @@ struct
 				| [], [] -> acc
 				| (_,true) :: elist, _ :: args -> mk_rate acc elist args
 				| (e,false) :: elist, (n,o,t) :: args ->
-					mk_rate (rate_conv 0 t e.etype :: acc) elist args
+					(* if the argument is an implicit cast, we need to start with a penalty *)
+					(* The penalty should be higher than any other implicit cast - other than Dynamic *)
+					(* since Dynamic has a penalty of max_int, we'll impose max_int - 1 to it *)
+					(match e.eexpr with
+						| TMeta( (Meta.ImplicitCast,_,_), _) ->
+							mk_rate ((max_int - 1, 0) :: acc) elist args
+						| _ ->
+							mk_rate (rate_conv 0 t e.etype :: acc) elist args)
 				| _ -> assert false
 			in
 

+ 70 - 43
common.ml

@@ -49,7 +49,6 @@ type stats = {
 
 type platform =
 	| Cross
-	| Flash8
 	| Js
 	| Neko
 	| Flash
@@ -96,6 +95,8 @@ type platform_config = {
 	pf_pattern_matching : bool;
 	(** can the platform use default values for non-nullable arguments *)
 	pf_can_skip_non_nullable_argument : bool;
+	(** type paths that are reserved on the platform *)
+	pf_reserved_type_paths : path list;
 }
 
 type display_mode =
@@ -133,6 +134,7 @@ type context = {
 	mutable get_macros : unit -> context option;
 	mutable run_command : string -> int;
 	file_lookup_cache : (string,string option) Hashtbl.t;
+	mutable stored_typed_exprs : (int, texpr) PMap.t;
 	(* output *)
 	mutable file : string;
 	mutable flash_version : float;
@@ -182,9 +184,13 @@ module Define = struct
 		| Dump
 		| DumpDependencies
 		| DumpIgnoreVarIds
+		| EraseGenerics
 		| Fdb
+		| FileExtension
 		| FlashStrict
 		| FlashUseStage
+		| ForceLibCheck
+		| ForceNativeProperty
 		| FormatWarning
 		| GencommonDebug
 		| HaxeBoot
@@ -195,8 +201,9 @@ module Define = struct
 		| JavaVer
 		| JsClassic
 		| JsEs5
-		| JsFlatten
+		| JsUnflatten
 		| KeepOldOutput
+		| LoopUnrollMaxCost
 		| Macro
 		| MacroTimes
 		| NekoSource
@@ -227,14 +234,12 @@ module Define = struct
 		| SwfDebugPassword
 		| SwfDirectBlit
 		| SwfGpu
-		| SwfMark
 		| SwfMetadata
 		| SwfPreloaderFrame
 		| SwfProtected
 		| SwfScriptTimeout
 		| SwfUseDoAbc
 		| Sys
-		| UnityStdTarget
 		| Unity46LineNumbers
 		| Unsafe
 		| UseNekoc
@@ -262,9 +267,14 @@ module Define = struct
 		| Dump -> ("dump","Dump the complete typed AST for internal debugging")
 		| DumpDependencies -> ("dump_dependencies","Dump the classes dependencies")
 		| DumpIgnoreVarIds -> ("dump_ignore_var_ids","Dump files do not contain variable IDs (helps with diff)")
+		| EraseGenerics -> ("erase_generics","Erase generic classes on C#")
 		| Fdb -> ("fdb","Enable full flash debug infos for FDB interactive debugging")
+		| FileExtension -> ("file_extension","Output filename extension for cpp source code")
 		| FlashStrict -> ("flash_strict","More strict typing for flash target")
 		| FlashUseStage -> ("flash_use_stage","Keep the SWF library initial stage")
+		(* force_lib_check is only here as a debug facility - compiler checking allows errors to be found more easily *)
+		| ForceLibCheck -> ("force_lib_check","Force the compiler to check -net-lib and -java-lib added classes (internal)")
+		| ForceNativeProperty -> ("force_native_property","Tag all properties with :nativeProperty metadata for 3.1 compatibility")
 		| FormatWarning -> ("format_warning","Print a warning for each formated string, for 2.x compatibility")
 		| GencommonDebug -> ("gencommon_debug","GenCommon internal")
 		| HaxeBoot -> ("haxe_boot","Given the name 'haxe' to the flash boot class instead of a generated name")
@@ -275,8 +285,9 @@ module Define = struct
 		| JavaVer -> ("java_ver", "<version:5-7> Sets the Java version to be targeted")
 		| JsClassic -> ("js_classic","Don't use a function wrapper and strict mode in JS output")
 		| JsEs5 -> ("js_es5","Generate JS for ES5-compliant runtimes")
-		| JsFlatten -> ("js_flatten","Generate classes to use fewer object property lookups")
+		| JsUnflatten -> ("js_unflatten","Generate nested objects for packages and types")
 		| KeepOldOutput -> ("keep_old_output","Keep old source files in the output directory (for C#/Java)")
+		| LoopUnrollMaxCost -> ("loop_unroll_max_cost","Maximum cost (number of expressions * iterations) before loop unrolling is canceled (default 250)")
 		| Macro -> ("macro","Defined when we compile code in the macro context")
 		| MacroTimes -> ("macro_times","Display per-macro timing when used with --times")
 		| NetVer -> ("net_ver", "<version:20-45> Sets the .NET version to be targeted")
@@ -305,17 +316,15 @@ module Define = struct
 		| SourceMapContent -> ("source-map-content","Include the hx sources as part of the JS source map")
 		| Swc -> ("swc","Output a SWC instead of a SWF")
 		| SwfCompressLevel -> ("swf_compress_level","<level:1-9> Set the amount of compression for the SWF output")
-		| SwfDebugPassword -> ("swf_debug_password", "Set a password for debugging.")
+		| SwfDebugPassword -> ("swf_debug_password", "Set a password for debugging")
 		| SwfDirectBlit -> ("swf_direct_blit", "Use hardware acceleration to blit graphics")
 		| SwfGpu -> ("swf_gpu", "Use GPU compositing features when drawing graphics")
-		| SwfMark -> ("swf_mark","GenSWF8 internal")
-		| SwfMetadata -> ("swf_metadata", "=<file> Include contents of <file> as metadata in the swf.")
+		| SwfMetadata -> ("swf_metadata", "=<file> Include contents of <file> as metadata in the swf")
 		| SwfPreloaderFrame -> ("swf_preloader_frame", "Insert empty first frame in swf")
 		| SwfProtected -> ("swf_protected","Compile Haxe private as protected in the SWF instead of public")
 		| SwfScriptTimeout -> ("swf_script_timeout", "Maximum ActionScript processing time before script stuck dialog box displays (in seconds)")
 		| SwfUseDoAbc -> ("swf_use_doabc", "Use DoAbc swf-tag instead of DoAbcDefine")
 		| Sys -> ("sys","Defined for all system platforms")
-		| UnityStdTarget -> ("unity_std_target", "Changes C# sources location so that each generated C# source is relative to the Haxe source location. If the location is outside the current directory, the value set here will be used")
 		(* see https://github.com/HaxeFoundation/haxe/issues/3759 *)
 		| Unity46LineNumbers -> ("unity46_line_numbers", "Fixes line numbers in generated C# files for Unity 4.6 Mono compiler")
 		| Unsafe -> ("unsafe","Allow unsafe code when targeting C#")
@@ -346,6 +355,7 @@ module MetaInfo = struct
 		| Internal
 
 	let to_string = function
+		| Abi -> ":abi",("Function ABI/calling convention",[Platforms [Cpp]])
 		| Abstract -> ":abstract",("Sets the underlying class implementation as 'abstract'",[Platforms [Java;Cs]])
 		| Access -> ":access",("Forces private access to package, type or field",[HasParam "Target path";UsedOnEither [TClass;TClassField]])
 		| Accessor -> ":accessor",("Used internally by DCE to mark property accessors",[UsedOn TClassField;Internal])
@@ -357,9 +367,9 @@ module MetaInfo = struct
 		| AutoBuild -> ":autoBuild",("Extends @:build metadata to all extending and implementing classes",[HasParam "Build macro call";UsedOn TClass])
 		| Bind -> ":bind",("Override Swf class declaration",[Platform Flash;UsedOn TClass])
 		| Bitmap -> ":bitmap",("Embeds given bitmap data into the class (must extend flash.display.BitmapData)",[HasParam "Bitmap file path";UsedOn TClass;Platform Flash])
-		| BridgeProperties -> ":bridgeProperties",("Creates native property bridges for all Haxe properties in this class.",[UsedOn TClass;Platform Cs])
+		| BridgeProperties -> ":bridgeProperties",("Creates native property bridges for all Haxe properties in this class",[UsedOn TClass;Platform Cs])
 		| Build -> ":build",("Builds a class or enum from a macro",[HasParam "Build macro call";UsedOnEither [TClass;TEnum]])
-		| BuildXml -> ":buildXml",("",[Platform Cpp])
+		| BuildXml -> ":buildXml",("Specify xml data to be injected into Build.xml",[Platform Cpp])
 		| Callable -> ":callable",("Abstract forwards call to its underlying type",[UsedOn TAbstract])
 		| Class -> ":class",("Used internally to annotate an enum that will be generated as a class",[Platforms [Java;Cs]; UsedOn TEnum; Internal])
 		| ClassCode -> ":classCode",("Used to inject platform-native code into a class",[Platforms [Java;Cs]; UsedOn TClass])
@@ -367,7 +377,8 @@ module MetaInfo = struct
 		| CompilerGenerated -> ":compilerGenerated",("Marks a field as generated by the compiler. Shouldn't be used by the end user",[Platforms [Java;Cs]])
 		| CoreApi -> ":coreApi",("Identifies this class as a core api class (forces Api check)",[UsedOnEither [TClass;TEnum;TTypedef;TAbstract]])
 		| CoreType -> ":coreType",("Identifies an abstract as core type so that it requires no implementation",[UsedOn TAbstract])
-		| CppFileCode -> ":cppFileCode",("",[Platform Cpp])
+		| CppFileCode -> ":cppFileCode",("Code to be injected into generated cpp file",[Platform Cpp])
+		| CppInclude -> ":cppInclude",("File to be included in generated cpp file",[Platform Cpp])
 		| CppNamespaceCode -> ":cppNamespaceCode",("",[Platform Cpp])
 		| CsNative -> ":csNative",("Automatically added by -net-lib on classes generated from .NET DLL files",[Platform Cs; UsedOnEither[TClass;TEnum]; Internal])
 		| Dce -> ":dce",("Forces dead code elimination even when -dce full is not specified",[UsedOnEither [TClass;TEnum]])
@@ -376,11 +387,12 @@ module MetaInfo = struct
 		| DefParam -> ":defParam",("?",[])
 		| Delegate -> ":delegate",("Automatically added by -net-lib on delegates",[Platform Cs; UsedOn TAbstract])
 		| Depend -> ":depend",("",[Platform Cpp])
-		| Deprecated -> ":deprecated",("Automatically added by -java-lib on class fields annotated with @Deprecated annotation. Has no effect on types compiled by Haxe.",[Platform Java; UsedOnEither [TClass;TEnum;TClassField]])
+		| Deprecated -> ":deprecated",("Automatically added by -java-lib on class fields annotated with @Deprecated annotation. Has no effect on types compiled by Haxe",[Platform Java; UsedOnEither [TClass;TEnum;TClassField]])
+		| DirectlyUsed -> ":directlyUsed",("Marks types that are directly referenced by non-extern code",[Internal])
 		| DynamicObject -> ":dynamicObject",("Used internally to identify the Dynamic Object implementation",[Platforms [Java;Cs]; UsedOn TClass; Internal])
 		| Enum -> ":enum",("Used internally to annotate a class that was generated from an enum",[Platforms [Java;Cs]; UsedOn TClass; Internal])
 		| EnumConstructorParam -> ":enumConstructorParam",("Used internally to annotate GADT type parameters",[UsedOn TClass; Internal])
-		| Event -> ":event",("Automatically added by -net-lib on events. Has no effect on types compiled by Haxe.",[Platform Cs; UsedOn TClassField])
+		| Event -> ":event",("Automatically added by -net-lib on events. Has no effect on types compiled by Haxe",[Platform Cs; UsedOn TClassField])
 		| Exhaustive -> ":exhaustive",("",[Internal])
 		| Expose -> ":expose",("Makes the class available on the window object",[HasParam "?Name=Class path";UsedOn TClass;Platform Js])
 		| Extern -> ":extern",("Marks the field as extern so it is not generated",[UsedOn TClassField])
@@ -398,14 +410,17 @@ module MetaInfo = struct
 		| GenericInstance -> ":genericInstance",("Internally used to mark instances of @:generic methods",[UsedOn TClassField;Internal])
 		| Getter -> ":getter",("Generates a native getter function on the given field",[HasParam "Class field name";UsedOn TClassField;Platform Flash])
 		| Hack -> ":hack",("Allows extending classes marked as @:final",[UsedOn TClass])
+		| HasUntyped -> (":has_untyped",("Used by the typer to mark fields that have untyped expressions",[Internal]))
 		| HaxeGeneric -> ":haxeGeneric",("Used internally to annotate non-native generic classes",[Platform Cs; UsedOnEither[TClass;TEnum]; Internal])
-		| HeaderClassCode -> ":headerClassCode",("",[Platform Cpp])
-		| HeaderCode -> ":headerCode",("",[Platform Cpp])
+		| HeaderClassCode -> ":headerClassCode",("Code to be injected into the generated class, in the header",[Platform Cpp])
+		| HeaderCode -> ":headerCode",("Code to be injected into the generated header file",[Platform Cpp])
+		| HeaderInclude -> ":headerInclude",("File to be included in generated header file",[Platform Cpp])
 		| HeaderNamespaceCode -> ":headerNamespaceCode",("",[Platform Cpp])
 		| HxGen -> ":hxGen",("Annotates that an extern class was generated by Haxe",[Platforms [Java;Cs]; UsedOnEither [TClass;TEnum]])
 		| IfFeature -> ":ifFeature",("Causes a field to be kept by DCE if the given feature is part of the compilation",[HasParam "Feature name";UsedOn TClassField])
 		| Impl -> ":impl",("Used internally to mark abstract implementation fields",[UsedOn TAbstractField; Internal])
 		| PythonImport -> ":pythonImport",("Generates python import statement for extern classes",[Platforms [Python]; UsedOn TClass])
+		| ImplicitCast -> ":implicitCast",("Generated automatically on the AST when an implicit abstract cast happens",[Internal; UsedOn TExpr])
 		| Include -> ":include",("",[Platform Cpp])
 		| InitPackage -> ":initPackage",("?",[])
 		| Meta.Internal -> ":internal",("Generates the annotated field/class with 'internal' access",[Platforms [Java;Cs]; UsedOnEither[TClass;TEnum;TClassField]])
@@ -416,21 +431,23 @@ module MetaInfo = struct
 		| Keep -> ":keep",("Causes a field or type to be kept by DCE",[])
 		| KeepInit -> ":keepInit",("Causes a class to be kept by DCE even if all its field are removed",[UsedOn TClass])
 		| KeepSub -> ":keepSub",("Extends @:keep metadata to all implementing and extending classes",[UsedOn TClass])
+		| LibType -> ":libType",("Used by -net-lib and -java-lib to mark a class that shouldn't be checked (overrides, interfaces, etc) by the type loader",[Internal; UsedOn TClass; Platforms [Java;Cs]])
 		| Meta -> ":meta",("Internally used to mark a class field as being the metadata field",[])
 		| Macro -> ":macro",("(deprecated)",[])
 		| MaybeUsed -> ":maybeUsed",("Internally used by DCE to mark fields that might be kept",[Internal])
-		| MergeBlock -> ":mergeBlock",("Internally used by typer to mark block that should be merged into the outer scope",[Internal])
+		| MergeBlock -> ":mergeBlock",("Merge the annotated block into the current scope",[UsedOn TExpr])
 		| MultiType -> ":multiType",("Specifies that an abstract chooses its this-type from its @:to functions",[UsedOn TAbstract; HasParam "Relevant type parameters"])
 		| Native -> ":native",("Rewrites the path of a class or enum during generation",[HasParam "Output type path";UsedOnEither [TClass;TEnum]])
 		| NativeChildren -> ":nativeChildren",("Annotates that all children from a type should be treated as if it were an extern definition - platform native",[Platforms [Java;Cs]; UsedOn TClass])
 		| NativeGen -> ":nativeGen",("Annotates that a type should be treated as if it were an extern definition - platform native",[Platforms [Java;Cs;Python]; UsedOnEither[TClass;TEnum]])
 		| NativeGeneric -> ":nativeGeneric",("Used internally to annotate native generic classes",[Platform Cs; UsedOnEither[TClass;TEnum]; Internal])
+		| NativeProperty -> ":nativeProperty",("Use native properties which will execute even with dynamic usage",[Platform Cpp])
 		| NoCompletion -> ":noCompletion",("Prevents the compiler from suggesting completion on this field",[UsedOn TClassField])
 		| NoDebug -> ":noDebug",("Does not generate debug information into the Swf even if -debug is set",[UsedOnEither [TClass;TClassField];Platform Flash])
 		| NoDoc -> ":noDoc",("Prevents a type from being included in documentation generation",[])
 		| NoExpr -> ":noExpr",("Internally used to mark abstract fields which have no expression by design",[Internal])
 		| NoImportGlobal -> ":noImportGlobal",("Prevents a static field from being imported with import Class.*",[UsedOn TAnyField])
-		| NoPackageRestrict -> ":noPackageRestrict",("Allows a module to be accessed across all targets if found on its first type.",[Internal])
+		| NoPackageRestrict -> ":noPackageRestrict",("Allows a module to be accessed across all targets if found on its first type",[Internal])
 		| NoStack -> ":noStack",("",[Platform Cpp])
 		| NotNull -> ":notNull",("Declares an abstract type as not accepting null values",[UsedOn TAbstract])
 		| NoUsing -> ":noUsing",("Prevents a field from being used with 'using'",[UsedOn TClassField])
@@ -440,11 +457,11 @@ module MetaInfo = struct
 		| Overload -> ":overload",("Allows the field to be called with different argument types",[HasParam "Function specification (no expression)";UsedOn TClassField])
 		| Public -> ":public",("Marks a class field as being public",[UsedOn TClassField])
 		| PublicFields -> ":publicFields",("Forces all class fields of inheriting classes to be public",[UsedOn TClass])
+		| QuotedField -> ":quotedField",("Used internally to mark structure fields which are quoted in syntax",[Internal])
 		| PrivateAccess -> ":privateAccess",("Allow private access to anything for the annotated expression",[UsedOn TExpr])
 		| Protected -> ":protected",("Marks a class field as being protected",[UsedOn TClassField])
 		| Property -> ":property",("Marks a property field to be compiled as a native C# property",[UsedOn TClassField;Platform Cs])
 		| ReadOnly -> ":readOnly",("Generates a field with the 'readonly' native keyword",[Platform Cs; UsedOn TClassField])
-		| ReallyUsed -> ":reallyUsed",("Marks types that are directly referenced by non-extern code",[Internal])
 		| RealPath -> ":realPath",("Internally used on @:native types to retain original path information",[Internal])
 		| Remove -> ":remove",("Causes an interface to be removed from all implementing classes before generation",[UsedOn TClass])
 		| Require -> ":require",("Allows access to a field only if the specified compiler flag is set",[HasParam "Compiler flag to check";UsedOn TClassField])
@@ -455,14 +472,17 @@ module MetaInfo = struct
 		| Runtime -> ":runtime",("?",[])
 		| RuntimeValue -> ":runtimeValue",("Marks an abstract as being a runtime value",[UsedOn TAbstract])
 		| SelfCall -> ":selfCall",("Translates method calls into calling object directly",[UsedOn TClassField; Platform Js])
-		| Setter -> ":setter",("Generates a native getter function on the given field",[HasParam "Class field name";UsedOn TClassField;Platform Flash])
+		| Setter -> ":setter",("Generates a native setter function on the given field",[HasParam "Class field name";UsedOn TClassField;Platform Flash])
+		| StoredTypedExpr -> ":storedTypedExpr",("Used internally to reference a typed expression returned from a macro",[Internal])
 		| SkipCtor -> ":skipCtor",("Used internally to generate a constructor as if it were a native type (no __hx_ctor)",[Platforms [Java;Cs]; Internal])
 		| SkipReflection -> ":skipReflection",("Used internally to annotate a field that shouldn't have its reflection data generated",[Platforms [Java;Cs]; UsedOn TClassField; Internal])
 		| Sound -> ":sound",( "Includes a given .wav or .mp3 file into the target Swf and associates it with the class (must extend flash.media.Sound)",[HasParam "File path";UsedOn TClass;Platform Flash])
-		| Struct -> ":struct",("Marks a class definition as a struct.",[Platform Cs; UsedOn TClass])
-		| StructAccess -> ":structAccess",("Marks an extern class as using struct access('.') not pointer('->').",[Platform Cpp; UsedOn TClass])
+		| SourceFile -> ":sourceFile",("Source code filename for external class",[Platform Cpp])
+		| Strict -> ":strict",("Used to declare a native C# attribute or a native Java metadata. Is type checked",[Platforms [Java;Cs]])
+		| Struct -> ":struct",("Marks a class definition as a struct",[Platform Cs; UsedOn TClass])
+		| StructAccess -> ":structAccess",("Marks an extern class as using struct access('.') not pointer('->')",[Platform Cpp; UsedOn TClass])
 		| SuppressWarnings -> ":suppressWarnings",("Adds a SuppressWarnings annotation for the generated Java class",[Platform Java; UsedOn TClass])
-		| Throws -> ":throws",("Adds a 'throws' declaration to the generated function.",[HasParam "Type as String"; Platform Java; UsedOn TClassField])
+		| Throws -> ":throws",("Adds a 'throws' declaration to the generated function",[HasParam "Type as String"; Platform Java; UsedOn TClassField])
 		| This -> ":this",("Internally used to pass a 'this' expression to macros",[Internal; UsedOn TExpr])
 		| To -> ":to",("Specifies that the field of the abstract is a cast operation to the type identified in the function",[UsedOn TAbstractField])
 		| ToString -> ":toString",("Internally used",[Internal])
@@ -524,6 +544,7 @@ let default_config =
 		pf_overload = false;
 		pf_pattern_matching = false;
 		pf_can_skip_non_nullable_argument = true;
+		pf_reserved_type_paths = [];
 	}
 
 let get_config com =
@@ -531,20 +552,6 @@ let get_config com =
 	match com.platform with
 	| Cross ->
 		default_config
-	| Flash8 ->
-		{
-			pf_static = false;
-			pf_sys = false;
-			pf_locals_scope = com.flash_version > 6.;
-			pf_captured_scope = false;
-			pf_unique_locals = false;
-			pf_capture_policy = CPLoopVars;
-			pf_pad_nulls = false;
-			pf_add_final_return = false;
-			pf_overload = false;
-			pf_pattern_matching = false;
-			pf_can_skip_non_nullable_argument = true;
-		}
 	| Js ->
 		{
 			pf_static = false;
@@ -558,6 +565,7 @@ let get_config com =
 			pf_overload = false;
 			pf_pattern_matching = false;
 			pf_can_skip_non_nullable_argument = true;
+			pf_reserved_type_paths = [([],"Object");([],"Error")];
 		}
 	| Neko ->
 		{
@@ -572,6 +580,7 @@ let get_config com =
 			pf_overload = false;
 			pf_pattern_matching = false;
 			pf_can_skip_non_nullable_argument = true;
+			pf_reserved_type_paths = [];
 		}
 	| Flash when defined Define.As3 ->
 		{
@@ -586,6 +595,7 @@ let get_config com =
 			pf_overload = false;
 			pf_pattern_matching = false;
 			pf_can_skip_non_nullable_argument = false;
+			pf_reserved_type_paths = [];
 		}
 	| Flash ->
 		{
@@ -600,6 +610,7 @@ let get_config com =
 			pf_overload = false;
 			pf_pattern_matching = false;
 			pf_can_skip_non_nullable_argument = false;
+			pf_reserved_type_paths = [([],"Object");([],"Error")];
 		}
 	| Php ->
 		{
@@ -614,6 +625,7 @@ let get_config com =
 			pf_overload = false;
 			pf_pattern_matching = false;
 			pf_can_skip_non_nullable_argument = true;
+			pf_reserved_type_paths = [];
 		}
 	| Cpp ->
 		{
@@ -628,6 +640,7 @@ let get_config com =
 			pf_overload = false;
 			pf_pattern_matching = false;
 			pf_can_skip_non_nullable_argument = true;
+			pf_reserved_type_paths = [];
 		}
 	| Cs ->
 		{
@@ -642,6 +655,7 @@ let get_config com =
 			pf_overload = true;
 			pf_pattern_matching = false;
 			pf_can_skip_non_nullable_argument = true;
+			pf_reserved_type_paths = [];
 		}
 	| Java ->
 		{
@@ -656,6 +670,7 @@ let get_config com =
 			pf_overload = true;
 			pf_pattern_matching = false;
 			pf_can_skip_non_nullable_argument = true;
+			pf_reserved_type_paths = [];
 		}
 	| Python ->
 		{
@@ -670,6 +685,7 @@ let get_config com =
 			pf_overload = false;
 			pf_pattern_matching = false;
 			pf_can_skip_non_nullable_argument = true;
+			pf_reserved_type_paths = [];
 		}
 
 let memory_marker = [|Unix.time()|]
@@ -728,6 +744,7 @@ let create v args =
 			tarray = (fun _ -> assert false);
 		};
 		file_lookup_cache = Hashtbl.create 0;
+		stored_typed_exprs = PMap.empty;
 		memory_marker = memory_marker;
 	}
 
@@ -766,7 +783,6 @@ let file_extension file =
 	| [] -> ""
 
 let platforms = [
-	Flash8;
 	Js;
 	Neko;
 	Flash;
@@ -779,7 +795,6 @@ let platforms = [
 
 let platform_name = function
 	| Cross -> "cross"
-	| Flash8 -> "flash8"
 	| Js -> "js"
 	| Neko -> "neko"
 	| Flash -> "flash"
@@ -866,6 +881,17 @@ let add_feature com f =
 let has_dce com =
 	(try defined_value com Define.Dce <> "no" with Not_found -> false)
 
+(*
+	TODO: The has_dce check is there because we mark types with @:directlyUsed in the DCE filter,
+	which is not run in dce=no and thus we can't know if a type is used directly or not,
+	so we just assume that they are.
+
+	If we had dce filter always running (even with dce=no), we would have types marked with @:directlyUsed
+	and we wouldn't need to generate unnecessary imports in dce=no, but that's good enough for now.
+*)
+let is_directly_used com meta =
+	not (has_dce com) || Ast.Meta.has Ast.Meta.DirectlyUsed meta
+
 let rec has_feature com f =
 	try
 		Hashtbl.find com.features f
@@ -917,16 +943,17 @@ let find_file ctx f =
 	with Exit ->
 		raise Not_found
 	| Not_found ->
-		let rec loop = function
-			| [] -> raise Not_found
+		let rec loop had_empty = function
+			| [] when had_empty -> raise Not_found
+			| [] -> loop true [""]
 			| p :: l ->
 				let file = p ^ f in
 				if Sys.file_exists file then
 					file
 				else
-					loop l
+					loop (had_empty || p = "") l
 		in
-		let r = (try Some (loop ctx.class_path) with Not_found -> None) in
+		let r = (try Some (loop false ctx.class_path) with Not_found -> None) in
 		Hashtbl.add ctx.file_lookup_cache f r;
 		(match r with
 		| None -> raise Not_found

+ 150 - 15
dce.ml

@@ -30,6 +30,7 @@ type dce = {
 	std_dirs : string list;
 	debug : bool;
 	follow_expr : dce -> texpr -> unit;
+	mutable curclass : tclass;
 	mutable added_fields : (tclass * tclass_field * bool) list;
 	mutable marked_fields : tclass_field list;
 	mutable marked_maybe_fields : tclass_field list;
@@ -85,6 +86,10 @@ let rec check_feature dce s =
 	with Not_found ->
 		()
 
+and check_and_add_feature dce s =
+	check_feature dce s;
+	Common.add_feature dce.com s;
+
 (* mark a field as kept *)
 and mark_field dce c cf stat =
 	let add cf =
@@ -136,6 +141,7 @@ end
 
 let rec mark_enum dce e = if not (Meta.has Meta.Used e.e_meta) then begin
 	e.e_meta <- (Meta.Used,[],e.e_pos) :: e.e_meta;
+	check_and_add_feature dce "has_enum";
 	check_feature dce (Printf.sprintf "%s.*" (s_type_path e.e_path));
 	PMap.iter (fun _ ef -> mark_t dce ef.ef_pos ef.ef_type) e.e_constrs;
 end
@@ -176,7 +182,7 @@ and mark_t dce p t =
 			List.iter (mark_t dce p) pl;
 			if not (Meta.has Meta.CoreType a.a_meta) then
 				mark_t dce p (Abstract.get_underlying_type a pl)
-		| TLazy _ | TDynamic _ | TAnon _ | TType _ | TMono _ -> ()
+		| TLazy _ | TDynamic _ | TType _ | TAnon _ | TMono _ -> ()
 		end;
 		dce.t_stack <- List.tl dce.t_stack
 	end
@@ -282,23 +288,63 @@ and field dce c n stat =
 	with Not_found ->
 		if dce.debug then prerr_endline ("[DCE] Field " ^ n ^ " not found on " ^ (s_type_path c.cl_path)) else ())
 
-and mark_really_used_class c =
-	if not (Meta.has Meta.ReallyUsed c.cl_meta) then
-		c.cl_meta <- (Meta.ReallyUsed,[],c.cl_pos) :: c.cl_meta
+and mark_directly_used_class c =
+	if not (Meta.has Meta.DirectlyUsed c.cl_meta) then
+		c.cl_meta <- (Meta.DirectlyUsed,[],c.cl_pos) :: c.cl_meta
+
+and mark_directly_used_enum e =
+	if not (Meta.has Meta.DirectlyUsed e.e_meta) then
+		e.e_meta <- (Meta.DirectlyUsed,[],e.e_pos) :: e.e_meta
 
-and mark_really_used_mt mt =
+and mark_directly_used_mt mt =
 	match mt with
 	| TClassDecl c ->
-		mark_really_used_class c
+		mark_directly_used_class c
+	| TEnumDecl e ->
+		mark_directly_used_enum e
 	| _ ->
 		()
 
+and check_dynamic_write dce fa =
+	let n = field_name fa in
+	check_and_add_feature dce ("dynamic_write");
+	check_and_add_feature dce ("dynamic_write." ^ n)
+
+and check_anon_optional_write dce fa =
+	let n = field_name fa in
+	check_and_add_feature dce ("anon_optional_write");
+	check_and_add_feature dce ("anon_optional_write." ^ n)
+
+and check_anon_write dce fa =
+	let n = field_name fa in
+	check_and_add_feature dce ("anon_write");
+	check_and_add_feature dce ("anon_write." ^ n)
+
+and is_array t = match follow t with
+	| TAbstract(a,tl) when not (Meta.has Meta.CoreType a.a_meta) -> is_array (Abstract.get_underlying_type a tl)
+	| TInst({ cl_path = ([], "Array")},_) -> true
+	| _ -> false
+
+and is_dynamic t = match follow t with
+	| TAbstract(a,tl) when not (Meta.has Meta.CoreType a.a_meta) -> is_dynamic (Abstract.get_underlying_type a tl)
+	| TDynamic _ -> true
+	| _ -> false
+
+and is_string t = match follow t with
+	| TAbstract(a,tl) when not (Meta.has Meta.CoreType a.a_meta) -> is_string (Abstract.get_underlying_type a tl)
+	| TInst( { cl_path = ([], "String")}, _) -> true
+	| _ -> false
+
+and is_const_string e = match e.eexpr with
+	| TConst(TString(_)) -> true
+	| _ -> false
+
 and expr dce e =
 	mark_t dce e.epos e.etype;
 	match e.eexpr with
 	| TNew(c,pl,el) ->
 		mark_class dce c;
-		mark_really_used_class c;
+		mark_directly_used_class c;
 		field dce c "new" false;
 		List.iter (expr dce) el;
 		List.iter (mark_t dce e.epos) pl;
@@ -308,11 +354,14 @@ and expr dce e =
 	| TCast(e, Some mt) ->
 		check_feature dce "typed_cast";
 		mark_mt dce mt;
-		mark_really_used_mt mt;
+		mark_directly_used_mt mt;
 		expr dce e;
+	| TObjectDecl(vl) ->
+		check_and_add_feature dce "has_anon";
+		List.iter (fun (_,e) -> expr dce e) vl;
 	| TTypeExpr mt ->
 		mark_mt dce mt;
-		mark_really_used_mt mt;
+		mark_directly_used_mt mt;
 	| TTry(e, vl) ->
 		expr dce e;
 		List.iter (fun (v,e) ->
@@ -320,10 +369,15 @@ and expr dce e =
 			expr dce e;
 			mark_t dce e.epos v.v_type;
 		) vl;
+	| TCall ({eexpr = TLocal ({v_name = "`trace"})},[p;{ eexpr = TObjectDecl(v)}]) ->
+		check_and_add_feature dce "has_anon_trace";
+		List.iter (fun (_,e) -> expr dce e) v;
+		expr dce p;
 	| TCall ({eexpr = TLocal ({v_name = "__define_feature__"})},[{eexpr = TConst (TString ft)};e]) ->
-		Common.add_feature dce.com ft;
+		Hashtbl.replace dce.curclass.cl_module.m_extra.m_features ft true;
 		check_feature dce ft;
-		expr dce e
+		expr dce e;
+
 	(* keep toString method when the class is argument to Std.string or haxe.Log.trace *)
 	| TCall ({eexpr = TField({eexpr = TTypeExpr (TClassDecl ({cl_path = (["haxe"],"Log")} as c))},FStatic (_,{cf_name="trace"}))} as ef, ((e2 :: el) as args))
 	| TCall ({eexpr = TField({eexpr = TTypeExpr (TClassDecl ({cl_path = ([],"Std")} as c))},FStatic (_,{cf_name="string"}))} as ef, ((e2 :: el) as args)) ->
@@ -349,6 +403,68 @@ and expr dce e =
 	| TCall ({eexpr = TConst TSuper} as e,el) ->
 		mark_t dce e.epos e.etype;
 		List.iter (expr dce) el;
+	| TBinop(OpAdd,e1,e2) when is_dynamic e1.etype || is_dynamic e2.etype ->
+		check_and_add_feature dce "add_dynamic";
+		expr dce e1;
+		expr dce e2;
+	| TBinop( (OpAdd | (OpAssignOp OpAdd)),e1,e2) when ((is_string e1.etype || is_string e2.etype) && not ( is_const_string e1 && is_const_string e2)) ->
+		check_and_add_feature dce "unsafe_string_concat";
+		expr dce e1;
+		expr dce e2;
+	| TArray(({etype = TDynamic t} as e1),e2) when t == t_dynamic ->
+		check_and_add_feature dce "dynamic_array_read";
+		expr dce e1;
+		expr dce e2;
+	| TBinop( (OpAssign | OpAssignOp _), ({eexpr = TArray({etype = TDynamic t},_)} as e1), e2) when t == t_dynamic ->
+		check_and_add_feature dce "dynamic_array_write";
+		expr dce e1;
+		expr dce e2;
+	| TArray(({etype = t} as e1),e2) when is_array t ->
+		check_and_add_feature dce "array_read";
+		expr dce e1;
+		expr dce e2;
+	| TBinop( (OpAssign | OpAssignOp _), ({eexpr = TArray({etype = t},_)} as e1), e2) when is_array t ->
+		check_and_add_feature dce "array_write";
+		expr dce e1;
+		expr dce e2;
+	| TBinop(OpAssign,({eexpr = TField(_,(FDynamic _ as fa) )} as e1),e2) ->
+		check_dynamic_write dce fa;
+		expr dce e1;
+		expr dce e2;
+	| TBinop(OpAssign,({eexpr = TField(_,(FAnon cf as fa) )} as e1),e2) ->
+		if Meta.has Meta.Optional cf.cf_meta then
+			check_anon_optional_write dce fa
+		else
+			check_anon_write dce fa;
+		expr dce e1;
+		expr dce e2;
+	| TBinop(OpAssignOp op,({eexpr = TField(_,(FDynamic _ as fa) )} as e1),e2) ->
+		check_dynamic_write dce fa;
+		expr dce e1;
+		expr dce e2;
+	| TBinop(OpAssignOp op,({eexpr = TField(_,(FAnon cf as fa) )} as e1),e2) ->
+		if Meta.has Meta.Optional cf.cf_meta then
+			check_anon_optional_write dce fa
+		else
+			check_anon_write dce fa;
+		expr dce e1;
+		expr dce e2;
+	| TBinop(OpEq,({ etype = t1} as e1), ({ etype = t2} as e2) ) when is_dynamic t1 || is_dynamic t2 ->
+		check_and_add_feature dce "dynamic_binop_==";
+		expr dce e1;
+		expr dce e2;
+	| TBinop(OpEq,({ etype = t1} as e1), ({ etype = t2} as e2) ) when is_dynamic t1 || is_dynamic t2 ->
+		check_and_add_feature dce "dynamic_binop_!=";
+		expr dce e1;
+		expr dce e2;
+	| TBinop(OpMod,e1,e2) ->
+		check_and_add_feature dce "binop_%";
+		expr dce e1;
+		expr dce e2;
+	| TBinop(OpUShr,e1,e2) ->
+		check_and_add_feature dce "binop_>>>";
+		expr dce e1;
+		expr dce e2;
 	| TField(e,fa) ->
 		begin match fa with
 			| FStatic(c,cf) ->
@@ -358,7 +474,21 @@ and expr dce e =
 				mark_class dce c;
 				mark_field dce c cf false;
 			| _ ->
+
 				let n = field_name fa in
+				(match fa with
+				| FAnon cf ->
+					if Meta.has Meta.Optional cf.cf_meta then begin
+						check_and_add_feature dce "anon_optional_read";
+						check_and_add_feature dce ("anon_optional_read." ^ n);
+					end else begin
+						check_and_add_feature dce "anon_read";
+						check_and_add_feature dce ("anon_read." ^ n);
+					end
+				| FDynamic _ ->
+					check_and_add_feature dce "dynamic_read";
+					check_and_add_feature dce ("dynamic_read." ^ n);
+				| _ -> ());
 				begin match follow e.etype with
 					| TInst(c,_) ->
 						mark_class dce c;
@@ -369,11 +499,14 @@ and expr dce e =
 							mark_class dce c;
 							field dce c n true;
 						| _ -> ())
+
+
 					| _ -> ()
 				end;
 		end;
 		expr dce e;
 	| TThrow e ->
+		check_and_add_feature dce "has_throw";
 		to_string dce e.etype;
 		expr dce e
 	| _ ->
@@ -416,6 +549,7 @@ let run com main full =
 		t_stack = [];
 		ts_stack = [];
 		features = Hashtbl.create 0;
+		curclass = null_class;
 	} in
 	begin match main with
 		| Some {eexpr = TCall({eexpr = TField(e,(FStatic(c,cf)))},_)} ->
@@ -427,7 +561,7 @@ let run com main full =
 		List.iter (fun (s,v) ->
 			if Hashtbl.mem dce.features s then Hashtbl.replace dce.features s (v :: Hashtbl.find dce.features s)
 			else Hashtbl.add dce.features s [v]
-		) m.m_extra.m_features;
+		) m.m_extra.m_if_feature;
 	) com.modules;
 	(* first step: get all entry points, which is the main method and all class methods which are marked with @:keep *)
 	List.iter (fun t -> match t with
@@ -477,7 +611,8 @@ let run com main full =
 				mark_t dce cf.cf_pos cf.cf_type
 			) cfl;
 			(* follow expressions to new types/fields *)
-			List.iter (fun (_,cf,_) ->
+			List.iter (fun (c,cf,_) ->
+				dce.curclass <- c;
 				opt (expr dce) cf.cf_expr;
 				List.iter (fun cf -> if cf.cf_expr <> None then opt (expr dce) cf.cf_expr) cf.cf_overloads
 			) cfl;
@@ -582,9 +717,9 @@ let run com main full =
 	(* mark extern classes as really used if they are extended by non-extern ones *)
 	List.iter (function
 		| TClassDecl ({cl_extern = false; cl_super = Some ({cl_extern = true} as csup, _)}) ->
-			mark_really_used_class csup
+			mark_directly_used_class csup
 		| TClassDecl ({cl_extern = false} as c) when c.cl_implements <> [] ->
-			List.iter (fun (iface,_) -> if (iface.cl_extern) then mark_really_used_class iface) c.cl_implements;
+			List.iter (fun (iface,_) -> if (iface.cl_extern) then mark_directly_used_class iface) c.cl_implements;
 		| _ -> ()
 	) com.types;
 

+ 48 - 4
extra/CHANGES.txt

@@ -1,4 +1,6 @@
-2014-??-??: 3.2.0
+2015-03-15: 3.2.0-RC1
+
+	This release removes support for Flash 8 target
 
 	New features:
 
@@ -8,10 +10,18 @@
 	all : allowed pattern matching on getters
 	all : allowed @:native on class fields
 	all : added static analyzer with constant propagation
+	all : added Haxe-based XML implementation
 	python : added python target
 	flash : flash player 12-14 support
 	js : added @:jsRequire and js.Lib.require
-	cs : added @:bridgeProperties, which creates native property bridges for all haxe properties in the annotated class
+	js : support haxe.CallStack.exceptionStack
+	cs : added @:bridgeProperties
+	cs : added -D erase_generics
+	cs : added -D dll_import to import haxe-generated dlls
+	java/cs : added `sys.db` package
+	java/cs : clean unused files in output folder, unless `-D keep_old_output` is defined
+	java/cs : added `-c-arg` to add C#/Java compiler arguments
+	cpp : inititial implementation of cppia scripting
 
 	Bugfixes:
 
@@ -30,10 +40,23 @@
 	all : fixed various @:generic issues
 	all : fixed default cases on @:enum abstract being omitted
 	all : fixed various expression positions
+	all : disallowed break/continue in closures in loops
+	all : disallowed inline functions in value places
+	all : fixed parsing of cast followed by parentheses
+	all : fixed resource naming in case of invalid file system characters
+	all : fixed issue with inlined array declarations with field access
 	cpp : fixed issue with the side-effect handler
 	cpp : fixed issue with NativeArray in --no-inline mode
 	php : fixed issue with invalid references for closures in for-loops
 	php : fixed Reflect.compare and string comparison for numeric strings
+	cs/java : fixed various issues with -java-lib and -net-lib. 
+	cs/java : added @:libType to skip checking on -java-lib / -net-lib types
+	cs/java : compilation server now works with C#/Java [experimental support]
+	cs : fixed Type.enumIndex / switch on C# native enums
+	cs : fixed reflection on COM types
+	java : fixed sys.net.Socket server implementation
+	spod : various fixes - working now on cpp, java, neko, php and c#
+	cpp : improved boot order, with enums constants first
 
 	General improvements and optimizations:
 
@@ -46,36 +69,57 @@
 	all : allowed variance on interface variables
 	all : allowed pattern matching on arrays if they are typed as Dynamic
 	all : allowed pattern matching on fields of parent classes
+	all : -D doc-gen no longer implies -dce no
+	all : allowed matching against null on any enum instance
 	flash/js: optimized haxe.ds.StringMap
 	neko : create output directory if it does not exist
 	js : inline Math methods and fields
 	cs/java : optimized Reflect.fields on dynamic structures
 	cs/java : haxe will now clear output directory of old files (use -D keep-old-output to keep them)
+	cs : optimized field lookup structure
 	cs : optimized casting of parametrized types
 	cs : beautify c# code output
+	cs : added `cs.Flags` to manipulate C# enums that can be also flags
 	xml : improved documentation generation and fixed missing entity escaping
+	cpp : property access via Dynamic variables now requires property to be declared with @:nativeProperty
+	cpp : allow injection of code from relative paths using @:sourceFile and @:cppInclude
+	cpp : stronger typing of native functions via cpp.Function + cpp.Callable
+	cpp : moved 'Class' implementation to hx namespace to improve objective C interaction
+	cpp : added file_extension define to change the output filename extension (eg, ".mm")
+	cpp : added pre-calculated hashes to string constants to allow faster lookups
+	cpp : map implementation allows strongly typed interactions in some cases (avoids boxing)
+	cpp : added native WeakMap implementation
+	cpp : put each resource into own cpp file to allow more data/smaller files
 
 	Standard Library:
 
+	all : added typed arrays to haxe.io package
 	all : added haxe.ds.Either
-	all : added haxe.Rest type for representing "rest" arguments in extern method signatures
-	all : added haxe.EitherType abstract type for dealing with externs for dynamic targets
+	all : added haxe.extern.Rest type for representing "rest" arguments in extern method signatures
+	all : added haxe.extern.EitherType abstract type for dealing with externs for dynamic targets
 	all : added haxe.DynamicAccess type for working with dynamic anonymous structures using a Map-like interface
 	all : [breaking] changed haxe.ds.Vector.get to return T instead of Null<T>
 	all : added haxe.macro.Compiler.addGlobalMetadata
+	all : changed haxe.Int64 to be an abstract type instead of a class
+	js : updated HTML externs
 
 	Macro features and changes:
 
 	macro : added Context.getLocalTVars
 	macro : added TypedExprTools.iter
+	macro : added Context.getCallArguments
 	macro : changed @:genericBuild macros to prefer ComplexType returns
 	macro : [breaking] extended TAnonymous structures now have AExtend status instead of AClosed
 	macro : added Context.getDefines
+	macro : fixed file_seek from end (position was inversed)
+	macro : added Context.storeTypedExpr
+	macro : allowed type name reification
 
 	Deprecations:
 
 	all : deprecated structurally extending classes and interfaces
 	sys : Sys.command shell special chars (&|<>#;*?(){}$) are now properly escaped
+	java/cs : Lib.nativeType is now renamed to Lib.getNativeType
 
 2014-04-13: 3.1.3
 

+ 0 - 4
extra/ImportAll.hx

@@ -40,8 +40,6 @@ class ImportAll {
 			if( !Context.defined("js") ) return;
 		case "cpp":
 			if( !Context.defined("cpp") ) return;
-		case "flash8":
-			if( !Context.defined("flash") || Context.defined("flash9") ) return;
 		case "flash":
 			if( !Context.defined("flash9") ) return;
 		case "sys":
@@ -74,8 +72,6 @@ class ImportAll {
 				var full = (pack == "") ? file : pack + "." + file;
 				if( StringTools.endsWith(file, ".hx") ) {
 					var cl = full.substr(0, full.length - 3);
-					if( StringTools.startsWith(cl,"flash8.") )
-						cl = "flash."+cl.substr(7);
 					switch( cl ) {
 					case "ImportAll", "neko.db.MacroManager": continue;
 					case "haxe.TimerQueue": if( Context.defined("neko") || Context.defined("php") || Context.defined("cpp") ) continue;

+ 0 - 7
extra/all.hxml

@@ -8,13 +8,6 @@
 
 --next
 
--swf all.swf
--swf-version 8
--xml flash8.xml
--D flash_lite
-
---next
-
 -js all.js
 -xml js.xml
 

+ 2 - 2
extra/extract.hxml

@@ -1,6 +1,6 @@
 -debug
 -swf-lib library.swf
 -swf test.swf
--swf-version 11.8
---macro patchTypes("../doc/extract.patch")
+-swf-version 15
+--macro patchTypes("../extra/extract.patch")
 --gen-hx-classes

+ 1 - 1
extra/haxelib_src

@@ -1 +1 @@
-Subproject commit 5c5e885c0edd2fd3d5773cb98af337ce17057233
+Subproject commit 0dfb33242a28d5a89178c1e48968174646e0fefe

+ 20 - 7
extra/release-checklist.txt

@@ -1,18 +1,31 @@
+# Preparing related projects
+
+- Check that haxelib is working
+- Make sure to update the haxelib submodule
+- Check that the run-time haxelibs are ready for release: hxcpp, hxjava, hxcs
+
+# Building the binaries and installers
+
 - Make sure CHANGES.txt has a proper date set!
 - Make sure `version` in main.ml has the correct value.
 - Merge development branch into master.
 - Wait for Travis to greenlight master.
 - Tag master as MAJOR.MINOR.PATCH.
 - Wait for builds.haxe.org to build master.
-- If required, tell Caue to fix builds.haxe.org.
 - Get https://github.com/waneck/hxbuilds/tree/master/release-helper
 - Run it with the fileName corresponding to the latest master file name on builds.haxe.org.
-- Upload generated files to some place.
-- Update Haxe download page.
+
+# Making the release
+
+- Push the generated binaries and installers to haxe.org.
+- Copy relevant changelog part to CHANGES.md.
+- Write announcement post.
+- Copy announcement post to RELEASE.md.
+- Update versions.json
+
+# Announcing the release
+
 - Update Github README page.
-- Double-check that you got the links right.
 - Regenerate and upload API documentation.
 - Update http://haxe.org/file/CHANGES.txt
-- Write announcement post.
-- Post announcement post.
-
+- Post announcement post to haxelang.

+ 1 - 1
extra/release.neko

@@ -54,7 +54,7 @@ chdir(dir+"/std/tools");
 
 chdir("haxedoc");
 cmd("haxe haxedoc.hxml");
-cmd(curdir+"haxedoc -v \"../../../../flash8.xml;flash8;flash\" \"../../../../neko.xml;neko\" \"../../../../js.xml;js\" \"../../../../flash9.xml;flash\" \"../../../../php.xml;php\" \"../../../../cpp.xml;cpp\"");
+cmd(curdir+"haxedoc -v \"../../../../neko.xml;neko\" \"../../../../js.xml;js\" \"../../../../flash9.xml;flash\" \"../../../../php.xml;php\" \"../../../../cpp.xml;cpp\"");
 cmd("mv index.html content ../../../doc");
 cmd("mv haxedoc"+binext+" ../../..");
 chdir("..");

+ 113 - 32
filters.ml

@@ -8,7 +8,7 @@ open Typecore
 let rec verify_ast e = match e.eexpr with
 	| TField(_) ->
 		()
-	| TTypeExpr(TClassDecl {cl_kind = KAbstractImpl _}) ->
+	| TTypeExpr(TClassDecl {cl_kind = KAbstractImpl a}) when not (Meta.has Meta.RuntimeValue a.a_meta) ->
 		error "Cannot use abstract as value" e.epos
 	| _ ->
 		Type.iter verify_ast e
@@ -59,11 +59,11 @@ let promote_complex_rhs com e =
 				| [] -> e
 			end
 		| TSwitch(es,cases,edef) ->
-			{e with eexpr = TSwitch(es,List.map (fun (el,e) -> List.map find el,loop f e) cases,match edef with None -> None | Some e -> Some (loop f e)); etype = com.basic.tvoid}
+			{e with eexpr = TSwitch(es,List.map (fun (el,e) -> List.map find el,loop f e) cases,match edef with None -> None | Some e -> Some (loop f e)); }
 		| TIf(eif,ethen,eelse) ->
-			{e with eexpr = TIf(find eif, loop f ethen, match eelse with None -> None | Some e -> Some (loop f e)); etype = com.basic.tvoid}
+			{e with eexpr = TIf(find eif, loop f ethen, match eelse with None -> None | Some e -> Some (loop f e)); }
 		| TTry(e1,el) ->
-			{e with eexpr = TTry(loop f e1, List.map (fun (el,e) -> el,loop f e) el); etype = com.basic.tvoid}
+			{e with eexpr = TTry(loop f e1, List.map (fun (el,e) -> el,loop f e) el); }
 		| TParenthesis e1 when not (Common.defined com Define.As3) ->
 			{e with eexpr = TParenthesis(loop f e1)}
 		| TMeta(m,e1) ->
@@ -81,6 +81,7 @@ let promote_complex_rhs com e =
 			| TVar(v,eo) ->
 				begin match eo with
 					| Some e when is_complex e ->
+						let e = find e in
 						r := (loop (fun e -> mk (TBinop(OpAssign,mk (TLocal v) v.v_type e.epos,e)) v.v_type e.epos) e)
 							:: ((mk (TVar (v,None)) com.basic.tvoid e.epos))
 							:: !r
@@ -138,6 +139,28 @@ let rec add_final_return e =
 			{ e with eexpr = TFunction f }
 		| _ -> e
 
+let rec wrap_js_exceptions com e =
+	let terr = List.find (fun mt -> match mt with TClassDecl {cl_path = ["js";"_Boot"],"HaxeError"} -> true | _ -> false) com.types in
+	let cerr = match terr with TClassDecl c -> c | _ -> assert false in
+
+	let rec is_error t =
+		match follow t with
+		| TInst ({cl_path = (["js"],"Error")},_) -> true
+		| TInst ({cl_super = Some (csup,tl)}, _) -> is_error (TInst (csup,tl))
+		| _ -> false
+	in
+
+	let rec loop e =
+		match e.eexpr with
+		| TThrow eerr when not (is_error eerr.etype) ->
+			let ewrap = { eerr with eexpr = TNew (cerr,[],[eerr]) } in
+			{ e with eexpr = TThrow ewrap }
+		| _ ->
+			Type.map_expr loop e
+	in
+
+	loop e
+
 (* -------------------------------------------------------------------------- *)
 (* CHECK LOCAL VARS INIT *)
 
@@ -338,13 +361,13 @@ let captured_vars com e =
 			method captured_type t = TInst (cnativearray,[t])
 
 			method mk_ref v ve p =
-				let earg = match ve with
-					| None ->
-						let t = match v.v_type with TInst (_, [t]) -> t | _ -> assert false in
-						mk (TConst TNull) t p (* generator will do the right thing for the non-nullable types *)
-					| Some e -> e
-				in
-				{ (Optimizer.mk_untyped_call "__array__" p [earg]) with etype = v.v_type }
+				match ve with
+				| None ->
+					let eone = mk (TConst (TInt (Int32.of_int 1))) t.tint p in
+					let t = match v.v_type with TInst (_, [t]) -> t | _ -> assert false in
+					mk (TNew (cnativearray,[t],[eone])) v.v_type p
+				| Some e ->
+					{ (Optimizer.mk_untyped_call "__array__" p [e]) with etype = v.v_type }
 
 			method mk_ref_access e v =
 				mk (TArray ({ e with etype = v.v_type }, mk (TConst (TInt 0l)) t.tint e.epos)) e.etype e.epos
@@ -630,7 +653,7 @@ let rename_local_vars ctx e =
 			let old = save() in
 			(* we have to look ahead for vars on these targets (issue #3344) *)
 			begin match ctx.com.platform with
-				| Js | Flash8 ->
+				| Js ->
 					let rec check_var e = match e.eexpr with
 						| TVar (v,eo) ->
 							(match eo with None -> () | Some e -> loop e);
@@ -681,10 +704,10 @@ let rename_local_vars ctx e =
 	loop e;
 	e
 
-let check_unification com e t =
+let check_unification ctx e t =
 	begin match follow e.etype,follow t with
 		| TEnum _,TDynamic _ ->
-			add_feature com "may_print_enum";
+			Hashtbl.replace ctx.curclass.cl_module.m_extra.m_features "may_print_enum" true;
 		| _ ->
 			()
 	end;
@@ -702,24 +725,44 @@ let check_unification com e t =
 (* Saves a class state so it can be restored later, e.g. after DCE or native path rewrite *)
 let save_class_state ctx t = match t with
 	| TClassDecl c ->
-		let meta = c.cl_meta and path = c.cl_path and ext = c.cl_extern in
-		let fl = c.cl_fields and ofl = c.cl_ordered_fields and st = c.cl_statics and ost = c.cl_ordered_statics in
-		let cst = c.cl_constructor and over = c.cl_overrides in
-		let oflk = List.map (fun f -> f.cf_kind,f.cf_expr,f.cf_type) ofl in
-		let ostk = List.map (fun f -> f.cf_kind,f.cf_expr,f.cf_type) ost in
+		let mk_field_restore f =
+			let rec mk_overload_restore f =
+				f.cf_name,f.cf_kind,f.cf_expr,f.cf_type,f.cf_meta,f.cf_params
+			in
+			( f,mk_overload_restore f, List.map (fun f -> f,mk_overload_restore f) f.cf_overloads )
+		in
+		let restore_field (f,res,overloads) =
+			let restore_field (f,(name,kind,expr,t,meta,params)) =
+				f.cf_name <- name; f.cf_kind <- kind; f.cf_expr <- expr; f.cf_type <- t; f.cf_meta <- meta; f.cf_params <- params;
+				f
+			in
+			let f = restore_field (f,res) in
+			f.cf_overloads <- List.map restore_field overloads;
+			f
+		in
+		let mk_pmap lst =
+			List.fold_left (fun pmap f -> PMap.add f.cf_name f pmap) PMap.empty lst
+		in
+
+		let meta = c.cl_meta and path = c.cl_path and ext = c.cl_extern and over = c.cl_overrides in
+		let sup = c.cl_super and impl = c.cl_implements in
+		let csr = Option.map (mk_field_restore) c.cl_constructor in
+		let ofr = List.map (mk_field_restore) c.cl_ordered_fields in
+		let osr = List.map (mk_field_restore) c.cl_ordered_statics in
+		let init = c.cl_init in
 		c.cl_restore <- (fun() ->
+			c.cl_super <- sup;
+			c.cl_implements <- impl;
 			c.cl_meta <- meta;
 			c.cl_extern <- ext;
 			c.cl_path <- path;
-			c.cl_fields <- fl;
-			c.cl_ordered_fields <- ofl;
-			c.cl_statics <- st;
-			c.cl_ordered_statics <- ost;
-			c.cl_constructor <- cst;
+			c.cl_init <- init;
+			c.cl_ordered_fields <- List.map restore_field ofr;
+			c.cl_ordered_statics <- List.map restore_field osr;
+			c.cl_fields <- mk_pmap c.cl_ordered_fields;
+			c.cl_statics <- mk_pmap c.cl_ordered_statics;
+			c.cl_constructor <- Option.map restore_field csr;
 			c.cl_overrides <- over;
-			(* DCE might modify the cf_kind, so let's restore it as well *)
-			List.iter2 (fun f (k,e,t) -> f.cf_kind <- k; f.cf_expr <- e; f.cf_type <- t;) ofl oflk;
-			List.iter2 (fun f (k,e,t) -> f.cf_kind <- k; f.cf_expr <- e; f.cf_type <- t;) ost ostk;
 		)
 	| _ ->
 		()
@@ -955,6 +998,37 @@ let check_void_field ctx t = match t with
 	| _ ->
 		()
 
+(* Interfaces have no 'super', but can extend many other interfaces.
+   This makes the first extended (implemented) interface the super for efficiency reasons (you can get one for 'free')
+   and leaves the remaining ones as 'implemented' *)
+let promote_first_interface_to_super ctx t = match t with
+	| TClassDecl c when c.cl_interface ->
+		begin match c.cl_implements with
+		| ({ cl_path = ["cpp";"rtti"],_ },_ ) :: _ -> ()
+		| first_interface  :: remaining ->
+			c.cl_super <- Some first_interface;
+			c.cl_implements <- remaining
+		| _ -> ()
+		end
+	| _ ->
+		()
+
+let commit_features ctx t =
+	let m = (t_infos t).mt_module in
+	Hashtbl.iter (fun k v ->
+		Common.add_feature ctx.com k;
+	) m.m_extra.m_features
+
+let check_reserved_type_paths ctx t =
+	let check path pos =
+		if List.mem path ctx.com.config.pf_reserved_type_paths then
+			ctx.com.warning ("Type path " ^ (s_type_path path) ^ " is reserved on this target") pos
+	in
+	match t with
+	| TClassDecl c when not c.cl_extern -> check c.cl_path c.cl_pos
+	| TEnumDecl e when not e.e_extern -> check e.e_path e.e_pos
+	| _ -> ()
+
 (* PASS 3 end *)
 
 let run_expression_filters ctx filters t =
@@ -1028,7 +1102,7 @@ let run com tctx main =
 	if use_static_analyzer then begin
 		(* PASS 1: general expression filters *)
 		let filters = [
-			Codegen.UnificationCallback.run (check_unification com);
+			Codegen.UnificationCallback.run (check_unification tctx);
 			Codegen.AbstractCast.handle_abstract_casts tctx;
 			Optimizer.inline_constructors tctx;
 			Optimizer.reduce_expression tctx;
@@ -1041,22 +1115,25 @@ let run com tctx main =
 		let filters = [
 			Optimizer.sanitize com;
 			if com.config.pf_add_final_return then add_final_return else (fun e -> e);
+			if com.platform = Js then wrap_js_exceptions com else (fun e -> e);
 			rename_local_vars tctx;
 		] in
 		List.iter (run_expression_filters tctx filters) new_types;
 	end else begin
 		(* PASS 1: general expression filters *)
 		let filters = [
-			Codegen.UnificationCallback.run (check_unification com);
+			Codegen.UnificationCallback.run (check_unification tctx);
 			Codegen.AbstractCast.handle_abstract_casts tctx;
 			blockify_ast;
 			( if (Common.defined com Define.NoSimplify) || (Common.defined com Define.Cppia) ||
-						( match com.platform with Cpp | Flash8 -> false | _ -> true ) then
+						( match com.platform with Cpp -> false | _ -> true ) then
 					fun e -> e
 				else
 					fun e ->
 						let save = save_locals tctx in
-						let e = try snd (Analyzer.Simplifier.apply com (Typecore.gen_local tctx) e) with Exit -> e in
+						let timer = timer "analyzer-simplify-apply" in
+						let e = try snd (Analyzer.Simplifier.apply com e) with Exit -> e in
+						timer();
 						save();
 					e );
 			if com.foptimize then (fun e -> Optimizer.reduce_expression tctx (Optimizer.inline_constructors tctx e)) else Optimizer.sanitize com;
@@ -1064,6 +1141,7 @@ let run com tctx main =
 			captured_vars com;
 			promote_complex_rhs com;
 			if com.config.pf_add_final_return then add_final_return else (fun e -> e);
+			if com.platform = Js then wrap_js_exceptions com else (fun e -> e);
 			rename_local_vars tctx;
 		] in
 		List.iter (run_expression_filters tctx filters) new_types;
@@ -1081,7 +1159,7 @@ let run com tctx main =
 	(* check @:remove metadata before DCE so it is ignored there (issue #2923) *)
 	List.iter (check_remove_metadata tctx) com.types;
 	(* DCE *)
-	let dce_mode = if Common.defined com Define.As3 || Common.defined com Define.DocGen then
+	let dce_mode = if Common.defined com Define.As3 then
 		"no"
 	else
 		(try Common.defined_value com Define.Dce with _ -> "no")
@@ -1113,5 +1191,8 @@ let run com tctx main =
 		(match com.platform with | Java | Cs -> (fun _ _ -> ()) | _ -> add_field_inits);
 		add_meta_field;
 		check_void_field;
+		(match com.platform with | Cpp -> promote_first_interface_to_super | _ -> (fun _ _ -> ()) );
+		commit_features;
+		(if com.config.pf_reserved_type_paths <> [] then check_reserved_type_paths else (fun _ _ -> ()));
 	] in
 	List.iter (fun t -> List.iter (fun f -> f tctx t) type_filters) com.types

+ 14 - 2
genas3.ml

@@ -54,6 +54,14 @@ let is_var_field f =
 	| _ ->
 		false
 
+let is_special_compare e1 e2 =
+	match e1.eexpr, e2.eexpr with
+	| TConst TNull, _  | _ , TConst TNull -> None
+	| _ ->
+	match follow e1.etype, follow e2.etype with
+	| TInst ({ cl_path = ["flash"],"NativeXml" } as c,_) , _ | _ , TInst ({ cl_path = ["flash"],"NativeXml" } as c,_) -> Some c
+	| _ -> None
+
 let protect name =
 	match name with
 	| "Error" | "Namespace" -> "_" ^ name
@@ -322,6 +330,7 @@ let generate_resources infos =
 		let dir = (infos.com.file :: ["__res"]) in
 		create_dir [] dir;
 		let add_resource name data =
+			let name = Base64.str_encode name in
 			let ch = open_out_bin (String.concat "/" (dir @ [name])) in
 			output_string ch data;
 			close_out ch
@@ -336,9 +345,9 @@ let generate_resources infos =
 		Hashtbl.iter (fun name _ ->
 			let varname = ("v" ^ (string_of_int !k)) in
 			k := !k + 1;
-			print ctx "\t\t[Embed(source = \"__res/%s\", mimeType = \"application/octet-stream\")]\n" name;
+			print ctx "\t\t[Embed(source = \"__res/%s\", mimeType = \"application/octet-stream\")]\n" (Base64.str_encode name);
 			print ctx "\t\tpublic static var %s:Class;\n" varname;
-			inits := ("list[\"" ^name^ "\"] = " ^ varname ^ ";") :: !inits;
+			inits := ("list[\"" ^ Ast.s_escape name ^ "\"] = " ^ varname ^ ";") :: !inits;
 		) infos.com.resources;
 		spr ctx "\t\tstatic public function __init__():void {\n";
 		spr ctx "\t\t\tlist = new Dictionary();\n";
@@ -578,6 +587,9 @@ and gen_expr ctx e =
 		spr ctx "[";
 		gen_value ctx e2;
 		spr ctx "]";
+	| TBinop (Ast.OpEq,e1,e2) when (match is_special_compare e1 e2 with Some c -> true | None -> false) ->
+		let c = match is_special_compare e1 e2 with Some c -> c | None -> assert false in
+		gen_expr ctx (mk (TCall (mk (TField (mk (TTypeExpr (TClassDecl c)) t_dynamic e.epos,FDynamic "compare")) t_dynamic e.epos,[e1;e2])) ctx.inf.com.basic.tbool e.epos);
 	(* what is this used for? *)
 (* 	| TBinop (op,{ eexpr = TField (e1,s) },e2) ->
 		gen_value_op ctx e1;

A diferenza do arquivo foi suprimida porque é demasiado grande
+ 318 - 138
gencommon.ml


A diferenza do arquivo foi suprimida porque é demasiado grande
+ 308 - 133
gencpp.ml


A diferenza do arquivo foi suprimida porque é demasiado grande
+ 437 - 192
gencs.ml


A diferenza do arquivo foi suprimida porque é demasiado grande
+ 377 - 175
genjava.ml


+ 48 - 34
genjs.ml

@@ -29,7 +29,7 @@ type pos = Ast.pos
 type sourcemap = {
 	sources : (string) DynArray.t;
 	sources_hash : (string, int) Hashtbl.t;
-	mappings : Buffer.t;
+	mappings : Rbuffer.t;
 
 	mutable source_last_line : int;
 	mutable source_last_col : int;
@@ -41,7 +41,7 @@ type sourcemap = {
 
 type ctx = {
 	com : Common.context;
-	buf : Buffer.t;
+	buf : Rbuffer.t;
 	packages : (string list,unit) Hashtbl.t;
 	smap : sourcemap;
 	js_modern : bool;
@@ -112,7 +112,7 @@ let kwds2 =
 	h
 
 let valid_js_ident s =
-	try
+	String.length s > 0 && try
 		for i = 0 to String.length s - 1 do
 			match String.unsafe_get s i with
 			| 'a'..'z' | 'A'..'Z' | '$' | '_' -> ()
@@ -141,7 +141,7 @@ let handle_newlines ctx str =
 		let rec loop from =
 			try begin
 				let next = String.index_from str from '\n' + 1 in
-				Buffer.add_char ctx.smap.mappings ';';
+				Rbuffer.add_char ctx.smap.mappings ';';
 				ctx.smap.output_last_col <- 0;
 				ctx.smap.print_comma <- false;
 				loop next
@@ -154,13 +154,13 @@ let handle_newlines ctx str =
 let spr ctx s =
 	ctx.separator <- false;
 	handle_newlines ctx s;
-	Buffer.add_string ctx.buf s
+	Rbuffer.add_string ctx.buf s
 
 let print ctx =
 	ctx.separator <- false;
 	Printf.kprintf (fun s -> begin
 		handle_newlines ctx s;
-		Buffer.add_string ctx.buf s
+		Rbuffer.add_string ctx.buf s
 	end)
 
 let unsupported p = error "This expression cannot be compiled to Javascript" p
@@ -182,7 +182,7 @@ let add_mapping ctx e =
 	let col = col - 1 in
 	if smap.source_last_file != file || smap.source_last_line != line || smap.source_last_col != col then begin
 		if smap.print_comma then
-			Buffer.add_char smap.mappings ','
+			Rbuffer.add_char smap.mappings ','
 		else
 			smap.print_comma <- true;
 
@@ -209,7 +209,7 @@ let add_mapping ctx e =
 				let continuation_bit = base in
 				let digit = vlq land mask in
 				let next = vlq asr shift in
-				Buffer.add_char smap.mappings (encode_digit (
+				Rbuffer.add_char smap.mappings (encode_digit (
 					if next > 0 then digit lor continuation_bit else digit));
 				if next > 0 then loop next else ()
 			in
@@ -227,14 +227,8 @@ let add_mapping ctx e =
 		smap.output_last_col <- smap.output_current_col
 	end
 
-let basename path =
-	try
-		let idx = String.rindex path '/' in
-		String.sub path (idx + 1) (String.length path - idx - 1)
-	with Not_found -> path
-
 let write_mappings ctx =
-	let basefile = basename ctx.com.file in
+	let basefile = Filename.basename ctx.com.file in
 	print ctx "\n//# sourceMappingURL=%s.map" basefile;
 	let channel = open_out_bin (ctx.com.file ^ ".map") in
 	let sources = DynArray.to_list ctx.smap.sources in
@@ -255,23 +249,23 @@ let write_mappings ctx =
 	end;
 	output_string channel "\"names\":[],\n";
 	output_string channel "\"mappings\":\"";
-	Buffer.output_buffer channel ctx.smap.mappings;
+	Rbuffer.output_buffer channel ctx.smap.mappings;
 	output_string channel "\"\n";
 	output_string channel "}";
 	close_out channel
 
 let newline ctx =
-	match Buffer.nth ctx.buf (Buffer.length ctx.buf - 1) with
+	match Rbuffer.nth ctx.buf (Rbuffer.length ctx.buf - 1) with
 	| '}' | '{' | ':' when not ctx.separator -> print ctx "\n%s" ctx.tabs
 	| _ -> print ctx ";\n%s" ctx.tabs
 
 let newprop ctx =
-	match Buffer.nth ctx.buf (Buffer.length ctx.buf - 1) with
+	match Rbuffer.nth ctx.buf (Rbuffer.length ctx.buf - 1) with
 	| '{' -> print ctx "\n%s" ctx.tabs
 	| _ -> print ctx "\n%s," ctx.tabs
 
 let semicolon ctx =
-	match Buffer.nth ctx.buf (Buffer.length ctx.buf - 1) with
+	match Rbuffer.nth ctx.buf (Rbuffer.length ctx.buf - 1) with
 	| '}' when not ctx.separator -> ()
 	| _ -> spr ctx ";"
 
@@ -627,7 +621,11 @@ and gen_expr ctx e =
 		handle_break();
 	| TObjectDecl fields ->
 		spr ctx "{ ";
-		concat ctx ", " (fun (f,e) -> print ctx "%s : " (anon_field f); gen_value ctx e) fields;
+		concat ctx ", " (fun (f,e) -> (match e.eexpr with
+			| TMeta((Meta.QuotedField,_,_),e) -> print ctx "'%s' : " f;
+			| _ -> print ctx "%s : " (anon_field f));
+			gen_value ctx e
+		) fields;
 		spr ctx "}";
 		ctx.separator <- true
 	| TFor (v,it,e) ->
@@ -665,6 +663,17 @@ and gen_expr ctx e =
 		let bend = open_block ctx in
 		let last = ref false in
 		let else_block = ref false in
+
+		if (has_feature ctx "haxe.CallStack.exceptionStack") then begin
+			newline ctx;
+			print ctx "%s.lastException = %s" (ctx.type_accessor (TClassDecl { null_class with cl_path = ["haxe"],"CallStack" })) vname
+		end;
+
+		if (has_feature ctx "js.Boot.HaxeError") then begin
+			newline ctx;
+			print ctx "if (%s instanceof %s) %s = %s.val" vname (ctx.type_accessor (TClassDecl { null_class with cl_path = ["js";"_Boot"],"HaxeError" })) vname vname;
+		end;
+
 		List.iter (fun (v,e) ->
 			if !last then () else
 			let t = (match follow v.v_type with
@@ -1127,14 +1136,14 @@ let generate_static ctx (c,f,e) =
 	gen_value ctx e;
 	newline ctx
 
-let generate_require ctx c =
-	let _, args, mp = Meta.get Meta.JsRequire c.cl_meta in
-	let p = (s_path ctx c.cl_path) in
+let generate_require ctx path meta =
+	let _, args, mp = Meta.get Meta.JsRequire meta in
+	let p = (s_path ctx path) in
 
 	if ctx.js_flatten then
 		spr ctx "var "
 	else
-		generate_package_create ctx c.cl_path;
+		generate_package_create ctx path;
 
 	(match args with
 	| [(EConst(String(module_name)),_)] ->
@@ -1160,14 +1169,15 @@ let generate_type ctx = function
 			()
 		else if not c.cl_extern then
 			generate_class ctx c
-		else if (Meta.has Meta.JsRequire c.cl_meta) && (Meta.has Meta.ReallyUsed c.cl_meta) then
-			generate_require ctx c
+		else if Meta.has Meta.JsRequire c.cl_meta && is_directly_used ctx.com c.cl_meta then
+			generate_require ctx c.cl_path c.cl_meta
 		else if not ctx.js_flatten && Meta.has Meta.InitPackage c.cl_meta then
 			(match c.cl_path with
 			| ([],_) -> ()
 			| _ -> generate_package_create ctx c.cl_path)
 	| TEnumDecl e when e.e_extern ->
-		()
+		if Meta.has Meta.JsRequire e.e_meta && is_directly_used ctx.com e.e_meta then
+			generate_require ctx e.e_path e.e_meta
 	| TEnumDecl e -> generate_enum ctx e
 	| TTypeDecl _ | TAbstractDecl _ -> ()
 
@@ -1177,7 +1187,7 @@ let set_current_class ctx c =
 let alloc_ctx com =
 	let ctx = {
 		com = com;
-		buf = Buffer.create 16000;
+		buf = Rbuffer.create 16000;
 		packages = Hashtbl.create 0;
 		smap = {
 			source_last_line = 0;
@@ -1188,10 +1198,10 @@ let alloc_ctx com =
 			output_current_col = 0;
 			sources = DynArray.create();
 			sources_hash = Hashtbl.create 0;
-			mappings = Buffer.create 16;
+			mappings = Rbuffer.create 16;
 		};
 		js_modern = not (Common.defined com Define.JsClassic);
-		js_flatten = Common.defined com Define.JsFlatten;
+		js_flatten = not (Common.defined com Define.JsUnflatten);
 		statics = [];
 		inits = [];
 		current = null_class;
@@ -1209,15 +1219,15 @@ let alloc_ctx com =
 		match t with
 		| TClassDecl ({ cl_extern = true } as c) when not (Meta.has Meta.JsRequire c.cl_meta)
 			-> dot_path p
-		| TEnumDecl { e_extern = true }
+		| TEnumDecl ({ e_extern = true } as e) when not (Meta.has Meta.JsRequire e.e_meta)
 			-> dot_path p
 		| _ -> s_path ctx p);
 	ctx
 
 let gen_single_expr ctx e expr =
 	if expr then gen_expr ctx e else gen_value ctx e;
-	let str = Buffer.contents ctx.buf in
-	Buffer.reset ctx.buf;
+	let str = Rbuffer.unsafe_contents ctx.buf in
+	Rbuffer.reset ctx.buf;
 	ctx.id_counter <- 0;
 	str
 
@@ -1285,6 +1295,10 @@ let generate com =
 		closureArgs
 	in
 
+	if Common.raw_defined com "nodejs" then
+		(* Add node globals to pseudo-keywords, so they are not shadowed by local vars *)
+		List.iter (fun s -> Hashtbl.replace kwds2 s ()) [ "global"; "process"; "__filename"; "__dirname"; "module" ];
+
 	if ctx.js_modern then begin
 		(* Additional ES5 strict mode keywords. *)
 		List.iter (fun s -> Hashtbl.replace kwds s ()) [ "arguments"; "eval" ];
@@ -1385,7 +1399,7 @@ let generate com =
 	end;
 	if com.debug then write_mappings ctx else (try Sys.remove (com.file ^ ".map") with _ -> ());
 	let ch = open_out_bin com.file in
-	output_string ch (Buffer.contents ctx.buf);
+	Rbuffer.output_buffer ch ctx.buf;
 	close_out ch);
 	t()
 

+ 12 - 2
genneko.ml

@@ -332,6 +332,7 @@ and gen_expr ctx e =
 				let path = (match follow v.v_type with
 					| TInst (c,_) -> Some c.cl_path
 					| TEnum (e,_) -> Some e.e_path
+					| TAbstract (a,_) -> Some a.a_path
 					| TDynamic _ -> None
 					| _ -> assert false
 				) in
@@ -662,7 +663,14 @@ let generate_libs_init = function
 			var @b = if( @s == "Windows" )
 				@env("HAXEPATH") + "\\lib\\"
 				else try $loader.loadprim("std@file_contents",1)(@env("HOME")+"/.haxelib") + "/"
-				catch e if( @s == "Linux" ) "/usr/lib/haxe/lib/" else "/usr/local/lib/haxe/lib/";
+				catch e
+					if( @s == "Linux" )
+						if( $loader(loadprim("std@sys_exists",1))("/usr/lib/haxe/lib") )
+							"/usr/lib/haxe/lib"
+						else
+							"/usr/share/haxe/lib/"
+					else
+						"/usr/local/lib/haxe/lib/";
 			if( try $loader.loadprim("std@sys_file_type",1)(".haxelib") == "dir" catch e false ) @b = $loader.loadprim("std@file_full_path",1)(".haxelib") + "/";
 			if( $loader.loadprim("std@sys_is64",0)() ) @s = @s + 64;
 			@b = @b + "/"
@@ -685,7 +693,9 @@ let generate_libs_init = function
 						op "+" (call p (loadp "file_contents" 1) [op "+" (call p (ident p "@env") [str p "HOME"]) (str p "/.haxelib")]) (str p "/"),
 						"e",
 						(EIf (op "==" es (str p "Linux"),
-							str p "/usr/lib/haxe/lib/",
+							(EIf (call p (loadp "sys_exists" 1) [ str p "/usr/lib/haxe/lib" ],
+								str p "/usr/lib/haxe/lib/",
+								Some (str p "/usr/share/haxe/lib/")),p),
 							Some (str p "/usr/local/lib/haxe/lib/")
 						),p)
 					),p)

+ 1 - 9
genphp.ml

@@ -111,10 +111,6 @@ and type_string_suff suffix haxe_type =
 	| TAbstract ({ a_path = [],"Float" },[]) -> "double"
 	| TAbstract ({ a_path = [],"Bool" },[]) -> "bool"
 	| TAbstract ({ a_path = [],"Void" },[]) -> "Void"
-	| TEnum ({ e_path = ([],"Void") },[]) -> "Void"
-	| TEnum ({ e_path = ([],"Bool") },[]) -> "bool"
-	| TInst ({ cl_path = ([],"Float") },[]) -> "double"
-	| TInst ({ cl_path = ([],"Int") },[]) -> "int"
 	| 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
@@ -336,14 +332,10 @@ let create_directory com ldir =
  	(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 i = ref 0 in
-	String.iter (fun c ->
-		if c = '\\' || c = '/' || c = ':' || c = '*' || c = '?' || c = '"' || c = '<' || c = '>' || c = '|' then String.blit "_" 0 name !i 1;
-		incr i
-	) name;
 	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

A diferenza do arquivo foi suprimida porque é demasiado grande
+ 396 - 217
genpy.ml


+ 3 - 35
genswf.ml

@@ -730,35 +730,6 @@ let remove_classes toremove lib hcl =
 			toremove := List.filter (fun p -> not (List.mem p classes)) !toremove;
 			fst lib, tags (snd lib)
 
-let build_swf8 com codeclip exports =
-	let code, clips = Genswf8.generate com in
-	let cid = ref 0 in
-	let clips = List.fold_left (fun acc m ->
-		let ename = Ast.s_type_path m in
-		if Hashtbl.mem exports ename then
-			acc
-		else begin
-			incr cid;
-			tag ~ext:true (TClip { c_id = !cid; c_frame_count = 1; c_tags = [] }) ::
-			tag ~ext:true (TExport [{ exp_id = !cid; exp_name = ename }]) ::
-			acc
-		end;
-	) [] clips in
-	let code = (match codeclip with
-		| None -> List.map tag code
-		| Some link ->
-			incr cid;
-			[
-				tag (TClip {
-					c_id = !cid;
-					c_frame_count = 1;
-					c_tags = List.map tag code @ [tag TShowFrame];
-				});
-				tag (TExport [{ exp_id = !cid; exp_name = link }]);
-			]
-	) in
-	clips @ code
-
 type file_format =
 	| BJPG
 	| BPNG
@@ -1062,7 +1033,6 @@ let merge com file priority (h1,tags1) (h2,tags2) =
 			classes := !classes @ List.map (fun e -> { f9_cid = Some e.exp_id; f9_classname = e.exp_name }) el;
 			false
 		| TF9Classes el when !nframe = 0 ->
-			if com.flash_version < 9. then failwith "You can't use AS3 SWF with Flash8 target";
 			classes := !classes @ List.filter (fun e -> e.f9_cid <> None) el;
 			false
 		| _ -> true
@@ -1108,9 +1078,7 @@ let merge com file priority (h1,tags1) (h2,tags2) =
 
 let generate com swf_header =
 	let t = Common.timer "generate swf" in
-	let isf9 = com.flash_version >= 9. in
 	let swc = if Common.defined com Define.Swc then Some (ref "") else None in
-	if swc <> None && not isf9 then failwith "SWC support is only available for Flash9+";
 	let file , codeclip = (try let f , c = ExtString.String.split com.file "@" in f, Some c with _ -> com.file , None) in
 	(* list exports *)
 	let exports = Hashtbl.create 0 in
@@ -1144,7 +1112,7 @@ let generate com swf_header =
 		) tags;
 	) com.swf_libs;
 	(* build haxe swf *)
-	let tags = if isf9 then build_swf9 com file swc else build_swf8 com codeclip exports in
+	let tags = build_swf9 com file swc in
 	let header, bg = (match swf_header with None -> default_header com | Some h -> convert_header com h) in
 	let bg = tag (TSetBgColor { cr = bg lsr 16; cg = (bg lsr 8) land 0xFF; cb = bg land 0xFF }) in
 	let swf_debug_password = try
@@ -1152,7 +1120,7 @@ let generate com swf_header =
 	with Not_found ->
 		""
 	in
-	let debug = (if isf9 && Common.defined com Define.Fdb then [tag (TEnableDebugger2 (0, swf_debug_password))] else []) in
+	let debug = (if Common.defined com Define.Fdb then [tag (TEnableDebugger2 (0, swf_debug_password))] else []) in
 	let meta_data =
 		try
 			let file = Common.defined_value com Define.SwfMetadata in
@@ -1165,7 +1133,7 @@ let generate com swf_header =
 	let fattr = (if com.flash_version < 8. then [] else
 		[tag (TFilesAttributes {
 			fa_network = Common.defined com Define.NetworkSandbox;
-			fa_as3 = isf9;
+			fa_as3 = true;
 			fa_metadata = meta_data <> [];
 			fa_gpu = com.flash_version > 9. && Common.defined com Define.SwfGpu;
 			fa_direct_blt = com.flash_version > 9. && Common.defined com Define.SwfDirectBlit;

+ 0 - 1590
genswf8.ml

@@ -1,1590 +0,0 @@
-(*
- * Copyright (C)2005-2013 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.
- *)
-
-open Swf
-open Ast
-open Type
-open Common
-
-type register =
-	| NoReg
-	| Reg of int
-
-type context = {
-
-	stack : Codegen.stack_context;
-
-	(* segs *)
-	mutable segs : (actions * (string * bool, int) Hashtbl.t) list;
-
-	(* code *)
-	mutable opcodes : actions;
-	mutable code_pos : int;
-	mutable stack_size : int;
-	mutable opt_push : bool;
-	mutable ident_count : int;
-	mutable ident_size : int;
-
-	(* management *)
-	com : Common.context;
-	packages : (string list,unit) Hashtbl.t;
-	flash6 : bool;
-	mutable idents : (string * bool,int) Hashtbl.t;
-	mutable movieclips : path list;
-	mutable inits : texpr list;
-	mutable statics : (tclass * bool * string * texpr) list;
-	mutable regs : (string,register) PMap.t;
-	mutable reg_count : int;
-	mutable reg_max : int;
-	mutable fun_stack : int;
-	mutable curclass : tclass;
-	mutable curmethod : (string * bool);
-	mutable fun_pargs : (int * bool list) list;
-	mutable static_init : bool;
-	mutable extern_boot : bool;
-
-	(* loops *)
-	mutable breaks : (unit -> unit) list;
-	mutable continues : (int -> unit) list;
-	mutable loop_stack : int;
-	mutable in_loop : bool;
-}
-
-let invalid_expr p = error "Invalid expression" p
-let stack_error p = error "Stack error" p
-let protect_all = ref true
-
-(* -------------------------------------------------------------- *)
-(* Bytecode Helpers *)
-
-type tmp_variable =
-	| TmpReg of int
-	| TmpVar of string * int
-
-type kind =
-	| VarReg of int
-	| VarStr
-	| VarObj
-	| VarClosure
-	| VarVolatile
-
-type push_style =
-	| VStr of string * bool
-	| VInt of int
-	| VInt32 of int32
-	| VFloat of float
-	| VReg of int
-	| VThis
-	| VNull
-	| VUndefined
-	| VSuper
-
-let stack_delta = function
-	| APush l -> List.length l
-	| ASetReg _ -> 0
-	| AAdd | ADivide | ASubtract | AMultiply | AMod | AStringAdd -> -1
-	| AAnd | AOr | AXor | AShl | AShr | AAsr -> -1
-	| ACompare | AGreater -> -1
-	| AEval | ANot | AJump _ | AToInt | AToNumber | AToString | ATry _ | ASwap -> 0
-	| ACondJump _ -> -1
-	| AEqual | APhysEqual -> -1
-	| ANew -> -1 (** only if 0 params **)
-	| AObject | AInitArray -> 0 (** calculated outside **)
-	| ASet -> -2
-	| APop -> -1
-	| AFunction _ | AFunction2 _ -> 1
-	| ADup -> 1
-	| AWith _ -> -1
-	| AObjGet -> -1
-	| AObjSet -> -3
-	| ALocalVar -> -1
-	| ALocalAssign -> -2
-	| AReturn -> -1
-	| AGetURL2 _ -> -2
-	| ADeleteObj | AInstanceOf | ACast -> -1
-	| AExtends | AImplements -> -2
-	| AEnum2 | ATrace | AThrow -> -1
-	| AGetTimer -> 1
-	| AIncrement | ADecrement | AChr | AOrd | ARandom | ADelete | ATypeOf | ATargetPath -> 0
-	| AObjCall | ACall | ANewMethod -> assert false
-	| AStringPool _ -> 0
-	| AFSCommand2 -> 0
-	| op -> failwith ("Unknown stack delta for " ^ (ActionScript.action_string (fun _ -> "") 0 op))
-
-let overflow ctx =
-	failwith ("In or near the method " ^ s_type_path ctx.curclass.cl_path ^ "." ^ fst ctx.curmethod ^
-	" too much code is causing an overflow that can't be handled by the SWF format. " ^
-	"Please split your code in several methods so it can be correctly compiled.")
-
-let write ctx op =
-	let write b op =
-		DynArray.add ctx.opcodes op;
-		ctx.code_pos <- ctx.code_pos + 1;
-		ctx.stack_size <- ctx.stack_size + stack_delta op;
-		ctx.opt_push <- b
-	in
-	match op with
-	| APush l when ctx.opt_push ->
-		(match DynArray.last ctx.opcodes with
-		| (APush l2) as a ->
-			ctx.code_pos <- ctx.code_pos - 1;
-			ctx.stack_size <- ctx.stack_size - stack_delta a;
-			DynArray.delete_last ctx.opcodes;
-			write true (APush (l2 @ l))
-		| _ ->
-			assert false)
-	| APush _ ->
-		write true op
-	| _ ->
-		write false op
-
-let call ctx kind n =
-	let op , n = (match kind with
-		| VarReg r ->
-			write ctx (APush [PReg r;PUndefined]);
-			AObjCall , n + 2
-		| VarStr ->
-			ACall , n + 1
-		| VarClosure | VarObj ->
-			AObjCall , n + 2
-		| VarVolatile ->
-			assert false
-	) in
-	DynArray.add ctx.opcodes op;
-	ctx.opt_push <- false;
-	ctx.code_pos <- ctx.code_pos + 1;
-	ctx.stack_size <- ctx.stack_size - n
-
-let new_call ctx kind n  =
-	let op , n = (match kind with
-		| VarReg r ->
-			write ctx (APush [PReg r;PUndefined]);
-			ANewMethod , n + 2
-		| VarStr ->
-			ANew , n + 1
-		| VarClosure | VarObj ->
-			ANewMethod , n + 2
-		| VarVolatile ->
-			assert false
-	) in
-	DynArray.add ctx.opcodes op;
-	ctx.opt_push <- false;
-	ctx.code_pos <- ctx.code_pos + 1;
-	ctx.stack_size <- ctx.stack_size - n
-
-let unprotect a = !protect_all || a = "" || a = "_" || (a.[0] = '_' && a.[1] != '_')
-
-let rec is_protected_path path ext =
-	match path with
-	| ["flash"] , "Boot" | ["flash"] , "Lib" -> false
-	| "flash" :: _ , _ | [] , "flash" -> ext
-	| [] , "Array" | [] , "Math" | [] , "Date" | [] , "String" | [] , "Bool" -> true
-	| [] , "Int" | [] , "Float" -> true
-	| "_global" :: l , n -> is_protected_path (l,n) ext
-	| _ -> false
-
-let rec is_protected ctx ?(stat=false) t field =
-	match follow t with
-	| TInst (c,_) ->
-		let rec loop c =
-			(is_protected_path c.cl_path c.cl_extern && PMap.mem field (if stat then c.cl_statics else c.cl_fields))
-			|| List.exists (fun (i,_) -> i.cl_path = (["mt"],"Protect") || (not stat && loop i)) c.cl_implements
-			|| (not stat && match c.cl_super with None -> false | Some (c,_) -> loop c)
-		in
-		loop c
-	| TAnon a ->
-		(match !(a.a_status) with
-		| Statics c -> is_protected ctx ~stat:true (TInst (c,[])) field
-		| _ -> false)
-	| _ -> false
-
-let push ctx items =
-	write ctx (APush (List.map (fun i ->
-		match i with
-		| VStr (str,flag) ->
-			let flag = if flag || unprotect str then true else flag in
-			let n = (try
-				Hashtbl.find ctx.idents (str,flag)
-			with Not_found ->
-				let n = ctx.ident_count in
-				ctx.ident_count <- n + 1;
-				ctx.ident_size <- ctx.ident_size + 1 + String.length str;
-				Hashtbl.add ctx.idents (str,flag) n;
-				n
-			) in
-			if n <= 0xFF then
-				PStack n
-			else
-				PStack2 n
-		| VInt n ->
-			PInt (Int32.of_int n)
-		| VInt32 n ->
-			PInt n
-		| VFloat f ->
-			PDouble f
-		| VThis ->
-			PReg 1
-		| VNull ->
-			PNull
-		| VUndefined ->
-			PUndefined
-		| VSuper ->
-			PReg 2
-		| VReg n ->
-			PReg n
-	) items))
-
-let pop ctx n dec =
-	let rec loop n =
-		if n <> 0 then begin
-			write ctx APop;
-			loop (n - 1)
-		end;
-	in
-	if n < 0 then assert false;
-	let old_s = ctx.stack_size in
-	loop n;
-	if not dec then ctx.stack_size <- old_s
-
-let cjmp ctx =
-	write ctx (ACondJump 0);
-	let start_pos = ctx.code_pos in
-	let op_pos = DynArray.length ctx.opcodes - 1 in
-	(fun() ->
-		let delta = ctx.code_pos - start_pos in
-		DynArray.set ctx.opcodes op_pos (ACondJump delta);
-		ctx.opt_push <- false
-	)
-
-let jmp ctx =
-	write ctx (AJump 0);
-	let start_pos = ctx.code_pos in
-	let op_pos = DynArray.length ctx.opcodes - 1 in
-	(fun() ->
-		let delta = ctx.code_pos - start_pos in
-		DynArray.set ctx.opcodes op_pos (AJump delta);
-		ctx.opt_push <- false
-	)
-
-let pos ctx =
-	ctx.opt_push <- false;
-	let start_pos = ctx.code_pos in
-	(fun ~cond ->
-		let delta = start_pos - (ctx.code_pos + 1) in
-		write ctx (if cond then ACondJump delta else AJump delta);
-	)
-
-let jmp_pos ctx cond =
-	write ctx (AJump 0);
-	let start_pos = ctx.code_pos in
-	let op_pos = DynArray.length ctx.opcodes - 1 in
-	(fun pos ->
-		let delta = pos - start_pos in
-		DynArray.set ctx.opcodes op_pos (if cond then ACondJump delta else AJump delta);
-		ctx.opt_push <- false
-	)
-
-let init_array ctx n =
-	push ctx [VInt n];
-	write ctx AInitArray;
-	ctx.stack_size <- ctx.stack_size - n
-
-let setvar ?(retval=false) ctx = function
-	| VarReg (-1) -> assert false (** true, false, null **)
-	| VarReg n -> write ctx (ASetReg n); if not retval then write ctx APop
-	| VarStr
-	| VarObj
-	| VarClosure as s ->
-		if retval then write ctx (ASetReg 0);
-		write ctx (if s = VarStr then ASet else AObjSet);
-		if retval then push ctx [VReg 0]
-	| VarVolatile ->
-		if retval then write ctx (ASetReg 0);
-		init_array ctx 1;
-		write ctx AObjSet;
-		if retval then push ctx [VReg 0]
-
-let getvar ctx = function
-	| VarReg (-1) -> () (** true, false, null **)
-	| VarReg n -> push ctx [VReg n]
-	| VarStr -> write ctx AEval
-	| VarObj -> write ctx AObjGet
-	| VarClosure ->
-		push ctx [VInt 2; VStr ("@closure",false)];
-		call ctx VarStr 2
-	| VarVolatile ->
-		write ctx AObjGet;
-		push ctx [VInt 0];
-		write ctx AObjGet
-
-let gen_path ctx ?(protect=false) (p,t) is_extern =
-	let flag = is_protected_path (p,t) is_extern in
-	match p with
-	| [] ->
-		push ctx [VStr (t,flag)];
-		VarStr
-	| x :: l ->
-		push ctx [VStr (x,protect && flag)];
-		write ctx AEval;
-		List.iter (fun x ->
-			push ctx [VStr (x,protect && flag)];
-			write ctx AObjGet;
-		) l;
-		push ctx [VStr (t,flag)];
-		VarObj
-
-let begin_func ctx need_super need_args args =
-	if ctx.flash6 then
-		let f = {
-			f_name = "";
-			Swf.f_args = List.map snd args;
-			f_codelen = 0;
-		} in
-		write ctx (AFunction f);
-		let start_pos = ctx.code_pos in
-		let old_stack = ctx.fun_stack in
-		ctx.fun_stack <- ctx.stack_size;
-		(fun() ->
-			let delta = ctx.code_pos - start_pos in
-			f.f_codelen <- delta;
-			let codesize = ActionScript.jump_index_to_size ctx.opcodes (start_pos-1) delta in
-			if codesize >= 1 lsl 16 then overflow ctx;
-			if ctx.fun_stack <> ctx.stack_size then assert false;
-			ctx.fun_stack <- old_stack;
-		)
-	else
-	let default_flags = ThisRegister :: (if need_args then [] else [ArgumentsNoVar]) in
-	let f = {
-		f2_name = "";
-		f2_args = args;
-		f2_codelen = 0;
-		f2_nregs = 0;
-		f2_flags = (if need_super then SuperRegister :: default_flags else SuperNoVar :: default_flags);
-	} in
-	write ctx (AFunction2 f);
-	let start_pos = ctx.code_pos in
-	let old_stack = ctx.fun_stack in
-	let old_rmax = ctx.reg_max in
-	let old_sinit = ctx.static_init in
-	ctx.fun_stack <- ctx.stack_size;
-	ctx.reg_max <- ctx.reg_count;
-	ctx.static_init <- false;
-	(fun() ->
-		let delta = ctx.code_pos - start_pos in
-		f.f2_codelen <- delta;
-		f.f2_nregs <- ctx.reg_max + 1;
-		let codesize = ActionScript.jump_index_to_size ctx.opcodes (start_pos-1) delta in
-		if codesize >= 1 lsl 16 then overflow ctx;
-		if ctx.fun_stack <> ctx.stack_size then assert false;
-		ctx.fun_stack <- old_stack;
-		ctx.reg_max <- old_rmax;
-		ctx.static_init <- old_sinit;
-	)
-
-let open_block ctx =
-	let old_regs = ctx.regs in
-	let old_rcount = ctx.reg_count in
-	(fun() ->
-		ctx.regs <- old_regs;
-		ctx.reg_count <- old_rcount;
-	)
-
-let begin_loop ctx =
-	let old_breaks = ctx.breaks in
-	let old_cont = ctx.continues in
-	let old_stack = ctx.loop_stack in
-	let old_loop = ctx.in_loop in
-	ctx.breaks <- [];
-	ctx.continues <- [];
-	ctx.loop_stack <- ctx.stack_size;
-	ctx.in_loop <- true;
-	(fun pos ->
-		List.iter (fun f -> f()) ctx.breaks;
-		List.iter (fun f -> f pos) ctx.continues;
-		ctx.breaks <- old_breaks;
-		ctx.continues <- old_cont;
-		ctx.loop_stack <- old_stack;
-		ctx.in_loop <- old_loop;
-	)
-
-let alloc_reg ctx =
-	ctx.reg_count <- ctx.reg_count + 1;
-	if ctx.reg_count > ctx.reg_max then ctx.reg_max <- ctx.reg_count;
-	ctx.reg_count
-
-let free_reg ctx r p =
-	if r <> ctx.reg_count then stack_error p;
-	ctx.reg_count <- ctx.reg_count - 1
-
-let segment ctx =
-	ctx.segs <- (ctx.opcodes,ctx.idents) :: ctx.segs;
-	ctx.opcodes <- DynArray.create();
-	ctx.idents <- Hashtbl.create 0;
-	ctx.ident_count <- 0;
-	ctx.ident_size <- 0;
-	ctx.code_pos <- 0;
-	write ctx (AStringPool [])
-
-(* -------------------------------------------------------------- *)
-(* Generation Helpers *)
-
-let define_var ctx v ef =
-	if ctx.flash6 || v.v_capture || ctx.static_init then begin
-		push ctx [VStr (v.v_name,false)];
-		ctx.regs <- PMap.add v.v_name NoReg ctx.regs;
-		match ef with
-		| None ->
-			write ctx ALocalVar
-		| Some f ->
-			f();
-			write ctx ALocalAssign
-	end else begin
-		let r = alloc_reg ctx in
-		ctx.regs <- PMap.add v.v_name (Reg r) ctx.regs;
-		match ef with
-		| None -> ()
-		| Some f ->
-			f();
-			setvar ctx (VarReg r)
-	end
-
-let alloc_tmp ctx =
-	let r = alloc_reg ctx in
-	if ctx.flash6 then
-		let name = "$" ^ string_of_int r in
-		define_var ctx (alloc_var name t_dynamic) None;
-		TmpVar (name,r);
-	else
-		TmpReg r
-
-let get_tmp ctx = function
-	| TmpVar (v,_) ->
-		push ctx [VStr (v,false)];
-		write ctx AEval;
-	| TmpReg r ->
-		push ctx [VReg r]
-
-let set_tmp ctx = function
-	| TmpVar (v,_) ->
-		write ctx ADup;
-		push ctx [VStr (v,false)];
-		write ctx ASwap;
-		write ctx ASet
-	| TmpReg r ->
-		write ctx (ASetReg r)
-
-let free_tmp ctx v p =
-	match v with
-	| TmpVar (v,r) ->
-		ctx.regs <- PMap.remove v ctx.regs;
-		free_reg ctx r p
-	| TmpReg r ->
-		free_reg ctx r p
-
-let no_value ctx retval =
-	(* does not push a null but still increment the stack like if
-	   a real value was pushed *)
-	if retval then ctx.stack_size <- ctx.stack_size + 1
-
-let gen_try ctx =
-	let tdata = {
-		tr_style = TryRegister 0;
-		tr_trylen = 0;
-		tr_catchlen = None;
-		tr_finallylen = None;
-	} in
-	write ctx (ATry tdata);
-	let start = ctx.code_pos in
-	(fun() ->
-		let jump_end = jmp ctx in
-		tdata.tr_trylen <- ctx.code_pos - start;
-		let start = ctx.code_pos in
-		(fun() ->
-			if ctx.code_pos <> start then tdata.tr_catchlen <- Some (ctx.code_pos - start);
-			jump_end()
-		)
-	)
-
-(* -------------------------------------------------------------- *)
-(* Generation *)
-
-let rec gen_big_string ctx s =
-	let len = String.length s in
-	let max = 65000 in
-	ctx.opt_push <- false;
-	if len <= max then
-		write ctx (APush [PString s])
-	else begin
-		write ctx (APush [PString (String.sub s 0 max)]);
-		gen_big_string ctx (String.sub s max (len - max));
-		write ctx AAdd;
-	end
-
-let rec gen_constant ctx c p =
-	match c with
-	| TInt i -> push ctx [VInt32 i]
-	| TFloat s -> push ctx [VFloat (try float_of_string s with _ -> invalid_expr p)]
-	| TString s ->
-		if String.contains s '\000' then error "A String cannot contain \\0 characters" p;
-		push ctx [VStr (s,true)]
-	| TBool b -> write ctx (APush [PBool b])
-	| TNull -> push ctx [VNull]
-	| TThis
-	| TSuper -> assert false
-
-let access_local ctx s =
-	match (try PMap.find s ctx.regs , false with Not_found -> NoReg, s <> "Enum") with
-	| NoReg , flag ->
-		push ctx [VStr (s,flag)];
-		VarStr
-	| Reg r , _ ->
-		VarReg r
-
-let rec gen_access ?(read_write=false) ctx forcall e =
-	match e.eexpr with
-	| TConst TSuper ->
-		(* for superconstructor *)
-		if ctx.flash6 then begin
-			push ctx [VStr ("super",true)];
-			VarStr
-		end else if forcall then begin
-			push ctx [VSuper];
-			write ctx (APush [PUndefined]);
-			VarObj
-		end else
-			VarReg 2
-	| TConst TThis ->
-		if ctx.flash6 then begin
-			push ctx [VStr ("this",true)];
-			VarStr
-		end else
-			VarReg 1
-	| TLocal { v_name = "__arguments__" } ->
-		push ctx [VStr ("arguments",true)];
-		VarStr
-	| TLocal v ->
-		access_local ctx v.v_name
-	| TField (e,FClosure (_,{ cf_name = f })) ->
-		gen_expr ctx true e;
-		if read_write then assert false;
-		push ctx [VStr (f,is_protected ctx e.etype f)];
-		VarClosure
-	| TEnumParameter(e,_,i) ->
-		gen_expr ctx true e;
-		push ctx [VInt (i + 2)];
-		VarObj
-	| TField (e2,f) ->
-		gen_expr ctx true e2;
-		if read_write then write ctx ADup;
-		let f = field_name f in
-		let p = VStr (f,is_protected ctx e2.etype f) in
-		push ctx [p];
-		if read_write then begin
-			write ctx ASwap;
-			push ctx [p];
-		end;
-		if not !protect_all && Codegen.is_volatile e.etype then
-			VarVolatile
-		else
-			VarObj
-	| TArray (ea,eb) ->
-		if read_write then
-			try
-				let r = (match ea.eexpr with TLocal l -> (match PMap.find l.v_name ctx.regs with Reg r -> r | _ -> raise Not_found) | _ -> raise Not_found) in
-				push ctx [VReg r];
-				gen_expr ctx true eb;
-				write ctx ADup;
-				push ctx [VReg r];
-				write ctx ASwap;
-			with Not_found ->
-				gen_expr ctx true eb;
-				gen_expr ctx true ea;
-				write ctx (ASetReg 0);
-				write ctx ASwap;
-				write ctx ADup;
-				push ctx [VReg 0];
-				write ctx ASwap;
-		else begin
-			gen_expr ctx true ea;
-			gen_expr ctx true eb;
-		end;
-		VarObj
-	| TTypeExpr t ->
-		(match t with
-		| TClassDecl c -> gen_path ctx c.cl_path c.cl_extern
-		| TEnumDecl e -> gen_path ctx e.e_path false
-		| TAbstractDecl a -> gen_path ctx a.a_path false
-		| TTypeDecl _ -> assert false)
-	| _ ->
-		if not forcall then invalid_expr e.epos;
-		gen_expr ctx true e;
-		write ctx (APush [PUndefined]);
-		VarObj
-
-and gen_access_rw ctx e =
-	match e.eexpr with
-	| TField ({ eexpr = TLocal _ },_) | TArray ({ eexpr = TLocal _ },{ eexpr = TConst _ }) | TArray ({ eexpr = TLocal _ },{ eexpr = TLocal _ }) ->
-		ignore(gen_access ctx false e);
-		gen_access ctx false e
-	| TField _ | TArray _ ->
-		gen_access ~read_write:true ctx false e
-	| _ ->
-		ignore(gen_access ctx false e);
-		gen_access ctx false e
-
-and gen_try_catch ctx retval e catchs =
-	let start_try = gen_try ctx in
-	gen_expr ctx retval e;
-	let end_try = start_try() in
-	let end_throw = ref true in
-	let jumps = List.map (fun (v,e) ->
-		if not !end_throw then
-			(fun () -> ())
-		else let t = (match follow v.v_type with
-			| TEnum (e,_) -> Some (TEnumDecl e)
-			| TInst (c,_) -> Some (TClassDecl c)
-			| TAbstract (a,_) -> Some (TAbstractDecl a)
-			| TFun _
-			| TLazy _
-			| TType _
-			| TAnon _ ->
-				assert false
-			| TMono _
-			| TDynamic _ ->
-				None
-		) in
-		let next_catch = (match t with
-		| None ->
-			end_throw := false;
-			(fun() -> ())
-		| Some t ->
-			getvar ctx (gen_access ctx false (mk (TTypeExpr t) (mk_mono()) e.epos));
-			push ctx [VReg 0; VInt 2; VStr ("@instanceof",false)];
-			call ctx VarStr 2;
-			write ctx ANot;
-			cjmp ctx
-		) in
-		let block = open_block ctx in
-		define_var ctx v (Some (fun() -> push ctx [VReg 0]));
-		gen_expr ctx retval e;
-		block();
-		if retval then ctx.stack_size <- ctx.stack_size - 1;
-		let j = jmp ctx in
-		next_catch();
-		j
-	) catchs in
-	if !end_throw && catchs <> [] then begin
-		push ctx [VReg 0];
-		write ctx AThrow;
-	end;
-	List.iter (fun j -> j()) jumps;
-	end_try()
-
-and gen_switch ctx retval e cases def =
-	gen_expr ctx true e;
-	let r = alloc_tmp ctx in
-	set_tmp ctx r;
-	let first = ref true in
-	let dispatch = List.map (fun (el,x) ->
-		List.map (fun e ->
-			if !first then first := false else get_tmp ctx r;
-			gen_expr ctx true e;
-			write ctx AEqual;
-			cjmp ctx
-		) el , x
-	) cases in
-	if !first then write ctx APop;
-	(match def with
-	| None -> if retval then push ctx [VNull]
-	| Some e -> gen_expr ctx retval e);
-	let jend = jmp ctx in
-	let jends = List.map (fun (jl,e) ->
-		List.iter (fun j -> j()) jl;
-		gen_expr ctx retval e;
-		if retval then ctx.stack_size <- ctx.stack_size - 1;
-		jmp ctx;
-	) dispatch in
-	jend();
-	free_tmp ctx r e.epos;
-	List.iter (fun j -> j()) jends
-
-and gen_match ctx retval e cases def =
-	gen_expr ctx true e;
-	let renum = alloc_tmp ctx in
-	set_tmp ctx renum;
-	push ctx [VInt 1];
-	write ctx AObjGet;
-	let rtag = alloc_tmp ctx in
-	set_tmp ctx rtag;
-	let first = ref true in
-	let dispatch = List.map (fun (cl,params,e) ->
-		List.map (fun c ->
-			if !first then first := false else get_tmp ctx rtag;
-			push ctx [VInt c];
-			write ctx APhysEqual;
-			cjmp ctx
-		) cl, params, e
-	) cases in
-	if !first then write ctx APop;
-	free_tmp ctx rtag e.epos;
-	(match def with
-	| None -> if retval then push ctx [VNull]
-	| Some e -> gen_expr ctx retval e);
-	let jend = jmp ctx in
-	let jends = List.map (fun (jl,args,e) ->
-		let regs = ctx.regs in
-		let nregs = ctx.reg_count in
-		List.iter (fun j -> j()) jl;
-		let n = ref 1 in
-		List.iter (fun v ->
-			incr n;
-			match v with
-			| None -> ()
-			| Some v ->
-				define_var ctx v (Some (fun() ->
-					get_tmp ctx renum;
-					push ctx [VInt !n];
-					write ctx AObjGet
-				))
-		) (match args with None -> [] | Some l -> l);
-		gen_expr ctx retval e;
-		if retval then ctx.stack_size <- ctx.stack_size - 1;
-		ctx.regs <- regs;
-		ctx.reg_count <- nregs;
-		jmp ctx;
-	) dispatch in
-	jend();
-	free_tmp ctx renum e.epos;
-	List.iter (fun j -> j()) jends
-
-and gen_binop ctx retval op e1 e2 =
-	let gen a =
-		gen_expr ctx true e1;
-		gen_expr ctx true e2;
-		write ctx a
-	in
-	let make_op = function
-		| OpAdd -> AAdd
-		| OpMult -> AMultiply
-		| OpDiv -> ADivide
-		| OpSub -> ASubtract
-		| OpAnd -> AAnd
-		| OpOr -> AOr
-		| OpXor -> AXor
-		| OpShl -> AShl
-		| OpShr -> AShr
-		| OpUShr -> AAsr
-		| OpMod -> AMod
-		| _ -> assert false
-	in
-	match op with
-	| OpAssign ->
-		let k = gen_access ctx false e1 in
-		gen_expr ctx true e2;
-		setvar ~retval ctx k
-	| OpAssignOp op ->
-		let k = gen_access_rw ctx e1 in
-		getvar ctx k;
-		gen_expr ctx true e2;
-		write ctx (make_op op);
-		setvar ~retval ctx k
-	| OpAdd | OpMult | OpDiv | OpSub | OpAnd | OpOr | OpXor | OpShl | OpShr | OpUShr | OpMod ->
-		gen (make_op op)
-	| OpEq ->
-		gen AEqual
-	| OpNotEq ->
-		gen AEqual;
-		write ctx ANot
-	| OpGt -> gen AGreater
-	| OpGte ->
-		gen ACompare;
-		write ctx ANot
-	| OpLt -> gen ACompare
-	| OpLte ->
-		gen AGreater;
-		write ctx ANot
-	| OpBoolAnd ->
-		gen_expr ctx true e1;
-		write ctx ADup;
-		write ctx ANot;
-		let jump_end = cjmp ctx in
-		write ctx APop;
-		gen_expr ctx true e2;
-		jump_end()
-	| OpBoolOr ->
-		gen_expr ctx true e1;
-		write ctx ADup;
-		let jump_end = cjmp ctx in
-		write ctx APop;
-		gen_expr ctx true e2;
-		jump_end()
-	| OpInterval | OpArrow ->
-		(* handled by typer *)
-		assert false
-
-and gen_unop ctx retval op flag e =
-	match op with
-	| Not ->
-		gen_expr ctx true e;
-		write ctx ANot
-	| Neg ->
-		push ctx [VInt 0];
-		gen_expr ctx true e;
-		write ctx ASubtract
-	| NegBits ->
-		gen_expr ctx true e;
-		push ctx [VInt (-1)];
-		write ctx AXor
-	| Increment
-	| Decrement ->
-		let k = gen_access_rw ctx e in
-		getvar ctx k;
-		(* store preincr value for later access *)
-		if retval && flag = Postfix then write ctx (ASetReg 0);
-		write ctx (match op with Increment -> AIncrement | Decrement -> ADecrement | _ -> assert false);
-		setvar ~retval:(retval && flag = Prefix) ctx k;
-		if retval && flag = Postfix then push ctx [VReg 0]
-
-and gen_call ctx e el =
-	let loc = match e.eexpr with TLocal v -> v.v_name | _ -> "" in
-	match loc, el with
-	| "__instanceof__" ,  [e1;e2] ->
-		gen_expr ctx true e1;
-		gen_expr ctx true e2;
-		write ctx AInstanceOf
-	| "__typeof__" , [e] ->
-		gen_expr ctx true e;
-		write ctx ATypeOf
-	| "__delete__" , [e1; e2] ->
-		gen_expr ctx true e1;
-		gen_expr ctx true e2;
-		write ctx ADeleteObj
-	| "__random__" , [e] ->
-		gen_expr ctx true e;
-		write ctx ARandom
-	| "__trace__" , [e] ->
-		gen_expr ctx true e;
-		write ctx ATrace
-	| "__eval__" , [e] ->
-		gen_expr ctx true e;
-		write ctx AEval
-	| "__gettimer__", [] ->
-		write ctx AGetTimer
-	| "__undefined__", [] ->
-		push ctx [VUndefined]
-	| "__geturl__" , url :: target :: post ->
-		gen_expr ctx true url;
-		gen_expr ctx true target;
-		write ctx (AGetURL2 (match post with [] -> 0 | [{ eexpr = TConst (TString "GET") }] -> 1 | _ -> 2))
-	| "__new__", e :: el ->
-		let nargs = List.length el in
-		List.iter (gen_expr ctx true) (List.rev el);
-		push ctx [VInt nargs];
-		let k = gen_access ctx true e in
-		new_call ctx k nargs
-	| "__keys__", [e2]
-	| "__hkeys__", [e2] ->
-		let r = alloc_tmp ctx in
-		push ctx [VInt 0; VStr ("Array",true)];
-		new_call ctx VarStr 0;
-		set_tmp ctx r;
-		write ctx APop;
-		gen_expr ctx true e2;
-		write ctx AEnum2;
-		ctx.stack_size <- ctx.stack_size + 1; (* fake *)
-		let loop = pos ctx in
-		write ctx (ASetReg 0);
-		push ctx [VNull];
-		write ctx AEqual;
-		let jump_end = cjmp ctx in
-		if loc = "__hkeys__" then begin
-			push ctx [VInt 1; VInt 1; VReg 0; VStr ("substr",true)];
-			call ctx VarObj 1;
-		end else begin
-			push ctx [VReg 0];
-		end;
-		push ctx [VInt 1];
-		get_tmp ctx r;
-		push ctx [VStr ("push",true)];
-		call ctx VarObj 1;
-		write ctx APop;
-		loop false;
-		jump_end();
-		get_tmp ctx r;
-		free_tmp ctx r e2.epos;
-	| "__physeq__" ,  [e1;e2] ->
-		gen_expr ctx true e1;
-		gen_expr ctx true e2;
-		write ctx APhysEqual;
-	| "__unprotect__", [{ eexpr = TConst (TString s) }] ->
-		push ctx [VStr (s,false)]
-	| "__resources__", [] ->
-		let count = ref 0 in
-		Hashtbl.iter (fun name data ->
-			incr count;
-			push ctx [VStr ("name",false);VStr (name,true)];
-			(* if the data contains \0 or is not UTF8 valid, encode into bytes *)
-			(try
-				(try ignore(String.index data '\000'); raise Exit; with Not_found -> ());
-				UTF8.validate data;
-				push ctx [VStr ("str",false)];
-				gen_big_string ctx data;
-			with _ ->
-				push ctx [VStr ("data",false)];
-				gen_big_string ctx (Codegen.bytes_serialize data));
-			push ctx [VInt 2];
-			write ctx AObject;
-			ctx.stack_size <- ctx.stack_size - 4;
-		) ctx.com.resources;
-		init_array ctx !count
-	| "__FSCommand2__", l ->
-		let nargs = List.length l in
-		List.iter (gen_expr ctx true) (List.rev l);
-		push ctx [VInt nargs];
-		write ctx AFSCommand2;
-		ctx.stack_size <- ctx.stack_size - nargs
-	| _ , _ ->
-		let nargs = List.length el in
-		List.iter (gen_expr ctx true) (List.rev el);
-		push ctx [VInt nargs];
-		let k = gen_access ctx true e in
-		call ctx k nargs
-
-
-and gen_expr_2 ctx retval e =
-	match e.eexpr with
-	| TConst TSuper
-	| TConst TThis
-	| TEnumParameter _
-	| TField _
-	| TArray _
-	| TLocal _
-	| TTypeExpr _ ->
-		getvar ctx (gen_access ctx false e)
-	| TConst c ->
-		gen_constant ctx c e.epos
-	| TParenthesis e | TMeta (_,e) ->
-		gen_expr ctx retval e
-	| TBlock el ->
-		let rec loop = function
-			| [] ->
-				if retval then push ctx [VNull]
-			| [e] ->
-				gen_expr ctx retval e
-			| e :: l ->
-				gen_expr ctx false e;
-				loop l
-		in
-		let b = open_block ctx in
-		loop el;
-		b()
-	| TVar (v,eo) ->
-		define_var ctx v (match eo with None -> None | Some e -> Some (fun() -> gen_expr ctx true e));
-		if retval then push ctx [VNull]
-	| TArrayDecl el ->
-		List.iter (gen_expr ctx true) (List.rev el);
-		init_array ctx (List.length el);
-	| TObjectDecl fl ->
-		let nfields = List.length fl in
-		List.iter (fun (s,v) ->
-			push ctx [VStr (s,false)];
-			gen_expr ctx true v
-		) fl;
-		push ctx [VInt nfields];
-		write ctx AObject;
-		ctx.stack_size <- ctx.stack_size - (nfields * 2);
-	| TFunction f ->
-		let block = open_block ctx in
-		let old_in_loop = ctx.in_loop in
-		let old_meth = ctx.curmethod in
-		let rec loop e =
-			match e.eexpr with
-			| TConst TSuper -> raise Exit
-			| _ -> Type.iter loop e
-		in
-		let reg_super = try loop f.tf_expr; false with Exit -> true in
-		let rec loop e =
-			match e.eexpr with
-			| TLocal { v_name = "__arguments__" } -> raise Exit
-			| _ -> Type.iter loop e
-		in
-		let reg_args = try loop f.tf_expr; false with Exit -> true in
-		if snd ctx.curmethod then
-			ctx.curmethod <- (fst ctx.curmethod ^ "@" ^ string_of_int (Lexer.get_error_line e.epos), true)
-		else
-			ctx.curmethod <- (fst ctx.curmethod, true);
-		(* only keep None bindings, for protect *)
-		ctx.regs <- PMap.foldi (fun v x acc ->
-			match x with
-			| NoReg -> PMap.add v x acc
-			| Reg _ -> acc
-		) ctx.regs PMap.empty;
-		ctx.reg_count <- (if reg_super then 2 else 1);
-		ctx.in_loop <- false;
-		let pargs = ref [] in
-		let rargs = List.map (fun (v,_) ->
-			let no_reg = ctx.flash6 || v.v_capture in
-			if no_reg then begin
-				ctx.regs <- PMap.add v.v_name NoReg ctx.regs;
-				pargs := unprotect v.v_name :: !pargs;
-				0 , v.v_name
-			end else begin
-				let r = alloc_reg ctx in
-				ctx.regs <- PMap.add v.v_name (Reg r) ctx.regs;
-				pargs := false :: !pargs;
-				r , ""
-			end
-		) f.tf_args in
-		let tf = begin_func ctx reg_super reg_args rargs in
-		ctx.fun_pargs <- (ctx.code_pos, List.rev !pargs) :: ctx.fun_pargs;
-		List.iter (fun (v,c) ->
-			match c with
-			| None | Some TNull -> ()
-			| Some c -> gen_expr ctx false (Codegen.set_default ctx.com v c e.epos)
-		) f.tf_args;
-		if ctx.com.debug then begin
-			gen_expr ctx false (ctx.stack.Codegen.stack_push ctx.curclass (fst ctx.curmethod));
-			gen_expr ctx false ctx.stack.Codegen.stack_save_pos;
-			let start_try = gen_try ctx in
-			gen_expr ctx false (Codegen.stack_block_loop ctx.stack f.tf_expr);
-			gen_expr ctx false ctx.stack.Codegen.stack_pop;
-			let end_try = start_try() in
-			(* if $spos == 1 , then no upper call, so report as uncaught *)
-			getvar ctx (access_local ctx ctx.stack.Codegen.stack_pos_var);
-			push ctx [VInt 1];
-			write ctx AEqual;
-			write ctx ANot;
-			let j = cjmp ctx in
-			push ctx [VReg 0];
-			push ctx [VInt 1];
-			getvar ctx (gen_path ctx (["flash"],"Boot") ctx.extern_boot);
-			push ctx [VStr ("__exc",false)];
-			call ctx VarObj 1;
-			write ctx AReturn;
-			j();
-			push ctx [VReg 0];
-			write ctx AThrow;
-			end_try();
-		end else
-			gen_expr ctx false f.tf_expr;
-		ctx.in_loop <- old_in_loop;
-		ctx.curmethod <- old_meth;
-		tf();
-		block();
-	| TIf (cond,e,None) ->
-		if retval then assert false;
-		gen_expr ctx true cond;
-		write ctx ANot;
-		let j = cjmp ctx in
-		gen_expr ctx retval e;
-		j()
-	| TIf (cond,e,Some e2) ->
-		gen_expr ctx true cond;
-		let j = cjmp ctx in
-		gen_expr ctx retval e2;
-		let jend = jmp ctx in
-		j();
-		gen_expr ctx retval e;
-		if retval then ctx.stack_size <- ctx.stack_size - 1;
-		jend()
-	| TWhile (cond,e,Ast.NormalWhile) ->
-		let loop_end = begin_loop ctx in
-		let cont_pos = ctx.code_pos in
-		let loop = pos ctx in
-		gen_expr ctx true cond;
-		write ctx ANot;
-		let jend = cjmp ctx in
-		gen_expr ctx false e;
-		loop false;
-		jend();
-		loop_end cont_pos
-	| TWhile (cond,e,Ast.DoWhile) ->
-		let loop_end = begin_loop ctx in
-		let p = pos ctx in
-		gen_expr ctx false e;
-		let cont_pos = ctx.code_pos in
-		gen_expr ctx true cond;
-		p true;
-		loop_end cont_pos
-	| TReturn None ->
-		pop ctx (ctx.stack_size - ctx.fun_stack) false;
-		write ctx (APush [PUndefined]);
-		write ctx AReturn;
-		no_value ctx retval
-	| TReturn (Some e) ->
-		pop ctx (ctx.stack_size - ctx.fun_stack) false;
-		gen_expr ctx true e;
-		write ctx AReturn;
-		no_value ctx retval
-	| TBreak ->
-		pop ctx (ctx.stack_size - ctx.loop_stack) false;
-		ctx.breaks <- jmp ctx :: ctx.breaks;
-		no_value ctx retval
-	| TContinue ->
-		pop ctx (ctx.stack_size - ctx.loop_stack) false;
-		ctx.continues <- jmp_pos ctx false :: ctx.continues;
-		no_value ctx retval
-	| TCall (e,el) ->
-		gen_call ctx e el
-	| TNew (c,_,el) ->
-		let nargs = List.length el in
-		List.iter (gen_expr ctx true) (List.rev el);
-		push ctx [VInt nargs];
-		let acc = gen_path ctx c.cl_path c.cl_extern in
-		new_call ctx acc nargs
-	| TSwitch (e,cases,def) ->
-		gen_switch ctx retval e cases def
-	| TThrow e ->
-		gen_expr ctx true e;
-		write ctx AThrow;
-		no_value ctx retval
-	| TTry (e,catchs) ->
-		gen_try_catch ctx retval e catchs
-	| TBinop (op,e1,e2) ->
-		gen_binop ctx retval op e1 e2
-	| TUnop (op,flag,e) ->
-		gen_unop ctx retval op flag e
-	| TCast (e,None) ->
-		gen_expr ctx retval e
-	| TCast (e1,Some t) ->
-		gen_expr ctx retval (Codegen.default_cast ctx.com e1 t e.etype e.epos)
-	| TFor (v,it,e) ->
-		gen_expr ctx true it;
-		let r = alloc_tmp ctx in
-		set_tmp ctx r;
-		write ctx APop;
-		let loop_end = begin_loop ctx in
-		let cont_pos = ctx.code_pos in
-		let j_begin = pos ctx in
-		push ctx [VInt 0];
-		get_tmp ctx r;
-		push ctx [VStr ("hasNext",false)];
-		call ctx VarObj 0;
-		write ctx ANot;
-		let j_end = cjmp ctx in
-		let b = open_block ctx in
-		define_var ctx v (Some (fun() ->
-			push ctx [VInt 0];
-			get_tmp ctx r;
-			push ctx [VStr ("next",false)];
-			call ctx VarObj 0;
-		));
-		gen_expr ctx false e;
-		j_begin false;
-		j_end();
-		loop_end cont_pos;
-		if retval then getvar ctx (access_local ctx v.v_name);
-		b();
-		free_tmp ctx r null_pos
-
-and gen_expr ctx retval e =
-	let old = ctx.stack_size in
-	gen_expr_2 ctx retval e;
-	if old <> ctx.stack_size then begin
-		if old + 1 <> ctx.stack_size then stack_error e.epos;
-		if not retval then write ctx APop;
-	end else if retval then stack_error e.epos
-
-let gen_class_static_field ctx c flag f =
-	match f.cf_expr with
-	| None ->
-		push ctx [VReg 0; VStr (f.cf_name,flag); VNull];
-		setvar ctx VarObj
-	| Some e ->
-		match e.eexpr with
-		| TFunction _ ->
-			push ctx [VReg 0; VStr (f.cf_name,flag)];
-			ctx.curmethod <- (f.cf_name,false);
-			gen_expr ctx true e;
-			setvar ctx VarObj
-		| _ ->
-			ctx.statics <- (c,flag,f.cf_name,e) :: ctx.statics
-
-let gen_class_static_init ctx (c,flag,name,e) =
-	ctx.curclass <- c;
-	ctx.curmethod <- (name,false);
-	getvar ctx (gen_path ctx c.cl_path c.cl_extern);
-	push ctx [VStr (name,flag)];
-	gen_expr ctx true e;
-	setvar ctx VarObj
-
-let gen_class_field ctx flag f =
-	push ctx [VReg 1; VStr (f.cf_name,flag)];
-	(match f.cf_expr with
-	| None ->
-		push ctx [VNull]
-	| Some e ->
-		ctx.curmethod <- (f.cf_name,false);
-		gen_expr ctx true e);
-	setvar ctx VarObj
-
-let gen_enum_field ctx e f =
-	push ctx [VReg 0; VStr (f.ef_name,false)];
-	(match follow f.ef_type with
-	| TFun (args,r) ->
-		ctx.regs <- PMap.empty;
-		ctx.reg_count <- 1;
-		let no_reg = ctx.flash6 in
-		let rargs = List.map (fun (n,_,_) -> if no_reg then 0, n else alloc_reg ctx , "") args in
-		let nregs = List.length rargs + 2 in
-		let tf = begin_func ctx false false rargs in
-		List.iter (fun (r,name) ->
-			if no_reg then begin
-				push ctx [VStr (name,false)];
-				write ctx AEval;
-			end else
-				push ctx [VReg r]
-		) (List.rev rargs);
-		push ctx [VInt f.ef_index; VStr (f.ef_name,false)];
-		init_array ctx nregs;
-		write ctx ADup;
-		write ctx ADup;
-		push ctx [VStr ("__enum__",false); VThis];
-		write ctx AObjSet;
-		push ctx [VStr ("toString",false); VStr ("@estr",false)];
-		write ctx AEval;
-		write ctx AObjSet;
-		write ctx AReturn;
-		tf();
-	| t ->
-		push ctx [VInt f.ef_index; VStr (f.ef_name,false)];
-		init_array ctx 2;
-		write ctx ADup;
-		write ctx ADup;
-		push ctx [VStr ("__enum__",false); VReg 0];
-		write ctx AObjSet;
-		push ctx [VStr ("toString",false); VStr ("@estr",false)];
-		write ctx AEval;
-		write ctx AObjSet;
-	);
-	write ctx AObjSet
-
-let init_name ctx path enum =
-	push ctx [VReg 0; VStr ((if enum then "__ename__" else "__name__"),false)];
-	let name = fst path @ [snd path] in
-	push ctx (List.map (fun s -> VStr (s,false)) (List.rev name));
-	init_array ctx (List.length name);
-	setvar ctx VarObj
-
-let gen_package ctx path ext =
-	let rec loop acc = function
-		| [] -> ()
-		| x :: l ->
-			let p = x :: acc in
-			if not (Hashtbl.mem ctx.packages p) then begin
-				(* create the package and copy the _global one if exists *)
-				Hashtbl.add ctx.packages p ();
-
-				(* create the package *)
-				let path = (List.rev acc,x) in
-				let acc = gen_path ctx path false in
-				push ctx [VInt 0; VStr ("Object",true)];
-				write ctx ANew;
-				write ctx (ASetReg 1);
-				setvar ctx acc;
-
-				(* copy the content of the _global package if exists *)
-				getvar ctx (gen_path ctx ~protect:true ("_global" :: fst path,snd path) ext);
-				write ctx (ASetReg 2);
-				write ctx AEnum2;
-				ctx.stack_size <- ctx.stack_size + 1; (* fake *)
-				let back = pos ctx in
-				write ctx (ASetReg 0);
-				push ctx [VNull];
-				write ctx AEqual;
-				let jend = cjmp ctx in
-				push ctx [VReg 1; VReg 0];
-				push ctx [VReg 2; VReg 0];
-				write ctx AObjGet;
-				write ctx AObjSet;
-				back false;
-				jend();
-
-				write ctx APop;
-			end;
-			loop p l
-	in
-	loop [] (fst path)
-
-let gen_type_def ctx t =
-	if ctx.ident_size > 50000 then segment ctx;
-	match t with
-	| TClassDecl c ->
-		(match c.cl_init with
-		| None -> ()
-		| Some e -> ctx.inits <- e :: ctx.inits);
-		gen_package ctx c.cl_path c.cl_extern;
-		if c.cl_extern then
-			()
-		else
-		let have_constr = ref false in
-		if c.cl_path = (["flash"] , "Boot") then ctx.extern_boot <- false;
-		let acc = gen_path ctx c.cl_path false in
-		let rec loop s =
-			match s.cl_super with
-			| None -> ()
-			| Some (s,_) ->
-				if s.cl_path = (["flash"],"MovieClip") then
-					ctx.movieclips <- c.cl_path :: ctx.movieclips
-				else
-					loop s
-		in
-		loop c;
-		ctx.curclass <- c;
-		(match c.cl_constructor with
-		| Some { cf_expr = Some e } ->
-			have_constr := true;
-			ctx.curmethod <- ("new",false);
-			gen_expr ctx true e
-		| _ ->
-			let f = begin_func ctx true false [] in
-			f());
-		write ctx (ASetReg 0);
-		setvar ctx acc;
-		init_name ctx c.cl_path false;
-		(match c.cl_super with
-		| None -> ()
-		| Some (csuper,_) ->
-			let path = (match csuper.cl_path with (["flash"],x) when csuper.cl_extern -> (["_global"],x) | p -> p) in
-			push ctx [VReg 0; VStr ("__super__",false)];
-			getvar ctx (gen_path ctx path csuper.cl_extern);
-			setvar ctx VarObj;
-			if ctx.flash6 then begin
-				(* myclass.prototype.__proto__ = superclass.prototype *)
-				push ctx [VReg 0; VStr ("prototype",true)];
-				getvar ctx VarObj;
-				push ctx [VStr ("__proto__",true)];
-				getvar ctx (gen_path ctx path csuper.cl_extern);
-				push ctx [VStr ("prototype",true)];
-				getvar ctx VarObj;
-				setvar ctx VarObj;
-				(* myclass.prototype.__constructor__ = superclass *)
-				push ctx [VReg 0; VStr ("prototype",true)];
-				getvar ctx VarObj;
-				push ctx [VStr ("__constructor__",true)];
-				getvar ctx (gen_path ctx path csuper.cl_extern);
-				setvar ctx VarObj
-			end else begin
-				push ctx [VReg 0];
-				getvar ctx (gen_path ctx path csuper.cl_extern);
-				write ctx AExtends;
-			end;
-		);
-		(match c.cl_implements with
-		| [] -> ()
-		| l ->
-			let nimpl = List.length l in
-			push ctx [VReg 0; VStr ("__interfaces__",false)];
-			List.iter (fun (c,_) -> getvar ctx (gen_path ctx c.cl_path c.cl_extern)) l;
-			init_array ctx nimpl;
-			setvar ctx VarObj;
-			if not ctx.flash6 then begin
-				List.iter (fun (c,_) -> getvar ctx (gen_path ctx c.cl_path c.cl_extern)) l;
-				push ctx [VInt nimpl; VReg 0];
-				write ctx AImplements;
-				ctx.stack_size <- ctx.stack_size - nimpl;
-			end);
-		push ctx [VReg 0; VStr ("prototype",true)];
-		getvar ctx VarObj;
-		write ctx (ASetReg 1);
-		write ctx APop;
-		push ctx [VReg 1; VStr ("__class__",false); VReg 0];
-		setvar ctx VarObj;
-		(* true if implements mt.Protect *)
-		let flag = is_protected ctx ~stat:true (TInst (c,[])) "" in
-		if (Common.has_feature ctx.com "Reflect.getProperty") || (Common.has_feature ctx.com "Reflect.setProperty") then
-			Codegen.add_property_field ctx.com c;
-		List.iter (fun f -> if not (is_extern_field f) then gen_class_static_field ctx c flag f) c.cl_ordered_statics;
-		let flag = is_protected ctx (TInst (c,[])) "" in
-		PMap.iter (fun _ f -> if not (is_extern_field f) then gen_class_field ctx flag f) c.cl_fields;
-	| TEnumDecl e when e.e_extern ->
-		()
-	| TEnumDecl e ->
-		gen_package ctx e.e_path e.e_extern;
-		let acc = gen_path ctx e.e_path false in
-		push ctx [VInt 0; VStr ("Object",true)];
-		write ctx ANew;
-		write ctx (ASetReg 0);
-		setvar ctx acc;
-		init_name ctx e.e_path true;
-		push ctx [VReg 0; VStr ("__constructs__",true)];
-		List.iter (fun s -> push ctx [VStr (s,false)]) (List.rev e.e_names);
-		init_array ctx (List.length e.e_names);
-		write ctx AObjSet;
-		(match Codegen.build_metadata ctx.com t with
-		| None -> ()
-		| Some e ->
-			push ctx [VReg 0; VStr ("__meta__",true)];
-			gen_expr ctx true e;
-			write ctx AObjSet;
-		);
-		PMap.iter (fun _ f -> gen_enum_field ctx e f) e.e_constrs
-	| TTypeDecl _ | TAbstractDecl _ ->
-		()
-
-let gen_boot ctx =
-	(* r0 = Boot *)
-	getvar ctx (gen_path ctx (["flash"],"Boot") ctx.extern_boot);
-	write ctx (ASetReg 0);
-	write ctx APop;
-	(* r0.__init(eval("this")) *)
-	push ctx [VStr ("this",true)];
-	write ctx AEval;
-	push ctx [VInt 1; VReg 0; VStr ("__init",false)];
-	call ctx VarObj 0;
-	write ctx APop
-
-let gen_movieclip ctx m =
-	getvar ctx (gen_path ctx m false);
-	push ctx [VStr (s_type_path m,true); VInt 2; VStr ("Object",true)];
-	write ctx AEval;
-	push ctx [VStr ("registerClass",true)];
-	call ctx VarObj 2;
-	write ctx APop
-
-let to_utf8 str =
-	try
-		UTF8.validate str;
-		str;
-	with
-		UTF8.Malformed_code ->
-			let b = UTF8.Buf.create 0 in
-			String.iter (fun c -> UTF8.Buf.add_char b (UChar.of_char c)) str;
-			UTF8.Buf.contents b
-
-let build_tag (opcodes,idents) =
-	let idents = Hashtbl.fold (fun ident pos acc -> (ident,pos) :: acc) idents [] in
-	let idents = List.sort (fun (_,p1) (_,p2) -> compare p1 p2) idents in
-	let pidents = List.map (fun ((_,flag),_) -> flag) idents in
-	let idents = AStringPool (List.map (fun ((id,_),_) -> to_utf8 id) idents) in
-	if ActionScript.action_length idents >= 1 lsl 16 then failwith "The SWF can't handle more than a total size of 64K of identifers and literal strings. Try reducing this number by using external data files loaded at runtime";
-	DynArray.set opcodes 0 idents;
-	TDoAction opcodes , pidents
-
-let convert_header ctx ver (w,h,fps,bg) =
-	{
-		h_version = ver;
-		h_size = {
-			rect_nbits = if (max w h) >= 820 then 16 else 15;
-			left = 0;
-			top = 0;
-			right = w * 20;
-			bottom = h * 20;
-		};
-		h_frame_count = 1;
-		h_fps = to_float16 (if fps > 127.0 then 127.0 else fps);
-		h_compressed = not (Common.defined ctx Define.NoSwfCompress);
-	} , bg
-
-let default_header ctx ver =
-	convert_header ctx ver (400,300,30.,0xFFFFFF)
-
-let generate com =
-	let ctx = {
-		com = com;
-		stack = Codegen.stack_init com true;
-		flash6 = com.flash_version = 6.;
-		segs = [];
-		opcodes = DynArray.create();
-		code_pos = 0;
-		stack_size = 0;
-		ident_count = 0;
-		ident_size = 0;
-		opt_push = false;
-		idents = Hashtbl.create 0;
-		packages = Hashtbl.create 0;
-		regs = PMap.empty;
-		reg_count = 0;
-		reg_max = 0;
-		breaks = [];
-		continues = [];
-		loop_stack = 0;
-		fun_stack = 0;
-		statics = [];
-		movieclips = [];
-		inits = [];
-		curclass = null_class;
-		curmethod = ("",false);
-		fun_pargs = [];
-		in_loop = false;
-		static_init = false;
-		extern_boot = true;
-	} in
-	write ctx (AStringPool []);
-	protect_all := not (Common.defined com Define.SwfMark);
-	if com.debug then begin
-		push ctx [VStr (ctx.stack.Codegen.stack_var,false); VInt 0];
-		write ctx AInitArray;
-		write ctx ASet;
-		push ctx [VStr (ctx.stack.Codegen.stack_exc_var,false); VInt 0];
-		write ctx AInitArray;
-		write ctx ASet;
-	end;
-	(* ----- @estr = function() { return flash.Boot.__string_rec(this,""); } ---- *)
-	push ctx [VStr ("@estr",false)];
-	ctx.reg_count <- 1;
-	let f = begin_func ctx false false [] in
-	push ctx [VStr ("xx",false); VThis; VInt 2];
-	getvar ctx (gen_path ctx (["flash"],"Boot") false);
-	push ctx [VStr ("__string_rec",false)];
-	call ctx VarObj 2;
-	write ctx AReturn;
-	f();
-	write ctx ASet;
-	ctx.reg_count <- 0;
-	(* ---- *)
-	List.iter (fun t -> gen_type_def ctx t) com.types;
-	gen_boot ctx;
-	List.iter (fun m -> gen_movieclip ctx m) ctx.movieclips;
-	ctx.static_init <- true;
-	List.iter (gen_expr ctx false) (List.rev ctx.inits);
-	let global_try = gen_try ctx in
-	List.iter (gen_class_static_init ctx) (List.rev ctx.statics);
-	(match com.main with
-	| None -> ()
-	| Some e -> gen_expr ctx false e);
-	ctx.static_init <- false;
-	let end_try = global_try() in
-	(* flash.Boot.__trace(exc) *)
-	push ctx [VReg 0; VInt 1];
-	getvar ctx (gen_path ctx (["flash"],"Boot") ctx.extern_boot);
-	push ctx [VStr ("__exc",false)];
-	call ctx VarObj 1;
-	write ctx APop;
-	end_try();
-	let segs = List.rev ((ctx.opcodes,ctx.idents) :: ctx.segs) in
-	let tags = List.map build_tag segs in
-	if Common.defined com Define.SwfMark then begin
-		if List.length segs > 1 then assert false;
-		let pidents = snd (List.hd tags) in
-		let ch = IO.output_channel (open_out_bin (Filename.chop_extension com.file ^ ".mark")) in
-		IO.write_i32 ch (List.length ctx.fun_pargs);
-		List.iter (fun (id,l) ->
-			IO.write_i32 ch id;
-			IO.write_i32 ch (List.length l);
-			List.iter (fun f -> IO.write_byte ch (if f then 1 else 0)) l;
-		) ctx.fun_pargs;
-		IO.write_i32 ch (List.length pidents);
-		List.iter (fun f -> IO.write_byte ch (if f then 1 else 0)) pidents;
-		IO.close_out ch;
-	end;
-	List.map fst tags , ctx.movieclips

+ 36 - 12
genswf9.ml

@@ -120,6 +120,14 @@ let tid (x : 'a index) : int = Obj.magic x
 let ethis = mk (TConst TThis) (mk_mono()) null_pos
 let dynamic_prop = HMMultiNameLate [HNPublic (Some "")]
 
+let is_special_compare e1 e2 =
+	match e1.eexpr, e2.eexpr with
+	| TConst TNull, _  | _ , TConst TNull -> None
+	| _ ->
+	match follow e1.etype, follow e2.etype with
+	| TInst ({ cl_path = ["flash"],"NativeXml" } as c,_) , _ | _ , TInst ({ cl_path = ["flash"],"NativeXml" } as c,_) -> Some c
+	| _ -> None
+
 let write ctx op =
 	DynArray.add ctx.code op;
 	ctx.infos.ipos <- ctx.infos.ipos + 1;
@@ -191,11 +199,7 @@ let rec follow_basic t =
 		| TAbstract ({ a_path = ([],"Float") },[])
 		| TAbstract ({ a_path = [],"UInt" },[])
 		| TAbstract ({ a_path = ([],"Bool") },[])
-		| TInst ({ cl_path = (["haxe"],"Int32") },[])
-		| TInst ({ cl_path = ([],"Int") },[])
-		| TInst ({ cl_path = ([],"Float") },[])
-		| TType ({ t_path = [],"UInt" },[])
-		| TEnum ({ e_path = ([],"Bool") },[]) -> t
+		| TInst ({ cl_path = (["haxe"],"Int32") },[]) -> t
 		| t -> t)
 	| TType ({ t_path = ["flash";"utils"],"Object" },[])
 	| TType ({ t_path = ["flash";"utils"],"Function" },[])
@@ -231,7 +235,7 @@ let rec type_id ctx t =
 		type_path ctx ([],"Function")
 	| TType ({ t_path = ([],"UInt") as path },_) ->
 		type_path ctx path
-	| TEnum ({ e_path = [],"XmlType"; e_extern = true },_) ->
+	| TEnum ({ e_path = ["flash"],"XmlType"; e_extern = true },_) ->
 		HMPath ([],"String")
 	| TEnum (e,_) ->
 		let rec loop = function
@@ -263,7 +267,7 @@ let classify ctx t =
 		KBool
 	| TAbstract ({ a_path = [],"Void" },_) | TEnum ({ e_path = [],"Void" },_) ->
 		KDynamic
-	| TEnum ({ e_path = [],"XmlType"; e_extern = true },_) ->
+	| TEnum ({ e_path = ["flash"],"XmlType"; e_extern = true },_) ->
 		KType (HMPath ([],"String"))
 	| TEnum (e,_) ->
 		let rec loop = function
@@ -623,6 +627,16 @@ let debug_infos ?(is_min=true) ctx p =
 		end
 	end
 
+let to_utf8 str =
+	try
+		UTF8.validate str;
+		str;
+	with
+		UTF8.Malformed_code ->
+			let b = UTF8.Buf.create 0 in
+			String.iter (fun c -> UTF8.Buf.add_char b (UChar.of_char c)) str;
+			UTF8.Buf.contents b
+
 let gen_constant ctx c t p =
 	match c with
 	| TInt i ->
@@ -636,7 +650,7 @@ let gen_constant ctx c t p =
 		let f = float_of_string f in
 		write ctx (HFloat f);
 	| TString s ->
-		write ctx (HString (Genswf8.to_utf8 s));
+		write ctx (HString (to_utf8 s));
 	| TBool b ->
 		write ctx (if b then HTrue else HFalse);
 	| TNull ->
@@ -1606,7 +1620,12 @@ and gen_binop ctx retval op e1 e2 t p =
 		write ctx (HOp o)
 	in
 	let gen_eq() =
-		gen_op A3OEq
+		match is_special_compare e1 e2 with
+		| None ->
+			gen_op A3OEq
+		| Some c ->
+			let f = FStatic (c,try PMap.find "compare" c.cl_statics with Not_found -> assert false) in
+			gen_expr ctx true (mk (TCall (mk (TField (mk (TTypeExpr (TClassDecl c)) t_dynamic p,f)) t_dynamic p,[e1;e2])) ctx.com.basic.tbool p);
 	in
 	match op with
 	| OpAssign ->
@@ -1637,10 +1656,15 @@ and gen_binop ctx retval op e1 e2 t p =
 		gen_expr ctx true e2;
 		write_op op;
 		setvar ctx wacc (if retval then Some (classify ctx e1.etype) else None)
-	| OpAdd | OpMult | OpDiv | OpSub | OpAnd | OpOr | OpXor | OpShl | OpShr | OpUShr | OpMod ->
+	| OpAdd | OpMult | OpDiv | OpSub | OpAnd | OpOr | OpXor | OpMod ->
 		gen_expr ctx true e1;
 		gen_expr ctx true e2;
 		write_op op
+	| OpShl | OpShr	| OpUShr ->
+		gen_expr ctx true e1;
+		gen_expr ctx true e2;
+		write_op op;
+		coerce ctx (classify ctx e1.etype)
 	| OpEq ->
 		gen_eq()
 	| OpNotEq ->
@@ -1708,8 +1732,8 @@ and jump_expr_gen ctx e jif jfun =
 			jfun (if jif then t else f)
 		in
 		(match op with
-		| OpEq -> j J3Eq J3Neq
-		| OpNotEq -> j J3Neq J3Eq
+		| OpEq when is_special_compare e1 e2 = None -> j J3Eq J3Neq
+		| OpNotEq when is_special_compare e1 e2 = None -> j J3Neq J3Eq
 		| OpGt -> j J3Gt J3NotGt
 		| OpGte -> j J3Gte J3NotGte
 		| OpLt -> j J3Lt J3NotLt

+ 11 - 3
genxml.ml

@@ -425,7 +425,7 @@ let generate_type com t =
 	let print_meta ml =
 		List.iter (fun (m,pl,_) ->
 			match m with
-			| Meta.DefParam | Meta.CoreApi | Meta.Used | Meta.MaybeUsed | Meta.FlatEnum -> ()
+			| Meta.DefParam | Meta.CoreApi | Meta.Used | Meta.MaybeUsed | Meta.FlatEnum | Meta.Value | Meta.DirectlyUsed -> ()
 			| _ ->
 			match pl with
 			| [] -> p "@%s " (fst (MetaInfo.to_string m))
@@ -441,9 +441,17 @@ let generate_type com t =
 		p "\t";
 		print_meta f.cf_meta;
 		if stat then p "static ";
+		let name = try (match Meta.get Meta.RealPath f.cf_meta with
+				| (Meta.RealPath, [EConst( String s ), _], _) ->
+					s
+				| _ ->
+					raise Not_found)
+			with Not_found ->
+				f.cf_name
+		in
 		(match f.cf_kind with
 		| Var v ->
-			p "var %s" f.cf_name;
+			p "var %s" name;
 			if v.v_read <> AccNormal || v.v_write <> AccNormal then p "(%s,%s)" (access true v.v_read) (access false v.v_write);
 			p " : %s" (stype f.cf_type);
 		| Method m ->
@@ -473,7 +481,7 @@ let generate_type com t =
 					assert false
 			) in
 			let tparams = (match f.cf_params with [] -> "" | l -> "<" ^ String.concat "," (List.map fst l) ^ ">") in
-			p "function %s%s(%s) : %s" f.cf_name tparams (String.concat ", " (List.map sparam params)) (stype ret);
+			p "function %s%s(%s) : %s" name tparams (String.concat ", " (List.map sparam params)) (stype ret);
 		);
 		p ";\n";
 		if Meta.has Meta.Overload f.cf_meta then List.iter (fun f -> print_field stat f) f.cf_overloads

+ 7 - 0
haxe.hxproj

@@ -143,6 +143,13 @@
     <hidden path="analyzer.cmi" />
     <hidden path="analyzer.cmx" />
     <hidden path="analyzer.obj" />
+    <hidden path="CONTRIBUTING.md" />
+    <hidden path="README.md" />
+    <hidden path="Makefile" />
+    <hidden path="Makefile.win" />
+    <hidden path="appveyor.yml" />
+    <hidden path="version.ml" />
+    <hidden path="lib" />
   </hiddenPaths>
   <!-- Executed before build -->
   <preBuildCommand>make -j4 MSVC=1 FD_OUTPUT=1 -f Makefile.win kill haxe</preBuildCommand>

+ 115 - 66
interp.ml

@@ -47,12 +47,13 @@ and vobject = {
 }
 
 and vabstract =
+	| ADeallocated of int ref
 	| AKind of vabstract
 	| AHash of (value, value) Hashtbl.t
 	| ARandom of Random.State.t ref
 	| ABuffer of Buffer.t
 	| APos of Ast.pos
-	| AFRead of in_channel
+	| AFRead of (in_channel * bool ref)
 	| AFWrite of out_channel
 	| AReg of regexp
 	| AZipI of zlib
@@ -66,6 +67,8 @@ and vabstract =
 	| ANekoBuffer of value
 	| ACacheRef of value
 	| AInt32Kind
+	| ATls of value ref
+	| AProcess of Process.process
 
 and vfunction =
 	| Fun0 of (unit -> value)
@@ -103,6 +106,7 @@ type extern_api = {
 	on_type_not_found : (string -> value) -> unit;
 	parse_string : string -> Ast.pos -> bool -> Ast.expr;
 	type_expr : Ast.expr -> Type.texpr;
+	store_typed_expr : Type.texpr -> Ast.expr;
 	get_display : string -> string;
 	allow_package : string -> unit;
 	type_patch : string -> string -> bool -> string option -> unit;
@@ -110,7 +114,7 @@ type extern_api = {
 	set_js_generator : (value -> unit) -> unit;
 	get_local_type : unit -> t option;
 	get_expected_type : unit -> t option;
-	get_constructor_arguments : unit -> Ast.expr list option;
+	get_call_arguments : unit -> Ast.expr list option;
 	get_local_method : unit -> string;
 	get_local_using : unit -> tclass list;
 	get_local_vars : unit -> (string, Type.tvar) PMap.t;
@@ -1049,6 +1053,11 @@ let builtins =
 (* ---------------------------------------------------------------------- *)
 (* STD LIBRARY *)
 
+let free_abstract a =
+	match a with
+	| VAbstract vp -> Obj.set_tag (Obj.repr vp) 0 (* this will mute it as Deallocated *)
+	| _ -> assert false
+
 let std_lib =
 	let p = { psource = "<stdlib>"; pline = 0 } in
 	let error() =
@@ -1417,8 +1426,8 @@ let std_lib =
 			| VString f, VString r ->
 				let perms = 0o666 in
 				VAbstract (match r with
-					| "r" -> AFRead (open_in_gen [Open_rdonly] 0 f)
-					| "rb" -> AFRead (open_in_gen [Open_rdonly;Open_binary] 0 f)
+					| "r" -> AFRead (open_in_gen [Open_rdonly] 0 f,ref false)
+					| "rb" -> AFRead (open_in_gen [Open_rdonly;Open_binary] 0 f,ref false)
 					| "w" -> AFWrite (open_out_gen [Open_wronly;Open_creat;Open_trunc] perms f)
 					| "wb" -> AFWrite (open_out_gen [Open_wronly;Open_creat;Open_trunc;Open_binary] perms f)
 					| "a" -> AFWrite (open_out_gen [Open_append] perms f)
@@ -1426,10 +1435,10 @@ let std_lib =
 					| _ -> error())
 			| _ -> error()
 		);
-		"file_close", Fun1 (fun f ->
-			(match f with
-			| VAbstract (AFRead f) -> close_in f
-			| VAbstract (AFWrite f) -> close_out f
+		"file_close", Fun1 (fun vf ->
+			(match vf with
+			| VAbstract (AFRead (f,_)) -> close_in f; free_abstract vf;
+			| VAbstract (AFWrite f) -> close_out f; free_abstract vf;
 			| _ -> error());
 			VNull
 		);
@@ -1441,9 +1450,12 @@ let std_lib =
 		);
 		"file_read", Fun4 (fun f s p l ->
 			match f, s, p, l with
-			| VAbstract (AFRead f), VString s, VInt p, VInt l ->
+			| VAbstract (AFRead (f,r)), VString s, VInt p, VInt l ->
 				let n = input f s p l in
-				if n = 0 then exc (VArray [|VString "file_read"|]);
+				if n = 0 then begin
+					r := true;
+					exc (VArray [|VString "file_read"|]);
+				end;
 				VInt n
 			| _ -> error()
 		);
@@ -1454,34 +1466,30 @@ let std_lib =
 		);
 		"file_read_char", Fun1 (fun f ->
 			match f with
-			| VAbstract (AFRead f) -> VInt (int_of_char (try input_char f with _ -> exc (VArray [|VString "file_read_char"|])))
+			| VAbstract (AFRead (f,r)) -> VInt (int_of_char (try input_char f with _ -> r := true; exc (VArray [|VString "file_read_char"|])))
 			| _ -> error()
 		);
 		"file_seek", Fun3 (fun f pos mode ->
 			match f, pos, mode with
-			| VAbstract (AFRead f), VInt pos, VInt mode ->
-				seek_in f (match mode with 0 -> pos | 1 -> pos_in f + pos | 2 -> in_channel_length f - pos | _ -> error());
+			| VAbstract (AFRead (f,r)), VInt pos, VInt mode ->
+				r := false;
+				seek_in f (match mode with 0 -> pos | 1 -> pos_in f + pos | 2 -> in_channel_length f + pos | _ -> error());
 				VNull;
 			| VAbstract (AFWrite f), VInt pos, VInt mode ->
-				seek_out f (match mode with 0 -> pos | 1 -> pos_out f + pos | 2 -> out_channel_length f - pos | _ -> error());
+				seek_out f (match mode with 0 -> pos | 1 -> pos_out f + pos | 2 -> out_channel_length f + pos | _ -> error());
 				VNull;
 			| _ -> error()
 		);
 		"file_tell", Fun1 (fun f ->
 			match f with
-			| VAbstract (AFRead f) -> VInt (pos_in f)
+			| VAbstract (AFRead (f,_)) -> VInt (pos_in f)
 			| VAbstract (AFWrite f) -> VInt (pos_out f)
 			| _ -> error()
 		);
 		"file_eof", Fun1 (fun f ->
 			match f with
-			| VAbstract (AFRead f) ->
-				VBool (try
-					ignore(input_char f);
-					seek_in f (pos_in f - 1);
-					false
-				with End_of_file ->
-					true)
+			| VAbstract (AFRead (f,r)) ->
+				VBool !r
 			| _ -> error()
 		);
 		"file_flush", Fun1 (fun f ->
@@ -1495,7 +1503,7 @@ let std_lib =
 			| VString f -> VString (Std.input_file ~bin:true f)
 			| _ -> error()
 		);
-		"file_stdin", Fun0 (fun() -> VAbstract (AFRead Pervasives.stdin));
+		"file_stdin", Fun0 (fun() -> VAbstract (AFRead (Pervasives.stdin, ref false)));
 		"file_stdout", Fun0 (fun() -> VAbstract (AFWrite Pervasives.stdout));
 		"file_stderr", Fun0 (fun() -> VAbstract (AFWrite Pervasives.stderr));
 	(* serialize *)
@@ -1507,9 +1515,9 @@ let std_lib =
 			| VBool b -> VAbstract (ASocket (Unix.socket PF_INET (if b then SOCK_DGRAM else SOCK_STREAM) 0));
 			| _ -> error()
 		);
-		"socket_close", Fun1 (fun s ->
-			match s with
-			| VAbstract (ASocket s) -> Unix.close s; VNull
+		"socket_close", Fun1 (fun vs ->
+			match vs with
+			| VAbstract (ASocket s) -> Unix.close s; free_abstract vs; VNull
 			| _ -> error()
 		);
 		"socket_send_char", Fun2 (fun s c ->
@@ -1813,6 +1821,65 @@ let std_lib =
 		"utf8_compare", Fun2 (fun s1 s2 ->
 			VInt (UTF8.compare (vstring s1) (vstring s2))
 		);
+	(* thread *)
+		"thread_create", Fun2 (fun f p ->
+			exc (VString "Can't create thread from within a macro");
+		);
+		"tls_create", Fun0 (fun() ->
+			VAbstract (ATls (ref VNull))
+		);
+		"tls_get", Fun1 (fun t ->
+			match t with
+			| VAbstract (ATls r) -> !r
+			| _ -> error();
+		);
+		"tls_set", Fun2 (fun t v ->
+			match t with
+			| VAbstract (ATls r) -> r := v; VNull
+			| _ -> error();
+		);
+		(* lock, mutex, deque : not implemented *)
+	(* process *)
+		"process_run", (Fun2 (fun p args ->
+			match p, args with
+			| VString p, VArray args -> VAbstract (AProcess (Process.run p (Array.map vstring args)))
+			| _ -> error()
+		));
+		"process_stdout_read", (Fun4 (fun p str pos len ->
+			match p, str, pos, len with
+			| VAbstract (AProcess p), VString str, VInt pos, VInt len -> VInt (Process.read_stdout p str pos len)
+			| _ -> error()
+		));
+		"process_stderr_read", (Fun4 (fun p str pos len ->
+			match p, str, pos, len with
+			| VAbstract (AProcess p), VString str, VInt pos, VInt len -> VInt (Process.read_stderr p str pos len)
+			| _ -> error()
+		));
+		"process_stdin_write", (Fun4 (fun p str pos len ->
+			match p, str, pos, len with
+			| VAbstract (AProcess p), VString str, VInt pos, VInt len -> VInt (Process.write_stdin p str pos len)
+			| _ -> error()
+		));
+		"process_stdin_close", (Fun1 (fun p ->
+			match p with
+			| VAbstract (AProcess p) -> Process.close_stdin p; VNull
+			| _ -> error()
+		));
+		"process_exit", (Fun1 (fun p ->
+			match p with
+			| VAbstract (AProcess p) -> VInt (Process.exit p)
+			| _ -> error()
+		));
+		"process_pid", (Fun1 (fun p ->
+			match p with
+			| VAbstract (AProcess p) -> VInt (Process.pid p)
+			| _ -> error()
+		));
+		"process_close", (Fun1 (fun vp ->
+			match vp with
+			| VAbstract (AProcess p) -> Process.close p; free_abstract vp; VNull
+			| _ -> error()
+		));
 	(* xml *)
 		"parse_xml", (match neko with
 		| None -> Fun2 (fun str o ->
@@ -1852,30 +1919,14 @@ let std_lib =
 			let parse_xml = neko.load "std@parse_xml" 2 in
 			Fun2 (fun str o -> neko.call parse_xml [str;o])
 		);
-	(* memory, module, thread : not planned *)
+	(* memory, module : not planned *)
 	]
 	(* process *)
 	@ (match neko with
 	| None -> []
 	| Some neko ->
-		let p_run = neko.load "std@process_run" 2 in
-		let p_stdout_read = neko.load "std@process_stdout_read" 4 in
-		let p_stderr_read = neko.load "std@process_stderr_read" 4 in
-		let p_stdin_write = neko.load "std@process_stdin_write" 4 in
-		let p_stdin_close = neko.load "std@process_stdin_close" 1 in
-		let p_exit = neko.load "std@process_exit" 1 in
-		let p_pid = neko.load "std@process_pid" 1 in
-		let p_close = neko.load "std@process_close" 1 in
 		let win_ec = (try Some (neko.load "std@win_env_changed" 0) with _ -> None) in
 	[
-		"process_run", (Fun2 (fun a b -> neko.call p_run [a;b]));
-		"process_stdout_read", (Fun4 (fun a b c d -> neko.call p_stdout_read [a;VAbstract (ANekoBuffer b);c;d]));
-		"process_stderr_read", (Fun4 (fun a b c d -> neko.call p_stderr_read [a;VAbstract (ANekoBuffer b);c;d]));
-		"process_stdin_write", (Fun4 (fun a b c d -> neko.call p_stdin_write [a;b;c;d]));
-		"process_stdin_close", (Fun1 (fun p -> neko.call p_stdin_close [p]));
-		"process_exit", (Fun1 (fun p -> neko.call p_exit [p]));
-		"process_pid", (Fun1 (fun p -> neko.call p_pid [p]));
-		"process_close", (Fun1 (fun p -> neko.call p_close [p]));
 		"win_env_changed", (Fun0 (fun() -> match win_ec with None -> error() | Some f -> neko.call f []));
 	]))
 
@@ -2019,14 +2070,14 @@ let z_lib =
 			let z = Extc.zlib_deflate_init (match f with VInt i -> i | _ -> error()) in
 			VAbstract (AZipD { z = z; z_flush = Extc.Z_NO_FLUSH })
 		);
-		"deflate_end", Fun1 (fun z ->
-			match z with
-			| VAbstract (AZipD z) -> Extc.zlib_deflate_end z.z; VNull;
+		"deflate_end", Fun1 (fun vz ->
+			match vz with
+			| VAbstract (AZipD z) -> Extc.zlib_deflate_end z.z; free_abstract vz; VNull;
 			| _ -> error()
 		);
-		"inflate_end", Fun1 (fun z ->
-			match z with
-			| VAbstract (AZipI z) -> Extc.zlib_inflate_end z.z; VNull;
+		"inflate_end", Fun1 (fun vz ->
+			match vz with
+			| VAbstract (AZipI z) -> Extc.zlib_inflate_end z.z; free_abstract vz; VNull;
 			| _ -> error()
 		);
 		"set_flush_mode", Fun2 (fun z f ->
@@ -2360,7 +2411,7 @@ let macro_lib =
 			VString (Type.s_type (print_context()) (decode_type v))
 		);
 		"s_expr", Fun2 (fun v b ->
-			let f = match b with VBool true -> Type.s_expr_pretty "" | _ -> Type.s_expr in
+			let f = match b with VBool true -> Type.s_expr_pretty "" | _ -> Type.s_expr_ast true "" in
 			VString (f (Type.s_type (print_context())) (decode_texpr v))
 		);
 		"is_fmt_string", Fun1 (fun v ->
@@ -2459,8 +2510,8 @@ let macro_lib =
 			| None -> VNull
 			| Some t -> encode_type t
 		);
-		"constructor_arguments", Fun0 (fun() ->
-			match (get_ctx()).curapi.get_constructor_arguments() with
+		"call_arguments", Fun0 (fun() ->
+			match (get_ctx()).curapi.get_call_arguments() with
 			| None -> VNull
 			| Some el -> enc_array (List.map encode_expr el)
 		);
@@ -2577,6 +2628,10 @@ let macro_lib =
 			let e = decode_texpr e in
 			encode_expr (make_ast e)
 		);
+		"store_typed_expr", Fun1 (fun e ->
+			let e = try decode_texpr e with Invalid_expr -> error() in
+			encode_expr ((get_ctx()).curapi.store_typed_expr e)
+		);
 		"get_output", Fun0 (fun() ->
 			VString (ccom()).file
 		);
@@ -3522,8 +3577,9 @@ let create com api =
 
 
 
-let do_reuse ctx =
-	ctx.is_reused <- false
+let do_reuse ctx api =
+	ctx.is_reused <- false;
+	ctx.curapi <- api
 
 let can_reuse ctx types =
 	let has_old_version t =
@@ -4384,7 +4440,7 @@ and encode_class_kind k =
 	enc_enum IClassKind tag pl
 
 and encode_tclass c =
-	c.cl_build();
+	ignore(c.cl_build());
 	encode_mtype (TClassDecl c) [
 		"kind", encode_class_kind c.cl_kind;
 		"isExtern", VBool c.cl_extern;
@@ -4547,6 +4603,7 @@ and encode_tvar v =
 		"capture", VBool v.v_capture;
 		"extra", vopt f_extra v.v_extra;
 		"meta", encode_meta_content v.v_meta;
+		"$", VAbstract (AUnsafe (Obj.repr v));
 	]
 
 and encode_module_type mt =
@@ -4656,17 +4713,9 @@ let decode_type_params v =
 	List.map (fun v -> dec_string (field v "name"),decode_type (field v "t")) (dec_array v)
 
 let decode_tvar v =
-	let f_extra v =
-		decode_type_params (field v "params"),opt decode_texpr (field v "expr")
-	in
-	{
-		v_id = (match (field v "id") with VInt i -> i | _ -> raise Invalid_expr);
-		v_name = dec_string (field v "name");
-		v_type = decode_type (field v "t");
-		v_capture = dec_bool (field v "capture");
-		v_extra = opt f_extra (field v "extra");
-		v_meta = decode_meta_content (field v "meta")
-	}
+	match field v "$" with
+	| VAbstract (AUnsafe t) -> Obj.obj t
+	| _ -> raise Invalid_expr
 
 let decode_var_access v =
 	match decode_enum v with

+ 1 - 1
libs

@@ -1 +1 @@
-Subproject commit 78d07983447744bab7095c4e57f290b950d3cf04
+Subproject commit 8bba5315cabf666f94031436653ee0c6115a1762

+ 96 - 49
main.ml

@@ -142,6 +142,7 @@ let deprecated = [
 	"Class not found : neko.zip.Writer", "neko.zip.Writer has been removed, use haxe.zip.Writer instead";
 	"Class not found : haxe.Public", "Use @:publicFields instead of implementing or extending haxe.Public";
 	"#Xml has no field createProlog", "Xml.createProlog was renamed to Xml.createProcessingInstruction";
+	"Module js.html.HtmlElement is loaded with a different case than js.html.HTMLElement", "htmlelement"
 ]
 
 let limit_string s offset =
@@ -158,7 +159,10 @@ let limit_string s offset =
 
 let error ctx msg p =
 	let msg = try List.assoc msg deprecated with Not_found -> msg in
-	message ctx msg p;
+	if msg = "htmlelement" then
+		message ctx "There was a problem with HtmlElement, please refer to https://github.com/HaxeFoundation/html-externs/blob/master/README.md#htmlelement" null_pos
+	else
+		message ctx msg p;
 	ctx.has_error <- true
 
 let htmlescape s =
@@ -168,7 +172,7 @@ let htmlescape s =
 	s
 
 let reserved_flags = [
-	"cross";"flash8";"js";"neko";"flash";"php";"cpp";"cs";"java";"python";
+	"cross";"js";"neko";"flash";"php";"cpp";"cs";"java";"python";
 	"as3";"swc";"macro";"sys"
 	]
 
@@ -718,7 +722,10 @@ and wait_loop boot_com host port =
 		Hashtbl.replace cache.c_modules (m.m_path,m.m_extra.m_sign) m;
 	in
 	let check_module_path com m p =
-		m.m_extra.m_file = Common.unique_full_path (Typeload.resolve_module_file com m.m_path (ref[]) p)
+		if m.m_extra.m_file <> Common.unique_full_path (Typeload.resolve_module_file com m.m_path (ref[]) p) then begin
+			if verbose then print_endline ("Module path " ^ s_type_path m.m_path ^ " has been changed");
+			raise Not_found;
+		end
 	in
 	let compilation_step = ref 0 in
 	let compilation_mark = ref 0 in
@@ -744,22 +751,32 @@ and wait_loop boot_com host port =
 					| MExtern ->
 						(* if we have a file then this will override our extern type *)
 						let has_file = (try ignore(Typeload.resolve_module_file com2 m.m_path (ref[]) p); true with Not_found -> false) in
-						if has_file then raise Not_found;
+						if has_file then begin
+							if verbose then print_endline ("A file is masking the library file " ^ s_type_path m.m_path);
+							raise Not_found;
+						end;
 						let rec loop = function
-							| [] -> raise Not_found (* no extern registration *)
+							| [] ->
+								if verbose then print_endline ("No library file was found for " ^ s_type_path m.m_path);
+								raise Not_found (* no extern registration *)
 							| load :: l ->
 								match load m.m_path p with
 								| None -> loop l
-								| Some (file,_) -> if Common.unique_full_path file <> m.m_extra.m_file then raise Not_found
+								| Some (file,_) ->
+									if Common.unique_full_path file <> m.m_extra.m_file then begin
+										if verbose then print_endline ("Library file was changed for " ^ s_type_path m.m_path);
+										raise Not_found;
+									end
 						in
 						loop com2.load_extern_type
-					| MCode -> if not (check_module_path com2 m p) then raise Not_found;
-					| MMacro when ctx.Typecore.in_macro -> if not (check_module_path com2 m p) then raise Not_found;
+					| MCode -> check_module_path com2 m p
+					| MMacro when ctx.Typecore.in_macro -> check_module_path com2 m p
 					| MMacro ->
 						let _, mctx = Typer.get_macro_context ctx p in
-						if not (check_module_path mctx.Typecore.com m p) then raise Not_found;
+						check_module_path mctx.Typecore.com m p
 					);
 					if file_time m.m_extra.m_file <> m.m_extra.m_time then begin
+						if verbose then print_endline ("File " ^ m.m_extra.m_file ^ (if m.m_extra.m_time = -1. then " not cached (macro-in-macro)" else " has been modified"));
 						if m.m_extra.m_kind = MFake then Hashtbl.remove Typecore.fake_modules m.m_extra.m_file;
 						raise Not_found;
 					end;
@@ -965,7 +982,7 @@ and do_connect host port args =
 
 and init ctx =
 	let usage = Printf.sprintf
-		"Haxe Compiler %s %s- (C)2005-2014 Haxe Foundation\n Usage : haxe%s -main <class> [-swf|-js|-neko|-php|-cpp|-as3] <output> [options]\n Options :"
+		"Haxe Compiler %s %s- (C)2005-2015 Haxe Foundation\n Usage : haxe%s -main <class> [-swf|-js|-neko|-php|-cpp|-as3] <output> [options]\n Options :"
 		s_version (match Version.version_extra with None -> "" | Some v -> v) (if Sys.os_type = "Win32" then ".exe" else "")
 	in
 	let com = ctx.com in
@@ -985,7 +1002,7 @@ try
 	let swf_version = ref false in
 	let evals = ref [] in
 	Common.define_value com Define.HaxeVer (float_repres (float_of_int version /. 1000.));
-	Common.define_value com Define.HxcppApiLevel "313";
+	Common.define_value com Define.HxcppApiLevel "321";
 	Common.raw_define com "haxe3";
 	Common.define_value com Define.Dce "std";
 	com.warning <- (fun msg p -> message ctx ("Warning : " ^ msg) p);
@@ -1009,7 +1026,7 @@ try
 	with
 		Not_found ->
 			if Sys.os_type = "Unix" then
-				com.class_path <- ["/usr/lib/haxe/std/";"/usr/local/lib/haxe/std/";"/usr/lib/haxe/extraLibs/";"/usr/local/lib/haxe/extraLibs/";""]
+				com.class_path <- ["/usr/lib/haxe/std/";"/usr/share/haxe/std/";"/usr/local/lib/haxe/std/";"/usr/lib/haxe/extraLibs/";"/usr/local/lib/haxe/extraLibs/";""]
 			else
 				let base_path = normalize_path (get_real_path (try executable_path() with _ -> "./")) in
 				com.class_path <- [base_path ^ "std/";base_path ^ "extraLibs/";""]);
@@ -1018,7 +1035,7 @@ try
 		if com.platform <> Cross then failwith "Multiple targets";
 		Common.init_platform com pf;
 		com.file <- file;
-		if (pf = Flash8 || pf = Flash) && file_extension file = "swc" then Common.define com Define.Swc;
+		if (pf = Flash) && file_extension file = "swc" then Common.define com Define.Swc;
 	in
 	let define f = Arg.Unit (fun () -> Common.define com f) in
 	let process_ref = ref (fun args -> ()) in
@@ -1124,7 +1141,8 @@ try
 			Genswf.add_swf_lib com file true
 		),"<file> : use the SWF library for type checking");
 		("-java-lib",Arg.String (fun file ->
-			arg_delays := (fun () -> Genjava.add_java_lib com file false) :: !arg_delays;
+			let std = file = "lib/hxjava-std.jar" in
+			arg_delays := (fun () -> Genjava.add_java_lib com file std) :: !arg_delays;
 		),"<file> : add an external JAR or class directory library");
 		("-net-lib",Arg.String (fun file ->
 			let file, is_std = match ExtString.String.nsplit file "@" with
@@ -1182,6 +1200,14 @@ try
 				List.iter (fun (_,_,extract) ->
 					Hashtbl.iter (fun n _ -> classes := n :: !classes) (extract())
 				) com.swf_libs;
+				List.iter (fun (_,std,_,all_files,_) ->
+					if not std then
+						List.iter (fun path -> if path <> (["java";"lang"],"String") then classes := path :: !classes) (all_files())
+				) com.java_libs;
+				List.iter (fun (_,std,all_files,_) ->
+					if not std then
+						List.iter (fun path -> classes := path :: !classes) (all_files())
+				) com.net_libs;
 			) :: !pre_compilation;
 			xml_out := Some "hx"
 		),": generate hx headers for all input classes");
@@ -1190,7 +1216,7 @@ try
 		("--display", Arg.String (fun file_pos ->
 			match file_pos with
 			| "classes" ->
-				pre_compilation := (fun() -> raise (Parser.TypePath (["."],None))) :: !pre_compilation;
+				pre_compilation := (fun() -> raise (Parser.TypePath (["."],None,true))) :: !pre_compilation;
 			| "keywords" ->
 				complete_fields com (Hashtbl.fold (fun k _ acc -> (k,"",None,"") :: acc) Lexer.keywords [])
 			| "memory" ->
@@ -1370,16 +1396,11 @@ try
 	process_ref := process;
 	process ctx.com.args;
 	process_libs();
-	(try ignore(Common.find_file com "mt/Include.hx"); Common.raw_define com "mt"; with Not_found -> ());
 	if com.display <> DMNone then begin
 		com.warning <- message ctx;
 		com.error <- error ctx;
 		com.main_class <- None;
 		let real = get_real_path (!Parser.resume_display).Ast.pfile in
-		(* try to fix issue on windows when get_real_path fails (8.3 DOS names disabled) *)
-		let real = (match List.rev (ExtString.String.nsplit real path_sep) with
-		| file :: path when String.length file > 0 && file.[0] >= 'a' && file.[1] <= 'z' -> file.[0] <- char_of_int (int_of_char file.[0] - int_of_char 'a' + int_of_char 'A'); String.concat path_sep (List.rev (file :: path))
-		| _ -> real) in
 		classes := lookup_classes com real;
 		if !classes = [] then begin
 			if not (Sys.file_exists real) then failwith "Display file does not exist";
@@ -1399,28 +1420,18 @@ try
 			(* no platform selected *)
 			set_platform Cross "";
 			"?"
-		| Flash8 | Flash ->
-			if com.flash_version >= 9. then begin
-				let rec loop = function
-					| [] -> ()
-					| (v,_) :: _ when v > com.flash_version -> ()
-					| (v,def) :: l ->
-						Common.raw_define com ("flash" ^ def);
-						loop l
-				in
-				loop Common.flash_versions;
-				Common.raw_define com "flash";
-				com.defines <- PMap.remove "flash8" com.defines;
-				com.package_rules <- PMap.remove "flash" com.package_rules;
-				add_std "flash";
-			end else begin
-				com.package_rules <- PMap.add "flash" (Directory "flash8") com.package_rules;
-				com.package_rules <- PMap.add "flash8" Forbidden com.package_rules;
-				Common.raw_define com "flash";
-				Common.raw_define com ("flash" ^ string_of_int (int_of_float com.flash_version));
-				com.platform <- Flash8;
-				add_std "flash8";
-			end;
+		| Flash ->
+			let rec loop = function
+				| [] -> ()
+				| (v,_) :: _ when v > com.flash_version -> ()
+				| (v,def) :: l ->
+					Common.raw_define com ("flash" ^ def);
+					loop l
+			in
+			loop Common.flash_versions;
+			Common.raw_define com "flash";
+			com.package_rules <- PMap.remove "flash" com.package_rules;
+			add_std "flash";
 			"swf"
 		| Neko ->
 			add_std "neko";
@@ -1435,12 +1446,18 @@ try
 			add_std "cpp";
 			"cpp"
 		| Cs ->
+			let old_flush = ctx.flush in
+			ctx.flush <- (fun () ->
+				com.net_libs <- [];
+				old_flush()
+			);
 			Gencs.before_generate com;
 			add_std "cs"; "cs"
 		| Java ->
 			let old_flush = ctx.flush in
 			ctx.flush <- (fun () ->
 				List.iter (fun (_,_,close,_,_) -> close()) com.java_libs;
+				com.java_libs <- [];
 				old_flush()
 			);
 			Genjava.before_generate com;
@@ -1527,10 +1544,10 @@ try
 			end;
 		| Cross ->
 			()
-		| Flash8 | Flash when Common.defined com Define.As3 ->
+		| Flash when Common.defined com Define.As3 ->
 			Common.log com ("Generating AS3 in : " ^ com.file);
 			Genas3.generate com;
-		| Flash8 | Flash ->
+		| Flash ->
 			Common.log com ("Generating swf : " ^ com.file);
 			Genswf.generate com !swf_header;
 		| Neko ->
@@ -1557,8 +1574,8 @@ try
 		);
 	end;
 	Sys.catch_break false;
+	List.iter (fun f -> f()) (List.rev com.final_filters);
 	if not !no_output then begin
-		List.iter (fun f -> f()) (List.rev com.final_filters);
 		List.iter (fun c ->
 			let r = run_command ctx c in
 			if r <> 0 then failwith ("Command failed with error " ^ string_of_int r)
@@ -1567,6 +1584,8 @@ try
 with
 	| Abort ->
 		()
+	| Ast.Error (m,p) ->
+		error ctx m p
 	| Typecore.Fatal_error (m,p) ->
 		error ctx m p
 	| Common.Abort (m,p) ->
@@ -1651,7 +1670,7 @@ with
 		) il;
 		Buffer.add_string b "</il>";
 		raise (Completion (Buffer.contents b))
-	| Parser.TypePath (p,c) ->
+	| Parser.TypePath (p,c,is_import) ->
 		(match c with
 		| None ->
 			let packs, classes = read_type_path com p in
@@ -1664,10 +1683,14 @@ with
 				)
 		| Some (c,cur_package) ->
 			try
+				let sl_pack,s_module = match List.rev p with
+					| s :: sl when s.[0] >= 'A' && s.[0] <= 'Z' -> List.rev sl,s
+					| _ -> p,c
+				in
 				let ctx = Typer.create com in
 				let rec lookup p =
 					try
-						Typeload.load_module ctx (p,c) Ast.null_pos
+						Typeload.load_module ctx (p,s_module) Ast.null_pos
 					with e ->
 						if cur_package then
 							match List.rev p with
@@ -1676,8 +1699,32 @@ with
 						else
 							raise e
 				in
-				let m = lookup p in
-				complete_fields com (List.map (fun t -> snd (t_path t),"",Some Typer.FKType,"") (List.filter (fun t -> not (t_infos t).mt_private) m.m_types))
+				let m = lookup sl_pack in
+				let statics = ref None in
+				let public_types = List.filter (fun t ->
+					let tinfos = t_infos t in
+					let is_module_type = snd tinfos.mt_path = c in
+					if is_import && is_module_type then begin match t with
+						| TClassDecl c ->
+							ignore(c.cl_build());
+							statics := Some c.cl_ordered_statics
+						| _ -> ()
+					end;
+					not tinfos.mt_private
+				) m.m_types in
+				let types = if c <> s_module then [] else List.map (fun t -> snd (t_path t),"",Some Typer.FKType,"") public_types in
+				let ctx = print_context() in
+				let make_field_doc cf =
+					cf.cf_name,
+					s_type ctx cf.cf_type,
+					Some (match cf.cf_kind with Method _ -> Typer.FKMethod | Var _ -> Typer.FKVar),
+					(match cf.cf_doc with Some s -> s | None -> "")
+				in
+				let types = match !statics with
+					| None -> types
+					| Some cfl -> types @ (List.map make_field_doc (List.filter (fun cf -> cf.cf_public) cfl))
+				in
+				complete_fields com types
 			with Completion c ->
 				raise (Completion c)
 			| _ ->

+ 11 - 7
matcher.ml

@@ -297,8 +297,7 @@ let rec is_value_type = function
 	| _ ->
 		false
 
-(* 	Determines if a type allows null-matching. This is similar to is_nullable, but it infers Null<T> on monomorphs,
-	and enums are not considered nullable *)
+(* 	Determines if a type allows null-matching. This is similar to is_nullable, but it infers Null<T> on monomorphs *)
 let rec matches_null ctx t = match t with
 	| TMono r ->
 		(match !r with None -> r := Some (ctx.t.tnull (mk_mono())); true | Some t -> matches_null ctx t)
@@ -308,7 +307,7 @@ let rec matches_null ctx t = match t with
 		matches_null ctx (!f())
 	| TType (t,tl) ->
 		matches_null ctx (apply_params t.t_params tl t.t_type)
-	| TFun _ | TEnum _ ->
+	| TFun _ ->
 		false
 	| TAbstract (a,_) -> not (Meta.has Meta.NotNull a.a_meta)
 	| _ ->
@@ -1059,13 +1058,18 @@ let convert_switch mctx st cases loop =
 		| _ -> DTSwitch(e, List.map (fun (c,dt) -> convert_con ctx c, loop dt) cases, !def)
 	in
 	match !null with
-	| None when is_explicit_null st.st_type ->
-		let econd = mk (TBinop(OpNotEq,e_st,mk (TConst TNull) (mk_mono()) p)) ctx.t.tbool p in
+	| None when is_explicit_null st.st_type && (!def <> None || not mctx.need_val) ->
+		let econd = mk (TBinop(OpNotEq,e_st,mk (TConst TNull) st.st_type p)) ctx.t.tbool p in
 		DTGuard(econd,dt,!def)
 	| None ->
 		dt
 	| Some dt_null ->
-		let econd = mk (TBinop(OpEq,e_st,mk (TConst TNull) (mk_mono()) p)) ctx.t.tbool p in
+		let t = match ctx.t.tnull ctx.t.tint with
+			| TType(t,_) ->TType(t,[st.st_type])
+			| t -> t
+		in
+		let e_null = mk (TConst TNull) t p in
+		let econd = mk (TBinop(OpEq,e_st, e_null)) ctx.t.tbool p in
 		DTGuard(econd,dt_null,Some dt)
 
 (* Decision tree compilation *)
@@ -1163,7 +1167,7 @@ let match_expr ctx e cases def with_type p =
 			let e = type_expr ctx e Value in
 			begin match follow e.etype with
 			(* TODO: get rid of the XmlType check *)
-			| TEnum(en,_) when (en.e_path = ([],"XmlType")) || Meta.has Meta.FakeEnum en.e_meta ->
+			| TEnum(en,_) when (match en.e_path with (["neko" | "php" | "flash" | "cpp"],"XmlType") -> true | _ -> Meta.has Meta.FakeEnum en.e_meta) ->
 				raise Exit
 			| TAbstract({a_path=[],("Int" | "Float" | "Bool")},_) | TInst({cl_path = [],"String"},_) when (Common.defined ctx.com Common.Define.NoPatternMatching) ->
 				raise Exit;

+ 151 - 52
optimizer.ml

@@ -53,10 +53,21 @@ let mk_untyped_call name p params =
 
 let api_inline ctx c field params p =
 	match c.cl_path, field, params with
-	| ([],"Type"),"enumIndex",[{ eexpr = TField (_,FEnum (en,f)) }] ->
-		Some (mk (TConst (TInt (Int32.of_int f.ef_index))) ctx.t.tint p)
+	| ([],"Type"),"enumIndex",[{ eexpr = TField (_,FEnum (en,f)) }] -> (match ctx.com.platform with
+		| Cs when en.e_extern && not (Meta.has Meta.HxGen en.e_meta) ->
+			(* We don't want to optimize enums from external sources; as they might change unexpectedly *)
+			(* and since native C# enums don't have the concept of index - they have rather a value, *)
+			(* which can't be mapped to a native API - this kind of substitution is dangerous *)
+			None
+		| _ ->
+			Some (mk (TConst (TInt (Int32.of_int f.ef_index))) ctx.t.tint p))
 	| ([],"Type"),"enumIndex",[{ eexpr = TCall({ eexpr = TField (_,FEnum (en,f)) },pl) }] when List.for_all (fun e -> not (has_side_effect e)) pl ->
-		Some (mk (TConst (TInt (Int32.of_int f.ef_index))) ctx.t.tint p)
+		(match ctx.com.platform with
+			| Cs when en.e_extern && not (Meta.has Meta.HxGen en.e_meta) ->
+				(* see comment above *)
+				None
+			| _ ->
+				Some (mk (TConst (TInt (Int32.of_int f.ef_index))) ctx.t.tint p))
 	| ([],"Std"),"int",[{ eexpr = TConst (TInt _) } as e] ->
 		Some { e with epos = p }
 	| ([],"String"),"fromCharCode",[{ eexpr = TConst (TInt i) }] when i > 0l && i < 128l ->
@@ -253,8 +264,9 @@ let rec type_inline ctx cf f ethis params tret config p ?(self_calling_closure=f
 			Hashtbl.add locals i.i_subst.v_id i;
 			i
 	in
+	let in_local_fun = ref false in
 	let read_local v =
-		try
+		let l = try
 			Hashtbl.find locals v.v_id
 		with Not_found ->
 			(* make sure to duplicate unbound inline variable to prevent dependency leak when unifying monomorph *)
@@ -267,6 +279,9 @@ let rec type_inline ctx cf f ethis params tret config p ?(self_calling_closure=f
 				i_force_temp = false;
 				i_read = 0;
 			}
+		in
+		if !in_local_fun then l.i_captured <- true;
+		l
 	in
 	(* use default values for null/unset arguments *)
 	let rec loop pl al first =
@@ -321,7 +336,6 @@ let rec type_inline ctx cf f ethis params tret config p ?(self_calling_closure=f
 	in
 	let has_vars = ref false in
 	let in_loop = ref false in
-	let in_local_fun = ref false in
 	let cancel_inlining = ref false in
 	let has_return_value = ref false in
 	let ret_val = (match follow f.tf_type with TAbstract ({ a_path = ([],"Void") },[]) -> false | _ -> true) in
@@ -332,12 +346,12 @@ let rec type_inline ctx cf f ethis params tret config p ?(self_calling_closure=f
 		match e.eexpr with
 		| TLocal v ->
 			let l = read_local v in
-			if !in_local_fun then l.i_captured <- true;
 			l.i_read <- l.i_read + (if !in_loop then 2 else 1);
 			(* never inline a function which contain a delayed macro because its bound
 				to its variables and not the calling method *)
 			if v.v_name = "__dollar__delay_call" then cancel_inlining := true;
-			{ e with eexpr = TLocal l.i_subst }
+			let e = { e with eexpr = TLocal l.i_subst } in
+			if Meta.has Meta.This v.v_meta then mk (TCast(e,None)) v.v_type e.epos else e
 		| TConst TThis ->
 			let l = read_local vthis in
 			l.i_read <- l.i_read + (if !in_loop then 2 else 1);
@@ -417,12 +431,29 @@ let rec type_inline ctx cf f ethis params tret config p ?(self_calling_closure=f
 		| TParenthesis e1 ->
 			let e1 = map term e1 in
 			mk (TParenthesis e1) e1.etype e.epos
-		| TUnop ((Increment|Decrement),_,{ eexpr = TLocal v }) ->
-			(read_local v).i_write <- true;
-			Type.map_expr (map false) e
-		| TBinop ((OpAssign | OpAssignOp _),{ eexpr = TLocal v },_) ->
-			(read_local v).i_write <- true;
-			Type.map_expr (map false) e;
+		| TUnop ((Increment|Decrement) as op,flag,({ eexpr = TLocal v } as e1)) ->
+			let l = read_local v in
+			l.i_write <- true;
+			{e with eexpr = TUnop(op,flag,{e1 with eexpr = TLocal l.i_subst})}
+		| TBinop ((OpAssign | OpAssignOp _) as op,({ eexpr = TLocal v } as e1),e2) ->
+			let l = read_local v in
+			l.i_write <- true;
+			let e2 = map false e2 in
+			{e with eexpr = TBinop(op,{e1 with eexpr = TLocal l.i_subst},e2)}
+(* 		| TCall({eexpr = TLocal v} as e1,el) ->
+			let el = List.map (map false) el in
+			let l = read_local v in
+			let edef() = {e with eexpr = TCall({e1 with eexpr = TLocal l.i_subst},el)} in
+			begin try
+				begin match List.assq l inlined_vars with
+				| {eexpr = TField(_, (FStatic(_,cf) | FInstance(_,_,cf)))} as e' when cf.cf_kind = Method MethInline ->
+					make_call ctx e' el e.etype e.epos
+				| _ ->
+					edef()
+				end
+			with Not_found ->
+				edef()
+			end *)
 		| TFunction f ->
 			(match f.tf_args with [] -> () | _ -> has_vars := true);
 			let old = save_locals ctx and old_fun = !in_local_fun in
@@ -665,6 +696,36 @@ let rec optimize_for_loop ctx (i,pi) e1 e2 p =
 					NormalWhile
 				)) t_void p;
 			])
+	| TArrayDecl el, TInst({ cl_path = [],"Array" },[pt]) when false ->
+		begin try
+			let num_expr = ref 0 in
+			let rec loop e = match fst e with
+				| EContinue | EBreak ->
+					raise Exit
+				| _ ->
+					incr num_expr;
+					Ast.map_expr loop e
+			in
+			ignore(loop e2);
+			let v = add_local ctx i pt in
+			let e2 = type_expr ctx e2 NoValue in
+			let cost = (List.length el) * !num_expr in
+			let max_cost = try
+				int_of_string (Common.defined_value ctx.com Define.LoopUnrollMaxCost)
+			with Not_found ->
+				250
+			in
+			if cost > max_cost then raise Exit;
+			let eloc = mk (TLocal v) v.v_type p in
+			let el = List.map (fun e ->
+				let e_assign = mk (TBinop(OpAssign,eloc,e)) e.etype e.epos in
+				concat e_assign e2
+			) el in
+			let ev = mk (TVar(v, None)) ctx.t.tvoid p in
+			Some (mk (TBlock (ev :: el)) ctx.t.tvoid p)
+		with Exit ->
+			gen_int_iter pt get_next_array_element get_array_length
+		end
 	| _ , TInst({ cl_path = [],"Array" },[pt])
 	| _ , TInst({ cl_path = ["flash"],"Vector" },[pt]) ->
 		gen_int_iter pt get_next_array_element get_array_length
@@ -1127,7 +1188,16 @@ let rec make_constant_expression ctx ?(concat_strings=false) e =
 		(match make_constant_expression ctx e1 with
 		| None -> None
 		| Some e1 -> Some {e with eexpr = TCast(e1,None)})
-	| TParenthesis e | TMeta(_,e) -> Some e
+	| TParenthesis e1 ->
+		begin match make_constant_expression ctx ~concat_strings e1 with
+			| None -> None
+			| Some e1 -> Some {e with eexpr = TParenthesis e1}
+		end
+	| TMeta(m,e1) ->
+		begin match make_constant_expression ctx ~concat_strings e1 with
+			| None -> None
+			| Some e1 -> Some {e with eexpr = TMeta(m,e1)}
+		end
 	| TTypeExpr _ -> Some e
 	(* try to inline static function calls *)
 	| TCall ({ etype = TFun(_,ret); eexpr = TField (_,FStatic (c,cf)) },el) ->
@@ -1228,6 +1298,11 @@ let inline_constructors ctx e =
 		| _ -> ());
 		vars := PMap.remove v.v_id !vars;
 	in
+	let rec skip_to_var e = match e.eexpr with
+		| TLocal v when v.v_id < 0 -> Some v
+		(* | TCast(e1,None) | TMeta(_,e1) | TParenthesis(e1) -> skip_to_var e1 *)
+		| _ -> None
+	in
 	let rec find_locals e =
 		match e.eexpr with
 		| TVar (v,eo) ->
@@ -1235,7 +1310,7 @@ let inline_constructors ctx e =
 			begin match eo with
 				| Some n ->
 					begin match get_inline_ctor_info n with
-					| IKCtor (f,cst,c,tl,pl,el_init) ->
+					| IKCtor (f,cst,c,tl,pl,el_init) when type_iseq v.v_type n.etype ->
 						(* inline the constructor *)
 						(match (try type_inline ctx cst f (mk (TLocal v) (TInst (c,tl)) n.epos) pl ctx.t.tvoid None n.epos true with Error (Custom _,_) -> None) with
 						| None -> ()
@@ -1271,17 +1346,21 @@ let inline_constructors ctx e =
 					| IKStructure fl ->
 						vars := PMap.add v.v_id (v,[],List.map (fun (s,e) -> s,e,e.etype) fl, false, n.epos) !vars;
 						v.v_id <- -v.v_id;
-					| IKNone ->
+					| _ ->
 						()
 					end
-				| None -> ()
+				| _ -> ()
+			end
+		| TField(e1, (FInstance(_, _, {cf_kind = Var _; cf_name = s}) | FAnon({cf_kind = Var _; cf_name = s}))) ->
+			(match skip_to_var e1 with None -> find_locals e1 | Some _ -> ())
+		| TArray (e1,{eexpr = TConst (TInt i)}) ->
+			begin match skip_to_var e1 with
+				| None -> find_locals e1
+				| Some v ->
+					let (_,_,fields,_,_) = PMap.find (-v.v_id) !vars in
+					let i = Int32.to_int i in
+					if i < 0 || i >= List.length fields then cancel v
 			end
-		| TField({eexpr = TLocal v}, (FInstance(_, _, {cf_kind = Var _; cf_name = s}) | FAnon({cf_kind = Var _; cf_name = s}))) ->
-			()
-		| TArray ({eexpr = TLocal v},{eexpr = TConst (TInt i)}) when v.v_id < 0 ->
-			let (_,_,fields,_,_) = PMap.find (-v.v_id) !vars in
-			let i = Int32.to_int i in
-			if i < 0 || i >= List.length fields then cancel v
 		| TBinop((OpAssign | OpAssignOp _),e1,e2) ->
 			begin match e1.eexpr with
 	 			| TArray ({eexpr = TLocal v},{eexpr = TConst (TInt i)}) when v.v_id < 0 ->
@@ -1310,6 +1389,38 @@ let inline_constructors ctx e =
 		) vars in
 		let el_b = ref [] in
 		let append e = el_b := e :: !el_b in
+		let inline_field c cf v =
+			let (_, vars),el_init = PMap.find (-v.v_id) vfields in
+			(try
+				let v = PMap.find cf.cf_name vars in
+				mk (TLocal v) v.v_type e.epos
+			with Not_found ->
+				if (c.cl_path = ([],"Array") && cf.cf_name = "length") then begin
+					(* this can only occur for inlined array declarations, so we can use the statically known length here (issue #2568)*)
+					let l = PMap.fold (fun _ i -> i + 1) vars 0 in
+					mk (TConst (TInt (Int32.of_int l))) ctx.t.tint e.epos
+				end else
+					(* the variable was not set in the constructor, assume null *)
+					mk (TConst TNull) e.etype e.epos)
+		in
+		let inline_anon_field cf v =
+			let (_, vars),_ = PMap.find (-v.v_id) vfields in
+			(try
+				let v = PMap.find cf.cf_name vars in
+				mk (TLocal v) v.v_type e.epos
+			with Not_found ->
+				(* this could happen in untyped code, assume null *)
+				mk (TConst TNull) e.etype e.epos)
+		in
+		let inline_array_access i v =
+			let (_, vars),_ = PMap.find (-v.v_id) vfields in
+			(try
+				let v = PMap.find (Int32.to_string i) vars in
+				mk (TLocal v) v.v_type e.epos
+			with Not_found ->
+				(* probably out-of-bounds, assume null *)
+				mk (TConst TNull) e.etype e.epos)
+		in
 		let rec subst e =
 			match e.eexpr with
 			| TBlock el ->
@@ -1330,35 +1441,21 @@ let inline_constructors ctx e =
 				in
 				List.iter (fun (v,e) -> append (mk (TVar(v,Some (subst e))) ctx.t.tvoid e.epos)) (List.rev vars);
 				mk (TVar (v_first, Some (subst e_first))) ctx.t.tvoid e.epos
-			| TField ({ eexpr = TLocal v },FInstance (c,_,cf)) when v.v_id < 0 ->
-				let (_, vars),el_init = PMap.find (-v.v_id) vfields in
-				(try
-					let v = PMap.find cf.cf_name vars in
-					mk (TLocal v) v.v_type e.epos
-				with Not_found ->
-					if (c.cl_path = ([],"Array") && cf.cf_name = "length") then begin
-						(* this can only occur for inlined array declarations, so we can use the statically known length here (issue #2568)*)
-						let l = PMap.fold (fun _ i -> i + 1) vars 0 in
-						mk (TConst (TInt (Int32.of_int l))) ctx.t.tint e.epos
-					end else
-						(* the variable was not set in the constructor, assume null *)
-						mk (TConst TNull) e.etype e.epos)
-			| TArray ({eexpr = TLocal v},{eexpr = TConst (TInt i)}) when v.v_id < 0 ->
-				let (_, vars),_ = PMap.find (-v.v_id) vfields in
-				(try
-					let v = PMap.find (Int32.to_string i) vars in
-					mk (TLocal v) v.v_type e.epos
-				with Not_found ->
-					(* probably out-of-bounds, assume null *)
-					mk (TConst TNull) e.etype e.epos)
-			| TField({eexpr = TLocal v},FAnon(cf)) when v.v_id < 0 ->
-				let (_, vars),_ = PMap.find (-v.v_id) vfields in
-				(try
-					let v = PMap.find cf.cf_name vars in
-					mk (TLocal v) v.v_type e.epos
-				with Not_found ->
-					(* this could happen in untyped code, assume null *)
-					mk (TConst TNull) e.etype e.epos)
+			| TField (e1,FInstance (c,_,cf)) ->
+				begin match skip_to_var e1 with
+					| None -> Type.map_expr subst e
+					| Some v -> inline_field c cf v
+				end
+			| TArray (e1,{eexpr = TConst (TInt i)}) ->
+				begin match skip_to_var e1 with
+					| None -> Type.map_expr subst e
+					| Some v -> inline_array_access i v
+				end
+			| TField (e1,FAnon(cf)) ->
+				begin match skip_to_var e1 with
+					| None -> Type.map_expr subst e
+					| Some v -> inline_anon_field cf v
+				end
 			| _ ->
 				Type.map_expr subst e
 		in
@@ -1519,6 +1616,8 @@ let optimize_completion_expr e =
 					with Not_found ->
 						(* not found locals are most likely to be member/static vars *)
 						e)
+				| EFunction (_,f) ->
+					Ast.map_expr (subst_locals { r = PMap.foldi (fun n i acc -> if List.exists (fun (a,_,_,_) -> a = n) f.f_args then acc else PMap.add n i acc) locals.r PMap.empty }) e
 				| _ ->
 					Ast.map_expr (subst_locals locals) e
 			in

+ 108 - 44
parser.ml

@@ -32,7 +32,7 @@ type error_msg =
 	| Custom of string
 
 exception Error of error_msg * pos
-exception TypePath of string list * (string * bool) option
+exception TypePath of string list * (string * bool) option * bool (* in import *)
 exception Display of expr
 
 let error_msg = function
@@ -50,7 +50,14 @@ let display_error : (error_msg -> pos -> unit) ref = ref (fun _ _ -> assert fals
 let quoted_ident_prefix = "@$__hx__"
 
 let quote_ident s =
-	try
+	quoted_ident_prefix ^ s
+
+let unquote_ident f =
+	let pf = quoted_ident_prefix in
+	let pflen = String.length pf in
+	let is_quoted = String.length f >= pflen && String.sub f 0 pflen = pf in
+	let s = if is_quoted then String.sub f pflen (String.length f - pflen) else f in
+	let is_valid = not is_quoted || try
 		for i = 0 to String.length s - 1 do
 			match String.unsafe_get s i with
 			| 'a'..'z' | 'A'..'Z' | '_' -> ()
@@ -58,14 +65,11 @@ let quote_ident s =
 			| _ -> raise Exit
 		done;
 		if Hashtbl.mem Lexer.keywords s then raise Exit;
-		s
+		true
 	with Exit ->
-		quoted_ident_prefix ^ s
-
-let unquote_ident f =
-	let pf = quoted_ident_prefix in
-	let pflen = String.length pf in
-	if String.length f >= pflen && String.sub f 0 pflen = pf then String.sub f pflen (String.length f - pflen), false else f, true
+		false
+	in
+	s,is_quoted,is_valid
 
 let cache = ref (DynArray.create())
 let last_doc = ref None
@@ -84,6 +88,10 @@ let do_resume() = !resume_display <> null_pos
 
 let display e = raise (Display e)
 
+let type_path sl in_import = match sl with
+	| n :: l when n.[0] >= 'A' && n.[0] <= 'Z' -> raise (TypePath (List.rev l,Some (n,false),in_import));
+	| _ -> raise (TypePath (List.rev sl,None,in_import))
+
 let is_resuming p =
 	let p2 = !resume_display in
 	p.pmax = p2.pmin && !use_parser_resume && Common.unique_full_path p.pfile = p2.pfile
@@ -510,10 +518,12 @@ let dollar_ident_macro pack = parser
 	| [< '(Const (Ident i),p) >] -> i,p
 	| [< '(Dollar i,p) >] -> ("$" ^ i),p
 	| [< '(Kwd Macro,p) when pack <> [] >] -> "macro", p
+	| [< '(Kwd Extern,p) when pack <> [] >] -> "extern", p
 
 let lower_ident_or_macro = parser
 	| [< '(Const (Ident i),p) when is_lower_ident i >] -> i
 	| [< '(Kwd Macro,_) >] -> "macro"
+	| [< '(Kwd Extern,_) >] -> "extern"
 
 let any_enum_ident = parser
 	| [< i = ident >] -> i
@@ -566,17 +576,17 @@ and parse_type_decls pack acc s =
 		match s with parser
 		| [< v = parse_type_decl; l = parse_type_decls pack (v :: acc) >] -> l
 		| [< >] -> List.rev acc
-	with TypePath ([],Some (name,false)) ->
+	with TypePath ([],Some (name,false),b) ->
 		(* resolve imports *)
 		List.iter (fun d ->
 			match fst d with
 			| EImport (t,_) ->
 				(match List.rev t with
-				| (n,_) :: path when n = name && List.for_all (fun (i,_) -> is_lower_ident i) path -> raise (TypePath (List.map fst (List.rev path),Some (name,false)))
+				| (n,_) :: path when n = name && List.for_all (fun (i,_) -> is_lower_ident i) path -> raise (TypePath (List.map fst (List.rev path),Some (name,false),b))
 				| _ -> ())
 			| _ -> ()
 		) acc;
-		raise (TypePath (pack,Some(name,true)))
+		raise (TypePath (pack,Some(name,true),b))
 
 and parse_type_decl s =
 	match s with parser
@@ -643,17 +653,22 @@ and parse_import s p1 =
 	let rec loop acc =
 		match s with parser
 		| [< '(Dot,p) >] ->
-			if is_resuming p then raise (TypePath (List.rev (List.map fst acc),None));
+			let resume() =
+				type_path (List.map fst acc) true
+			in
+			if is_resuming p then resume();
 			(match s with parser
 			| [< '(Const (Ident k),p) >] ->
 				loop ((k,p) :: acc)
 			| [< '(Kwd Macro,p) >] ->
 				loop (("macro",p) :: acc)
+			| [< '(Kwd Extern,p) >] ->
+				loop (("extern",p) :: acc)
 			| [< '(Binop OpMult,_); '(Semicolon,p2) >] ->
 				p2, List.rev acc, IAll
 			| [< '(Binop OpOr,_) when do_resume() >] ->
 				set_resume p;
-				raise (TypePath (List.rev (List.map fst acc),None))
+				resume()
 			| [< >] ->
 				serror());
 		| [< '(Semicolon,p2) >] ->
@@ -764,8 +779,21 @@ and parse_common_flags = parser
 	| [< '(Kwd Extern,_); l = parse_common_flags >] -> (HExtern, EExtern) :: l
 	| [< >] -> []
 
+and parse_meta_argument_expr s =
+	try
+		expr s
+	with Display e -> match fst e with
+		| EDisplay(e,_) ->
+			begin try
+				type_path (string_list_of_expr_path_raise e) false
+			with Exit ->
+				e
+			end
+		| _ ->
+			e
+
 and parse_meta_params pname s = match s with parser
-	| [< '(POpen,p) when p.pmin = pname.pmax; params = psep Comma expr; '(PClose,_); >] -> params
+	| [< '(POpen,p) when p.pmin = pname.pmax; params = psep Comma parse_meta_argument_expr; '(PClose,_); >] -> params
 	| [< >] -> []
 
 and parse_meta_entry = parser
@@ -830,7 +858,7 @@ and parse_type_path1 pack = parser
 			(match s with parser
 			| [< '(Dot,p) >] ->
 				if is_resuming p then
-					raise (TypePath (List.rev (name :: pack),None))
+					raise (TypePath (List.rev (name :: pack),None,false))
 				else
 					parse_type_path1 (name :: pack) s
 			| [< '(Semicolon,_) >] ->
@@ -840,12 +868,12 @@ and parse_type_path1 pack = parser
 			let sub = (match s with parser
 				| [< '(Dot,p); s >] ->
 					(if is_resuming p then
-						raise (TypePath (List.rev pack,Some (name,false)))
+						raise (TypePath (List.rev pack,Some (name,false),false))
 					else match s with parser
 						| [< '(Const (Ident name),_) when not (is_lower_ident name) >] -> Some name
 						| [< '(Binop OpOr,_) when do_resume() >] ->
 							set_resume p;
-							raise (TypePath (List.rev pack,Some (name,false)))
+							raise (TypePath (List.rev pack,Some (name,false),false))
 						| [< >] -> serror())
 				| [< >] -> None
 			) in
@@ -860,7 +888,7 @@ and parse_type_path1 pack = parser
 				tsub = sub;
 			}
 	| [< '(Binop OpOr,_) when do_resume() >] ->
-		raise (TypePath (List.rev pack,None))
+		raise (TypePath (List.rev pack,None,false))
 
 and type_name = parser
 	| [< '(Const (Ident name),p) >] ->
@@ -868,6 +896,7 @@ and type_name = parser
 			error (Custom "Type name should start with an uppercase letter") p
 		else
 			name
+	| [< '(Dollar name,_) >] -> "$" ^ name
 
 and parse_type_path_or_const = parser
 	(* we can't allow (expr) here *)
@@ -1074,10 +1103,9 @@ and block acc s =
 			block acc s
 
 and parse_block_elt = parser
-	| [< '(Kwd Var,p1); vl = psep Comma parse_var_decl; p2 = semicolon >] ->
-		(match vl with
-			| [] -> error (Custom "Missing variable identifier") p1
-			| _ -> (EVars vl,punion p1 p2))
+	| [< '(Kwd Var,p1); vl = parse_var_decls p1; p2 = semicolon >] ->
+		(EVars vl,punion p1 p2)
+	| [< '(Kwd Inline,p1); '(Kwd Function,_); e = parse_function p1 true; _ = semicolon >] -> e
 	| [< e = expr; _ = semicolon >] -> e
 
 and parse_obj_decl = parser
@@ -1096,11 +1124,38 @@ and parse_array_decl = parser
 	| [< >] ->
 		[]
 
+and parse_var_decl_head = parser
+	| [< name, _ = dollar_ident; t = parse_type_opt >] -> (name,t)
+
+and parse_var_assignment = parser
+	| [< '(Binop OpAssign,p1); s >] ->
+		begin match s with parser
+		| [< e = expr >] -> Some e
+		| [< >] -> error (Custom "expression expected after =") p1
+		end
+	| [< >] -> None
+
+and parse_var_decls_next vl = parser
+	| [< '(Comma,p1); name,t = parse_var_decl_head; s >] ->
+		begin try
+			let eo = parse_var_assignment s in
+			parse_var_decls_next ((name,t,eo) :: vl) s
+		with Display e ->
+			let v = (name,t,Some e) in
+			let e = (EVars(List.rev (v :: vl)),punion p1 (pos e)) in
+			display e
+		end
+	| [< >] ->
+		vl
+
+and parse_var_decls p1 = parser
+	| [< name,t = parse_var_decl_head; s >] ->
+		let eo = parse_var_assignment s in
+		List.rev (parse_var_decls_next [name,t,eo] s)
+	| [< s >] -> error (Custom "Missing variable identifier") p1
+
 and parse_var_decl = parser
-	| [< name, _ = dollar_ident; t = parse_type_opt; s >] ->
-		match s with parser
-		| [< '(Binop OpAssign,_); s >] -> let e = try expr s with Display e -> e in (name,t,Some e)
-		| [< >] -> (name,t,None)
+	| [< name,t = parse_var_decl_head; eo = parse_var_assignment >] -> (name,t,eo)
 
 and inline_function = parser
 	| [< '(Kwd Inline,_); '(Kwd Function,p1) >] -> true, p1
@@ -1124,6 +1179,22 @@ and parse_macro_expr p = parser
 	| [< e = secure_expr >] ->
 		reify_expr e
 
+and parse_function p1 inl = parser
+	| [< name = popt dollar_ident; pl = parse_constraint_params; '(POpen,_); al = psep Comma parse_fun_param; '(PClose,_); t = parse_type_opt; s >] ->
+		let make e =
+			let f = {
+				f_params = pl;
+				f_type = t;
+				f_args = al;
+				f_expr = Some e;
+			} in
+			EFunction ((match name with None -> None | Some (name,_) -> Some (if inl then "inline_" ^ name else name)),f), punion p1 (pos e)
+		in
+		(try
+			expr_next (make (secure_expr s)) s
+		with
+			Display e -> display (make e))
+
 and expr = parser
 	| [< (name,params,p) = parse_meta_entry; s >] ->
 		(try
@@ -1145,10 +1216,15 @@ and expr = parser
 	| [< '(Kwd Null,p); s >] -> expr_next (EConst (Ident "null"),p) s
 	| [< '(Kwd Cast,p1); s >] ->
 		(match s with parser
-		| [< '(POpen,_); e = expr; s >] ->
+		| [< '(POpen,pp); e = expr; s >] ->
 			(match s with parser
 			| [< '(Comma,_); t = parse_complex_type; '(PClose,p2); s >] -> expr_next (ECast (e,Some t),punion p1 p2) s
-			| [< '(PClose,p2); s >] -> expr_next (ECast (e,None),punion p1 (pos e)) s
+			| [< t = parse_type_hint; '(PClose,p2); s >] ->
+				let ep = EParenthesis (ECheckType(e,t),punion p1 p2), punion p1 p2 in
+				expr_next (ECast (ep,None),punion p1 (pos ep)) s
+			| [< '(PClose,p2); s >] ->
+				let ep = expr_next (EParenthesis(e),punion pp p2) s in
+				expr_next (ECast (ep,None),punion p1 (pos ep)) s
 			| [< >] -> serror())
 		| [< e = secure_expr >] -> expr_next (ECast (e,None),punion p1 (pos e)) s)
 	| [< '(Kwd Throw,p); e = expr >] -> (EThrow e,p)
@@ -1159,22 +1235,10 @@ and expr = parser
 		| [< >] -> serror())
 	| [< '(POpen,p1); e = expr; s >] -> (match s with parser
 		| [< '(PClose,p2); s >] -> expr_next (EParenthesis e, punion p1 p2) s
-		| [< t = parse_type_hint; '(PClose,p2); s >] -> expr_next (EParenthesis (ECheckType(e,t),punion p1 p2), punion p1 p2) s)
+		| [< t = parse_type_hint; '(PClose,p2); s >] -> expr_next (EParenthesis (ECheckType(e,t),punion p1 p2), punion p1 p2) s
+		| [< >] -> serror())
 	| [< '(BkOpen,p1); l = parse_array_decl; '(BkClose,p2); s >] -> expr_next (EArrayDecl l, punion p1 p2) s
-	| [< inl, p1 = inline_function; name = popt dollar_ident; pl = parse_constraint_params; '(POpen,_); al = psep Comma parse_fun_param; '(PClose,_); t = parse_type_opt; s >] ->
-		let make e =
-			let f = {
-				f_params = pl;
-				f_type = t;
-				f_args = al;
-				f_expr = Some e;
-			} in
-			EFunction ((match name with None -> None | Some (name,_) -> Some (if inl then "inline_" ^ name else name)),f), punion p1 (pos e)
-		in
-		(try
-			expr_next (make (secure_expr s)) s
-		with
-			Display e -> display (make e))
+	| [< '(Kwd Function,p1); e = parse_function p1 false; >] -> e
 	| [< '(Unop op,p1) when is_prefix op; e = expr >] -> make_unop op e p1
 	| [< '(Binop OpSub,p1); e = expr >] ->
 		let neg s =

+ 1 - 17
std/Date.hx

@@ -124,17 +124,13 @@ extern class Date
 
 #if flash
 	private static function __init__() : Void untyped {
-		var d #if !swf_mark : Dynamic #end = Date;
+		var d : Dynamic = Date;
 		d.now = function() {
 			return __new__(Date);
 		};
 		d.fromTime = function(t){
 			var d : Date = __new__(Date);
-			#if flash9
 			d.setTime(t);
-			#else
-			d["setTime"]( t );
-			#end
 			return d;
 		};
 		d.fromString = function(s : String) {
@@ -142,17 +138,10 @@ extern class Date
 			case 8: // hh:mm:ss
 				var k = s.split(":");
 				var d : Date = __new__(Date);
-				#if flash9
 				d.setTime(0);
 				d.setUTCHours(k[0]);
 				d.setUTCMinutes(k[1]);
 				d.setUTCSeconds(k[2]);
-				#else
-				d["setTime"](0);
-				d["setUTCHours"](k[0]);
-				d["setUTCMinutes"](k[1]);
-				d["setUTCSeconds"](k[2]);
-				#end
 				return d;
 			case 10: // YYYY-MM-DD
 				var k = s.split("-");
@@ -180,11 +169,6 @@ extern class Date
 				+":"+(if( mi < 10 ) "0"+mi else ""+mi)
 				+":"+(if( s < 10 ) "0"+s else ""+s);
 		};
-		#if flash9
-		#elseif flash
-		d.prototype[__unprotect__("__class__")] = d;
-		d[__unprotect__("__name__")] = ["Date"];
-		#end
 	}
 #end
 }

+ 1 - 1
std/EReg.hx

@@ -34,7 +34,7 @@
 	its methods.
 
 	A detailed explanation of the supported operations is available at
-	http://haxe.org/doc/cross/regexp
+	http://haxe.org/manual/std-regex.html
 **/
 class EReg {
 

+ 4 - 10
std/Math.hx

@@ -230,7 +230,7 @@ extern class Math
 	**/
 	static function random() : Float;
 
-	#if ((flash9 && !as3) || cpp)
+	#if ((flash && !as3) || cpp)
 	/**
 		Returns the largest integer value that is not greater than `v`, as a Float.
 
@@ -290,7 +290,7 @@ extern class Math
 	static function isNaN( f : Float ) : Bool;
 
 	private static function __init__() : Void untyped {
-	#if flash9
+	#if flash
 		NaN = __global__["Number"].NaN;
 		NEGATIVE_INFINITY = __global__["Number"].NEGATIVE_INFINITY;
 		POSITIVE_INFINITY = __global__["Number"].POSITIVE_INFINITY;
@@ -302,20 +302,16 @@ extern class Math
 	#end
 		Math.isFinite = function(i) {
 			return
-			#if flash9
+			#if flash
 			__global__["isFinite"](i);
-			#elseif flash
-			_global["isFinite"](i);
 			#else
 			false;
 			#end
 		};
 		Math.isNaN = function(i) {
 			return
-			#if flash9
+			#if flash
 			__global__["isNaN"](i);
-			#elseif flash
-			_global["isNaN"](i);
 			#else
 			false;
 			#end
@@ -323,5 +319,3 @@ extern class Math
 	}
 
 }
-
-

+ 6 - 3
std/StdTypes.hx

@@ -48,7 +48,7 @@
 
 /**
 	`Null` can be useful in two cases. In order to document some methods
-	that accepts or can return a `null` value, or for the Flash9 compiler and AS3
+	that accepts or can return a `null` value, or for the Flash compiler and AS3
 	generator to distinguish between base values that can be null and others that
 	can't.
 **/
@@ -94,8 +94,11 @@ typedef Iterator<T> = {
 	/**
 		Returns the current item of the Iterator and advances to the next one.
 
-		This method is not required to check hasNext() first. A call to this
-		method while hasNext() is false yields unspecified behavior.
+		This method is not required to check `hasNext` first. A call to this
+		method while `hasNext` is false yields unspecified behavior.
+
+		On the other hand iterators should not require a call to `hasNext`
+		before the first call to `next` if an element is available.
 	**/
 	function next() : T;
 

+ 6 - 14
std/StringTools.hx

@@ -37,10 +37,8 @@ class StringTools {
 		Encode an URL by using the standard format.
 	**/
 	#if (!java && !cpp) inline #end public static function urlEncode( s : String ) : String {
-		#if flash9
+		#if flash
 			return untyped __global__["encodeURIComponent"](s);
-		#elseif flash
-			return untyped _global["escape"](s);
 		#elseif neko
 			return untyped new String(_urlEncode(s.__s));
 		#elseif js
@@ -64,10 +62,8 @@ class StringTools {
 		Decode an URL using the standard format.
 	**/
 	#if (!java && !cpp) inline #end public static function urlDecode( s : String ) : String {
-		#if flash9
+		#if flash
 			return untyped __global__["decodeURIComponent"](s.split("+").join(" "));
-		#elseif flash
-			return untyped _global["unescape"](s);
 		#elseif neko
 			return untyped new String(_urlDecode(s.__s));
 		#elseif js
@@ -339,7 +335,7 @@ class StringTools {
 		its length equals `digits`.
 	**/
 	public static function hex( n : Int, ?digits : Int ) {
-		#if flash9
+		#if flash
 			var n : UInt = n;
 			var s : String = untyped n.toString(16);
 			s = s.toUpperCase();
@@ -385,10 +381,8 @@ class StringTools {
 		return untyped __dollar__sget(s.__s, index);
 		#elseif cpp
 		return untyped s.cca(index);
-		#elseif flash9
-		return untyped s.cca(index);
 		#elseif flash
-		return untyped s["cca"](index);
+		return untyped s.cca(index);
 		#elseif java
 		return ( index < s.length ) ? cast(_charAt(s, index), Int) : -1;
 		#elseif cs
@@ -396,7 +390,7 @@ class StringTools {
 		#elseif js
 		return (untyped s).charCodeAt(index);
 		#elseif python
-		return if (index >= s.length) -1 else python.lib.Builtin.ord(python.Syntax.arrayAccess(s, index));
+		return if (index >= s.length) -1 else python.internal.UBuiltins.ord(python.Syntax.arrayAccess(s, index));
 		#else
 		return untyped s.cca(index);
 		#end
@@ -406,10 +400,8 @@ class StringTools {
 		Tells if `c` represents the end-of-file (EOF) character.
 	*/
 	@:noUsing public static inline function isEof( c : Int ) : Bool {
-		#if (flash9 || cpp)
+		#if (flash || cpp)
 		return c == 0;
-		#elseif flash8
-		return c <= 0; // fast NaN
 		#elseif js
 		return c != c; // fast NaN
 		#elseif neko

+ 33 - 24
std/UInt.hx

@@ -20,9 +20,9 @@
  * DEALINGS IN THE SOFTWARE.
  */
 
-#if ((flash9 || flash9doc || cs) && !doc_gen)
+#if ((flash || flash9doc || cs) && !doc_gen)
 /**
-	The unsigned Int type is only defined for Flash9 and C#. It's currently
+	The unsigned Int type is only defined for Flash and C#. It's currently
 	handled the same as a normal Int.
 **/
 @:coreType
@@ -34,40 +34,49 @@ abstract UInt to Int from Int
 	@:commutative @:op(A+B) private static function addI(lhs:UInt, rhs:Int):UInt;
 	@:commutative @:op(A+B) private static function addF(lhs:UInt, rhs:Float):Float;
 	@:op(A+B) private static function add(lhs:UInt, rhs:UInt):UInt;
+
 	@:commutative @:op(A*B) private static function mulI(lhs:UInt, rhs:Int):UInt;
 	@:commutative @:op(A*B) private static function mulF(lhs:UInt, rhs:Float):Float;
 	@:op(A*B) private static function mul(lhs:UInt, rhs:UInt):UInt;
-	@:commutative @:op(A%B) private static function modI(lhs:UInt, rhs:Int):UInt;
-	@:commutative @:op(A%B) private static function modF(lhs:UInt, rhs:Float):Float;
+
+	@:op(A%B) private static function modI(lhs:UInt, rhs:Int):UInt;
+	@:op(A%B) private static function modF(lhs:UInt, rhs:Float):Float;
 	@:op(A%B) private static function mod(lhs:UInt, rhs:UInt):UInt;
-	@:commutative @:op(A-B) private static function subI(lhs:UInt, rhs:Int):UInt;
-	@:commutative @:op(A-B) private static function subF(lhs:UInt, rhs:Float):Float;
+
+	@:op(A-B) private static function subI(lhs:UInt, rhs:Int):UInt;
+	@:op(A-B) private static function subF(lhs:UInt, rhs:Float):Float;
 	@:op(A-B) private static function sub(lhs:UInt, rhs:UInt):UInt;
-	@:commutative @:op(A/B) private static function divI(lhs:UInt, rhs:Int):Float;
-	@:commutative @:op(A/B) private static function divF(lhs:UInt, rhs:Float):Float;
+
+	@:op(A/B) private static function divI(lhs:UInt, rhs:Int):Float;
+	@:op(A/B) private static function divF(lhs:UInt, rhs:Float):Float;
 	@:op(A/B) private static function div(lhs:UInt, rhs:UInt):Float;
+
 	@:commutative @:op(A|B) private static function orI(lhs:UInt, rhs:Int):UInt;
 	@:op(A|B) private static function or(lhs:UInt, rhs:UInt):UInt;
+
 	@:commutative @:op(A^B) private static function xorI(lhs:UInt, rhs:Int):UInt;
 	@:op(A^B) private static function xor(lhs:UInt, rhs:UInt):UInt;
+
 	@:commutative @:op(A&B) private static function andI(lhs:UInt, rhs:Int):UInt;
 	@:op(A&B) private static function and(lhs:UInt, rhs:UInt):UInt;
-	@:commutative @:op(A<<B) private static function shlI(lhs:UInt, rhs:Int):UInt;
-	@:op(A<<B) private static function shl(lhs:UInt, rhs:UInt):UInt;
-	@:commutative @:op(A>>B) private static function shrI(lhs:UInt, rhs:Int):UInt;
-	@:op(A>>B) private static function shr(lhs:UInt, rhs:UInt):UInt;
-	@:commutative @:op(A>>>B) private static function ushrI(lhs:UInt, rhs:Int):UInt;
-	@:op(A>>>B) private static function ushr(lhs:UInt, rhs:UInt):UInt;
+
+	@:op(A<<B) private static function shl(lhs:UInt, rhs:Int):UInt;
+	@:op(A>>B) private static function shr(lhs:UInt, rhs:Int):UInt;
+	@:op(A>>>B) private static function ushr(lhs:UInt, rhs:Int):UInt;
 
 	@:op(A>B) private static function gt(lhs:UInt, rhs:UInt):Bool;
 	@:op(A>=B) private static function gte(lhs:UInt, rhs:UInt):Bool;
 	@:op(A<B) private static function lt(lhs:UInt, rhs:UInt):Bool;
 	@:op(A<=B) private static function lte(lhs:UInt, rhs:UInt):Bool;
 
-	@:commutative @:op(A>B) private static function gtf(lhs:UInt, rhs:Float):Bool;
-	@:commutative @:op(A>=B) private static function gtef(lhs:UInt, rhs:Float):Bool;
-	@:commutative @:op(A<B) private static function ltf(lhs:UInt, rhs:Float):Bool;
-	@:commutative @:op(A<=B) private static function ltef(lhs:UInt, rhs:Float):Bool;
+	@:op(A>B) private static function gtf(lhs:UInt, rhs:Float):Bool;
+	@:op(A>B) private static function gtf(lhs:Float, rhs:UInt):Bool;
+	@:op(A>=B) private static function gtef(lhs:UInt, rhs:Float):Bool;
+	@:op(A>=B) private static function gtef(lhs:Float, rhs:UInt):Bool;
+	@:op(A<B) private static function ltf(lhs:UInt, rhs:Float):Bool;
+	@:op(A<B) private static function ltf(lhs:Float, rhs:UInt):Bool;
+	@:op(A<=B) private static function ltef(lhs:UInt, rhs:Float):Bool;
+	@:op(A<=B) private static function ltef(lhs:Float, rhs:UInt):Bool;
 
 	@:op(~A) private static function bneg(t:UInt):UInt;
 
@@ -83,7 +92,7 @@ abstract UInt to Int from Int
 }
 #else
 /**
-	The unsigned Int type is only defined for Flash9 and C#.
+	The unsigned Int type is only defined for Flash and C#.
 	Simulate it for other platforms.
 **/
 abstract UInt(Int) from Int to Int {
@@ -144,12 +153,12 @@ abstract UInt(Int) from Int to Int {
 		return a.toInt() << b;
 	}
 
-	@:op(A >> B) private static inline function shr(a:UInt, b:UInt):UInt {
-		return a.toInt() >> b.toInt();
+	@:op(A >> B) private static inline function shr(a:UInt, b:Int):UInt {
+		return a.toInt() >> b;
 	}
 
-	@:op(A >>> B) private static inline function ushr(a:UInt, b:UInt):UInt {
-		return a.toInt() >>> b.toInt();
+	@:op(A >>> B) private static inline function ushr(a:UInt, b:Int):UInt {
+		return a.toInt() >>> b;
 	}
 
 	@:op(A % B) private static inline function mod(a:UInt, b:UInt):UInt {
@@ -266,7 +275,7 @@ abstract UInt(Int) from Int to Int {
 		return this;
 	}
 
-	@:to private #if !js inline #end function toFloat():Float {
+	@:to private #if (!js || analyzer) inline #end function toFloat():Float {
 		var int = toInt();
 		if (int < 0) {
 			return 4294967296.0 + int;

+ 5 - 0
std/cpp/Callable.hx

@@ -0,0 +1,5 @@
+package cpp;
+
+typedef Callable<T> = Function<T, cpp.abi.Abi >
+
+

+ 13 - 0
std/cpp/CastCharStar.hx

@@ -0,0 +1,13 @@
+package cpp;
+
+abstract CastCharStar( RawPointer<Char> ) to(RawPointer<Char>)
+{
+   inline function new(s:String) this = untyped s.__s;
+
+   @:from
+   static public inline function fromString(s:String) return new CastCharStar(s);
+
+    @:to
+    public inline function toPointer() return this;
+}
+

+ 13 - 0
std/cpp/ConstCharStar.hx

@@ -0,0 +1,13 @@
+package cpp;
+
+abstract ConstCharStar( RawConstPointer<Char> ) to(RawConstPointer<Char>)
+{
+   inline function new(s:String) this = untyped s.__s;
+
+   @:from
+   static public inline function fromString(s:String) return new ConstCharStar(s);
+
+    @:to
+    public inline function toPointer() return this;
+}
+

+ 8 - 9
std/cpp/Function.hx

@@ -2,22 +2,21 @@ package cpp;
 
 @:coreType @:structAccess @:include("cpp/Pointer.h")
 @:analyzer(no_simplification)
-extern class Function<T>
+extern class Function<T,ABI:cpp.abi.Abi>
 {
    public function new(d:Dynamic);
 
    // Actually a function pointer, but can be called using haxe notation
 	public var call(default,null):T;
 
-   public static function getProcAddress<T>(inModule:String, inFunction:String) : Function<T>;
-   public static function fromStaticFunction<T>(inStaticFunction:T) : Function<T>;
-
-	public function lt(inOther:Function<T>):Bool;
-	public function leq(inOther:Function<T>):Bool;
-	public function gt(inOther:Function<T>):Bool;
-	public function geq(inOther:Function<T>):Bool;
-
+   public static function getProcAddress<T,ABI:cpp.abi.Abi>(inModule:String, inFunction:String) : Function<T,ABI>;
+   public static function fromStaticFunction<T>(inStaticFunction:T) : Callable<T>;
 
+	public function lt(inOther:Function<T,ABI>):Bool;
+	public function leq(inOther:Function<T,ABI>):Bool;
+	public function gt(inOther:Function<T,ABI>):Bool;
+	public function geq(inOther:Function<T,ABI>):Bool;
 }
 
 
+

+ 32 - 5
std/cpp/Lib.hx

@@ -25,12 +25,17 @@ package cpp;
 import haxe.macro.Context;
 import haxe.macro.Type;
 import haxe.macro.Expr;
-#end
+#else
 
 using cpp.NativeString;
 using cpp.RawConstPointer;
 using cpp.Char;
 
+#end
+
+#if macro
+@:noPackageRestrict
+#end
 class Lib {
 
    #if !macro
@@ -47,7 +52,7 @@ class Lib {
 
    @:analyzer(no_simplification)
 	public static function _loadPrime( lib : String, prim : String, signature : String, quietFail = false ) : Dynamic {
-		var factory:Function< RawConstPointer<Char> -> RawPointer<Object> > =
+		var factory:Callable< RawConstPointer<Char> -> RawPointer<Object> > =
                untyped __global__.__hxcpp_cast_get_proc_address(lib, prim + "__prime", quietFail);
       if (factory!=null)
       {
@@ -82,7 +87,24 @@ class Lib {
 
 	public static function rethrow(inExp:Dynamic) { throw inExp; }
 
-	public static function stringReference(inExp:Dynamic) { throw inExp; }
+	public static function stringReference(inBytes:haxe.io.Bytes) : String
+   {
+      var result:String = "";
+      untyped __global__.__hxcpp_string_of_bytes(inBytes.b, result, 0, 0, true);
+      return result;
+   }
+
+	/**
+		Returns bytes referencing the content of a string.
+      Use with extreme caution - changing constant strings will crash.
+      Changing one string can cause others to change unexpectedly.
+      Only really safe if you are using it read-only or if it comes from stringReference above
+	**/
+	public inline static function bytesReference( s : String ) : haxe.io.Bytes {
+      var bytes = new haxe.io.BytesData();
+      untyped bytes.__unsafeStringReference(s);
+		return haxe.io.Bytes.ofData(bytes);
+	}
 
 	/**
 		Print the specified value on the default output.
@@ -125,13 +147,18 @@ class Lib {
          case "s" : return "String";
          case "o" : return "cpp.Object";
          case "v" : return "cpp.Void";
-         case "c" : return "cpp.RawConstPtr<cpp.Char> ";
+         case "c" : return "cpp.ConstCharStar";
          default:
             throw "Unknown signature type :" + code;
       }
    }
    #end
 
+   public static function setFloatFormat(inFormat:String):Void
+   {
+      untyped __global__.__hxcpp_set_float_format(inFormat);
+   }
+
    public static macro function loadPrime(inModule:String, inName:String, inSig:String,inAllowFail:Bool = false)
    {
       var parts = inSig.split("");
@@ -140,7 +167,7 @@ class Lib {
       var typeString = parts.length==1 ? "Void" : codeToType(parts.shift());
       for(p in parts)
          typeString += "->" + codeToType(p);
-      typeString = "cpp.Function<" + typeString + ">";
+      typeString = "cpp.Callable<" + typeString + ">";
       var expr = 'new $typeString(cpp.Lib._loadPrime("$inModule","$inName","$inSig",$inAllowFail))';
       return Context.parse( expr, Context.currentPos() );
    }

+ 424 - 0
std/cpp/NativeXml.hx

@@ -0,0 +1,424 @@
+/*
+ * 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 cpp;
+
+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;
+
+
+	private var _nodeName : String;
+	private var _nodeValue : String;
+	private var _attributes : Dynamic<String>;
+	private var _children : Array<Xml>;
+	private var _parent : Xml;
+
+	function new() : Void {
+	}
+
+	private static var _parse = cpp.Lib.load("std","parse_xml",2);
+
+	@:analyzer(ignore) public static function parse( str : String ) : Xml {
+		var x = new Xml();
+		x._children = new Array();
+		var parser = {
+			cur : x,
+			xml : function(name,att) {
+				var x = new Xml();
+				x._parent = untyped __this__.cur;
+				x.nodeType = Xml.Element;
+				x._nodeName = new String(name);
+				x._attributes = att;
+				x._children = new Array();
+				untyped {
+					var i = 0;
+					__this__.cur.addChild(x);
+					__this__.cur = x;
+				}
+			},
+			cdata : function(text) {
+				var x = new Xml();
+				x._parent = untyped __this__.cur;
+				x.nodeType = Xml.CData;
+				x._nodeValue = new String(text);
+				untyped __this__.cur.addChild(x);
+			},
+			pcdata : function(text) {
+				var x = new Xml();
+				x._parent = untyped __this__.cur;
+				x.nodeType = Xml.PCData;
+				x._nodeValue = new String(text);
+				untyped __this__.cur.addChild(x);
+			},
+			comment : function(text:String) {
+				var x = new Xml();
+				x._parent = untyped __this__.cur;
+				if( untyped text.cca(0) == 63 ) {
+					x.nodeType = Xml.ProcessingInstruction;
+					text = new String(text);
+					text = text.substr(1, text.length - 2);
+				} else {
+					x.nodeType = Xml.Comment;
+					text = new String(text);
+				}
+				x._nodeValue = text;
+				untyped __this__.cur.addChild(x);
+			},
+			doctype : function(text) {
+				var x = new Xml();
+				x._parent = untyped __this__.cur;
+				x.nodeType = Xml.DocType;
+				x._nodeValue = (new String(text)).substr(1);
+				var p : Xml = untyped __this__.cur;
+				p.addChild(x);
+			},
+			done : function() {
+				untyped __this__.cur = __this__.cur._parent;
+			}
+		};
+		untyped _parse(str,parser);
+		x.nodeType = Xml.Document;
+		return x;
+	}
+
+
+	public static function createElement( name : String ) : Xml {
+		var r = new Xml();
+		r.nodeType = Xml.Element;
+		r._nodeName = name;
+		r._attributes = null;
+		r._children = new Array();
+		return r;
+	}
+
+	public static function createPCData( data : String ) : Xml {
+		var r = new Xml();
+		r.nodeType = Xml.PCData;
+		r._nodeValue = data;
+		return r;
+	}
+
+	public static function createCData( data : String ) : Xml {
+		var r = new Xml();
+		r.nodeType = Xml.CData;
+		r._nodeValue = data;
+		return r;
+	}
+
+	public static function createComment( data : String ) : Xml {
+		var r = new Xml();
+		r.nodeType = Xml.Comment;
+		r._nodeValue = data;
+		return r;
+	}
+
+	public static function createDocType( data : String ) : Xml {
+		var r = new Xml();
+		r.nodeType = Xml.DocType;
+		r._nodeValue = data;
+		return r;
+	}
+
+	public static function createProcessingInstruction( data : String ) : Xml {
+		var r = new Xml();
+		r.nodeType = Xml.ProcessingInstruction;
+		r._nodeValue = data;
+		return r;
+	}
+
+	public static function createDocument() : Xml {
+		var r = new Xml();
+		r.nodeType = Xml.Document;
+		r._children = new Array();
+		return r;
+	}
+
+	public var nodeType(default,null) : XmlType;
+
+	public var nodeName(get,set) : String;
+
+	public var nodeValue(get,set) : String;
+
+
+	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;
+	}
+
+	public var parent(get,null) : Xml;
+	private function get_parent() : Xml {
+		return _parent;
+	}
+
+	public function get( att : String ) : String {
+		if( nodeType != Xml.Element )
+			throw "bad nodeType";
+		return Reflect.field( _attributes, att );
+	}
+
+	public function set( att : String, value : String ) : Void {
+		if( nodeType != Xml.Element )
+			throw "bad nodeType";
+		if (_attributes==null)
+			_attributes = {};
+		Reflect.setField (_attributes, att, value );
+		return null;
+	}
+
+	public function remove( att : String ) : Void{
+		if( nodeType != Xml.Element )
+			throw "bad nodeType";
+		Reflect.deleteField( _attributes, att );
+		return null;
+	}
+
+	public function exists( att : String ) : Bool {
+		if( nodeType != Xml.Element )
+			throw "bad nodeType";
+		return Reflect.hasField( _attributes, att );
+	}
+
+	public function attributes() : Iterator<String> {
+		if( nodeType != Xml.Element )
+			throw "bad nodeType";
+		return Reflect.fields( _attributes ).iterator();
+	}
+
+	public function iterator() : Iterator<Xml> {
+		if( _children == null )
+			throw "bad nodetype";
+      return untyped _children.iterator();
+	}
+
+
+	@:analyzer(ignore) public function elements(): Iterator<Xml> {
+		if( _children == null )
+			throw "bad nodetype";
+      var children = _children;
+		return untyped {
+			cur: 0,
+			hasNext : function() {
+				var k:Int = __this__.cur;
+				var l = children.length;
+				while( k < l ) {
+					if( children[k].nodeType == Xml.Element )
+						break;
+					k += 1;
+				}
+				__this__.cur = k;
+				return k < l;
+			},
+			next : function() {
+				var k = __this__.cur;
+				var l = children.length;
+				while( k < l ) {
+					var n = children[k];
+					k += 1;
+					if( n.nodeType == Xml.Element ) {
+						__this__.cur = k;
+						return n;
+					}
+				}
+				return null;
+			}
+		}
+	}
+
+	@:analyzer(ignore) public function elementsNamed( name : String ) : Iterator<Xml> {
+		if( _children == null )
+			throw "bad nodetype";
+      var children = _children;
+		return untyped {
+			cur: 0,
+			hasNext : function() {
+				var k = __this__.cur;
+				var l = children.length;
+				while( k < l ) {
+					var n = children[k];
+					if( n.nodeType == Xml.Element && n._nodeName == name )
+						break;
+					k++;
+				}
+				__this__.cur = k;
+				return k < l;
+			},
+			next : function() {
+				var k = __this__.cur;
+				var l = children.length;
+				while( k < l ) {
+					var n = children[k];
+					k++;
+					if( n.nodeType == Xml.Element && n._nodeName == name ) {
+						__this__.cur = k;
+						return n;
+					}
+				}
+				return null;
+			}
+		}
+	}
+
+	public function firstChild() : Xml {
+		if( _children == null )
+			throw "bad nodetype";
+		return _children[0];
+	}
+
+	public function firstElement() : Xml {
+		if( _children == null )
+			throw "bad nodetype";
+		for( cur in 0..._children.length ) {
+			var n:Xml = _children[cur];
+			if( n.nodeType == Xml.Element )
+				return n;
+		}
+		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 );
+		return null;
+	}
+
+   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 );
+		return null;
+	}
+
+	public function toString() : String {
+		var s = new StringBuf();
+		toStringRec(s);
+		return s.toString();
+	}
+
+	private function toStringRec(s: StringBuf) : Void {
+		switch( nodeType ) {
+		case Xml.Document:
+			for( x in _children )
+				x.toStringRec(s);
+		case Xml.Element:
+			s.addChar("<".code);
+			s.add(_nodeName);
+			for( k in Reflect.fields(_attributes) ) {
+				s.addChar(" ".code);
+				s.add(k);
+				s.addChar("=".code);
+				s.addChar("\"".code);
+				s.add(Reflect.field(_attributes,k));
+				s.addChar("\"".code);
+			}
+			if( _children.length == 0 ) {
+				s.addChar("/".code);
+				s.addChar(">".code);
+				return;
+			}
+			s.addChar(">".code);
+			for( x in _children )
+				x.toStringRec(s);
+			s.addChar("<".code);
+			s.addChar("/".code);
+			s.add(_nodeName);
+			s.addChar(">".code);
+		case Xml.PCData:
+			s.add(StringTools.htmlEscape(_nodeValue));
+		case Xml.CData:
+			s.add("<![CDATA[");
+			s.add(_nodeValue);
+			s.add("]]>");
+		case Xml.Comment:
+			s.add("<!--");
+			s.add(_nodeValue);
+			s.add("-->");
+		case Xml.DocType:
+			s.add("<!DOCTYPE ");
+			s.add(_nodeValue);
+			s.add(">");
+		case Xml.ProcessingInstruction:
+			s.add("<?");
+			s.add(_nodeValue);
+			s.add("?>");
+		}
+	}
+
+	static function __init__() : Void untyped {
+		PCData = Type.createEnum(XmlType,"__");
+		Element = Type.createEnum(XmlType,"__");
+		CData =  Type.createEnum(XmlType,"__");
+		Comment = Type.createEnum(XmlType,"__");
+		DocType = Type.createEnum(XmlType,"__");
+		ProcessingInstruction =  Type.createEnum(XmlType,"__");
+		Document = Type.createEnum(XmlType,"__");
+		__global__.__hxcpp_enum_force(PCData , "pcdata", 0);
+		__global__.__hxcpp_enum_force(Element , "element", 1);
+		__global__.__hxcpp_enum_force(CData , "cdata", 2);
+		__global__.__hxcpp_enum_force(Comment , "comment", 3);
+		__global__.__hxcpp_enum_force(DocType , "doctype", 4);
+		__global__.__hxcpp_enum_force(ProcessingInstruction , "processingInstruction", 5);
+		__global__.__hxcpp_enum_force(Document , "document", 6);
+	}
+
+}

+ 0 - 15
std/cpp/_std/Reflect.hx

@@ -21,34 +21,28 @@
  */
 @:coreApi class Reflect {
 
-   @:analyzer(ignore)
 	public  static function hasField( o : Dynamic, field : String ) : Bool untyped {
 		return o!=null && o.__HasField(field);
 	}
 
-   @:analyzer(ignore)
 	public static function field( o : Dynamic, field : String ) : Dynamic untyped {
 		return (o==null) ? null : o.__Field(field,untyped __cpp__("hx::paccNever") );
 	}
 
-   @:analyzer(ignore)
 	public static function setField( o : Dynamic, field : String, value : Dynamic ) : Void untyped {
 		if (o!=null)
 			o.__SetField(field,value,untyped __cpp__("hx::paccNever") );
 	}
 
-   @:analyzer(ignore)
 	public static function getProperty( o : Dynamic, field : String ) : Dynamic {
 		return (o==null) ? null : o.__Field(field,untyped __cpp__("hx::paccAlways") );
 	}
 
-   @:analyzer(ignore)
 	public static function setProperty( o : Dynamic, field : String, value : Dynamic ) : Void {
 		if (o!=null)
 			o.__SetField(field,value,untyped __cpp__("hx::paccAlways") );
 	}
 
-   @:analyzer(ignore)
 	public static function callMethod( o : Dynamic, func : haxe.Constraints.Function, args : Array<Dynamic> ) : Dynamic untyped {
 			if (func!=null && func.__GetType()==__global__.vtString)
 				func = o.__Field(func,untyped __cpp__("hx::paccDynamic"));
@@ -56,7 +50,6 @@
          return untyped func.__Run(args);
 	}
 
-   @:analyzer(ignore)
 	public static function fields( o : Dynamic ) : Array<String> untyped {
 		if( o == null ) return new Array();
 		var a : Array<String> = [];
@@ -64,17 +57,14 @@
 		return a;
 	}
 
-   @:analyzer(ignore)
 	public static function isFunction( f : Dynamic ) : Bool untyped {
 		return f!=null && f.__GetType() ==  __global__.vtFunction;
 	}
 
-   @:analyzer(ignore)
 	public static function compare<T>( a : T, b : T ) : Int {
 		return ( a == b ) ? 0 : (((a:Dynamic) > (b:Dynamic)) ? 1 : -1);
 	}
 
-   @:analyzer(ignore)
 	public static function compareMethods( f1 : Dynamic, f2 : Dynamic ) : Bool {
 		if( f1 == f2 )
 			return true;
@@ -83,7 +73,6 @@
 		return untyped __global__.__hxcpp_same_closure(f1,f2);
 	}
 
-   @:analyzer(ignore)
 	public static function isObject( v : Dynamic ) : Bool untyped {
 		if (v==null) return false;
 		var t:Int = v.__GetType();
@@ -91,18 +80,15 @@
 				t==__global__.vtArray;
 	}
 
-   @:analyzer(ignore)
 	public static function isEnumValue( v : Dynamic ) : Bool untyped {
 		return v!=null && v.__GetType() == __global__.vtEnum;
 	}
 
-   @:analyzer(ignore)
 	public static function deleteField( o : Dynamic, field : String ) : Bool untyped {
 		if (o==null) return false;
 		return untyped __global__.__hxcpp_anon_remove(o,field);
 	}
 
-   @:analyzer(ignore)
 	public static function copy<T>( o : T ) : T {
 		if (o==null) return null;
 		if(untyped o.__GetType()==__global__.vtString ) return o;
@@ -114,7 +100,6 @@
 		return o2;
 	}
 
-   @:analyzer(ignore)
 	@:overload(function( f : Array<Dynamic> -> Void ) : Dynamic {})
 	public static function makeVarArgs( f : Array<Dynamic> -> Dynamic ) : Dynamic {
 		return untyped __global__.__hxcpp_create_var_args(f);

+ 356 - 0
std/cpp/_std/haxe/Int64.hx

@@ -0,0 +1,356 @@
+/*
+ * 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 haxe;
+
+
+
+@:notNull
+
+@:native("cpp::Int64Struct")
+private extern class ___Int64 { public function get():cpp.Int64; }
+
+private typedef __Int64 = ___Int64;
+
+@:coreApi
+abstract Int64( __Int64 ) from __Int64 to __Int64
+{
+   /**
+		Makes a copy of `this` Int64.
+	**/
+	public #if !cppua inline #end function copy():Int64 return this;
+
+
+	public static #if !cppia inline #end function make( high : Int32, low : Int32 ) : Int64 {
+      return untyped __cpp__("cpp::Int64Struct(( ( (cpp::Int64)((unsigned int){0}) ) << 32 ) | ((unsigned int){1}))",high, low);
+	}
+
+	@:from public static function ofInt( x : Int ) : Int64 {
+		return untyped __cpp__("((cpp::Int64)({0}))", x);
+	}
+
+
+	/**
+		Returns an Int with the value of the Int64 `x`.
+		Throws an exception  if `x` cannot be represented in 32 bits.
+	**/
+	public static #if !cppia inline #end function toInt( x : Int64 ) : Int {
+		if( x.high != x.low >> 31 )
+			throw "Overflow";
+
+		return x.low;
+	}
+
+	/**
+		Returns whether the value `val` is of type `haxe.Int64`
+	**/
+	public static #if !cppia inline #end function is( val : Dynamic ) : Bool
+      return untyped __cpp__("(cpp::Int64Struct::is({0}))",val);
+
+	/**
+		Returns the high 32-bit word of `x`.
+	**/
+	@:deprecated("Use high instead")
+	public static #if !cppia inline #end function getHigh( x : Int64 ) : Int32
+		return x.high;
+
+	/**
+		Returns the low 32-bit word of `x`.
+	**/
+	@:deprecated("Use low instead")
+	public static #if !cppia inline #end function getLow( x : Int64 ) : Int32
+		return x.low;
+
+	/**
+		Returns `true` if `x` is less than zero.
+	**/
+	public static #if !cppia inline #end function isNeg( x : Int64) : Bool
+		return untyped __cpp__("(({0}.get()) < 0)", x);
+
+	/**
+		Returns `true` if `x` is exactly zero.
+	**/
+	public static #if !cppia inline #end function isZero( x : Int64 ) : Bool
+		return untyped __cpp__("(({0}.get()) == 0)", x);
+
+	/**
+		Compares `a` and `b` in signed mode.
+		Returns a negative value if `a < b`, positive if `a > b`,
+		or 0 if `a == b`.
+	**/
+	public static #if !cppia inline #end function compare( a : Int64, b : Int64 ) : Int {
+		return untyped __cpp__("( ({0}.get()) < ({1}.get()) ? -1 : ({0})==({1}) ? 0 : 1)", a, b, a, b);
+	}
+
+	/**
+		Compares `a` and `b` in unsigned mode.
+		Returns a negative value if `a < b`, positive if `a > b`,
+		or 0 if `a == b`.
+	**/
+	public static #if !cppia inline #end function ucompare( a : Int64, b : Int64 ) : Int {
+		return untyped __cpp__("( (cpp::UInt64)({0}.get()) < (cpp::UInt64)({1}.get()) ? -1 : ({0}.get())==({1}.get()) ? 0 : 1)", a, b, a, b);
+	}
+
+	/**
+		Returns a signed decimal `String` representation of `x`.
+	**/
+	public static #if !cppia inline #end function toStr(x:Int64) : String
+		return x.toString();
+
+	private function toString() : String
+	{
+		return untyped __cpp__("String( ({0}).get() )", this);
+	}
+
+	/**
+		Performs signed integer divison of `dividend` by `divisor`.
+		Returns `{ quotient : Int64, modulus : Int64 }`.
+	**/
+	public static function divMod( dividend : Int64, divisor : Int64 ) : { quotient : Int64, modulus : Int64 }
+	{
+      var q = dividend/divisor;
+
+      if (isZero(divisor))
+	       throw "divide by zero";
+
+      var m = dividend - q*divisor;
+
+      return { quotient : q, modulus : m };
+	}
+
+	/**
+		Returns the negative of `x`.
+	**/
+	@:op(-A) public static #if !cppia inline #end function neg( x : Int64 ) : Int64 {
+		return untyped __cpp__("(-({0}.get()))",x);
+	}
+
+	@:op(++A) private inline  function preIncrement() : Int64 {
+      #if cppia
+      this = this + make(0,1);
+      return this;
+      #else
+		return untyped __cpp__("(++({0}.get()))",this);
+      #end
+	}
+
+	@:op(A++) private inline function postIncrement() : Int64 {
+      #if cppia
+      var result = this;
+      this = this + make(0,1);
+      return result;
+      #else
+		return untyped __cpp__("(({0}.get())++)",this);
+      #end
+	}
+
+	@:op(--A) private inline function preDecrement() : Int64 {
+      #if cppia
+      untyped this = this - make(0,1);
+      return this;
+      #else
+		return untyped __cpp__("(--({0}.get()))",this);
+      #end
+	}
+
+	@:op(A--) private inline function postDecrement() : Int64 {
+      #if cppia
+      var result = this;
+      this = this - make(0,1);
+      return result;
+      #else
+		return untyped __cpp__("(({0}.get())--)",this);
+      #end
+	}
+
+	/**
+		Returns the sum of `a` and `b`.
+	**/
+	@:op(A + B) public static #if !cppia inline #end function add( a : Int64, b : Int64 ) : Int64 {
+		return untyped __cpp__("(({0}.get()) + ({1}.get()))", a, b);
+	}
+
+	@:op(A + B) @:commutative private static #if !cppia inline #end function addInt( a : Int64, b : Int ) : Int64
+		return add( a, b );
+
+	/**
+		Returns `a` minus `b`.
+	**/
+	@:op(A - B) public static #if !cppia inline #end function sub( a : Int64, b : Int64 ) : Int64 {
+		return untyped __cpp__("(({0}.get()) - ({1}.get()))", a, b);
+	}
+
+	@:op(A - B) private static #if !cppia inline #end function subInt( a : Int64, b : Int ) : Int64
+		return sub( a, b );
+
+	@:op(A - B) private static #if !cppia inline #end function intSub( a : Int, b : Int64 ) : Int64
+		return sub( a, b );
+
+	/**
+		Returns the product of `a` and `b`.
+	**/
+	@:op(A * B) public static #if !cppia inline #end function mul( a : Int64, b : Int64 ) : Int64 {
+		return untyped __cpp__("(({0}.get()) * ({1}.get()))", a, b);
+	}
+
+	@:op(A * B) @:commutative private static #if !cppia inline #end function mulInt( a : Int64, b : Int ) : Int64
+		return mul( a, b );
+
+	/**
+		Returns the quotient of `a` divided by `b`.
+	**/
+	@:op(A / B) public static function div( a : Int64, b : Int64 ) : Int64 {
+		if (untyped __cpp__("(({0}.get()) == 0)",b) )
+			throw "divide by zero";
+		return untyped __cpp__("(({0}.get()) / ({1}.get()))", a, b);
+	}
+
+
+	@:op(A / B) private static #if !cppia inline #end function divInt( a : Int64, b : Int ) : Int64
+		return div( a, b );
+
+	@:op(A / B) private static #if !cppia inline #end function intDiv( a : Int, b : Int64 ) : Int64
+		return toInt(div( a, b ));
+
+	/**
+		Returns the modulus of `a` divided by `b`.
+	**/
+	@:op(A % B) public static #if !cppia inline #end function mod( a : Int64, b : Int64 ) : Int64
+   {
+		if (untyped __cpp__("(({0}.get()) == 0)",b) )
+			throw "divide by zero";
+		return untyped __cpp__("(({0}.get()) % ({1}.get()))", a, b);
+   }
+
+	@:op(A % B) private static #if !cppia inline #end function modInt( a : Int64, b : Int ) : Int64
+		return toInt(mod( a, b ));
+
+	@:op(A % B) private static #if !cppia inline #end function intMod( a : Int, b : Int64 ) : Int64
+		return toInt(mod( a, b ));
+
+	/**
+		Returns `true` if `a` is equal to `b`.
+	**/
+	@:op(A == B) public static #if !cppia inline #end function eq( a : Int64, b : Int64 ) : Bool
+		return untyped __cpp__("(({0}.get()) == ({1}.get()))", a, b);
+
+	@:op(A == B) @:commutative private static #if !cppia inline #end function eqInt( a : Int64, b : Int ) : Bool
+		return eq( a, b );
+
+	/**
+		Returns `true` if `a` is not equal to `b`.
+	**/
+	@:op(A != B) public static #if !cppia inline #end function neq( a : Int64, b : Int64 ) : Bool
+		return untyped __cpp__("(({0}.get()) != ({1}.get()))", a, b);
+
+	@:op(A != B) @:commutative private static #if !cppia inline #end function neqInt( a : Int64, b : Int ) : Bool
+		return neq(a, b);
+
+	@:op(A < B) private static #if !cppia inline #end function lt( a : Int64, b : Int64 ) : Bool
+		return compare(a, b) < 0;
+
+	@:op(A < B) private static #if !cppia inline #end function ltInt( a : Int64, b : Int ) : Bool
+		return lt(a, b);
+
+	@:op(A < B) private static #if !cppia inline #end function intLt( a : Int, b : Int64 ) : Bool
+		return lt(a, b);
+
+	@:op(A <= B) private static #if !cppia inline #end function lte( a : Int64, b : Int64 ) : Bool
+		return compare(a, b) <= 0;
+
+	@:op(A <= B) private static #if !cppia inline #end function lteInt( a : Int64, b : Int ) : Bool
+		return lte(a, b);
+
+	@:op(A <= B) private static #if !cppia inline #end function intLte( a : Int, b : Int64 ) : Bool
+		return lte(a, b);
+
+	@:op(A > B) private static #if !cppia inline #end function gt( a : Int64, b : Int64 ) : Bool
+		return compare(a, b) > 0;
+
+	@:op(A > B) private static #if !cppia inline #end function gtInt( a : Int64, b : Int ) : Bool
+		return gt(a, b);
+
+	@:op(A > B) private static #if !cppia inline #end function intGt( a : Int, b : Int64 ) : Bool
+		return gt( a, b );
+
+	@:op(A >= B) private static #if !cppia inline #end function gte( a : Int64, b : Int64 ) : Bool
+		return compare(a, b) >= 0;
+
+	@:op(A >= B) private static #if !cppia inline #end function gteInt( a : Int64, b : Int ) : Bool
+		return gte(a, b);
+
+	@:op(A >= B) private static #if !cppia inline #end function intGte( a : Int, b : Int64 ) : Bool
+		return gte(a, b);
+
+	/**
+		Returns the bitwise NOT of `a`.
+	**/
+	@:op(~A) private static #if !cppia inline #end function complement( a : Int64 ) : Int64
+		return untyped __cpp__("(~({0}.get()))", a);
+
+	/**
+		Returns the bitwise AND of `a` and `b`.
+	**/
+	@:op(A & B) public static #if !cppia inline #end function and( a : Int64, b : Int64 ) : Int64
+		return untyped __cpp__("(({0}) & ({1}))", a, b);
+
+	/**
+		Returns the bitwise OR of `a` and `b`.
+	**/
+	@:op(A | B) public static #if !cppia inline #end function or( a : Int64, b : Int64 ) : Int64
+		return untyped __cpp__("(({0}) | ({1}))", a, b);
+
+	/**
+		Returns the bitwise XOR of `a` and `b`.
+	**/
+	@:op(A ^ B) public static #if !cppia inline #end function xor( a : Int64, b : Int64 ) : Int64
+		return untyped __cpp__("(({0}) ^ ({1}))", a, b);
+
+	/**
+		Returns `a` left-shifted by `b` bits.
+	**/
+	@:op(A << B) public static #if !cppia inline #end function shl( a : Int64, b : Int ) : Int64
+		return untyped __cpp__("(({0}) << ({1}))", a, (b&63));
+
+	/**
+		Returns `a` right-shifted by `b` bits in signed mode.
+		`a` is sign-extended.
+	**/
+	@:op(A >> B) public static #if !cppia inline #end function shr( a : Int64, b : Int) : Int64
+		return untyped __cpp__("(({0}) >> ({1}))", a, (b&63));
+
+	/**
+		Returns `a` right-shifted by `b` bits in unsigned mode.
+		`a` is padded with zeroes.
+	**/
+	@:op(A >>> B) public static #if !cppia inline #end function ushr( a : Int64, b : Int ) : Int64
+		return untyped __cpp__("(((cpp::UInt64)({0})) >> ({1}))", a, (b&63));
+
+	public var high(get, never) : Int32;
+	private #if !cppia inline #end function get_high() : Int32
+		return  untyped __cpp__("(int)(((cpp::Int64)({0}))>>32)",this);
+
+	public var low(get, never) : Int32;
+	private #if !cppia inline #end function get_low() : Int32
+		return untyped __cpp__("(int)(({0})&0xffffffff)", this);
+
+}
+

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

@@ -53,7 +53,7 @@ class FileSystem {
 		return new String(file_full_path(relPath));
 	}
 
-	public static function absPath ( relPath : String ) : String {
+	public static function absolutePath ( relPath : String ) : String {
 		if (haxe.io.Path.isAbsolute(relPath)) return relPath;
 		return haxe.io.Path.join([Sys.getCwd(), relPath]);
 	}

+ 4 - 0
std/cpp/abi/Abi.hx

@@ -0,0 +1,4 @@
+package cpp.abi;
+
+// Base case, for calling conventions - means "use default"
+extern class Abi { }

+ 4 - 0
std/cpp/abi/CDecl.hx

@@ -0,0 +1,4 @@
+package cpp.abi;
+
+@:abi("__cdecl")
+extern class CDecl extends Abi { }

+ 4 - 0
std/cpp/abi/FastCall.hx

@@ -0,0 +1,4 @@
+package cpp.abi;
+
+@:abi("__fastcall")
+extern class FastCall extends Abi { }

+ 4 - 0
std/cpp/abi/StdCall.hx

@@ -0,0 +1,4 @@
+package cpp.abi;
+
+@:abi("__stdcall")
+extern class StdCall extends Abi { }

+ 4 - 0
std/cpp/abi/ThisCall.hx

@@ -0,0 +1,4 @@
+package cpp.abi;
+
+@:abi("__thiscall")
+extern class ThisCall extends Abi { }

+ 4 - 0
std/cpp/abi/Winapi.hx

@@ -0,0 +1,4 @@
+package cpp.abi;
+
+@:abi("__stdcall")
+extern class Winapi extends Abi { }

+ 28 - 0
std/cpp/cppia/Host.hx

@@ -0,0 +1,28 @@
+package cpp.cppia;
+
+
+@:build(cpp.cppia.HostClasses.include())
+class Host
+{
+   public static function run(source:String)
+   {
+      untyped __global__.__scriptable_load_cppia(source);
+   }
+
+   public static function main()
+   {
+      var script = Sys.args()[0];
+      #if (!scriptable && !doc_gen)
+      #error "Please define scriptable to use cppia"
+      #end
+      if (script==null)
+      {
+         Sys.println("Usage : Cppia scriptname");
+      }
+      else
+      {
+         var source = sys.io.File.getContent(script);
+         run(source);
+      }
+   }
+}

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

@@ -0,0 +1,229 @@
+package cpp.cppia;
+
+import haxe.macro.Compiler;
+import haxe.macro.Context;
+import haxe.macro.Type;
+
+#if !macro
+  #if cppia
+  @:build(cpp.cppia.HostClasses.exclude())
+  #end
+class HostClasses { }
+#else
+
+import Sys;
+import haxe.Constraints;
+
+@:noPackageRestrict
+class HostClasses
+{
+   static var classes = [
+   "cpp.Lib",
+   "cpp.NativeArray",
+   "cpp.NativeString",
+   "cpp.vm.Debugger",
+   "cpp.vm.Deque",
+   "cpp.vm.ExecutionTrace",
+   "cpp.vm.Gc",
+   "cpp.vm.Lock",
+   "cpp.vm.Mutex",
+   "cpp.vm.Profiler",
+   "cpp.vm.Thread",
+   "cpp.vm.Tls",
+   "cpp.vm.Unsafe",
+   "cpp.vm.WeakRef",
+   "cpp.Object",
+   "cpp.Int64",
+   "Std",
+   "StringBuf",
+   "sys.db.Mysql",
+   "sys.db.Sqlite",
+   "sys.db.Object",
+   "sys.db.Manager",
+   "sys.db.Connection",
+   "sys.FileSystem",
+   "sys.io.File",
+   "sys.io.FileInput",
+   "sys.net.Socket",
+   "Enum",
+   "EnumValue",
+   //"Sys",
+   "Type",
+   "Xml",
+   "Date",
+   "DateTools",
+   "List",
+   "Math",
+   "Reflect",
+   "StringBuf",
+   "StringTools",
+
+   "haxe.ds.IntMap",
+   "haxe.ds.ObjectMap",
+   "haxe.ds.StringMap",
+   "haxe.CallStack",
+   "haxe.Serializer",
+   "haxe.Unserializer",
+   "haxe.Resource",
+   "haxe.Template",
+   "haxe.Utf8",
+   "haxe.Log",
+   "haxe.zip.Uncompress",
+
+   "haxe.crypto.BaseCode",
+   "haxe.crypto.Sha256",
+   "haxe.crypto.Hmac",
+   "haxe.crypto.Crc32",
+   "haxe.crypto.Base64",
+   "haxe.crypto.Adler32",
+   "haxe.crypto.Md5",
+   "haxe.crypto.Sha1",
+ 
+   "haxe.io.BufferInput",
+   "haxe.io.Bytes",
+   "haxe.io.BytesBuffer",
+   "haxe.io.BytesData",
+   "haxe.io.BytesInput",
+   "haxe.io.BytesOutput",
+   "haxe.io.Eof",
+   "haxe.io.Error",
+   "haxe.io.FPHelper",
+   "haxe.io.Input",
+   "haxe.io.Output",
+   "haxe.io.Path",
+   "haxe.io.StringInput",
+   "haxe.xml.Parser",
+   "haxe.Json",
+
+   "haxe.CallStack",
+   "haxe.Resource",
+   "haxe.Utf8",
+   "haxe.Int64",
+   "haxe.Int32",
+   "haxe.Serializer",
+   "haxe.Unserializer",
+
+
+   "haxe.ds.ArraySort",
+   "haxe.ds.GenericStack",
+   "haxe.ds.ObjectMap",
+   "haxe.ds.Vector",
+   "haxe.ds.BalancedTree",
+   "haxe.ds.HashMap",
+   "haxe.ds.Option",
+   "haxe.ds.WeakMap",
+   "haxe.ds.EnumValueMap",
+   "haxe.ds.IntMap",
+   "haxe.ds.StringMap",
+
+   "StdTypes",
+   "Array",
+   "Class",
+   "Date",
+   "EReg",
+   "Enum",
+   "EnumValue",
+   "IntIterator",
+   "List",
+   "Map",
+   "String",
+
+
+   ];
+
+
+   static function parseClassInfo(externs:Map<String,Bool>, filename:String)
+   {
+      if (sys.FileSystem.exists(filename))
+      {
+         var file = sys.io.File.read(filename);
+         try
+         {
+            while(true)
+            {
+               var line = file.readLine();
+               var parts = line.split(" ");
+               if (parts[0]=="class" || parts[0]=="interface" || parts[0]=="enum")
+                  externs.set(parts[1],true);
+            }
+         } catch( e : Dynamic ) { }
+         if (file!=null)
+            file.close();
+      }
+   }
+
+
+   static function onGenerateCppia(types:Array<Type>):Void
+   {
+      var externs = new Map<String,Bool>();
+      externs.set("Sys",true);
+      externs.set("haxe.IMap",true);
+      externs.set("haxe.crypto.HashMethod",true);
+      externs.set("haxe._Int64.Int64_Impl_",true);
+      externs.set("haxe._Int64.___Int64",true);
+      externs.set("haxe._Int32.Int32_Impl_",true);
+      externs.set("haxe._Int32.___Int32",true);
+      for(e in classes)
+         externs.set(e,true);
+
+
+      var define = Context.defined("dll_import") ? Context.definedValue("dll_import") : "1";
+      if (define!="1")
+         parseClassInfo(externs,define);
+      else
+      {
+         var tried = new Map<String, Bool>();
+         for(path in Context.getClassPath())
+            if (!tried.exists(path))
+            {
+                tried.set(path,true);
+                parseClassInfo(externs,path + "/export_classes.info");
+            }
+      }
+
+      for(type in types)
+      {
+         switch(type)
+         {
+            case TInst(classRef, params):
+               if (externs.exists(classRef.toString()))
+                    classRef.get().exclude();
+            case TEnum(enumRef, params):
+               if (externs.exists(enumRef.toString()))
+                    enumRef.get().exclude();
+            default:
+         }
+      }
+   }
+
+   // Exclude the standard classes, and any described in 'export_classes.info' files found in the classpath
+   public static function exclude()
+   {
+      if (Context.defined("cppia"))
+         Context.onGenerate(onGenerateCppia);
+      else
+         Context.error("cpp.cppia.excludeHostFiles is only for cppia code", Context.currentPos());
+      return Context.getBuildFields();
+   }
+
+
+   // Ensure that the standard classes are included in the host
+   public static function include()
+   {
+      Compiler.keep("haxe.IMap");
+      Compiler.keep("haxe.crypto.HashMethod");
+      Compiler.keep("haxe._Int64.Int64_Impl_");
+      Compiler.keep("haxe._Int32.Int32_Impl_");
+      Compiler.keep("haxe._Int64.___Int64");
+      Compiler.keep("haxe._Int32.___Int32");
+      for(cls in classes)
+      {
+         Context.getModule(cls);
+         Compiler.keep(cls);
+      }
+      return Context.getBuildFields();
+   }
+}
+#end
+
+

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

@@ -93,7 +93,7 @@ class Gc
    }
 
    @:unreflective
-   inline static public function setFinalizer<T>(inObject:T, inFinalizer:cpp.Function<T->Void> ) : Void
+   inline static public function setFinalizer<T>(inObject:T, inFinalizer:cpp.Callable<T->Void> ) : Void
    {
       untyped __global__.__hxcpp_set_finalizer(inObject, inFinalizer);
    }

+ 2 - 0
std/cs/Boot.hx

@@ -26,7 +26,9 @@ import cs.internal.Function;
 import cs.internal.HxObject;
 import cs.internal.Runtime;
 import cs.internal.Iterator;
+#if !erase_generics
 import cs.internal.Null;
+#end
 import cs.internal.StringExt;
 #if unsafe
 import cs.internal.BoxedPointer;

+ 100 - 0
std/cs/Flags.hx

@@ -0,0 +1,100 @@
+package cs;
+
+/**
+	Use this type to have access to the bitwise operators of C# enums that have a `cs.system.FlagsAttribute` attribute.
+
+	Usage example:
+	```haxe
+		import cs.system.reflection.BindingFlags;
+
+		var binding = new Flags(BindingFlags.Public) | BindingFlags.Static | BindingFlags.NonPublic;
+	```
+ **/
+abstract Flags<T : EnumValue>(T) from T to T
+{
+
+	/**
+		Creates a new `Flags` type with an optional initial value. If no initial value was specified,
+		the default enum value for an empty flags attribute is specified
+	 **/
+	@:extern inline public function new(?initial:T)
+		this = initial;
+
+	/**
+		Accessible through the bitwise OR operator (`|`). Returns a new `Flags` type with the flags
+		passed at `flags` added to it.
+	 **/
+	@:op(A|B) @:extern inline public function add(flags:Flags<T>):Flags<T>
+	{
+		return new Flags(underlying() | flags.underlying());
+	}
+
+	/**
+		Accessible through the bitwise AND operator (`&`). Returns a new `Flags` type with
+		the flags that are set on both `this` and `flags`
+	 **/
+	@:op(A&B) @:extern inline public function bitAnd(flags:Flags<T>):Flags<T>
+	{
+		return new Flags(underlying() & flags.underlying());
+	}
+
+	/**
+		Accessible through the bitwise XOR operator (`^`).
+	 **/
+	@:op(A^B) @:extern inline public function bitXor(flags:Flags<T>):Flags<T>
+	{
+		return new Flags(underlying() & flags.underlying());
+	}
+
+	/**
+		Accesible through the bitwise negation operator (`~`). Returns a new `Flags` type
+		with all unset flags as set - but the ones that are set already.
+	 **/
+	@:op(~A) @:extern inline public function bitNeg():Flags<T>
+	{
+		return new Flags(~underlying());
+	}
+
+	/**
+		Returns a new `Flags` type with all flags set by `flags` unset
+	 **/
+	@:extern inline public function remove(flags:Flags<T>):Flags<T>
+	{
+		return new Flags(underlying() & ~flags.underlying());
+	}
+
+	/**
+		Returns whether `flag` is present on `this` type
+	 **/
+	@:extern inline public function has(flag:T):Bool
+	{
+		return underlying() & new Flags(flag).underlying() != null;
+	}
+
+	/**
+		Returns whether `this` type has any flag set by `flags` also set
+	 **/
+	@:extern inline public function hasAny(flags:Flags<T>):Bool
+	{
+		return underlying() & flags.underlying() != null;
+	}
+
+	/**
+		Returns whether `this` type has all flags set by `flags` also set
+	 **/
+	@:extern inline public function hasAll(flags:Flags<T>):Bool
+	{
+		return underlying() & flags.underlying() == flags.underlying();
+	}
+
+	@:extern inline private function underlying():EnumUnderlying<T>
+		return this;
+}
+
+@:coreType private abstract EnumUnderlying<T> from T to T
+{
+	@:op(A|B) public static function or<T>(lhs:EnumUnderlying<T>, rhs:EnumUnderlying<T>):T;
+	@:op(A^B) public static function xor<T>(lhs:EnumUnderlying<T>, rhs:EnumUnderlying<T>):T;
+	@:op(A&B) public static function and<T>(lhs:EnumUnderlying<T>, rhs:EnumUnderlying<T>):T;
+	@:op(~A) public static function bneg<T>(t:EnumUnderlying<T>):T;
+}

+ 38 - 5
std/cs/Lib.hx

@@ -60,16 +60,23 @@ class Lib
 	@:extern inline public static function nativeArray<T>(arr:Array<T>, equalLengthRequired:Bool):NativeArray<T>
 	{
 		var ret = new cs.NativeArray(arr.length);
+#if erase_generics
+		for (i in 0...arr.length)
+			ret[i] = arr[i];
+#else
 		p_nativeArray(arr,ret);
+#end
 		return ret;
 	}
 
+#if !erase_generics
 	static function p_nativeArray<T>(arr:Array<T>, ret:cs.system.Array):Void
 	{
 		var native:NativeArray<T> = untyped arr.__a;
 		var len = arr.length;
 		cs.system.Array.Copy(native, 0, ret, 0, len);
 	}
+#end
 
 	/**
 		Provides support for the "as" keyword in C#.
@@ -114,20 +121,46 @@ class Lib
 
 	/**
 		Gets the native System.Type from the supplied object. Will throw an exception in case of null being passed.
+		[deprecated] - use `getNativeType` instead
 	**/
+	@:deprecated('The function `nativeType` is deprecated and will be removed in later versions. Please use `getNativeType` instead')
 	public static function nativeType(obj:Dynamic):Type
 	{
 		return untyped obj.GetType();
 	}
 
+	/**
+		Gets the native System.Type from the supplied object. Will throw an exception in case of null being passed.
+	**/
+	public static function getNativeType(obj:Dynamic):Type
+	{
+		return untyped obj.GetType();
+	}
+
+#if erase_generics
+	inline private static function mkDynamic<T>(native:NativeArray<T>):NativeArray<Dynamic>
+	{
+		var ret = new cs.NativeArray<Dynamic>(native.Length);
+		for (i in 0...native.Length)
+			ret[i] = native[i];
+		return ret;
+	}
+#end
+
 	/**
 		Returns a Haxe Array of a native Array.
-		It won't copy the contents of the native array, so unless any operation triggers an array resize,
-		all changes made to the Haxe array will affect the native array argument.
+		Unless `erase_generics` is defined, it won't copy the contents of the native array,
+		so unless any operation triggers an array resize, all changes made to the Haxe array
+		will affect the native array argument.
 	**/
-	public static function array<T>(native:cs.NativeArray<T>):Array<T>
+	inline public static function array<T>(native:cs.NativeArray<T>):Array<T>
 	{
-		return untyped Array.ofNative(native);
+#if erase_generics
+		var dyn:NativeArray<Dynamic> = mkDynamic(native);
+		return @:privateAccess Array.ofNative(dyn);
+#else
+		return @:privateAccess Array.ofNative(native);
+#end
 	}
 
 	/**
@@ -135,7 +168,7 @@ class Lib
 	**/
 	public static function arrayAlloc<T>(size:Int):Array<T>
 	{
-		return untyped Array.alloc(size);
+		return @:privateAccess Array.alloc(size);
 	}
 
 	/**

+ 49 - 3
std/cs/NativeArray.hx

@@ -21,14 +21,60 @@
  */
 package cs;
 
+import haxe.extern.Rest;
+
+/**
+	Represents a C# fixed-size Array (`T[]`)
+**/
 extern class NativeArray<T> extends cs.system.Array implements ArrayAccess<T>
 {
-	// public var Length(default, null):Int;
+	/**
+		Creates a new array with the specified elements.
+
+		Usage:
+		```haxe
+		var elements = NativeArray.make(1,2,3,4,5,6);
+		```
+	 **/
+	public static function make<T>(elements:Rest<T>):NativeArray<T>;
 
+	/**
+		Allocates a new array with size `len`
+	 **/
 	public function new(len:Int):Void;
 
-	// @:overload(function(arr:cs.system.Array, destIndex:haxe.Int64):Void {} )
-	// public function CopyTo(arr:cs.system.Array, destIndex:Int):Void;
+	/**
+		Alias to array's `Length` property. Returns the size of the array
+	 **/
+	public var length(get,never):Int;
+
+	@:extern inline private function get_length():Int return this.Length;
 
 	static function Reverse(arr:cs.system.Array):Void;
+
+	/**
+		Returns an iterator so it's possible to use `for` with C#'s `NativeArray`
+	 **/
+	@:extern inline public function iterator():NativeArrayIterator<T>
+		return new NativeArrayIterator(this);
+}
+
+@:dce private class NativeArrayIterator<T>
+{
+	public var arr(default,null):NativeArray<T>;
+	public var idx(default,null):UInt;
+
+	inline public function new(arr)
+	{
+		this.arr = arr;
+		this.idx = 0;
+	}
+
+	inline public function hasNext():Bool
+		return this.idx < this.arr.Length;
+
+	inline public function next():T
+	{
+		return this.arr[this.idx++];
+	}
 }

+ 11 - 1
std/cs/StdTypes.hx

@@ -26,7 +26,7 @@ package cs;
 @:notNull @:runtimeValue @:coreType abstract Char16 from Int {}
 @:notNull @:runtimeValue @:coreType abstract UInt8 to Int from Int {}
 @:notNull @:runtimeValue @:coreType abstract UInt16 to Int {}
-@:notNull @:runtimeValue @:coreType abstract Int64 from Int from Float from haxe.Int64
+@:notNull @:runtimeValue @:coreType abstract Int64 from Int from Float
 {
 	@:op(A+B) public static function addI(lhs:Int64, rhs:Int):Int64;
 	@:op(A+B) public static function add(lhs:Int64, rhs:Int64):Int64;
@@ -56,6 +56,11 @@ package cs;
 
 	@:op(~A) public static function bneg(t:Int64):Int64;
 	@:op(-A) public static function neg(t:Int64):Int64;
+
+	@:op(++A) public static function preIncrement(t:Int64):Int64;
+	@:op(A++) public static function postIncrement(t:Int64):Int64;
+	@:op(--A) public static function preDecrement(t:Int64):Int64;
+	@:op(A--) public static function postDecrement(t:Int64):Int64;
 }
 @:notNull @:runtimeValue @:coreType abstract UInt64 from Int from Int64 from Float from haxe.Int64
 {
@@ -87,4 +92,9 @@ package cs;
 
 	@:op(~A) public static function bneg(t:UInt64):UInt64;
 	@:op(-A) public static function neg(t:UInt64):UInt64;
+
+	@:op(++A) public static function preIncrement(t:UInt64):UInt64;
+	@:op(A++) public static function postIncrement(t:UInt64):UInt64;
+	@:op(--A) public static function preDecrement(t:UInt64):UInt64;
+	@:op(A--) public static function postDecrement(t:UInt64):UInt64;
 }

+ 37 - 29
std/cs/_std/Array.hx

@@ -21,44 +21,52 @@
  */
 import cs.NativeArray;
 
-@:classCode('
-	public Array(T[] native)
-	{
-		this.__a = native;
-		this.length = native.Length;
-	}
-')
 #if core_api_serialize
 @:meta(System.Serializable)
 #end
-@:final @:coreApi class Array<T> implements ArrayAccess<T> {
+@:final class Array<T> implements ArrayAccess<T> {
 
 	public var length(default,null) : Int;
 
 	private var __a:NativeArray<T>;
 
-	@:functionCode('
-			return new Array<X>(native);
-	')
-	private static function ofNative<X>(native:NativeArray<X>):Array<X>
+#if erase_generics
+	inline private static function ofNative<X>(native:NativeArray<Dynamic>):Array<X>
 	{
-		return null;
+		return new Array(native);
 	}
+#else
+	inline private static function ofNative<X>(native:NativeArray<X>):Array<X>
+	{
+		return new Array(native);
+	}
+#end
 
-	@:functionCode('
-			return new Array<Y>(new Y[size]);
-	')
-	private static function alloc<Y>(size:Int):Array<Y>
+	inline private static function alloc<Y>(size:Int):Array<Y>
 	{
-		return null;
+		return new Array(new NativeArray(size));
 	}
 
-	public function new() : Void
+	@:overload public function new() : Void
 	{
 		this.length = 0;
 		this.__a = new NativeArray(0);
 	}
 
+#if erase_generics
+	@:overload private function new(native:NativeArray<Dynamic>)
+	{
+		this.length = native.Length;
+		this.__a = untyped native;
+	}
+#else
+	@:overload private function new(native:NativeArray<T>)
+	{
+		this.length = native.Length;
+		this.__a = native;
+	}
+#end
+
 	public function concat( a : Array<T> ) : Array<T>
 	{
 		var len = length + a.length;
@@ -99,7 +107,7 @@ import cs.NativeArray;
 		{
 			return -1;
 		}
-		return cs.system.Array._IndexOf(__a, x, i, len - i);
+		return cs.system.Array.IndexOf(__a, x, i, len - i);
 	}
 
 	public function lastIndexOf( x : T, ?fromIndex:Int ) : Int
@@ -230,23 +238,23 @@ import cs.NativeArray;
 
 	private function quicksort( lo : Int, hi : Int, f : T -> T -> Int ) : Void
 	{
-        var buf = __a;
+		var buf = __a;
 		var i = lo, j = hi;
-        var p = buf[(i + j) >> 1];
+		var p = buf[(i + j) >> 1];
 		while ( i <= j )
 		{
-			while ( f(buf[i], p) < 0 ) i++;
-            while ( f(buf[j], p) > 0 ) j--;
+			while ( i < hi && f(buf[i], p) < 0 ) i++;
+			while ( j > lo && f(buf[j], p) > 0 ) j--;
 			if ( i <= j )
 			{
-                var t = buf[i];
-                buf[i++] = buf[j];
-                buf[j--] = t;
-            }
+				var t = buf[i];
+				buf[i++] = buf[j];
+				buf[j--] = t;
+			}
 		}
 
 		if( lo < j ) quicksort( lo, j, f );
-        if( i < hi ) quicksort( i, hi, f );
+		if( i < hi ) quicksort( i, hi, f );
 	}
 
 	public function splice( pos : Int, len : Int ) : Array<T>

+ 73 - 107
std/cs/_std/Reflect.hx

@@ -1,5 +1,5 @@
 /*
- * Copyright (C)2005-2012 Haxe Foundation
+ * Copyright (C)2005-2015 Haxe Foundation
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -20,124 +20,101 @@
  * DEALINGS IN THE SOFTWARE.
  */
 import cs.internal.Function;
-/*
- * Copyright (c) 2005, The Haxe Project Contributors
- * All rights reserved.
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- *   - Redistributions of source code must retain the above copyright
- *     notice, this list of conditions and the following disclaimer.
- *   - Redistributions in binary form must reproduce the above copyright
- *     notice, this list of conditions and the following disclaimer in the
- *     documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE HAXE PROJECT CONTRIBUTORS "AS IS" AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE HAXE PROJECT CONTRIBUTORS BE LIABLE FOR
- * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
- * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
- * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
- * DAMAGE.
- */
+import cs.system.reflection.*;
 
-@:keep @:coreApi class Reflect {
+import cs.internal.*;
+import cs.internal.HxObject;
+import cs.internal.Runtime;
+import cs.Flags;
+import cs.Lib;
+import cs.system.Object;
+import cs.system.reflection.*;
 
-	@:functionCode('
-		if (o is haxe.lang.IHxObject)
-			return ((haxe.lang.IHxObject) o).__hx_getField(field, haxe.lang.FieldLookup.hash(field), false, true, false) != haxe.lang.Runtime.undefined;
+@:keep @:coreApi class Reflect {
 
-		return haxe.lang.Runtime.slowHasField(o, field);
-	')
 	public static function hasField( o : Dynamic, field : String ) : Bool
 	{
-		return false;
-	}
+		var ihx:IHxObject = Lib.as(o,IHxObject);
+		if (ihx != null) return untyped ihx.__hx_getField(field, FieldLookup.hash(field), false, true, false) != Runtime.undefined;
 
-	@:functionCode('
-		if (o is haxe.lang.IHxObject)
-			return ((haxe.lang.IHxObject) o).__hx_getField(field, haxe.lang.FieldLookup.hash(field), false, false, false);
+		return Runtime.slowHasField(o,field);
+	}
 
-		return haxe.lang.Runtime.slowGetField(o, field, false);
-	')
 	public static function field( o : Dynamic, field : String ) : Dynamic
 	{
-		return null;
+		var ihx:IHxObject = Lib.as(o,IHxObject);
+		if (ihx != null) return untyped ihx.__hx_getField(field, FieldLookup.hash(field), false, false, false);
+
+		return Runtime.slowGetField(o,field,false);
 	}
 
-	@:functionCode('
-		if (o is haxe.lang.IHxObject)
-			((haxe.lang.IHxObject) o).__hx_setField(field, haxe.lang.FieldLookup.hash(field), value, false);
-		else
-			haxe.lang.Runtime.slowSetField(o, field, value);
-	')
 	public static function setField( o : Dynamic, field : String, value : Dynamic ) : Void
 	{
-
+		var ihx:IHxObject = Lib.as(o,IHxObject);
+		if (ihx != null)
+			untyped ihx.__hx_setField(field, FieldLookup.hash(field), value, false);
+		else
+			Runtime.slowSetField(o,field,value);
 	}
 
-	@:functionCode('
-		if (o is haxe.lang.IHxObject)
-			return ((haxe.lang.IHxObject) o).__hx_getField(field, haxe.lang.FieldLookup.hash(field), false, false, true);
-
-		if (haxe.lang.Runtime.slowHasField(o, "get_" + field))
-			return haxe.lang.Runtime.slowCallField(o, "get_" + field, null);
-
-		return haxe.lang.Runtime.slowGetField(o, field, false);
-	')
 	public static function getProperty( o : Dynamic, field : String ) : Dynamic
 	{
-		return null;
+		var ihx:IHxObject = Lib.as(o,IHxObject);
+		if (ihx != null) return untyped ihx.__hx_getField(field, FieldLookup.hash(field), false, false, true);
+
+		if (Runtime.slowHasField(o, "get_" + field))
+			return Runtime.slowCallField(o, "get_" + field, null);
+
+		return Runtime.slowGetField(o, field, false);
 	}
 
-	@:functionCode('
-		if (o is haxe.lang.IHxObject)
-			((haxe.lang.IHxObject) o).__hx_setField(field, haxe.lang.FieldLookup.hash(field), value, true);
-		else if (haxe.lang.Runtime.slowHasField(o, "set_" + field))
-			haxe.lang.Runtime.slowCallField(o, "set_" + field, new Array<object>(new object[]{value}));
-		else
-			haxe.lang.Runtime.slowSetField(o, field, value);
-	')
 	public static function setProperty( o : Dynamic, field : String, value : Dynamic ) : Void
 	{
-
+		var ihx:IHxObject = Lib.as(o,IHxObject);
+		if (ihx != null)
+			untyped ihx.__hx_setField(field, FieldLookup.hash(field), value, true);
+		else if (Runtime.slowHasField(o, 'set_$field'))
+			Runtime.slowCallField(o, 'set_$field', [value]);
+		else
+			Runtime.slowSetField(o,field,value);
 	}
 
-	@:functionCode('
-		return ((haxe.lang.Function) func).__hx_invokeDynamic(args);
-	')
 	public static function callMethod( o : Dynamic, func : haxe.Constraints.Function, args : Array<Dynamic> ) : Dynamic
 	{
-		return null;
+		return untyped cast(func, Function).__hx_invokeDynamic(args);
 	}
 
-	@:functionCode('
-		if (o is haxe.lang.IHxObject)
+	public static function fields( o : Dynamic ) : Array<String>
+	{
+		var ihx = Lib.as(o,IHxObject);
+		if (o != null)
 		{
-			Array<object> ret = new Array<object>();
-				((haxe.lang.IHxObject) o).__hx_getFields(ret);
+			var ret = [];
+			untyped ihx.__hx_getFields(ret);
 			return ret;
-		} else if (o is System.Type) {
-			return Type.getClassFields( (System.Type) o);
+		} else if (Std.is(o, cs.system.Type)) {
+			return Type.getClassFields(o);
 		} else {
-			return new Array<object>();
+			return instanceFields( untyped o.GetType() );
 		}
-	')
-	public static function fields( o : Dynamic ) : Array<String>
+	}
+
+	private static function instanceFields( c : Class<Dynamic> ) : Array<String>
 	{
-		return null;
+		var c = cs.Lib.toNativeType(c);
+		var ret = [];
+		var mis = c.GetFields(new cs.Flags(BindingFlags.Public) | BindingFlags.Instance | BindingFlags.FlattenHierarchy);
+		for (i in 0...mis.Length)
+		{
+			var i = mis[i];
+			ret.push(i.Name);
+		}
+		return ret;
 	}
 
-	@:functionCode('
-		return f is haxe.lang.Function;
-	')
-	public static function isFunction( f : Dynamic ) : Bool
+	inline public static function isFunction( f : Dynamic ) : Bool
 	{
-		return false;
+		return Std.is(f, Function);
 	}
 
 	public static function compare<T>( a : T, b : T ) : Int
@@ -145,48 +122,37 @@ import cs.internal.Function;
 		return cs.internal.Runtime.compare(a, b);
 	}
 
-	@:functionCode('
+	@:access(cs.internal.Closure)
+	public static function compareMethods( f1 : Dynamic, f2 : Dynamic ) : Bool
+	{
 		if (f1 == f2)
 			return true;
 
-		if (f1 is haxe.lang.Closure && f2 is haxe.lang.Closure)
+		if (Std.is(f1, Closure) && Std.is(f2, Closure))
 		{
-			haxe.lang.Closure f1c = (haxe.lang.Closure) f1;
-			haxe.lang.Closure f2c = (haxe.lang.Closure) f2;
+			var f1c:Closure = cast f1;
+			var f2c:Closure = cast f2;
 
-			return haxe.lang.Runtime.refEq(f1c.obj, f2c.obj) && f1c.field.Equals(f2c.field);
+			return Runtime.refEq(f1c.obj, f2c.obj) && f1c.field == f2c.field;
 		}
 
-		return false;
-	')
-	public static function compareMethods( f1 : Dynamic, f2 : Dynamic ) : Bool
-	{
 		return false;
 	}
 
-	@:functionCode('
-		return v != null && !(v is haxe.lang.Enum || v is haxe.lang.Function || v is System.ValueType);
-	')
 	public static function isObject( v : Dynamic ) : Bool
 	{
-		return false;
+		return v != null && !(Std.is(v, HxEnum) || Std.is(v, Function) || Std.is(v, cs.system.ValueType));
 	}
 
-	@:functionCode('
-		return v != null && (v is haxe.lang.Enum || v is System.Enum);
-	')
 	public static function isEnumValue( v : Dynamic ) : Bool {
-		return switch(Type.typeof(v)) {
-			case TEnum(_): true;
-			case _: false;
-		}
+		return v != null && (Std.is(v, HxEnum) || Std.is(v, cs.system.Enum));
 	}
 
-	@:functionCode('
-		return (o is haxe.lang.DynamicObject && ((haxe.lang.DynamicObject) o).__hx_deleteField(field, haxe.lang.FieldLookup.hash(field)));
-	')
 	public static function deleteField( o : Dynamic, field : String ) : Bool
 	{
+		var ihx = Lib.as(o,DynamicObject);
+		if (ihx != null)
+			return untyped ihx.__hx_deleteField(field, FieldLookup.hash(field));
 		return false;
 	}
 

+ 32 - 86
std/cs/_std/Std.hx

@@ -47,7 +47,7 @@ import cs.internal.Exceptions;
 				return true;
 		}
 
-		return clt.IsAssignableFrom(cs.Lib.nativeType(v));
+		return clt.IsAssignableFrom(cs.Lib.getNativeType(v));
 	}
 
 	public static function string( s : Dynamic ) : String {
@@ -134,103 +134,49 @@ import cs.internal.Exceptions;
 	public static function parseFloat( x : String ) : Float {
 		if (x == null) return Math.NaN;
 		x = StringTools.ltrim(x);
-
-		var ret = 0.0;
-		var div = 0.0;
-		var e = 0.0;
-
-		var len = x.length;
-		var foundAny = false;
-		var isNeg = false;
+		var found = false, isHex = false, hasDot = false, hasE = false, hasNeg = false, hasENeg = false;
 		var i = -1;
-		while (++i < len)
-		{
-			var c = cast(untyped x[i], Int); //fastCodeAt
-			if (!foundAny)
-			{
-				switch(c)
-				{
-					case '-'.code:
-						isNeg = true;
-						continue;
-					case ' '.code, '\t'.code, '\n'.code, '\r'.code, '+'.code:
-						if (isNeg)
-							return Math.NaN;
-						continue;
-				}
-			}
+		inline function getch(i:Int):Int return cast ((untyped x : cs.system.String)[i]);
 
-			if (c == '.'.code)
-			{
-				if (div != 0.0)
-					break;
-				div = 1.0;
-				foundAny = true;
-
-				continue;
-			}
-
-			if (c >= '0'.code && c <= '9'.code)
+		while (++i < x.length)
+		{
+			var chr = getch(i);
+			if (chr >= '0'.code && chr <= '9'.code)
 			{
-				if (!foundAny && c == '0'.code)
+				if ( !found && chr == '0'.code && (i+1) < x.length )
 				{
-					foundAny = true;
-					continue;
-				}
-
-				ret *= 10; foundAny = true; div *= 10;
-
-				ret += c - '0'.code;
-			} else if (foundAny && (c == 'e'.code || c == 'E'.code)) {
-				var eNeg = false;
-				var eFoundAny = false;
-				if (i + 1 < len)
-				{
-					var next = untyped cast(x[i + 1], Int);
-					if (next == '-'.code)
+					var next = getch(i+1);
+					if (next == 'x'.code || next == 'X'.code)
 					{
-						eNeg = true;
-						i++;
-					} else if (next == '+'.code) {
+						isHex = true;
 						i++;
 					}
 				}
-
-				while (++i < len)
-				{
-					c = untyped cast(x[i], Int);
-					if (c >= '0'.code && c <= '9'.code)
-					{
-						if (!eFoundAny && c == '0'.code)
-							continue;
-						eFoundAny = true;
-						e *= 10;
-						e += c - '0'.code;
-					} else {
-						break;
-					}
-				}
-
-				if (eNeg) e = -e;
-			} else {
-				break;
+				found = true;
+			} else switch (chr) {
+				case 'a'.code | 'b'.code | 'c'.code | 'd'.code | 'e'.code | 'f'.code
+				   | 'A'.code | 'B'.code | 'C'.code | 'D'.code | 'E'.code | 'F'.code if (isHex):
+					//do nothing - it's alright
+				case 'e'.code | 'E'.code if(!hasE):
+					hasE = true;
+				case '.'.code if (!hasDot):
+					hasDot = true;
+				case '-'.code if (!found && !hasNeg):
+					hasNeg = true;
+				case '-'.code if (found && !hasENeg && hasE):
+					hasENeg = true;
+				case _:
+					break;
 			}
 		}
-
-		if (div == 0.0) div = 1.0;
-
-		if (foundAny)
+		if (i != x.length)
 		{
-			ret = isNeg ? -(ret / div) : (ret / div);
-			if (e != 0.0)
-			{
-				return ret * Math.pow(10.0, e);
-			} else {
-				return ret;
-			}
-		} else {
-			return Math.NaN;
+			x = x.substr(0,i);
 		}
+		return try
+			cs.system.Double.Parse(x, (null : cs.system.IFormatProvider))
+		catch(e:Dynamic)
+			Math.NaN;
 	}
 
 	@:extern inline public static function instance<T:{},S:T>( value : T, c : Class<S> ) : S {

+ 1 - 25
std/cs/_std/Sys.hx

@@ -1,5 +1,5 @@
 /*
- * Copyright (C)2005-2012 Haxe Foundation
+ * Copyright (C)2005-2015 Haxe Foundation
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -22,30 +22,6 @@
 import sys.io.Process;
 import cs.system.Environment;
 import cs.system.threading.Thread;
-/*
- * Copyright (c) 2005-2012, The Haxe Project Contributors
- * All rights reserved.
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- *   - Redistributions of source code must retain the above copyright
- *     notice, this list of conditions and the following disclaimer.
- *   - Redistributions in binary form must reproduce the above copyright
- *     notice, this list of conditions and the following disclaimer in the
- *     documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE HAXE PROJECT CONTRIBUTORS "AS IS" AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE HAXE PROJECT CONTRIBUTORS BE LIABLE FOR
- * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
- * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
- * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
- * DAMAGE.
- */
 
 @:coreApi
 class Sys {

+ 101 - 164
std/cs/_std/Type.hx

@@ -1,5 +1,5 @@
 /*
- * Copyright (C)2005-2012 Haxe Foundation
+ * Copyright (C)2005-2015 Haxe Foundation
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -22,32 +22,11 @@
 import cs.Lib;
 import cs.internal.HxObject;
 import cs.internal.Runtime;
+import cs.internal.Function;
+import cs.Flags;
+import cs.system.Object;
 import cs.system.reflection.*;
 using StringTools;
-/*
- * Copyright (c) 2005, The Haxe Project Contributors
- * All rights reserved.
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- *   - Redistributions of source code must retain the above copyright
- *     notice, this list of conditions and the following disclaimer.
- *   - Redistributions in binary form must reproduce the above copyright
- *     notice, this list of conditions and the following disclaimer in the
- *     documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE HAXE PROJECT CONTRIBUTORS "AS IS" AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE HAXE PROJECT CONTRIBUTORS BE LIABLE FOR
- * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
- * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
- * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
- * DAMAGE.
- */
 
 @:keep enum ValueType {
 	TNull;
@@ -63,24 +42,18 @@ using StringTools;
 
 @:keep @:coreApi class Type {
 
-	@:functionCode('
-		if (o == null || o is haxe.lang.DynamicObject || o is System.Type)
-			return null;
-
-		return o.GetType();
-	')
 	public static function getClass<T>( o : T ) : Class<T> untyped
 	{
-		return null;
+		if (Object.ReferenceEquals(o,null) || Std.is(o,DynamicObject) || Std.is(o,cs.system.Type))
+			return null;
+
+		return untyped o.GetType();
 	}
 
-	@:functionCode('
-		if (o is System.Enum || o is haxe.lang.Enum)
-			return o.GetType();
-		return null;
-	')
 	public static function getEnum( o : EnumValue ) : Enum<Dynamic> untyped
 	{
+		if (Std.is(o, cs.system.Enum) || Std.is(o,HxEnum))
+			return untyped o.GetType();
 		return null;
 	}
 
@@ -88,11 +61,8 @@ using StringTools;
 	{
 		var t:cs.system.Type = Lib.toNativeType(c);
 		var base = t.BaseType;
-		if (base == null || (base + "") == ("haxe.lang.HxObject") || (base + "") == ("System.Object"))
-		{
+		if (base == null || base.ToString() == "haxe.lang.HxObject" || base.ToString() == "System.Object")
 			return null;
-		}
-
 		return Lib.fromNativeType(base);
 	}
 
@@ -157,34 +127,29 @@ using StringTools;
 				case #if no_root "haxe.root.String" #else "String" #end: return cast String;
 				default: return null;
 			}
+#if !erase_generics
 		} else if (t.IsInterface && cast(untyped __typeof__(IGenericObject), cs.system.Type).IsAssignableFrom(t)) {
-			t = null;
-			var i = 0;
-			var ts = "";
-			while (t == null && i < 18)
+			for (attr in t.GetCustomAttributes(true))
 			{
-				i++;
-				ts += (i == 1 ? "" : ",") + "System.Object";
-				t = cs.system.Type._GetType(name + "`" + i + "[" + ts + "]");
+				var g = cs.Lib.as(attr, cs.internal.HxObject.GenericInterface);
+				if (g != null)
+					return Lib.fromNativeType(g.generic);
 			}
 
 			return Lib.fromNativeType(t);
+#end
 		} else {
 			return Lib.fromNativeType(t);
 		}
 	}
 
-	@:functionCode('
-		if (name == "Bool") return typeof(bool);
-		System.Type t = resolveClass(name);
-		if (t != null && (t.BaseType.Equals(typeof(System.Enum)) || t.BaseType.Equals(typeof(haxe.lang.Enum))))
-			return t;
-		return null;
-	')
 	public static function resolveEnum( name : String ) : Enum<Dynamic> untyped
 	{
 		if (name == "Bool") return Bool;
-		return cast resolveClass(name);
+		var t = Lib.toNativeType(resolveClass(name));
+		if (t != null && t.BaseType.Equals( Lib.toNativeType(cs.system.Enum) ) || Lib.toNativeType(HxEnum).IsAssignableFrom(t))
+			return t;
+		return null;
 	}
 
 	public static function createInstance<T>( cl : Class<T>, args : Array<Dynamic> ) : T
@@ -229,20 +194,17 @@ using StringTools;
 		return cs.system.Activator.CreateInstance(t);
 	}
 
-	@:functionCode('
-		if (@params == null || @params[0] == null)
+	public static function createEnum<T>( e : Enum<T>, constr : String, ?params : Array<Dynamic> ) : T
+	{
+		if (params == null || params[0] == null)
 		{
-			object ret = haxe.lang.Runtime.slowGetField(e, constr, true);
-			if (ret is haxe.lang.Function)
-				throw haxe.lang.HaxeException.wrap("Constructor " + constr + " needs parameters");
-			return (T) ret;
+			var ret = cs.internal.Runtime.slowGetField(e, constr, true);
+			if (Reflect.isFunction(ret))
+				throw 'Constructor $constr needs parameters';
+			return ret;
 		} else {
-			return (T) haxe.lang.Runtime.slowCallField(e, constr, @params);
+			return cs.internal.Runtime.slowCallField(e,constr,params);
 		}
-	')
-	public static function createEnum<T>( e : Enum<T>, constr : String, ?params : Array<Dynamic> ) : T
-	{
-		return null;
 	}
 
 	public static function createEnumIndex<T>( e : Enum<T>, index : Int, ?params : Array<Dynamic> ) : T {
@@ -257,8 +219,7 @@ using StringTools;
 
 		var c = cs.Lib.toNativeType(c);
 		var ret = [];
-		var bindingFlags:BindingFlags = cast cast(BindingFlags.Public, Int) | cast(BindingFlags.Instance, Int) | cast(BindingFlags.FlattenHierarchy,Int);
-		var mis = c.GetMembers(bindingFlags);
+		var mis = c.GetMembers(new cs.Flags(BindingFlags.Public) | BindingFlags.Instance | BindingFlags.FlattenHierarchy);
 		for (i in 0...mis.Length)
 		{
 			var i = mis[i];
@@ -278,132 +239,108 @@ using StringTools;
 		return ret;
 	}
 
-	@:functionCode('
-		Array<object> ret = new Array<object>();
-
-		if (c == typeof(string))
+	public static function getClassFields( c : Class<Dynamic> ) : Array<String> {
+		if (Object.ReferenceEquals(c, String))
 		{
-			ret.push("fromCharCode");
-			return ret;
+			return ['fromCharCode'];
 		}
 
-        System.Reflection.MemberInfo[] mis = c.GetMembers(System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Static);
-        for (int i = 0; i < mis.Length; i++)
-        {
-            string n = mis[i].Name;
-			if (!n.StartsWith("__hx_"))
-				ret.push(mis[i].Name);
-        }
-
-        return ret;
-	')
-	public static function getClassFields( c : Class<Dynamic> ) : Array<String> {
-		return null;
+		var ret = [];
+		var infos = Lib.toNativeType(c).GetMembers(new Flags(BindingFlags.Public) | BindingFlags.Static);
+		for (i in 0...infos.Length)
+		{
+			var name = infos[i].Name;
+			if (!name.startsWith('__hx_'))
+			{
+				ret.push(name);
+			}
+		}
+		return ret;
 	}
 
 	public static function getEnumConstructs( e : Enum<Dynamic> ) : Array<String> {
-		if (Reflect.hasField(e, "constructs"))
-			return untyped e.constructs.copy();
+		if (Reflect.hasField(e, "__hx_constructs")) {
+			var ret:Array<String> = cs.Lib.array(untyped e.__hx_constructs);
+			return ret.copy();
+		}
 		return cs.Lib.array(cs.system.Enum.GetNames(untyped e));
 	}
 
-	@:functionCode('
+	public static function typeof( v : Dynamic ) : ValueType {
 		if (v == null) return ValueType.TNull;
 
-        System.Type t = v as System.Type;
-        if (t != null)
-        {
-            //class type
-            return ValueType.TObject;
-        }
-
-        t = v.GetType();
-        if (t.IsEnum)
-            return ValueType.TEnum(t);
-        if (t.IsValueType)
-        {
-            System.IConvertible vc = v as System.IConvertible;
-            if (vc != null)
-            {
-                switch (vc.GetTypeCode())
-                {
-                    case System.TypeCode.Boolean: return ValueType.TBool;
-                    case System.TypeCode.Double:
-						double d = vc.ToDouble(null);
-						if (d >= int.MinValue && d <= int.MaxValue && d == vc.ToInt32(null))
+		var t:cs.system.Type = cs.Lib.as(v, cs.system.Type);
+		if (t != null) {
+			//class type
+			return ValueType.TObject;
+		}
+
+		t = v.GetType();
+		if (t.IsEnum || Std.is(v, HxEnum))
+			return ValueType.TEnum(cast t);
+		if (t.IsValueType) {
+			var vc:cs.system.IConvertible = cast v;
+			if (vc != null) {
+				switch (vc.GetTypeCode()) {
+					case cs.system.TypeCode.Boolean: return ValueType.TBool;
+					case cs.system.TypeCode.Double:
+						var d:Float = vc.ToDouble(null);
+						if (d >= cs.system.Int32.MinValue && d <= cs.system.Int32.MaxValue && d == vc.ToInt32(null))
 							return ValueType.TInt;
 						else
 							return ValueType.TFloat;
-                    case System.TypeCode.Int32:
-                        return ValueType.TInt;
-                    default:
-                        return ValueType.TClass(t);
-                }
-            } else {
-                return ValueType.TClass(t);
-            }
-        }
-
-        if (v is haxe.lang.IHxObject)
-        {
-            if (v is haxe.lang.DynamicObject)
-                return ValueType.TObject;
-            else if (v is haxe.lang.Enum)
-                return ValueType.TEnum(t);
-            return ValueType.TClass(t);
-        } else if (v is haxe.lang.Function) {
-            return ValueType.TFunction;
-        } else {
-            return ValueType.TClass(t);
-        }
-	')
-	public static function typeof( v : Dynamic ) : ValueType
-	{
-		return null;
+					case cs.system.TypeCode.Int32:
+						return ValueType.TInt;
+					default:
+						return ValueType.TClass(cast t);
+				}
+			} else {
+				return ValueType.TClass(cast t);
+			}
+		}
+
+		if (Std.is(v, IHxObject)) {
+			if (Std.is(v, DynamicObject))
+				return ValueType.TObject;
+			else if (Std.is(v, HxEnum))
+				return ValueType.TEnum(cast t);
+			return ValueType.TClass(cast t);
+		} else if (Std.is(v, Function)) {
+			return ValueType.TFunction;
+		} else {
+			return ValueType.TClass(cast t);
+		}
 	}
 
-	@:functionCode('
-			if (a is haxe.lang.Enum)
-				return a.Equals(b);
-			else
-				return haxe.lang.Runtime.eq(a, b);
-	')
 	public static function enumEq<T>( a : T, b : T ) : Bool
 	{
-		return untyped a.Equals(b);
+		if (a == null)
+			return b == null;
+		else if (b == null)
+			return false;
+		else
+			return untyped a.Equals(b);
 	}
 
-	@:functionCode('
-		if (e is System.Enum)
-			return e + "";
-		else
-			return ((haxe.lang.Enum) e).getTag();
-	')
 	public static function enumConstructor( e : EnumValue ) : String untyped
 	{
-		return e.tag;
+		return Std.is(e, cs.system.Enum) ? e+'' : cast(e,HxEnum).getTag();
 	}
 
-	@:functionCode('
-		return ( e is System.Enum ) ? new Array<object>() : ((haxe.lang.Enum) e).@params;
-	')
 	public static function enumParameters( e : EnumValue ) : Array<Dynamic> untyped
 	{
-		return null;
+		return Std.is(e, cs.system.Enum) ? [] : cast(e,HxEnum).getParams();
 	}
 
-	@:functionCode('
-		if (e is System.Enum)
+	public static function enumIndex( e : EnumValue ) : Int  untyped
+	{
+		if (Std.is(e, cs.system.Enum))
 		{
-			System.Array values = System.Enum.GetValues(e.GetType());
-			return System.Array.IndexOf(values, e);
+			var values = cs.system.Enum.GetValues(Lib.getNativeType(e));
+			return cs.system.Array.IndexOf(values, e);
 		} else {
-			return ((haxe.lang.Enum) e).index;
+			return cast(e, HxEnum).index;
 		}
-	')
-	public static function enumIndex( e : EnumValue ) : Int  untyped
-	{
-		return e.index;
 	}
 
 	public static function allEnums<T>( e : Enum<T> ) : Array<T>

+ 163 - 89
std/cs/_std/haxe/Int64.hx

@@ -21,124 +21,198 @@
  */
 package haxe;
 using haxe.Int64;
-import cs.StdTypes.Int64 in NativeInt64;
-import cs.StdTypes.UInt64 in NativeUInt64;
+
+private typedef __Int64 = cs.StdTypes.Int64;
 
 @:coreApi
-@:nativeGen class Int64
+abstract Int64(__Int64) from __Int64 to __Int64
 {
-	@:extern private static inline function asNative(i:Int64):NativeInt64 return untyped i;
-	@:extern private static inline function ofNative(i:NativeInt64):Int64 return untyped i;
-	@:extern private static inline function ofUNative(i:NativeUInt64):Int64 return untyped i;
-	@:extern private static inline function mkNative(i:Int):NativeInt64 return cast i;
 
-	public static inline function make( high : Int, low : Int ) : Int64
-	{
-		return ((cast(high, NativeInt64) << 32 ) | (low & untyped __cs__('0xffffffffL'))).ofNative();
-	}
+	public static inline function make( high : Int32, low : Int32 ) : Int64
+		return new Int64( (cast(high, __Int64) << 32) | (cast(low, __Int64)& untyped __cs__('0xffffffffL')) );
 
-	public static inline function getLow( x : Int64 ) : Int
-	{
-		return cast (x.asNative() & (untyped __cs__("0xFFFFFFFFL")), Int);
-	}
+	private inline function new(x : __Int64)
+		this = x;
 
-	public static inline function getHigh( x : Int64 ) : Int {
-		return cast(cast(x,NativeUInt64) >> 32, Int);
-	}
+	private var val( get, set ) : __Int64;
+	inline function get_val() : __Int64 return this;
+	inline function set_val( x : __Int64 ) : __Int64 return this = x;
 
-	public static inline function ofInt( x : Int ) : Int64 {
-		return cast x;
-	}
+	public var high( get, never ):Int32;
+	public inline function get_high():Int32 return cast(this >> 32);
 
-	public static inline function toInt( x : Int64 ) : Int
-	{
+	public var low( get, never ):Int32;
+	public inline function get_low():Int32 return cast this;
+
+	public inline function copy():Int64
+		return new Int64( this );
+
+	@:from public static inline function ofInt( x : Int ) : Int64
 		return cast x;
-	}
 
-	public static inline function add( a : Int64, b : Int64 ) : Int64
-	{
-		return (a.asNative() + b.asNative()).ofNative();
+	public static inline function toInt( x : Int64 ) : Int {
+		if( x.val < 0x80000000 || x.val > 0x7FFFFFFF )
+			throw "Overflow";
+		return cast x.val;
 	}
 
-	public static inline function sub( a : Int64, b : Int64 ) : Int64
-	{
-		return (a.asNative() - b.asNative()).ofNative();
-	}
+	inline public static function is( val : Dynamic ) : Bool
+		return Std.is(val,cs.system.Int64);
 
-	public static inline function mul( a : Int64, b : Int64 ) : Int64 {
-		return (a.asNative() * b.asNative()).ofNative();
-	}
+	public static inline function getHigh( x : Int64 ) : Int32
+		return cast( x.val >> 32 );
+
+	public static inline function getLow( x : Int64 ) : Int32
+		return cast( x.val );
+
+	public static inline function isNeg( x : Int64 ) : Bool
+		return x.val < 0;
+
+	public static inline function isZero( x : Int64 ) : Bool
+		return x.val == 0;
 
-	static function divMod( modulus : Int64, divisor : Int64 ) : { quotient : Int64, modulus : Int64 }
+	public static inline function compare( a : Int64, b : Int64 ) : Int
 	{
-		var q:Int64 = (modulus.asNative() / divisor.asNative()).ofNative();
-		var m:Int64 = (modulus.asNative() % divisor.asNative()).ofNative();
-		return { quotient : q, modulus : m };
+		if( a.val < b.val ) return -1;
+		if( a.val > b.val ) return 1;
+		return 0;
 	}
 
-	public static inline function div( a : Int64, b : Int64 ) : Int64 {
-		return (a.asNative() / b.asNative()).ofNative();
+	public static inline function ucompare( a : Int64, b : Int64 ) : Int {
+		if( a.val < 0 )
+			return ( b.val < 0 ) ? compare( a, b ) : 1;
+		return ( b.val < 0 ) ? -1 : compare( a, b );
 	}
 
-	public static inline function mod( a : Int64, b : Int64 ) : Int64 {
-		return (a.asNative() % b.asNative()).ofNative();
-	}
+	public static inline function toStr( x : Int64 ) : String
+		return '${x.val}';
 
-	public static inline function shl( a : Int64, b : Int ) : Int64 {
-		return (a.asNative() << b).ofNative();
-	}
+	public static inline function divMod( dividend : Int64, divisor : Int64 ) : { quotient : Int64, modulus : Int64 }
+		return { quotient: dividend / divisor, modulus: dividend % divisor };
 
-	public static inline function shr( a : Int64, b : Int ) : Int64 {
-		return (a.asNative() >> b).ofNative();
-	}
+	private inline function toString() : String
+		return '$this';
 
-	public static inline function ushr( a : Int64, b : Int ) : Int64 {
-		return cast(cast(a, NativeUInt64) >> b, NativeInt64).ofNative();
-	}
+	@:op(-A) public static function neg( x : Int64 ) : Int64
+		return -x.val;
 
-	public static inline function and( a : Int64, b : Int64 ) : Int64
-	{
-		return (a.asNative() & b.asNative()).ofNative();
-	}
+	@:op(++A) private inline function preIncrement() : Int64
+		return ++this;
 
-	public static inline function or( a : Int64, b : Int64 ) : Int64
-	{
-		return (a.asNative() | b.asNative()).ofNative();
-	}
+	@:op(A++) private inline function postIncrement() : Int64
+		return this++;
 
-	public static inline function xor( a : Int64, b : Int64 ) : Int64
-	{
-		return (a.asNative() ^ b.asNative()).ofNative();
-	}
+	@:op(--A) private inline function preDecrement() : Int64
+		return --this;
 
-	public static inline function neg( a : Int64 ) : Int64
-	{
-		return (-(a.asNative())).ofNative();
-	}
+	@:op(A--) private inline function postDecrement() : Int64
+		return this--;
 
-	public static inline function isNeg( a : Int64 ) : Bool
-	{
-		return (a.asNative() < 0.mkNative());
-	}
+	@:op(A + B) public static inline function add( a : Int64, b : Int64 ) : Int64
+		return a.val + b.val;
 
-	public static inline function isZero( a : Int64 ) : Bool
-	{
-		return (a.asNative() == 0.mkNative());
-	}
+	@:op(A + B) @:commutative private static inline function addInt( a : Int64, b : Int ) : Int64
+		return a.val + b;
 
-	public static inline function compare( a : Int64, b : Int64 ) : Int
-	{
-		return (a.asNative() < b.asNative()) ? -1 : (a.asNative() > b.asNative()) ? 1 : 0;
-	}
+	@:op(A - B) public static inline function sub( a : Int64, b : Int64 ) : Int64
+		return a.val - b.val;
 
-	public static function ucompare( a : Int64, b : Int64 ) : Int
-	{
-		var a:NativeUInt64 = cast a,
-				b:NativeUInt64 = cast b;
-		return (a < b) ? -1 : (a > b) ? 1 : 0;
-	}
+	@:op(A - B) private static inline function subInt( a : Int64, b : Int ) : Int64
+		return a.val - b;
 
-	public static inline function toStr( a : Int64 ) : String {
-		return a + "";
-	}
+	@:op(A - B) private static inline function intSub( a : Int, b : Int64 ) : Int64
+		return a - b.val;
+
+	@:op(A * B) public static inline function mul( a : Int64, b : Int64 ) : Int64
+		return a.val * b.val;
+
+	@:op(A * B) @:commutative private static inline function mulInt( a : Int64, b : Int ) : Int64
+		return a.val * b;
+
+	@:op(A / B) public static inline function div( a : Int64, b : Int64 ) : Int64
+		return a.val / b.val;
+
+	@:op(A / B) private static inline function divInt( a : Int64, b : Int ) : Int64
+		return a.val / b;
+
+	@:op(A / B) private static inline function intDiv( a : Int, b : Int64 ) : Int64
+		return a / b.val;
+
+	@:op(A % B) public static inline function mod( a : Int64, b : Int64 ) : Int64
+		return a.val % b.val;
+
+	@:op(A % B) private static inline function modInt( a : Int64, b : Int ) : Int64
+		return a.val % b;
+
+	@:op(A % B) private static inline function intMod( a : Int, b : Int64 ) : Int64
+		return a % b.val;
+
+	@:op(A == B) public static inline function eq( a : Int64, b : Int64 ) : Bool
+		return a.val == b.val;
+
+	@:op(A == B) @:commutative private static inline function eqInt( a : Int64, b : Int ) : Bool
+		return a.val == b;
+
+	@:op(A != B) public static inline function neq( a : Int64, b : Int64 ) : Bool
+		return a.val != b.val;
+
+	@:op(A != B) @:commutative private static inline function neqInt( a : Int64, b : Int ) : Bool
+		return a.val != b;
+
+	@:op(A < B) private static inline function lt( a : Int64, b : Int64 ) : Bool
+		return a.val < b.val;
+
+	@:op(A < B) private static inline function ltInt( a : Int64, b : Int ) : Bool
+		return a.val < b;
+
+	@:op(A < B) private static inline function intLt( a : Int, b : Int64 ) : Bool
+		return a < b.val;
+
+	@:op(A <= B) private static inline function lte( a : Int64, b : Int64 ) : Bool
+		return a.val <= b.val;
+
+	@:op(A <= B) private static inline function lteInt( a : Int64, b : Int ) : Bool
+		return a.val <= b;
+
+	@:op(A <= B) private static inline function intLte( a : Int, b : Int64 ) : Bool
+		return a <= b.val;
+
+	@:op(A > B) private static inline function gt( a : Int64, b : Int64 ) : Bool
+		return a.val > b.val;
+
+	@:op(A > B) private static inline function gtInt( a : Int64, b : Int ) : Bool
+		return a.val > b;
+
+	@:op(A > B) private static inline function intGt( a : Int, b : Int64 ) : Bool
+		return a > b.val;
+
+	@:op(A >= B) private static inline function gte( a : Int64, b : Int64 ) : Bool
+		return a.val >= b.val;
+
+	@:op(A >= B) private static inline function gteInt( a : Int64, b : Int ) : Bool
+		return a.val >= b;
+
+	@:op(A >= B) private static inline function intGte( a : Int, b : Int64 ) : Bool
+		return a >= b.val;
+
+	@:op(~A) private static inline function complement( x : Int64 ) : Int64
+		return ~x.val;
+
+	@:op(A & B) public static inline function and( a : Int64, b : Int64 ) : Int64
+		return a.val & b.val;
+
+	@:op(A | B) public static inline function or( a : Int64, b : Int64 ) : Int64
+		return a.val | b.val;
+
+	@:op(A ^ B) public static inline function xor( a : Int64, b : Int64 ) : Int64
+		return a.val ^ b.val;
+
+	@:op(A << B) public static inline function shl( a : Int64, b : Int ) : Int64
+		return a.val << b;
+
+	@:op(A >> B) public static inline function shr( a : Int64, b : Int ) : Int64
+		return a.val >> b;
+
+	@:op(A >>> B) public static inline function ushr( a : Int64, b : Int ) : Int64
+		return cast ( (a.val : cs.StdTypes.UInt64) >> b );
 }

+ 4 - 0
std/cs/_std/haxe/Resource.hx

@@ -44,7 +44,9 @@ package haxe;
 		return content.copy();
 	}
 
+	@:access(haxe.io.Path.escape)
 	public static function getString( name : String ) : String {
+		name = haxe.io.Path.escape(name, true);
 		var path = getPaths().get(name);
 		var str = cs.Lib.toNativeType(haxe.Resource).Assembly.GetManifestResourceStream(path);
 		if (str != null)
@@ -52,7 +54,9 @@ package haxe;
 		return null;
 	}
 
+	@:access(haxe.io.Path.escape)
 	public static function getBytes( name : String ) : haxe.io.Bytes {
+		name = haxe.io.Path.escape(name, true);
 		var path = getPaths().get(name);
 		var str = cs.Lib.toNativeType(haxe.Resource).Assembly.GetManifestResourceStream(path);
 		if (str != null)

+ 9 - 2
std/cs/_std/haxe/ds/IntMap.hx

@@ -76,14 +76,17 @@ import cs.NativeArray;
 			var k = hash(key);
 			var i = k & mask;
 
+			var delKey = -1;
 			//for speed up
 			if (flagIsEmpty(flags, i)) {
 				x = i;
 			} else {
 				var inc = getInc(k, mask);
 				var last = i;
-				while (! (isEither(flags, i) || _keys[i] == key) )
+				while (! (flagIsEmpty(flags, i) || _keys[i] == key) )
 				{
+					if (delKey == -1 && flagIsDel(flags,i))
+						delKey = i;
 					i = (i + inc) & mask;
 #if DEBUG_HASHTBL
 					if (i == last)
@@ -92,7 +95,11 @@ import cs.NativeArray;
 					}
 #end
 				}
-				x = i;
+
+				if (flagIsEmpty(flags,i) && delKey != -1)
+					x = delKey;
+				else
+					x = i;
 			}
 		}
 

+ 10 - 3
std/cs/_std/haxe/ds/ObjectMap.hx

@@ -83,14 +83,17 @@ import cs.NativeArray;
 			k = hash(key);
 			var i = k & mask, nProbes = 0;
 
+			var delKey = -1;
 			//for speed up
-			if (isEither(hashes[i])) {
+			if (isEmpty(hashes[i])) {
 				x = i;
 			} else {
 				//var inc = getInc(k, mask);
 				var last = i, flag;
-				while(! (isEither(flag = hashes[i]) || (flag == k && _keys[i] == key)) )
+				while(! (isEmpty(flag = hashes[i]) || (flag == k && _keys[i] == key)) )
 				{
+					if (isDel(flag) && delKey == -1)
+						delKey = i;
 					i = (i + ++nProbes) & mask;
 #if DEBUG_HASHTBL
 					probeTimes++;
@@ -98,7 +101,11 @@ import cs.NativeArray;
 						throw "assert";
 #end
 				}
-				x = i;
+
+				if (isEmpty(flag) && delKey != -1)
+					x = delKey;
+				else
+					x = i;
 			}
 
 #if DEBUG_HASHTBL

+ 10 - 4
std/cs/_std/haxe/ds/StringMap.hx

@@ -83,14 +83,16 @@ import cs.NativeArray;
 			k = hash(key);
 			var i = k & mask, nProbes = 0;
 
+			var delKey = -1;
 			//for speed up
-			if (isEither(hashes[i])) {
+			if (isEmpty(hashes[i])) {
 				x = i;
 			} else {
-				//var inc = getInc(k, mask);
 				var last = i, flag;
-				while(! (isEither(flag = hashes[i]) || (flag == k && _keys[i] == key)) )
+				while(! (isEmpty(flag = hashes[i]) || (flag == k && _keys[i] == key)) )
 				{
+					if (isDel(flag) && delKey == -1)
+						delKey = i;
 					i = (i + ++nProbes) & mask;
 #if DEBUG_HASHTBL
 					probeTimes++;
@@ -98,7 +100,11 @@ import cs.NativeArray;
 						throw "assert";
 #end
 				}
-				x = i;
+
+				if (isEmpty(flag) && delKey != -1)
+					x = delKey;
+				else
+					x = i;
 			}
 
 #if DEBUG_HASHTBL

+ 17 - 10
std/cs/_std/haxe/ds/WeakMap.hx → std/cs/_std/haxe/ds/WeakMap.hx2

@@ -101,32 +101,39 @@ import cs.system.WeakReference;
 			var i = k & mask, nProbes = 0;
 
 			//for speed up
-			if (isEither(hashes[i])) {
+			var delKey = -1;
+			if (isEmpty(hashes[i])) {
 				x = i;
 			} else {
 				//var inc = getInc(k, mask);
 				var last = i, flag;
-				while(! (isEither(flag = hashes[i]) || (flag == k && entries[i].keyEquals(key) )) )
+				while(! (isEmpty(flag = hashes[i]) || (flag == k && entries[i].keyEquals(key) )) )
 				{
+					if (delKey == -1 && isDel(flag))
+						delKey = i;
+
 					var entry = entries[i];
 					if (entry.Target == null)
 					{
-						entry.reuse(key,k);
-						hashes[i] = k;
-						break;
+						hashes[i] = FLAG_DEL;
+						entries[i] = null;
+						--size;
+						if (delKey == -1)
+							delKey = i;
 					}
+
 					i = (i + ++nProbes) & mask;
-					if (i == last)
-					{
-						//all
-					}
 #if DEBUG_HASHTBL
 					probeTimes++;
 					if (i == last)
 						throw "assert";
 #end
 				}
-				x = i;
+
+				if (isEmpty(flag) && delKey != -1)
+					x = delKey;
+				else
+					x = i;
 			}
 
 #if DEBUG_HASHTBL

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

@@ -82,7 +82,7 @@ class FileSystem {
 		return new FileInfo(relPath).FullName;
 	}
 
-	public static function absPath ( relPath : String ) : String {
+	public static function absolutePath ( relPath : String ) : String {
 		if (haxe.io.Path.isAbsolute(relPath)) return relPath;
 		return haxe.io.Path.join([Sys.getCwd(), relPath]);
 	}

+ 4 - 4
std/cs/_std/sys/io/File.hx

@@ -56,7 +56,7 @@ class File {
 
 	public static function read( path : String, binary : Bool = true ) : FileInput
 	{
-		#if std-buffer //standardize 4kb buffers
+		#if std_buffer //standardize 4kb buffers
 		var stream = new cs.system.io.FileStream(path, Open, Read, ReadWrite, 4096);
 		#else
 		var stream = new cs.system.io.FileStream(path, Open, Read, ReadWrite);
@@ -66,7 +66,7 @@ class File {
 
 	public static function write( path : String, binary : Bool = true ) : FileOutput
 	{
-		#if std-buffer //standardize 4kb buffers
+		#if std_buffer //standardize 4kb buffers
 		var stream = new cs.system.io.FileStream(path, Create, Write, ReadWrite, 4096);
 		#else
 		var stream = new cs.system.io.FileStream(path, Create, Write, ReadWrite);
@@ -76,7 +76,7 @@ class File {
 
 	public static function append( path : String, binary : Bool = true ) : FileOutput
 	{
-		#if std-buffer //standardize 4kb buffers
+		#if std_buffer //standardize 4kb buffers
 		var stream = new cs.system.io.FileStream(path, Append, Write, ReadWrite, 4096);
 		#else
 		var stream = new cs.system.io.FileStream(path, Append, Write, ReadWrite);
@@ -88,4 +88,4 @@ class File {
 	{
 		cs.system.io.File.Copy(srcPath, dstPath);
 	}
-}
+}

+ 217 - 12
std/cs/internal/FieldLookup.hx

@@ -23,11 +23,82 @@ package cs.internal;
 
 @:native('haxe.lang.FieldLookup')
 @:final @:nativeGen
-@:keep @:static private class FieldLookup
+@:classCode("#pragma warning disable 628\n")
+@:keep @:static class FieldLookup
 {
+	@:protected private static var fieldIds:cs.NativeArray<Int>;
+	@:protected private static var fields:cs.NativeArray<String>;
+	@:protected private static var length:Int;
 
-	@:private private static var fieldIds:Array<Int>;
-	@:private private static var fields:Array<String>;
+	static function __init__()
+	{
+		length = fieldIds.Length;
+	}
+
+	private static function addFields(nids:cs.NativeArray<Int>, nfields:cs.NativeArray<String>):Void
+	{
+		// first see if we need to add anything
+		var cids = fieldIds,
+		    cfields = fields;
+		var nlen = nids.Length;
+		var clen = length;
+		if (nfields.Length != nlen) throw 'Different fields length: $nlen and ${nfields.Length}';
+
+		//TODO optimize
+		var needsChange = false;
+		for (i in nids)
+		{
+			if (findHash(i, cids, clen) < 0)
+			{
+				needsChange = true;
+				break;
+			}
+		}
+
+		// if we do, lock and merge
+		if (needsChange)
+		{
+			cs.Lib.lock(FieldLookup, {
+				// trace(cs.Lib.array(nids), cs.Lib.array(cids));
+				var ansIds = new cs.NativeArray(clen + nlen),
+				    ansFields = new cs.NativeArray(clen + nlen);
+				var ci = 0, ni = 0, ansi = 0;
+				while (ci < clen && ni < nlen)
+				{
+					if (cids[ci] < nids[ni])
+					{
+						ansIds[ansi] = cids[ci];
+						ansFields[ansi] = cfields[ci];
+						++ci;
+					} else {
+						ansIds[ansi] = nids[ni];
+						ansFields[ansi] = nfields[ni];
+						++ni;
+					}
+					++ansi;
+				}
+
+				if (ci < clen)
+				{
+					cs.system.Array.Copy(cids, ci, ansIds, ansi, clen - ci);
+					cs.system.Array.Copy(cfields, ci, ansFields, ansi, clen - ci);
+					ansi += clen - ci;
+				}
+
+				if (ni < nlen)
+				{
+					cs.system.Array.Copy(nids, ni, ansIds, ansi, nlen - ni);
+					cs.system.Array.Copy(nfields, ni, ansFields, ansi, nlen - ni);
+					ansi += nlen - ni;
+				}
+
+				// trace(cs.Lib.array(ansIds));
+				fieldIds = ansIds;
+				fields = ansFields;
+				length = ansi;
+			});
+		}
+	}
 
 	//s cannot be null here
 	private static inline function doHash(s:String):Int
@@ -46,7 +117,7 @@ package cs.internal;
 		//start of binary search algorithm
 		var ids = fieldIds;
 		var min = 0;
-		var max = ids.length;
+		var max = length;
 
 		while (min < max)
 		{
@@ -72,9 +143,12 @@ package cs.internal;
 		var key = doHash(s);
 
 		//start of binary search algorithm
-		var ids = fieldIds;
+		var ids = fieldIds,
+		    fld = fields;
 		var min = 0;
-		var max = ids.length;
+		var max = length;
+
+		var len = length;
 
 		while (min < max)
 		{
@@ -86,22 +160,37 @@ package cs.internal;
 			} else if (key > imid) {
 				min = mid + 1;
 			} else {
-				var field = fields[mid];
+				var field = fld[mid];
 				if (field != s)
 					return ~key; //special case
 				return key;
 			}
 		}
+
 		//if not found, min holds the value where we should insert the key
-		ids.insert(min, key);
-		fields.insert(min, s);
+		//ensure thread safety:
+		cs.Lib.lock(FieldLookup, {
+			if (len != length) //race condition which will very rarely happen - other thread modified sooner.
+				return hash(s); //since we already own the lock, this second try will always succeed
+
+#if erase_generics
+			fieldIds = insertInt(fieldIds, length, min, key);
+			fields = insertString(fields, length, min, s);
+#else
+			insert(fieldIds, length, min, key);
+			insert(fields, length, min, s);
+			// ids.insert(min, key);
+			// fields.insert(min, s);
+#end
+			++length;
+		});
 		return key;
 	}
 
-	public static function findHash(hash:Int, hashs:Array<Int>):Int
+	public static function findHash(hash:Int, hashs:cs.NativeArray<Int>, length:Int):Int
 	{
 		var min = 0;
-		var max = hashs.length;
+		var max = length;
 
 		while (min < max)
 		{
@@ -120,4 +209,120 @@ package cs.internal;
 		return ~min;
 	}
 
-}
+	#if !erase_generics
+	static function remove<T>(a:cs.NativeArray<T>, length:Int, pos:Int)
+	{
+		cs.system.Array.Copy(a, pos + 1, a, pos, length - pos - 1);
+		a[length - 1] = null;
+	}
+
+	static function insert<T>(a:cs.Ref<cs.NativeArray<T>>, length:Int, pos:Int, x:T)
+	{
+		var capacity = a.Length;
+		if (pos == length)
+		{
+			if (capacity == length)
+			{
+				var newarr = new NativeArray((length << 1) + 1);
+				a.CopyTo(newarr, 0);
+				a = newarr;
+			}
+		}
+		else if (pos == 0)
+		{
+			if (capacity == length)
+			{
+				var newarr = new NativeArray((length << 1) + 1);
+				cs.system.Array.Copy(a, 0, newarr, 1, length);
+				a = newarr;
+			}
+			else
+			{
+				cs.system.Array.Copy(a, 0, a, 1, length);
+			}
+		}
+		else
+		{
+			if (capacity == length)
+			{
+				var newarr = new NativeArray((length << 1) + 1);
+				cs.system.Array.Copy(a, 0, newarr, 0, pos);
+				cs.system.Array.Copy(a, pos, newarr, pos + 1, length - pos);
+				a = newarr;
+			}
+			else
+			{
+				cs.system.Array.Copy(a, pos, a, pos + 1, length - pos);
+				cs.system.Array.Copy(a, 0, a, 0, pos);
+			}
+		}
+		a[pos] = x;
+	}
+	#else
+	static function removeInt(a:cs.NativeArray<Int>, length:Int, pos:Int)
+	{
+		cs.system.Array.Copy(a, pos + 1, a, pos, length - pos - 1);
+		a[length - 1] = 0;
+	}
+	static function removeFloat(a:cs.NativeArray<Float>, length:Int, pos:Int)
+	{
+		cs.system.Array.Copy(a, pos + 1, a, pos, length - pos - 1);
+		a[length - 1] = 0;
+	}
+	static function removeDynamic(a:cs.NativeArray<Dynamic>, length:Int, pos:Int)
+	{
+		cs.system.Array.Copy(a, pos + 1, a, pos, length - pos - 1);
+		a[length - 1] = null;
+	}
+
+	@:extern
+	static inline function __insert<T>(a:cs.NativeArray<T>, length:Int, pos:Int, x:T):cs.NativeArray<T>
+	{
+		var capacity = a.Length;
+		if (pos == length)
+		{
+			if (capacity == length)
+			{
+				var newarr = new NativeArray((length << 1) + 1);
+				a.CopyTo(newarr, 0);
+				a = newarr;
+			}
+		}
+		else if (pos == 0)
+		{
+			if (capacity == length)
+			{
+				var newarr = new NativeArray((length << 1) + 1);
+				cs.system.Array.Copy(a, 0, newarr, 1, length);
+				a = newarr;
+			}
+			else
+			{
+				cs.system.Array.Copy(a, 0, a, 1, length);
+			}
+		}
+		else
+		{
+			if (capacity == length)
+			{
+				var newarr = new NativeArray((length << 1) + 1);
+				cs.system.Array.Copy(a, 0, newarr, 0, pos);
+				cs.system.Array.Copy(a, pos, newarr, pos + 1, length - pos);
+				a = newarr;
+			}
+			else
+			{
+				cs.system.Array.Copy(a, pos, a, pos + 1, length - pos);
+				cs.system.Array.Copy(a, 0, a, 0, pos);
+			}
+		}
+		a[pos] = x;
+		return a;
+	}
+
+	static function insertInt(a:cs.NativeArray<Int>, length:Int, pos:Int, x:Int):cs.NativeArray<Int> return __insert(a, length, pos, x);
+	static function insertFloat(a:cs.NativeArray<Float>, length:Int, pos:Int, x:Float):cs.NativeArray<Float> return __insert(a, length, pos, x);
+	static function insertDynamic(a:cs.NativeArray<Dynamic>, length:Int, pos:Int, x:Dynamic):cs.NativeArray<Dynamic> return __insert(a, length, pos, x);
+	static function insertString(a:cs.NativeArray<String>, length:Int, pos:Int, x:Dynamic):cs.NativeArray<String> return __insert(a, length, pos, x);
+	#end
+}

+ 16 - 2
std/cs/internal/Function.hx

@@ -27,7 +27,7 @@ package cs.internal;
  in modules (untested).
 **/
 
-@:keep @:abstract @:nativeGen @:native("haxe.lang.Function") private class Function
+@:keep @:abstract @:nativeGen @:native("haxe.lang.Function") class Function
 {
 	function new(arity:Int, type:Int)
 	{
@@ -77,4 +77,18 @@ package cs.internal;
 	{
 		return Runtime.callField(obj, field, hash, dynArgs);
 	}
-}
+
+	public function Equals(obj:Dynamic):Bool
+	{
+		if (obj == null)
+			return false;
+
+		var c:Closure = cast obj;
+		return (c.obj == this.obj && c.field == this.field);
+	}
+
+	public function GetHashCode():Int
+	{
+		return obj.GetHashCode() ^ untyped field.GetHashCode();
+	}
+}

+ 55 - 15
std/cs/internal/HxObject.hx

@@ -21,15 +21,16 @@
  */
 package cs.internal;
 import cs.system.Type;
+import haxe.ds.Vector;
 private typedef StdType = std.Type;
 
 @:keep @:native('haxe.lang.HxObject')
-private class HxObject implements IHxObject
+class HxObject implements IHxObject
 {
 }
 
 @:keep @:native('haxe.lang.IHxObject')
-private interface IHxObject
+interface IHxObject
 {
 }
 
@@ -37,7 +38,7 @@ private interface IHxObject
 @:meta(System.Serializable)
 #end
 @:keep @:native('haxe.lang.DynamicObject')
-private class DynamicObject extends HxObject implements Dynamic
+class DynamicObject extends HxObject implements Dynamic
 {
 	@:skipReflection public function toString():String
 	{
@@ -63,31 +64,69 @@ private class DynamicObject extends HxObject implements Dynamic
 	}
 }
 
+#if !erase_generics
 @:keep @:native('haxe.lang.IGenericObject') interface IGenericObject
 {
 }
 
-@:native('haxe.lang.Enum')
-@:keep @:skipCtor
+@:nativeGen @:keep @:native('haxe.lang.GenericInterface') class GenericInterface extends cs.system.Attribute
+{
+	@:readOnly public var generic(default,never):cs.system.Type;
+
+	public function new(generic)
+	{
+		super();
+		untyped this.generic = generic;
+	}
+}
+#end
+
+@:keep @:native('haxe.lang.Enum') @:nativeGen
 #if core_api_serialize
 @:meta(System.Serializable)
 #end
-private class Enum
+class HxEnum
 {
 	@:readOnly private var index(default,never):Int;
-	@:readOnly private var params(default,never):Array<{}>;
 
-	public function new(index:Int, params:Array<{}>)
+	public function new(index:Int)
 	{
 		untyped this.index = index;
-		untyped this.params = params;
 	}
-	@:final public function getTag():String
+
+	public function getTag():String
 	{
-		var cl:Dynamic = StdType.getClass(this);
-		return cl.constructs[index];
+		return throw 'Not Implemented';
 	}
+
+	public function getParams():Array<{}>
+	{
+		return [];
+	}
+
 	public function toString():String
+	{
+		return getTag();
+	}
+}
+
+@:keep @:native('haxe.lang.ParamEnum') @:nativeGen
+private class ParamEnum extends HxEnum
+{
+	@:readOnly private var params(default,never):Vector<Dynamic>;
+
+	public function new(index:Int, params:Vector<Dynamic>)
+	{
+		super(index);
+		untyped this.params = params;
+	}
+
+	override public function getParams():Array<{}>
+	{
+		return params == null ? [] : cs.Lib.array(cast params.toData());
+	}
+
+	override public function toString():String
 	{
 		if (params == null || params.length == 0) return getTag();
 		var ret = new StringBuf();
@@ -104,11 +143,12 @@ private class Enum
 		ret.add(")");
 		return ret.toString();
 	}
+
 	public function Equals(obj:Dynamic)
 	{
 		if (obj == this) //we cannot use == as .Equals !
 			return true;
-		var obj:Enum = cast obj;
+		var obj:ParamEnum = Std.instance(obj, ParamEnum);
 		var ret = obj != null && Std.is(obj, StdType.getClass(this)) && obj.index == this.index;
 		if (!ret)
 			return false;
@@ -127,12 +167,12 @@ private class Enum
 
 	public function GetHashCode():Int
 	{
-		var h = 19;
+		var h:Int = 19;
 		if (params != null) for (p in params)
 		{
 			h = h * 31;
 			if (p != null)
-				h += untyped p.GetHashCode();
+				untyped h += p.GetHashCode();
 		}
 		h += index;
 		return h;

+ 317 - 198
std/cs/internal/Runtime.hx

@@ -29,6 +29,7 @@ import cs.system.IConvertible;
 import cs.system.IComparable;
 import cs.system.reflection.MethodBase;
 import cs.system.reflection.MethodInfo;
+import cs.system.reflection.*;
 import cs.system.Type;
 import cs.system.Object;
 
@@ -70,14 +71,11 @@ import cs.system.Object;
 ')
 @:keep class Runtime
 {
-	public static var undefined(default, never):Dynamic = { };
+	@:readOnly public static var undefined(default, never):Dynamic = new cs.system.Object();
 
-	@:functionCode('
-		return new haxe.lang.Closure(obj, field, hash);
-	')
 	public static function closure(obj:Dynamic, hash:Int, field:String):Dynamic
 	{
-		return null;
+		return new cs.internal.Function.Closure(obj, field, hash);
 	}
 
 	public static function eq(v1:Dynamic, v2:Dynamic):Bool
@@ -104,28 +102,16 @@ import cs.system.Object;
 			if (t1 == cs.system.TypeCode.String || t2 == cs.system.TypeCode.String)
 				return false;
 
-			switch(t1)
+			switch [t1,t2]
 			{
-				case Decimal:
+				case [Decimal, _] | [_, Decimal]:
 					return v1c.ToDecimal(null) == v2c.ToDecimal(null);
-				case UInt64 | Int64:
-					if (t2 == Decimal)
-						return v1c.ToDecimal(null) == v2c.ToDecimal(null);
-					else
-						return v1c.ToUInt64(null) == v2c.ToUInt64(null);
-				default:
-					switch(t2)
-					{
-						case Decimal:
-							return v1c.ToDecimal(null) == v2c.ToDecimal(null);
-						case UInt64 | Int64:
-							if (t2 == Decimal)
-								return v1c.ToDecimal(null) == v2c.ToDecimal(null);
-							else
-								return v1c.ToUInt64(null) == v2c.ToUInt64(null);
-						default:
-							return v1c.ToDouble(null) == v2c.ToDouble(null);
-					}
+				case [UInt64 | Int64 | DateTime, _] | [_, UInt64 | Int64 | DateTime]:
+					return v1c.ToUInt64(null) == v2c.ToUInt64(null);
+				case [Double | Single, _] | [_, Double | Single]:
+					return v1c.ToDouble(null) == v2c.ToDouble(null);
+				case _:
+					return v1c.ToInt32(null) == v2c.ToInt32(null);
 			}
 		}
 
@@ -133,6 +119,7 @@ import cs.system.Object;
 		if (v1v != null)
 		{
 			return v1.Equals(v2);
+#if !erase_generics
 		} else {
 			var v1t = Lib.as(v1, Type);
 			if (v1t != null)
@@ -142,6 +129,7 @@ import cs.system.Object;
 					return typeEq(v1t, v2t);
 				return false;
 			}
+#end
 		}
 
 		return false;
@@ -149,8 +137,10 @@ import cs.system.Object;
 
 	public static function refEq(v1: { }, v2: { } ):Bool
 	{
+#if !erase_generics
 		if (Std.is(v1, Type))
 			return typeEq(Lib.as(v1,Type), Lib.as(v2,Type));
+#end
 		return Object.ReferenceEquals(v1,v2);
 	}
 
@@ -216,14 +206,14 @@ import cs.system.Object;
 
 			if (cv2 == null)
 			{
-				throw new cs.system.ArgumentException("Cannot compare " + nativeType(v1).ToString() + " and " + nativeType(v2).ToString());
+				throw new cs.system.ArgumentException("Cannot compare " + getNativeType(v1).ToString() + " and " + getNativeType(v2).ToString());
 			}
 
 			switch(cv1.GetTypeCode())
 			{
 				case cs.system.TypeCode.String:
 					if (cv2.GetTypeCode() != cs.system.TypeCode.String)
-						throw new cs.system.ArgumentException("Cannot compare " + nativeType(v1).ToString() + " and " + nativeType(v2).ToString());
+						throw new cs.system.ArgumentException("Cannot compare " + getNativeType(v1).ToString() + " and " + getNativeType(v2).ToString());
 					var s1 = Lib.as(v1,String);
 					var s2 = Lib.as(v2,String);
 					return String.Compare(s1,s2, cs.system.StringComparison.Ordinal);
@@ -243,7 +233,7 @@ import cs.system.Object;
 
 		if (c1 == null || c2 == null)
 		{
-			throw new cs.system.ArgumentException("Cannot compare " + nativeType(v1).ToString() + " and " + nativeType(v2).ToString());
+			throw new cs.system.ArgumentException("Cannot compare " + getNativeType(v1).ToString() + " and " + getNativeType(v2).ToString());
 		}
 
 		return c1.CompareTo(c2);
@@ -254,13 +244,19 @@ import cs.system.Object;
 		if (Std.is(v1,String) || Std.is(v2,String))
 			return Std.string(v1) + Std.string(v2);
 
+		if (v1 == null)
+		{
+			if (v2 == null) return null;
+			v1 = 0;
+		} else if (v2 == null) v2 = 0;
+
 		var cv1 = Lib.as(v1, IConvertible);
 		if (cv1 != null)
 		{
 			var cv2 = Lib.as(v2, IConvertible);
 			if (cv2 == null)
 			{
-				throw new cs.system.ArgumentException("Cannot dynamically add " + cs.Lib.nativeType(v1).ToString() + " and " + cs.Lib.nativeType(v2).ToString());
+				throw new cs.system.ArgumentException("Cannot dynamically add " + cs.Lib.getNativeType(v1).ToString() + " and " + cs.Lib.getNativeType(v2).ToString());
 			}
 			return cv1.ToDouble(null) + cv2.ToDouble(null);
 		}
@@ -268,131 +264,160 @@ import cs.system.Object;
 		throw new cs.system.ArgumentException("Cannot dynamically add " + v1 + " and " + v2);
 	}
 
-	@:functionCode('
-
+	public static function slowGetField(obj:Dynamic, field:String, throwErrors:Bool):Dynamic
+	{
 		if (obj == null)
 			if (throwErrors)
-				throw new System.NullReferenceException("Cannot access field \'" + field + "\' of null.");
+				throw new cs.system.NullReferenceException("Cannot access field \'" + field + "\' of null.");
 			else
 				return null;
 
-		System.Type t = obj as System.Type;
-		System.Reflection.BindingFlags bf;
-        if (t == null)
-		{
-			string s = obj as string;
-			if (s != null)
-				return haxe.lang.StringRefl.handleGetField(s, field, throwErrors);
-			t = obj.GetType();
-			bf = System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.FlattenHierarchy;
-		} else {
-			if (t == typeof(string) && field.Equals("fromCharCode"))
-				return new haxe.lang.Closure(typeof(haxe.lang.StringExt), field, 0);
-
-			obj = null;
-			bf = System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.Public;
-		}
+		var t = Lib.as(obj, cs.system.Type);
+		var bf =
+			if (t == null)
+			{
+				var s = Lib.as(obj, String);
+				if (s != null)
+					return cs.internal.StringExt.StringRefl.handleGetField(s, field, throwErrors);
+				t = obj.GetType();
+				new cs.Flags(BindingFlags.Instance) | BindingFlags.Public | BindingFlags.FlattenHierarchy;
+			} else {
+				if (t == Lib.toNativeType(String) && field == "fromCharCode")
+					return new cs.internal.Function.Closure(StringExt, field, 0);
+
+				obj = null;
+				new cs.Flags(BindingFlags.Static) | BindingFlags.Public;
+			}
 
-		System.Reflection.FieldInfo f = t.GetField(field, bf);
+		var f = t.GetField(field, bf);
 		if (f != null)
 		{
-			return haxe.lang.Runtime.unbox(f.GetValue(obj));
-		} else {
-			System.Reflection.PropertyInfo prop = t.GetProperty(field, bf);
+			return unbox(f.GetValue(obj));
+		}
+		else
+		{
+			var prop = t.GetProperty(field, bf);
 			if (prop == null)
 			{
-				System.Reflection.MemberInfo[] m = t.GetMember(field, bf);
+				var m = t.GetMember(field, bf);
+				if (m.length == 0 && (field == "__get" || field == "__set"))
+					m = t.GetMember(field == "__get" ? "get_Item" : "set_Item", bf);
+
 				if (m.Length > 0)
 				{
-					return new haxe.lang.Closure(obj != null ? obj : t, field, 0);
-				} else {
+					return new cs.internal.Function.Closure(obj != null ? obj : t, field, 0);
+				}
+				else
+				{
+					// COM object handling
+					if (t.IsCOMObject)
+					{
+						try
+						{
+							return t.InvokeMember(field, BindingFlags.GetProperty, null, obj, new cs.NativeArray(0));
+						}
+						catch (e:cs.system.Exception)
+						{
+							//Closures of COM objects not supported currently
+						}
+					}
+
 					if (throwErrors)
-						throw HaxeException.wrap("Cannot access field \'" + field + "\'.");
+						throw "Cannot access field \'" + field + "\'.";
 					else
 						return null;
 				}
 			}
-			return haxe.lang.Runtime.unbox(prop.GetValue(obj, null));
+			return unbox(prop.GetValue(obj, null));
 		}
-
-	')
-	public static function slowGetField(obj:Dynamic, field:String, throwErrors:Bool):Dynamic
-	{
-		return null;
 	}
 
-	@:functionCode('
-		if (obj == null) return false;
-		System.Type t = obj as System.Type;
-		System.Reflection.BindingFlags bf;
-        if (t == null)
-		{
-			string s = obj as string;
-			if (s != null)
-				return haxe.lang.StringRefl.handleGetField(s, field, false) != null;
-			t = obj.GetType();
-			bf = System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.FlattenHierarchy;
-		} else {
-			if (t == typeof(string))
-				return field.Equals("fromCharCode");
-			obj = null;
-			bf = System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.Public;
-		}
-
-		System.Reflection.MemberInfo[] mi = t.GetMember(field, bf);
-		return mi != null && mi.Length > 0;
-	')
 	public static function slowHasField(obj:Dynamic, field:String):Bool
 	{
-		return false;
+		if (obj == null) return false;
+		var t = Lib.as(obj, cs.system.Type);
+		var bf =
+			if (t == null) {
+				var s = Lib.as(obj, String);
+				if (s != null)
+					return cs.internal.StringExt.StringRefl.handleGetField(s, field, false) != null;
+				t = obj.GetType();
+				new cs.Flags(BindingFlags.Instance) | BindingFlags.Public | BindingFlags.FlattenHierarchy;
+			} else {
+				if (t == Lib.toNativeType(String))
+					return field == "fromCharCode";
+				obj = null;
+				new cs.Flags(BindingFlags.Static) | BindingFlags.Public;
+			}
+		var mi = t.GetMember(field, bf);
+		return mi != null && mi.length > 0;
 	}
 
-	@:functionCode('
+	public static function slowSetField(obj:Dynamic, field:String, value:Dynamic):Dynamic
+	{
 		if (obj == null)
-			throw new System.NullReferenceException("Cannot access field \'" + field + "\' of null.");
+			throw new cs.system.NullReferenceException("Cannot access field \'" + field + "\' of null.");
 
-		System.Type t = obj as System.Type;
-		System.Reflection.BindingFlags bf;
-        if (t == null)
-		{
-			t = obj.GetType();
-			bf = System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.FlattenHierarchy;
-		} else {
-			obj = null;
-			bf = System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.Public;
-		}
+		var t = Lib.as(obj, cs.system.Type);
+		var bf =
+			if (t == null)
+			{
+				t = obj.GetType();
+				new cs.Flags(BindingFlags.Instance) | BindingFlags.Public | BindingFlags.FlattenHierarchy;
+			} else {
+				obj = null;
+				new cs.Flags(BindingFlags.Static) | BindingFlags.Public;
+			}
 
-		System.Reflection.FieldInfo f = t.GetField(field, bf);
+		var f = t.GetField(field, bf);
 		if (f != null)
 		{
 			if (f.FieldType.ToString().StartsWith("haxe.lang.Null"))
 			{
-				@value = haxe.lang.Runtime.mkNullable(@value, f.FieldType);
+				value = mkNullable(value, f.FieldType);
+			}
+			if (Object.ReferenceEquals(Lib.toNativeType(cs.system.Double), Lib.getNativeType(value)) && !Object.ReferenceEquals(t, f.FieldType))
+			{
+				var ic = Lib.as(value, IConvertible);
+				value = ic.ToType(f.FieldType, null);
 			}
 
-			f.SetValue(obj, @value);
-			return @value;
-		} else {
-			System.Reflection.PropertyInfo prop = t.GetProperty(field, bf);
+			f.SetValue(obj, value);
+			return value;
+		}
+		else
+		{
+			var prop = t.GetProperty(field, bf);
 			if (prop == null)
 			{
-				throw haxe.lang.HaxeException.wrap("Field \'" + field + "\' not found for writing from Class " + t);
+				// COM object handling
+				if (t.IsCOMObject)
+				{
+					try
+					{
+						return t.InvokeMember(field, BindingFlags.SetProperty, null, obj, cs.NativeArray.make(value));
+					}
+					catch (e:cs.system.Exception)
+					{
+						//Closures of COM objects not supported currently
+					}
+				}
+				throw "Field \'" + field + "\' not found for writing from Class " + t;
 			}
 
 			if (prop.PropertyType.ToString().StartsWith("haxe.lang.Null"))
 			{
-				@value = haxe.lang.Runtime.mkNullable(@value, prop.PropertyType);
+				value = mkNullable(value, prop.PropertyType);
+			}
+			if (Object.ReferenceEquals(Lib.toNativeType(cs.system.Double), Lib.getNativeType(value)) && !Object.ReferenceEquals(t, f.FieldType))
+			{
+				var ic = Lib.as(value, IConvertible);
+				value = ic.ToType(f.FieldType, null);
 			}
-			prop.SetValue(obj, @value, null);
+			prop.SetValue(obj, value, null);
 
-			return @value;
+			return value;
 		}
-
-	')
-	public static function slowSetField(obj:Dynamic, field:String, value:Dynamic):Dynamic
-	{
-		//not implemented yet;
-		throw "Not implemented";
 	}
 
 	public static function callMethod(obj:Dynamic, methods:NativeArray<MethodBase>, methodLength:Int, args:Array<Dynamic>):Dynamic
@@ -407,7 +432,7 @@ import cs.system.Object;
 		{
 			oargs[i] = args[i];
 			if (args[i] != null)
-				ts[i] = Lib.nativeType(args[i]);
+				ts[i] = Lib.getNativeType(args[i]);
 		}
 
 		var last = 0;
@@ -487,7 +512,7 @@ import cs.system.Object;
 				if (arg == null) {
 					if (param.IsValueType)
 						oargs[i] = Activator.CreateInstance(param);
-				} else if (!cs.Lib.nativeType(arg).IsAssignableFrom(param)) {
+				} else if (!cs.Lib.getNativeType(arg).IsAssignableFrom(param)) {
 					oargs[i] = cast(arg, IConvertible).ToType(param, null);
 				}
 			}
@@ -519,7 +544,7 @@ import cs.system.Object;
 
 	public static function unbox(dyn:Dynamic):Dynamic
 	{
-		if (dyn != null && untyped (Lib.nativeType(dyn) + "").StartsWith("haxe.lang.Null"))
+		if (dyn != null && untyped (Lib.getNativeType(dyn) + "").StartsWith("haxe.lang.Null"))
 		{
 			return dyn.toDynamic();
 		} else {
@@ -527,6 +552,7 @@ import cs.system.Object;
 		}
 	}
 
+#if !erase_generics
 	@:functionCode('
 		if (nullableType.ContainsGenericParameters)
 			return haxe.lang.Null<object>.ofDynamic<object>(obj);
@@ -536,120 +562,185 @@ import cs.system.Object;
 	{
 		return null;
 	}
-
-	@:functionCode('
-		if (field == "toString")
+#else
+	public static function mkNullable(obj:Dynamic, nullable:Type):Dynamic
+	{
+		return obj; //do nothing
+	}
+#end
+
+	// @:functionCode('
+	// 	if (field == "toString")
+	// 	{
+	// 		if (args == null)
+	// 			return obj.ToString();
+	// 		field = "ToString";
+	// 	}
+	// 	if (args == null) args = new Array<object>();
+
+	// 	System.Reflection.BindingFlags bf;
+	// 	System.Type t = obj as System.Type;
+	// 	if (t == null)
+	// 	{
+	// 		string s = obj as string;
+	// 		if (s != null)
+	// 			return haxe.lang.StringRefl.handleCallField(s, field, args);
+	// 		t = obj.GetType();
+	// 		bf = System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.FlattenHierarchy;
+	// 	} else {
+	// 		if (t == typeof(string) && field.Equals("fromCharCode"))
+	// 			return haxe.lang.StringExt.fromCharCode(toInt(args[0]));
+	// 		obj = null;
+	// 		bf = System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.Public;
+	// 	}
+
+	// 	System.Reflection.MethodInfo[] mis = t.GetMethods(bf);
+	// 	int last = 0;
+	// 	for (int i = 0; i < mis.Length; i++)
+	// 	{
+	// 		string name = mis[i].Name;
+	// 		if (name.Equals(field))
+	// 		{
+	// 			mis[last++] = mis[i];
+	// 		}
+	// 	}
+
+	// 	if (last == 0 && (field == "__get" || field == "__set"))
+	// 	{
+	// 		field = field == "__get" ? "get_Item" : "set_Item";
+	// 		for (int i = 0; i < mis.Length; i++)
+	// 		{
+	// 			string name = mis[i].Name;
+	// 			if (name.Equals(field))
+	// 			{
+	// 				mis[last++] = mis[i];
+	// 			}
+	// 		}
+	// 	}
+
+	// 	if (last == 0 && t.IsCOMObject)
+	// 	{
+	// 		object[] oargs = new object[arrLen(args)];
+	// 		for (int i = 0; i < oargs.Length; i++)
+	// 		{
+	// 			oargs[i] = args[i];
+	// 		}
+	// 		return t.InvokeMember(field, System.Reflection.BindingFlags.InvokeMethod, null, obj, oargs);
+	// 	}
+
+	// 	if (last == 0)
+	// 	{
+	// 		throw haxe.lang.HaxeException.wrap("Method \'" + field + "\' not found on type " + t);
+	// 	}
+
+	// 	return haxe.lang.Runtime.callMethod(obj, mis, last, args);
+	// ')
+	public static function slowCallField(obj:Dynamic, field:String, args:Array<Dynamic>):Dynamic
+	{
+		if (field == "toString" && (args == null || args.length == 0))
 		{
-			if (args == null)
-				return obj.ToString();
-			field = "ToString";
+			return obj.ToString();
 		}
-		if (args == null) args = new Array<object>();
+		if (args == null) args = [];
 
-		System.Reflection.BindingFlags bf;
-		System.Type t = obj as System.Type;
+		var bf:BindingFlags;
+		var t = Lib.as(obj,cs.system.Type);
 		if (t == null)
 		{
-			string s = obj as string;
+			var s = Lib.as(obj,String);
 			if (s != null)
-				return haxe.lang.StringRefl.handleCallField(s, field, args);
-			t = obj.GetType();
-			bf = System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.FlattenHierarchy;
+				return cs.internal.StringExt.StringRefl.handleCallField(untyped s, untyped field, args);
+			t = untyped obj.GetType();
+			bf = new Flags(BindingFlags.Instance) | BindingFlags.Public | BindingFlags.FlattenHierarchy;
 		} else {
-			if (t == typeof(string) && field.Equals("fromCharCode"))
-				return haxe.lang.StringExt.fromCharCode(toInt(args[0]));
+			if (t == Lib.toNativeType(String) && field == 'fromCharCode')
+				return cs.internal.StringExt.fromCharCode(toInt(args[0]));
 			obj = null;
-			bf = System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.Public;
+			bf = new Flags(BindingFlags.Static) | BindingFlags.Public;
 		}
 
-		System.Reflection.MethodInfo[] mis = t.GetMethods(bf);
-		int last = 0;
-		for (int i = 0; i < mis.Length; i++)
+		var mis:NativeArray<MethodBase> = untyped t.GetMethods(bf);
+		var last = 0;
+		for (i in 0...mis.Length)
 		{
-			if (mis[i].Name.Equals(field))
-			{
+			var name = mis[i].Name;
+			if (name == field)
 				mis[last++] = mis[i];
+		}
+
+		if (last == 0 && (field == "__get" || field == "__set"))
+		{
+			field = field == "__get" ? "get_Item" : "set_Item";
+			for (i in 0...mis.Length)
+			{
+				var name = mis[i].Name;
+				if (name == field)
+				{
+					mis[last++] = mis[i];
+				}
+			}
+		}
+
+		if (last == 0 && t.IsCOMObject)
+		{
+			var oargs = new NativeArray(args.length);
+			for (i in 0...oargs.Length)
+			{
+				oargs[i] = args[i];
 			}
+			return t.InvokeMember(field, BindingFlags.InvokeMethod, null, obj, oargs);
 		}
 
 		if (last == 0)
 		{
-			throw haxe.lang.HaxeException.wrap("Method \'" + field + "\' not found on type " + t);
+			throw 'Method "$field" not found on type $t';
 		}
 
-		return haxe.lang.Runtime.callMethod(obj, mis, last, args);
-	')
-	public static function slowCallField(obj:Dynamic, field:String, args:Array<Dynamic>):Dynamic
-	{
-		throw "not implemented";
+		return Runtime.callMethod(obj, mis, last, args);
 	}
 
-	@:functionCode('
-		haxe.lang.HxObject hxObj = obj as haxe.lang.HxObject;
-		if (hxObj != null)
-			return hxObj.__hx_invokeField(field, (fieldHash == 0) ? haxe.lang.FieldLookup.hash(field) : fieldHash, args);
-
-		return slowCallField(obj, field, args);
-	')
 	public static function callField(obj:Dynamic, field:String, fieldHash:Int, args:Array<Dynamic>):Dynamic
 	{
-		return null;
+		var hxObj = Lib.as(obj, HxObject);
+		if (hxObj != null)
+			return untyped hxObj.__hx_invokeField(field, (fieldHash == 0) ? FieldLookup.hash(field) : fieldHash, args);
+		return slowCallField(obj, field, args);
 	}
 
-	@:functionCode('
-
-		haxe.lang.HxObject hxObj = obj as haxe.lang.HxObject;
+	public static function getField(obj:Dynamic, field:String, fieldHash:Int, throwErrors:Bool):Dynamic
+	{
+		var hxObj = Lib.as(obj, HxObject);
 		if (hxObj != null)
-			return hxObj.__hx_getField(field, (fieldHash == 0) ? haxe.lang.FieldLookup.hash(field) : fieldHash, throwErrors, false, false);
+			return untyped hxObj.__hx_getField(field, (fieldHash == 0) ? FieldLookup.hash(field) : fieldHash, throwErrors, false, false);
 
 		return slowGetField(obj, field, throwErrors);
-
-	')
-	public static function getField(obj:Dynamic, field:String, fieldHash:Int, throwErrors:Bool):Dynamic
-	{
-		return null;
 	}
 
-	@:functionCode('
-
-		haxe.lang.HxObject hxObj = obj as haxe.lang.HxObject;
+	public static function getField_f(obj:Dynamic, field:String, fieldHash:Int, throwErrors:Bool):Float
+	{
+		var hxObj = Lib.as(obj, HxObject);
 		if (hxObj != null)
-			return hxObj.__hx_getField_f(field, (fieldHash == 0) ? haxe.lang.FieldLookup.hash(field) : fieldHash, throwErrors, false);
+			return untyped hxObj.__hx_getField_f(field, (fieldHash == 0) ? FieldLookup.hash(field) : fieldHash, throwErrors, false);
 
 		return toDouble(slowGetField(obj, field, throwErrors));
-
-	')
-	public static function getField_f(obj:Dynamic, field:String, fieldHash:Int, throwErrors:Bool):Float
-	{
-		return 0.0;
 	}
 
-	@:functionCode('
-
-		haxe.lang.HxObject hxObj = obj as haxe.lang.HxObject;
+	public static function setField(obj:Dynamic, field:String, fieldHash:Int, value:Dynamic):Dynamic
+	{
+		var hxObj = Lib.as(obj, HxObject);
 		if (hxObj != null)
-			return hxObj.__hx_setField(field, (fieldHash == 0) ? haxe.lang.FieldLookup.hash(field) : fieldHash, value, false);
+			return untyped hxObj.__hx_setField(field, (fieldHash == 0) ? FieldLookup.hash(field) : fieldHash, value, false);
 
 		return slowSetField(obj, field, value);
-
-	')
-	public static function setField(obj:Dynamic, field:String, fieldHash:Int, value:Dynamic):Dynamic
-	{
-		return null;
 	}
 
-	@:functionCode('
-
-		haxe.lang.HxObject hxObj = obj as haxe.lang.HxObject;
+	public static function setField_f(obj:Dynamic, field:String, fieldHash:Int, value:Float):Float
+	{
+		var hxObj = Lib.as(obj, HxObject);
 		if (hxObj != null)
-			return hxObj.__hx_setField_f(field, (fieldHash == 0) ? haxe.lang.FieldLookup.hash(field) : fieldHash, value, false);
+			return untyped hxObj.__hx_setField_f(field, (fieldHash == 0) ? FieldLookup.hash(field) : fieldHash, value, false);
 
 		return toDouble(slowSetField(obj, field, value));
-
-	')
-	public static function setField_f(obj:Dynamic, field:String, fieldHash:Int, value:Float):Float
-	{
-		return 0.0;
 	}
 
 	public static function toString(obj:Dynamic):String
@@ -665,19 +756,48 @@ import cs.system.Object;
 		return untyped obj.ToString();
 	}
 
-	@:functionCode('
-			if (t1 == null || t2 == null)
-				return t1 == t2;
-			string n1 = Type.getClassName(t1);
-			string n2 = Type.getClassName(t2);
-			return n1.Equals(n2);
-	')
+#if erase_generics
+	inline
+#end
 	public static function typeEq(t1:Type, t2:Type):Bool
 	{
-		return false;
+		if (t1 == null || t2 == null)
+			return t1 == t2;
+#if !erase_generics
+		var t1i = t1.IsInterface,
+		    t2i = t2.IsInterface;
+		if (t1i != t2i)
+		{
+			if (t1i)
+			{
+				var g = getGenericAttr(t1);
+				if (g != null)
+					t1 = g.generic;
+			} else {
+				var g = getGenericAttr(t2);
+				if (g != null)
+					t2 = g.generic;
+			}
+		}
+
+#end
+		if (t1.GetGenericArguments().Length > 0) t1 = t1.GetGenericTypeDefinition();
+		if (t2.GetGenericArguments().Length > 0) t2 = t2.GetGenericTypeDefinition();
+		return Object.ReferenceEquals(t1,t2);
 	}
 
 
+#if !erase_generics
+	private static function getGenericAttr(t:cs.system.Type):cs.internal.HxObject.GenericInterface
+	{
+		for (attr in t.GetCustomAttributes(true))
+			if (Std.is(attr,cs.internal.HxObject.GenericInterface))
+				return cast attr;
+		return null;
+	}
+#end
+
+#if !erase_generics
 	@:functionCode('
 		if (obj is To)
 			return (To) obj;
@@ -698,6 +818,7 @@ import cs.system.Object;
 	{
 		return null;
 	}
+#end
 
 	@:functionCode('
 		return (s1 == null ? "null" : s1) + (s2 == null ? "null" : s2);
@@ -707,12 +828,9 @@ import cs.system.Object;
 		return null;
 	}
 
-	@:functionCode('
-		return dyn == null ? false : ((bool) dyn);
-	')
 	public static function toBool(dyn:Dynamic):Bool
 	{
-		return false;
+		return if (dyn == null) false else untyped __cs__("(bool){0}", dyn);
 	}
 
 
@@ -731,6 +849,7 @@ import cs.system.Object;
 	}*/
 }
 
+@:nativeGen
 @:keep @:native("haxe.lang.EmptyObject") private enum EmptyObject
 {
 	EMPTY;

+ 93 - 112
std/cs/internal/StringExt.hx

@@ -21,153 +21,143 @@
  */
 package cs.internal;
 import cs.internal.Function;
-private typedef NativeString = String;
+private typedef NativeString = cs.system.String;
 
-@:keep @:nativeGen @:native("haxe.lang.StringExt") private class StringExt
+@:keep @:nativeGen @:native("haxe.lang.StringExt") class StringExt
 {
+	@:readOnly static var empty(default,never) = new NativeString(cast 0,0);
 
-	@:functionCode('
-			if ( ((uint) index) >= me.Length)
-				return "";
-			else
-				return new string(me[index], 1);
-	')
 	public static function charAt(me:NativeString, index:Int):NativeString
 	{
-		return null;
+		if (cast(index,UInt) >= me.Length)
+			return empty;
+		else
+			return new NativeString(me[index], 1);
 	}
 
 	public static function charCodeAt(me:NativeString, index:Int):Null<Int>
 	{
-		if (cast(index,UInt) >= me.length)
+		if (cast(index,UInt) >= me.Length)
 			return null;
 		else
-			return cast me[index];
+			return cast(me[index], Int);
 	}
 
-	public static function indexOf(me:NativeString, str:NativeString, ?startIndex:Int):Int
+	public static function indexOf(me:NativeString, str:String, ?startIndex:Int):Int
 	{
 		var sIndex:Int = startIndex != null ? startIndex : 0;
-		if (sIndex >= me.length)
+		if (sIndex >= me.Length)
 			return -1;
 		return @:privateAccess me.IndexOf(str, sIndex, cs.system.StringComparison.Ordinal);
 	}
 
-	@:functionCode('
-			int sIndex = (startIndex.hasValue) ? (startIndex.@value) : (me.Length - 1);
-			if (sIndex >= me.Length)
-				sIndex = me.Length - 1;
-			else if (sIndex < 0)
-				return -1;
+	public static function lastIndexOf(me:NativeString, str:NativeString, ?startIndex:Int):Int
+	{
+		var sIndex:Int = startIndex == null ? me.Length - 1 : startIndex;
+		if (sIndex >= me.Length)
+			sIndex = me.Length - 1;
+		else if (sIndex < 0)
+			return -1;
 
-			//TestBaseTypes.hx@133 fix
-			if (startIndex.hasValue)
+		//TestBaseTypes.hx@133 fix
+		if (startIndex != null)
+		{
+			var i = sIndex + 1;
+			while (i --> 0)
 			{
-				for(int i = sIndex; i >= 0; i--)
+				var found = true;
+				for (j in 0...str.Length)
 				{
-					bool found = true;
-					for(int j = 0; j < str.Length; j++)
+					if(me[i + j] != str[j])
 					{
-						if(me[i + j] != str[j])
-						{
-							found = false;
-							break;
-						}
+						found = false;
+						break;
 					}
-
-					if (found)
-						return i;
 				}
 
-				return -1;
-			} else {
-				return me.LastIndexOf(str, sIndex, System.StringComparison.Ordinal);
+				if (found)
+					return i;
 			}
-	')
-	public static function lastIndexOf(me:NativeString, str:NativeString, ?startIndex:Int):Int
-	{
+
+			return -1;
+		} else {
+			return me.LastIndexOf(untyped str, sIndex, cs.system.StringComparison.Ordinal);
+		}
 		return -1;
 	}
 
-	@:functionCode('
-			string[] native;
-			if (delimiter.Length == 0)
-			{
-				int len = me.Length;
-				native = new string[len];
-				for (int i = 0; i < len; i++)
-					native[i] = new string(me[i], 1);
-			} else {
-				native = me.Split(new string[] { delimiter }, System.StringSplitOptions.None);
-			}
-			return new Array<object>(native);
-	')
-	public static function split(me:NativeString, delimiter:NativeString):Array<NativeString>
+	public static function split(me:NativeString, delimiter:NativeString):Array<String>
 	{
-		return null;
+		var native:NativeArray<String>;
+		if (delimiter.Length == 0)
+		{
+			var len = me.Length;
+			native = new NativeArray(len);
+			for (i in 0...len)
+				native[i] = untyped new NativeString(me[i],1);
+		} else {
+			var str = new NativeArray<String>(1);
+			str[0] = cast delimiter;
+
+			native = me.Split(str, cs.system.StringSplitOptions.None);
+		}
+
+		return cs.Lib.array(native);
 	}
 
-	@:functionCode('
-			int meLen = me.Length;
-			int targetLen = meLen;
-			if (len.hasValue)
-			{
-				targetLen = len.@value;
-				if (targetLen == 0)
-					return "";
-				if( pos != 0 && targetLen < 0 ){
-					return "";
-				}
-			}
+	public static function substr(me:NativeString, pos:Int, ?len:Int):String
+	{
+		var meLen = me.Length;
+		var targetLen = meLen;
+		if (len != null)
+		{
+			targetLen = len;
+			if (targetLen == 0 || (pos != 0 && targetLen < 0))
+				return "";
+		}
 
-			if( pos < 0 ){
-				pos = meLen + pos;
-				if( pos < 0 ) pos = 0;
-			} else if( targetLen < 0 ){
-				targetLen = meLen + targetLen - pos;
-			}
+		if (pos < 0)
+		{
+			pos = meLen + pos;
+			if (pos < 0) pos = 0;
+		} else if (targetLen < 0) {
+			targetLen = meLen + targetLen - pos;
+		}
 
-			if( pos + targetLen > meLen ){
-				targetLen = meLen - pos;
-			}
+		if (pos + targetLen > meLen)
+		{
+			targetLen = meLen - pos;
+		}
 
-			if ( pos < 0 || targetLen <= 0 ) return "";
+		if (pos < 0 || targetLen <= 0) return "";
 
-			return me.Substring(pos, targetLen);
-	')
-	public static function substr(me:NativeString, pos:Int, ?len:Int):NativeString
-	{
-		return null;
+		return me.Substring(pos, targetLen);
 	}
 
-	@:functionCode('
-		int endIdx;
-		int len = me.Length;
-		if ( !endIndex.hasValue ) {
+	public static function substring(me:NativeString, startIndex:Int, ?endIndex:Int):String
+	{
+		var len = me.Length;
+		var endIdx:Int;
+		if (endIndex == null)
 			endIdx = len;
-		} else if ( (endIdx = endIndex.@value) < 0 ) {
+		else if ( (endIdx = endIndex) < 0 )
 			endIdx = 0;
-		} else if ( endIdx > len ) {
+		else if (endIdx > len)
 			endIdx = len;
-		}
 
-		if ( startIndex < 0 ) {
+		if (startIndex < 0)
 			startIndex = 0;
-		} else if ( startIndex > len ) {
+		else if (startIndex > len)
 			startIndex = len;
-		}
 
-		if ( startIndex > endIdx ) {
-			int tmp = startIndex;
+		if (startIndex > endIdx)
+		{
+			var tmp = startIndex;
 			startIndex = endIdx;
 			endIdx = tmp;
 		}
 
 		return me.Substring(startIndex, endIdx - startIndex);
-	')
-	public static function substring(me:NativeString, startIndex:Int, ?endIndex:Int):NativeString
-	{
-		return null;
 	}
 
 	public static function toString(me:NativeString):NativeString
@@ -175,20 +165,14 @@ private typedef NativeString = String;
 		return me;
 	}
 
-	@:functionCode('
-			return me.ToLowerInvariant();
-	')
-	public static function toLowerCase(me:NativeString):NativeString
+	public static function toLowerCase(me:NativeString):String
 	{
-		return null;
+		return me.ToLowerInvariant();
 	}
 
-	@:functionCode('
-			return me.ToUpperInvariant();
-	')
-	public static function toUpperCase(me:NativeString):NativeString
+	public static function toUpperCase(me:NativeString):String
 	{
-		return null;
+		return me.ToUpperInvariant();
 	}
 
 	public static function toNativeString(me:NativeString):NativeString
@@ -196,12 +180,9 @@ private typedef NativeString = String;
 		return me;
 	}
 
-	@:functionCode('
-			return new string( (char) code, 1 );
-	')
 	public static function fromCharCode(code:Int):NativeString
 	{
-		return null;
+		return new NativeString( cast(code,cs.StdTypes.Char16), 1 );
 	}
 }
 
@@ -209,7 +190,7 @@ private typedef NativeString = String;
 {
 	public static var fields = ["length", "toUpperCase", "toLowerCase", "charAt", "charCodeAt", "indexOf", "lastIndexOf", "split", "substr", "substring"];
 
-	public static function handleGetField(str:NativeString, f:NativeString, throwErrors:Bool):Dynamic
+	public static function handleGetField(str:String, f:String, throwErrors:Bool):Dynamic
 	{
 		switch(f)
 		{
@@ -224,7 +205,7 @@ private typedef NativeString = String;
 		}
 	}
 
-	public static function handleCallField(str:NativeString, f:NativeString, args:Array<Dynamic>):Dynamic
+	public static function handleCallField(str:NativeString, f:String, args:Array<Dynamic>):Dynamic
 	{
 		var _args:Array<Dynamic> = [str];
 		if (args == null)

+ 15 - 6
std/cs/io/NativeInput.hx

@@ -31,16 +31,22 @@ class NativeInput extends Input
 	public var canSeek(get_canSeek, null):Bool;
 
 	var stream:cs.system.io.Stream;
+	var _eof:Bool;
+
 	public function new(stream)
 	{
 		this.stream = stream;
+		this._eof = false;
 		if (!stream.CanRead) throw "Write-only stream";
 	}
 
 	override public function readByte():Int
 	{
 		var ret = stream.ReadByte();
-		if (ret == -1) throw new Eof();
+		if (ret == -1) {
+			_eof = true;
+			throw new Eof();
+		}
 		return ret;
 	}
 
@@ -49,8 +55,10 @@ class NativeInput extends Input
 		if( pos < 0 || len < 0 || pos + len > s.length )
 			throw Error.OutsideBounds;
 		var ret = stream.Read(s.getData(), pos, len);
-		if (ret == 0)
+		if (ret == 0) {
+			_eof = true;
 			throw new Eof();
+		}
 		return ret;
 	}
 
@@ -66,14 +74,15 @@ class NativeInput extends Input
 
 	public function seek( p : Int, pos : sys.io.FileSeek ) : Void
 	{
-		var p = switch(pos)
+		_eof = false;
+		var pos = switch(pos)
 		{
 			case SeekBegin: cs.system.io.SeekOrigin.Begin;
 			case SeekCur: cs.system.io.SeekOrigin.Current;
 			case SeekEnd: cs.system.io.SeekOrigin.End;
 		};
 
-		stream.Seek(cast(p, Int64), p);
+		stream.Seek(cast(p, Int64), pos);
 	}
 
 	public function tell() : Int
@@ -81,8 +90,8 @@ class NativeInput extends Input
 		return cast(stream.Position, Int);
 	}
 
-	public function eof() : Bool
+	public inline function eof() : Bool
 	{
-		return stream.Position == stream.Length;
+		return _eof;
 	}
 }

+ 0 - 1
std/flash/Boot.hx

@@ -51,7 +51,6 @@ class Boot extends flash.display.MovieClip {
 	public static var skip_constructor = false;
 
 	function start() {
-		#if (mt && !doc_gen) mt.flash.Init.check(); #end
 		#if dontWaitStage
 			init();
 		#else

+ 421 - 0
std/flash/NativeXml.hx

@@ -0,0 +1,421 @@
+/*
+ * 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 flash;
+
+import flash.xml.XML;
+import flash.xml.XMLList;
+
+extern 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 _node : flash.xml.XML;
+
+	public static function parse( str : String ) : Xml {
+		XML.ignoreWhitespace = false;
+		XML.ignoreProcessingInstructions = false;
+		XML.ignoreComments = false;
+		var prefix = "<__document";
+		var root = null;
+		while( root == null ) {
+			try {
+				root = new flash.xml.XML(prefix+">" + str + "</__document>");
+			} catch( e : flash.errors.TypeError ) {
+				// if we miss a namespace, let's add it !
+				var r = ~/"([^"]+)"/; //"
+				if( e.errorID == 1083 && r.match(e.message) ) {
+					var ns = r.matched(1);
+					prefix += " xmlns:" + ns + '="@' + ns + '"';
+				} else
+					throw e;
+			}
+		}
+		return wrap( root, Xml.Document );
+	}
+
+	@:keep #if as3 @:hack public #end static function compare( a : Xml, b : Xml ) : Bool {
+		return a == null ? b == null : (b == null ? false : a._node == b._node);
+	}
+
+	private function new() : Void {}
+
+	public static function createElement( name : String ) : Xml {
+		return wrap( new flash.xml.XML("<"+name+"/>"), Xml.Element );
+	}
+
+	public static function createPCData( data : String ) : Xml {
+		XML.ignoreWhitespace = false;
+		return wrap( new flash.xml.XML(data), Xml.PCData );
+	}
+
+	public static function createCData( data : String ) : Xml {
+		return wrap( new flash.xml.XML("<![CDATA["+data+"]]>"), Xml.CData );
+	}
+
+	public static function createComment( data : String ) : Xml {
+		XML.ignoreComments = false;
+		return wrap( new flash.xml.XML("<!--"+data+"-->"), Xml.Comment );
+	}
+
+	public static function createDocType( data : String ) : Xml {
+		return wrap( new flash.xml.XML("<!DOCTYPE "+data+">"), Xml.DocType );
+	}
+
+	public static function createProcessingInstruction( data : String ) : Xml {
+		XML.ignoreProcessingInstructions = false;
+		return wrap( new flash.xml.XML("<?"+data+"?>"), Xml.ProcessingInstruction );
+	}
+
+	public static function createDocument() : Xml {
+		return wrap( new flash.xml.XML("<__document/>"), Xml.Document );
+	}
+
+	private static function getNodeType( node : flash.xml.XML ) : XmlType {
+		switch( node.nodeKind() ) {
+		case "element":
+			return Xml.Element;
+		case "text":
+			return Xml.PCData;
+		case "processing-instruction":
+			return Xml.ProcessingInstruction;
+		case "comment":
+			return Xml.Comment;
+		default :
+			throw "unimplemented node type: " + node.nodeType;
+		}
+	}
+
+	private function get_nodeName() : String {
+		if( nodeType != Xml.Element )
+			throw "bad nodeType";
+		var ns = _node.namespace();
+		return (ns.prefix == "") ? _node.localName() : ns.prefix+":"+_node.localName();
+	}
+
+	private function set_nodeName( n : String ) : String {
+		if( nodeType != Xml.Element )
+			throw "bad nodeType";
+		var ns = n.split(":");
+		if( ns.length == 1 )
+			_node.setLocalName(n);
+		else {
+			_node.setLocalName(ns[1]);
+			_node.setNamespace(_node.namespace(ns[0]));
+		}
+		return n;
+	}
+
+	private function get_nodeValue() : String {
+		var nodeType = nodeType;
+		if( nodeType == Xml.Element || nodeType == Xml.Document )
+			throw "bad nodeType";
+		if( nodeType == Xml.Comment )
+			return _node.toString().substr(4,-7);
+		return _node.toString();
+	}
+
+	private function set_nodeValue( v : String ) : String {
+		var nodeType = nodeType;
+		var x = null;
+		if( nodeType == Xml.Element || nodeType == Xml.Document )
+			throw "bad nodeType";
+		else if( nodeType == Xml.PCData )
+			x = createPCData(v);
+		else if( nodeType == Xml.CData )
+			x = createCData(v);
+		else if( nodeType == Xml.Comment )
+			x = createComment(v);
+		else if( nodeType == Xml.DocType )
+			x = createDocType(v);
+		else
+			x = createProcessingInstruction(v);
+		var p = _node.parent();
+		if( p != null ) {
+			p.insertChildAfter(_node, x._node);
+			var i = _node.childIndex();
+			var children = p.children();
+			untyped __delete__(children, Reflect.fields(children)[i]);
+		}
+		_node = x._node;
+		return v;
+	}
+
+	private function get_parent() :Xml {
+		var p = _node.parent();
+		return p == null ? null : wrap( p );
+	}
+
+	private static function wrap( node : XML, ?type : XmlType ) : Xml {
+		var x = new Xml();
+		x._node = node;
+		x.nodeType = (type != null) ? type : getNodeType( node );
+		return x;
+	}
+
+	private function wraps( xList : XMLList ) : Array<Xml> {
+		var out = new Array<Xml>();
+		for( i in 0...xList.length() )
+			out.push( wrap(xList[i]) );
+		return out;
+	}
+
+	function getAttribNS( cur : XML, ns : Array<String> ) : XMLList {
+		var n = cur.namespace(ns[0]);
+		if( n == null ) {
+			var parent = cur.parent();
+			if( parent == null ) {
+				n = new flash.utils.Namespace(ns[0], "@"+ns[0]);
+				cur.addNamespace(n);
+			} else
+				return getAttribNS(parent, ns);
+		}
+		return _node.attribute(new flash.utils.QName(n,ns[1]));
+	}
+
+	public function get( att : String ) : String {
+		if( nodeType != Xml.Element )
+			throw "bad nodeType";
+		var ns = att.split(":");
+		if( ns[0] == "xmlns" ) {
+			var n = _node.namespace((ns[1] == null) ? "" : ns[1]);
+			return (n == null) ? null : n.uri;
+		}
+		if( ns.length == 1 ) {
+			if( !Reflect.hasField(_node,"@"+att) )
+				return null;
+			return Reflect.field(_node, "@"+att);
+		}
+		var a = getAttribNS(_node,ns);
+		return (a.length() == 0) ? null : a.toString();
+	}
+
+	public function set( att : String, value : String ) : Void {
+		if( nodeType != Xml.Element )
+			throw "bad nodeType";
+		var ns = att.split(":");
+		if( ns[0] == "xmlns" ) {
+			var n = _node.namespace((ns[1] == null) ? "" : ns[1]);
+			if( n != null )
+				throw "Can't modify namespace";
+			if( ns[1] == null )
+				throw "Can't set default namespace";
+			_node.addNamespace(new flash.utils.Namespace(ns[1], value));
+			return;
+		}
+		if( ns.length == 1 )
+			Reflect.setField(_node, "@"+att, value);
+		else {
+			var a = getAttribNS(_node,ns);
+			untyped a[0] = value;
+		}
+	}
+
+	public function remove( att : String ) : Void{
+		if( nodeType != Xml.Element )
+			throw "bad nodeType";
+		var ns = att.split(":");
+		if( ns.length == 1 )
+			Reflect.deleteField(_node, "@"+att);
+		else
+			untyped __delete__(getAttribNS(_node,ns),0);
+	}
+
+	public function exists( att : String ) : Bool {
+		if( nodeType != Xml.Element )
+			throw "bad nodeType";
+		var ns = att.split(":");
+		if( ns[0] == "xmlns" )
+			return _node.namespace((ns[1] == null) ? "" : ns[1]) != null;
+		if( ns.length == 1 )
+			return Reflect.hasField(_node, "@"+att);
+		return getAttribNS(_node,ns).length() > 0;
+	}
+
+	public function attributes() : Iterator<String> {
+	    if( nodeType != Xml.Element )
+	        throw "bad nodeType";
+	    var attributes :XMLList = _node.attributes();
+	    var names = Reflect.fields(attributes);
+	    var cur = 0;
+	    var nss = _node.namespaceDeclarations();
+	    return {
+	        hasNext : function(){
+	            return cur < names.length + nss.length;
+	        },
+	        next : function() {
+	            if(cur<names.length){
+	                return attributes[Std.parseInt(names[cur++])].name();
+	            }else {
+	                var ns:flash.utils.Namespace = nss[cur++ - names.length];
+	                return "xmlns:"+ns.prefix;
+	            }
+	        }
+	    }
+	}
+
+	public function iterator() : Iterator<Xml> {
+		if( nodeType != Xml.Element && nodeType != Xml.Document )
+			throw "bad nodeType";
+		var children:XMLList = _node.children();
+		var wrappers :Array<Xml> = wraps(children);
+		var cur = 0;
+		return {
+			hasNext : function(){
+				return cur < wrappers.length;
+			},
+			next : function(){
+				return wrappers[cur++];
+			}
+		};
+	}
+
+	public function elements() : Iterator<Xml> {
+		if( nodeType != Xml.Element && nodeType != Xml.Document )
+			throw "bad nodeType";
+		var elements:XMLList = _node.elements();
+		var wrappers :Array<Xml> = wraps(elements);
+		var cur = 0;
+		return {
+			hasNext : function(){
+				return cur < wrappers.length;
+			},
+			next : function(){
+				return wrappers[cur++];
+			}
+		};
+	}
+
+	public function elementsNamed( name : String ) : Iterator<Xml> {
+		if( nodeType != Xml.Element && nodeType != Xml.Document )
+			throw "bad nodeType";
+		var ns = name.split(":");
+		var elements:XMLList;
+		if( ns.length == 1 )
+			elements = _node.elements(name);
+		else
+			elements = _node.elements();
+		var wrappers :Array<Xml> = wraps(elements);
+		if( ns.length != 1 )
+			for( w in wrappers.copy() )
+				if( w._node.localName() != ns[1] || w._node.namespace().prefix != ns[0] )
+					wrappers.remove(w);
+		var cur = 0;
+		return {
+			hasNext : function(){
+				return cur < wrappers.length;
+			},
+			next : function(){
+				return wrappers[cur++];
+			}
+		};
+	}
+
+	public function firstChild() : Xml {
+		if( nodeType != Xml.Element && nodeType != Xml.Document )
+			throw "bad nodeType";
+		var children:XMLList = _node.children();
+		if( children.length() == 0 )
+			return null;
+		return wrap( children[0] );
+	}
+
+	public function firstElement() : Xml {
+		if( nodeType != Xml.Element && nodeType != Xml.Document )
+			throw "bad nodeType";
+		var elements:XMLList = _node.elements();
+		if( elements.length() == 0 )
+			return null;
+		return wrap( elements[0] );
+	}
+
+	public function addChild( x : Xml ) : Void {
+		if( nodeType != Xml.Element && nodeType != Xml.Document )
+			throw "bad nodeType";
+		if (x.parent != null)
+			x.parent.removeChild(x);
+		var children:XMLList = _node.children();
+		_node.appendChild(x._node);
+	}
+
+	public function removeChild( x : Xml ) : Bool {
+		if( nodeType != Xml.Element && nodeType != Xml.Document )
+			throw "bad nodeType";
+		var children:XMLList = _node.children();
+		if( _node != x._node.parent() )
+			return false;
+		var i = x._node.childIndex();
+		untyped __delete__(children, Reflect.fields(children)[i]);
+		return true;
+	}
+
+	public function insertChild( x : Xml, pos : Int ) : Void {
+		if( nodeType != Xml.Element && nodeType != Xml.Document )
+			throw "bad nodeType";
+		if (x.parent != null)
+			x.parent.removeChild(x);
+		var children:XMLList = _node.children();
+		if( pos < children.length() )
+			_node.insertChildBefore(children[pos], x._node);
+		else
+			_node.appendChild(x._node);
+	}
+
+	public function toString() : String {
+		XML.prettyPrinting = false;
+		if( nodeType == Xml.Document ) {
+			var str = _node.toXMLString();
+			// remove <__document xmlns....>STR</__document> wrapper
+			str = str.substr(str.indexOf(">") + 1);
+			str = str.substr(0, str.length - 13);
+			return str;
+		}
+		return _node.toXMLString();
+	}
+
+	static function __init__() : Void untyped {
+		Element = "element";
+		PCData = "pcdata";
+		CData = "cdata";
+		Comment = "comment";
+		DocType = "doctype";
+		ProcessingInstruction = "processingInstruction";
+		Document = "document";
+	}
+
+
+}

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

@@ -145,8 +145,8 @@ private class StringMapKeysIterator {
 		this.h = h;
 		this.rh = rh;
 		this.index = 0;
-		this.nextIndex = 0;
 		isReserved = false;
+		hasNext();
 	}
 
 	public inline function hasNext():Bool {
@@ -183,7 +183,7 @@ private class StringMapValuesIterator<T> {
 		this.h = h;
 		this.rh = rh;
 		this.index = 0;
-		this.nextIndex = 0;
+		hasNext();
 	}
 
 	public inline function hasNext():Bool {

+ 1 - 0
std/flash/display/Stage.hx

@@ -4,6 +4,7 @@ extern class Stage extends DisplayObjectContainer {
 	var align : StageAlign;
 	@:require(flash10_2) var allowsFullScreen(default,null) : Bool;
 	@:require(flash11_3) var allowsFullScreenInteractive(default,null) : Bool;
+	@:require(flash15) var browserZoomFactor(default,null) : Float;
 	@:require(flash10_2) var color : UInt;
 	@:require(flash10) var colorCorrection : ColorCorrection;
 	@:require(flash10) var colorCorrectionSupport(default,null) : ColorCorrectionSupport;

+ 8 - 1
std/flash/display3D/Context3D.hx

@@ -1,17 +1,22 @@
 package flash.display3D;
 
 @:final extern class Context3D extends flash.events.EventDispatcher {
+	@:require(flash15) var backBufferHeight(default,null) : Int;
+	@:require(flash15) var backBufferWidth(default,null) : Int;
 	var driverInfo(default,null) : String;
 	var enableErrorChecking : Bool;
+	@:require(flash15) var maxBackBufferHeight : Int;
+	@:require(flash15) var maxBackBufferWidth : Int;
 	@:require(flash12) var profile(default,null) : String;
 	function clear(red : Float = 0, green : Float = 0, blue : Float = 0, alpha : Float = 1, depth : Float = 1, stencil : UInt = 0, mask : UInt = 0xFFFFFFFF) : Void;
-	function configureBackBuffer(width : Int, height : Int, antiAlias : Int, enableDepthAndStencil : Bool = true, wantsBestResolution : Bool = false) : Void;
+	function configureBackBuffer(width : Int, height : Int, antiAlias : Int, enableDepthAndStencil : Bool = true, wantsBestResolution : Bool = false, wantsBestResolutionOnBrowserZoom : Bool = false) : Void;
 	function createCubeTexture(size : Int, format : Context3DTextureFormat, optimizeForRenderToTexture : Bool, streamingLevels : Int = 0) : flash.display3D.textures.CubeTexture;
 	function createIndexBuffer(numIndices : Int, ?bufferUsage : Context3DBufferUsage) : IndexBuffer3D;
 	function createProgram() : Program3D;
 	@:require(flash11_8) function createRectangleTexture(width : Int, height : Int, format : Context3DTextureFormat, optimizeForRenderToTexture : Bool) : flash.display3D.textures.RectangleTexture;
 	function createTexture(width : Int, height : Int, format : Context3DTextureFormat, optimizeForRenderToTexture : Bool, streamingLevels : Int = 0) : flash.display3D.textures.Texture;
 	function createVertexBuffer(numVertices : Int, data32PerVertex : Int, ?bufferUsage : Context3DBufferUsage) : VertexBuffer3D;
+	@:require(flash15) function createVideoTexture() : flash.display3D.textures.VideoTexture;
 	function dispose(recreate : Bool = true) : Void;
 	function drawToBitmapData(destination : flash.display.BitmapData) : Void;
 	function drawTriangles(indexBuffer : IndexBuffer3D, firstIndex : Int = 0, numTriangles : Int = -1) : Void;
@@ -20,6 +25,7 @@ package flash.display3D;
 	function setColorMask(red : Bool, green : Bool, blue : Bool, alpha : Bool) : Void;
 	function setCulling(triangleFaceToCull : Context3DTriangleFace) : Void;
 	function setDepthTest(depthMask : Bool, passCompareMode : Context3DCompareMode) : Void;
+	@:require(flash16) function setFillMode( fillMode : Context3DFillMode ) : Void;
 	function setProgram(program : Program3D) : Void;
 	@:require(flash11_2) function setProgramConstantsFromByteArray(programType : Context3DProgramType, firstRegister : Int, numRegisters : Int, data : flash.utils.ByteArray, byteArrayOffset : UInt) : Void;
 	function setProgramConstantsFromMatrix(programType : Context3DProgramType, firstRegister : Int, matrix : flash.geom.Matrix3D, transposedMatrix : Bool = false) : Void;
@@ -32,4 +38,5 @@ package flash.display3D;
 	function setStencilReferenceValue(referenceValue : UInt, readMask : UInt = 255, writeMask : UInt = 255) : Void;
 	function setTextureAt(sampler : Int, texture : flash.display3D.textures.TextureBase) : Void;
 	function setVertexBufferAt(index : Int, buffer : VertexBuffer3D, bufferOffset : Int = 0, ?format : Context3DVertexBufferFormat) : Void;
+	@:require(flash15) static var supportsVideoTexture(default,null) : Bool;
 }

+ 1 - 1
std/flash/display3D/Context3DBufferUsage.hx

@@ -1,6 +1,6 @@
 package flash.display3D;
 
-@:require(flash12) @:fakeEnum(String) extern enum Context3DBufferUsage {
+@:fakeEnum(String) @:require(flash12) extern enum Context3DBufferUsage {
 	DYNAMIC_DRAW;
 	STATIC_DRAW;
 }

+ 6 - 0
std/flash/display3D/Context3DFillMode.hx

@@ -0,0 +1,6 @@
+package flash.display3D;
+
+@:fakeEnum(String) @:require(flash16) extern enum Context3DFillMode {
+	SOLID;
+	WIREFRAME;
+}

+ 1 - 0
std/flash/display3D/Context3DProfile.hx

@@ -5,4 +5,5 @@ package flash.display3D;
 	BASELINE_CONSTRAINED;
 	BASELINE_EXTENDED;
 	STANDARD;
+	STANDARD_CONSTRAINED;
 }

+ 9 - 0
std/flash/display3D/textures/VideoTexture.hx

@@ -0,0 +1,9 @@
+package flash.display3D.textures;
+
+@:final extern class VideoTexture extends TextureBase {
+	var videoHeight(default,null) : Int;
+	var videoWidth(default,null) : Int;
+	function new() : Void;
+	function attachCamera(theCamera : flash.media.Camera) : Void;
+	function attachNetStream(netStream : flash.net.NetStream) : Void;
+}

+ 8 - 0
std/flash/events/AVDictionaryDataEvent.hx

@@ -0,0 +1,8 @@
+package flash.events;
+
+extern class AVDictionaryDataEvent extends Event {
+	var dictionary(default,null) : flash.utils.Dictionary;
+	var time(default,null) : Float;
+	function new(?type : String, bubbles : Bool = false, cancelable : Bool = false, ?init_dictionary : flash.utils.Dictionary, init_dataTime : Float = 0) : Void;
+	static var AV_DICTIONARY_DATA : String;
+}

+ 9 - 0
std/flash/events/AVHTTPStatusEvent.hx

@@ -0,0 +1,9 @@
+package flash.events;
+
+extern class AVHTTPStatusEvent extends Event {
+	var responseHeaders : Array<Dynamic>;
+	var responseURL : String;
+	var status(default,null) : Int;
+	function new(type : String, bubbles : Bool = false, cancelable : Bool = false, status : Int = 0, ?responseUrl : String, ?responseHeaders : Array<Dynamic>) : Void;
+	static var AV_HTTP_RESPONSE_STATUS : String;
+}

+ 7 - 0
std/flash/events/AVPauseAtPeriodEndEvent.hx

@@ -0,0 +1,7 @@
+package flash.events;
+
+extern class AVPauseAtPeriodEndEvent extends Event {
+	var userData(default,null) : Int;
+	function new(?type : String, bubbles : Bool = false, cancelable : Bool = false, userData : Int = 0) : Void;
+	static var AV_PAUSE_AT_PERIOD_END : String;
+}

+ 2 - 0
std/flash/events/AVStatusEvent.hx

@@ -6,6 +6,8 @@ extern class AVStatusEvent extends Event {
 	var result(default,null) : flash.media.AVResult;
 	function new(?type : String, bubbles : Bool = false, cancelable : Bool = false, ?inNotificationType : String, inResult : Int = 0, ?inDescription : String) : Void;
 	static var AV_STATUS : String;
+	static var BACKGROUND_MANIFEST_ERROR : String;
+	static var BACKGROUND_MANIFEST_WARNING : String;
 	static var BUFFER_STATE : String;
 	static var DECODER_TYPE : String;
 	static var DIMENSION_CHANGE : String;

Algúns arquivos non se mostraron porque demasiados arquivos cambiaron neste cambio