Browse Source

Merge branch 'development' into merge_candidate

Conflicts:
	Makefile
	src/main.ml
	src/optimization/analyzer.ml
Simon Krajewski 9 years ago
parent
commit
83fa460ff4
100 changed files with 4812 additions and 3549 deletions
  1. 1 1
      .gitignore
  2. 0 1
      .travis.yml
  3. 12 2
      CONTRIBUTING.md
  4. 38 16
      Makefile
  5. 5 5
      Makefile.win
  6. 0 2
      appveyor.yml
  7. 1 0
      extra/extract.patch
  8. 92 1
      haxe.hxproj
  9. 0 562
      src/generators/codegen.ml
  10. 1 1
      src/generators/genas3.ml
  11. 173 375
      src/generators/gencpp.ml
  12. 29 7
      src/generators/genhl.ml
  13. 6 4
      src/generators/genjs.ml
  14. 1 1
      src/generators/genpy.ml
  15. 24 4
      src/main.ml
  16. 9 1648
      src/optimization/analyzer.ml
  17. 119 0
      src/optimization/analyzerConfig.ml
  18. 713 0
      src/optimization/analyzerTexpr.ml
  19. 702 0
      src/optimization/analyzerTexprTransformer.ml
  20. 522 0
      src/optimization/analyzerTypes.ml
  21. 3 3
      src/optimization/filters.ml
  22. 19 14
      src/optimization/optimizer.ml
  23. 12 1
      src/syntax/ast.ml
  24. 3 72
      src/typing/common.ml
  25. 3 0
      src/typing/matcher.ml
  26. 79 2
      src/typing/type.ml
  27. 9 47
      src/typing/typecore.ml
  28. 549 2
      src/typing/typeload.ml
  29. 41 38
      src/typing/typer.ml
  30. 3 0
      std/Array.hx
  31. 2 0
      std/Class.hx
  32. 1 1
      std/EReg.hx
  33. 2 0
      std/Enum.hx
  34. 2 0
      std/EnumValue.hx
  35. 2 0
      std/IntIterator.hx
  36. 2 0
      std/Lambda.hx
  37. 2 0
      std/List.hx
  38. 2 0
      std/Map.hx
  39. 2 0
      std/Math.hx
  40. 2 0
      std/Reflect.hx
  41. 29 1
      std/StdTypes.hx
  42. 1 1
      std/String.hx
  43. 2 1
      std/StringTools.hx
  44. 4 0
      std/Type.hx
  45. 6 2
      std/UInt.hx
  46. 2 0
      std/Xml.hx
  47. 0 1
      std/cpp/ConstPointer.hx
  48. 0 1
      std/cpp/Function.hx
  49. 0 1
      std/cpp/Lib.hx
  50. 64 0
      std/cpp/NativeFile.hx
  51. 38 0
      std/cpp/NativeProcess.hx
  52. 23 0
      std/cpp/NativeRandom.hx
  53. 135 0
      std/cpp/NativeSocket.hx
  54. 108 0
      std/cpp/NativeSys.hx
  55. 466 399
      std/cpp/NativeXml.hx
  56. 365 0
      std/cpp/NativeXmlImport.cpp
  57. 19 0
      std/cpp/ObjectType.hx
  58. 0 1
      std/cpp/Pointer.hx
  59. 1 2
      std/cpp/Prime.hx
  60. 4 9
      std/cpp/Random.hx
  61. 27 17
      std/cpp/_std/EReg.hx
  62. 10 7
      std/cpp/_std/Reflect.hx
  63. 21 38
      std/cpp/_std/Sys.hx
  64. 15 6
      std/cpp/_std/haxe/zip/Compress.hx
  65. 12 5
      std/cpp/_std/haxe/zip/Uncompress.hx
  66. 12 23
      std/cpp/_std/sys/FileSystem.hx
  67. 42 21
      std/cpp/_std/sys/db/Mysql.hx
  68. 32 13
      std/cpp/_std/sys/db/Sqlite.hx
  69. 7 10
      std/cpp/_std/sys/io/File.hx
  70. 7 15
      std/cpp/_std/sys/io/FileInput.hx
  71. 7 14
      std/cpp/_std/sys/io/FileOutput.hx
  72. 10 19
      std/cpp/_std/sys/io/Process.hx
  73. 7 10
      std/cpp/_std/sys/net/Host.hx
  74. 24 47
      std/cpp/_std/sys/net/Socket.hx
  75. 4 6
      std/cpp/_std/sys/net/UdpSocket.hx
  76. 7 0
      std/cpp/cppia/HostClasses.hx
  77. 7 19
      std/cpp/net/Poll.hx
  78. 16 16
      std/haxe/EnumTools.hx
  79. 9 3
      std/haxe/Json.hx
  80. 6 6
      std/haxe/Serializer.hx
  81. 1 1
      std/haxe/Template.hx
  82. 10 7
      std/haxe/Unserializer.hx
  83. 2 0
      std/haxe/ds/GenericStack.hx
  84. 34 0
      std/haxe/ds/HashMap.hx
  85. 2 0
      std/haxe/ds/IntMap.hx
  86. 1 1
      std/haxe/ds/ListSort.hx
  87. 2 0
      std/haxe/ds/ObjectMap.hx
  88. 2 0
      std/haxe/ds/Option.hx
  89. 2 0
      std/haxe/ds/StringMap.hx
  90. 2 0
      std/haxe/ds/Vector.hx
  91. 2 0
      std/haxe/ds/WeakMap.hx
  92. 3 1
      std/haxe/format/JsonParser.hx
  93. 2 0
      std/haxe/format/JsonPrinter.hx
  94. 0 3
      std/haxe/io/Input.hx
  95. 5 8
      std/haxe/io/Path.hx
  96. 1 1
      std/haxe/remoting/HttpConnection.hx
  97. 1 0
      std/hl/types/Api.hx
  98. 1 1
      std/js/Boot.hx
  99. 1 1
      std/js/Promise.hx
  100. 1 1
      std/js/_std/Array.hx

+ 1 - 1
.gitignore

@@ -3,6 +3,7 @@
 *.cmx
 *.cmx
 *.cmi
 *.cmi
 *.cmxa
 *.cmxa
+*.cmo
 *.a
 *.a
 *.exe
 *.exe
 .*.swp
 .*.swp
@@ -69,7 +70,6 @@ tests/misc/pythonImport/native_python/__pycache__
 tests/unit/unit.py
 tests/unit/unit.py
 tests/unit/unit.py.res1.txt
 tests/unit/unit.py.res1.txt
 tests/unit/unit.py.res2.bin
 tests/unit/unit.py.res2.bin
-*.cmo
 tests/sys/bin/
 tests/sys/bin/
 tests/optimization/dump/
 tests/optimization/dump/
 tests/misc/projects/*/*.n
 tests/misc/projects/*/*.n

+ 0 - 1
.travis.yml

@@ -160,7 +160,6 @@ script:
   - eval `ssh-agent -s`
   - eval `ssh-agent -s`
   - make package_src -s
   - make package_src -s
   - make -s
   - make -s
-  - make tools -s
   - make package_bin -s
   - make package_bin -s
   - export PATH="$PATH:$TRAVIS_BUILD_DIR"
   - export PATH="$PATH:$TRAVIS_BUILD_DIR"
   - export HAXE_STD_PATH="$TRAVIS_BUILD_DIR/std"
   - export HAXE_STD_PATH="$TRAVIS_BUILD_DIR/std"

+ 12 - 2
CONTRIBUTING.md

@@ -1,11 +1,21 @@
-Things to check before/while filing an issue:
+## Things to check before/while filing an issue:
 
 
 - Check if you actually suspect that there's an issue in the Haxe code. If you find yourself writing "How do I..." you may want to consider a different communication channel. Refer to http://haxe.org/community/community-support.html for more information.
 - Check if you actually suspect that there's an issue in the Haxe code. If you find yourself writing "How do I..." you may want to consider a different communication channel. Refer to http://haxe.org/community/community-support.html for more information.
 - 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.
 - 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/).
 - 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` subdirectory.
 - 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` subdirectory.
 
 
-Other remarks:
+## Is this the right repository to report the issue?
+
+This repository is about the Haxe compiler itself and the Haxe standard library. Here's an overview of repositories that are part of the Haxe ecosystem:
+
+* The haxelib command line tool or lib.haxe.org: <https://github.com/HaxeFoundation/haxelib/issues>
+* Something on try.haxe.org: <https://github.com/clemos/try-haxe/issues>
+* Something under haxe.org/manual: <https://github.com/HaxeFoundation/HaxeManual/issues>
+* Something on api.haxe.org: For content this is probably the right repository. If it's about the representation, try <https://github.com/dpeek/dox/issues> instead.
+* Something else on haxe.org: <https://github.com/HaxeFoundation/haxe.org/issues>
+
+## 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.
 - 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 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.

+ 38 - 16
Makefile

@@ -55,8 +55,10 @@ MODULES=syntax/ast typing/type syntax/lexer typing/common generators/genxml synt
 	optimization/optimizer typing/typeload generators/codegen generators/gencommon generators/genas3 \
 	optimization/optimizer typing/typeload generators/codegen generators/gencommon generators/genas3 \
 	generators/gencpp generators/genjs generators/genneko generators/genphp generators/genswf9 \
 	generators/gencpp generators/genjs generators/genneko generators/genphp generators/genswf9 \
 	generators/genswf generators/genjava generators/gencs generators/genpy macro/interp generators/genhl \
 	generators/genswf generators/genjava generators/gencs generators/genpy macro/interp generators/genhl \
-	generators/genlua optimization/dce optimization/analyzer optimization/filters typing/typer \
-	typing/matcher version main
+	generators/genlua \
+	optimization/dce optimization/analyzerConfig optimization/analyzerTypes optimization/analyzerTexpr \
+	optimization/analyzerTexprTransformer optimization/analyzer \
+	optimization/filters typing/typer typing/matcher version main
 
 
 ADD_REVISION?=0
 ADD_REVISION?=0
 
 
@@ -128,19 +130,13 @@ uninstall:
 
 
 # Modules
 # Modules
 
 
-src/optimization/analyzer.$(MODULE_EXT): src/syntax/ast.$(MODULE_EXT) src/typing/type.$(MODULE_EXT) src/typing/common.$(MODULE_EXT) src/generators/codegen.$(MODULE_EXT)
+# generators
 
 
-src/generators/codegen.$(MODULE_EXT): src/optimization/optimizer.$(MODULE_EXT) src/typing/typeload.$(MODULE_EXT) src/typing/typecore.$(MODULE_EXT) src/typing/type.$(MODULE_EXT) src/generators/genxml.$(MODULE_EXT) src/typing/common.$(MODULE_EXT) src/syntax/ast.$(MODULE_EXT)
-
-src/typing/common.$(MODULE_EXT): src/typing/type.$(MODULE_EXT) src/syntax/ast.$(MODULE_EXT) libs/ilib/il.$(LIB_EXT)
-
-src/optimization/dce.$(MODULE_EXT): src/syntax/ast.$(MODULE_EXT) src/typing/common.$(MODULE_EXT) src/generators/codegen.$(MODULE_EXT) src/typing/type.$(MODULE_EXT)
-
-src/optimization/filters.$(MODULE_EXT): src/syntax/ast.$(MODULE_EXT) src/optimization/analyzer.$(MODULE_EXT) src/typing/common.$(MODULE_EXT) src/typing/type.$(MODULE_EXT) src/optimization/dce.$(MODULE_EXT) src/generators/codegen.$(MODULE_EXT) src/typing/typecore.$(MODULE_EXT)
+src/generators/codegen.$(MODULE_EXT): src/typing/typecore.$(MODULE_EXT) src/typing/type.$(MODULE_EXT) src/generators/genxml.$(MODULE_EXT) src/typing/common.$(MODULE_EXT) src/syntax/ast.$(MODULE_EXT)
 
 
 src/generators/genas3.$(MODULE_EXT): src/typing/type.$(MODULE_EXT) src/typing/common.$(MODULE_EXT) src/generators/codegen.$(MODULE_EXT) src/syntax/ast.$(MODULE_EXT)
 src/generators/genas3.$(MODULE_EXT): src/typing/type.$(MODULE_EXT) src/typing/common.$(MODULE_EXT) src/generators/codegen.$(MODULE_EXT) src/syntax/ast.$(MODULE_EXT)
 
 
-src/generators/gencommon.$(MODULE_EXT): src/typing/type.$(MODULE_EXT) src/typing/common.$(MODULE_EXT) src/generators/codegen.$(MODULE_EXT) src/syntax/ast.$(MODULE_EXT) libs/ilib/il.$(LIB_EXT)
+src/generators/gencommon.$(MODULE_EXT): src/typing/type.$(MODULE_EXT) src/typing/common.$(MODULE_EXT) src/generators/codegen.$(MODULE_EXT) src/syntax/ast.$(MODULE_EXT) src/typing/typeload.$(MODULE_EXT) libs/ilib/il.$(LIB_EXT)
 
 
 src/generators/gencpp.$(MODULE_EXT): src/typing/type.$(MODULE_EXT) src/syntax/lexer.$(MODULE_EXT) src/typing/common.$(MODULE_EXT) src/generators/codegen.$(MODULE_EXT) src/syntax/ast.$(MODULE_EXT) src/generators/gencommon.$(MODULE_EXT)
 src/generators/gencpp.$(MODULE_EXT): src/typing/type.$(MODULE_EXT) src/syntax/lexer.$(MODULE_EXT) src/typing/common.$(MODULE_EXT) src/generators/codegen.$(MODULE_EXT) src/syntax/ast.$(MODULE_EXT) src/generators/gencommon.$(MODULE_EXT)
 
 
@@ -148,7 +144,7 @@ src/generators/gencs.$(MODULE_EXT): src/typing/type.$(MODULE_EXT) src/syntax/lex
 
 
 src/generators/genjava.$(MODULE_EXT): src/typing/type.$(MODULE_EXT) src/generators/gencommon.$(MODULE_EXT) src/typing/common.$(MODULE_EXT) src/generators/codegen.$(MODULE_EXT) src/syntax/ast.$(MODULE_EXT)
 src/generators/genjava.$(MODULE_EXT): src/typing/type.$(MODULE_EXT) src/generators/gencommon.$(MODULE_EXT) src/typing/common.$(MODULE_EXT) src/generators/codegen.$(MODULE_EXT) src/syntax/ast.$(MODULE_EXT)
 
 
-src/generators/genjs.$(MODULE_EXT): src/typing/type.$(MODULE_EXT) src/optimization/optimizer.$(MODULE_EXT) src/syntax/lexer.$(MODULE_EXT) src/typing/common.$(MODULE_EXT) src/generators/codegen.$(MODULE_EXT) src/syntax/ast.$(MODULE_EXT)
+src/generators/genjs.$(MODULE_EXT): src/typing/type.$(MODULE_EXT) src/syntax/lexer.$(MODULE_EXT) src/typing/common.$(MODULE_EXT) src/generators/codegen.$(MODULE_EXT) src/syntax/ast.$(MODULE_EXT)
 
 
 src/generators/genneko.$(MODULE_EXT): src/typing/type.$(MODULE_EXT) src/syntax/lexer.$(MODULE_EXT) src/typing/common.$(MODULE_EXT) src/generators/codegen.$(MODULE_EXT) src/syntax/ast.$(MODULE_EXT)
 src/generators/genneko.$(MODULE_EXT): src/typing/type.$(MODULE_EXT) src/syntax/lexer.$(MODULE_EXT) src/typing/common.$(MODULE_EXT) src/generators/codegen.$(MODULE_EXT) src/syntax/ast.$(MODULE_EXT)
 
 
@@ -166,17 +162,43 @@ src/generators/genswf9.$(MODULE_EXT): src/typing/type.$(MODULE_EXT) src/syntax/l
 
 
 src/generators/genxml.$(MODULE_EXT): src/typing/type.$(MODULE_EXT) src/syntax/lexer.$(MODULE_EXT) src/typing/common.$(MODULE_EXT) src/syntax/ast.$(MODULE_EXT)
 src/generators/genxml.$(MODULE_EXT): src/typing/type.$(MODULE_EXT) src/syntax/lexer.$(MODULE_EXT) src/typing/common.$(MODULE_EXT) src/syntax/ast.$(MODULE_EXT)
 
 
+# macro
+
 src/macro/interp.$(MODULE_EXT): src/typing/typecore.$(MODULE_EXT) src/typing/type.$(MODULE_EXT) src/syntax/lexer.$(MODULE_EXT) src/generators/genneko.$(MODULE_EXT) src/typing/common.$(MODULE_EXT) src/generators/codegen.$(MODULE_EXT) src/syntax/ast.$(MODULE_EXT) src/generators/genswf.$(MODULE_EXT) src/generators/genjava.$(MODULE_EXT) src/generators/gencs.$(MODULE_EXT) src/syntax/parser.$(MODULE_EXT) libs/ilib/il.$(LIB_EXT)
 src/macro/interp.$(MODULE_EXT): src/typing/typecore.$(MODULE_EXT) src/typing/type.$(MODULE_EXT) src/syntax/lexer.$(MODULE_EXT) src/generators/genneko.$(MODULE_EXT) src/typing/common.$(MODULE_EXT) src/generators/codegen.$(MODULE_EXT) src/syntax/ast.$(MODULE_EXT) src/generators/genswf.$(MODULE_EXT) src/generators/genjava.$(MODULE_EXT) src/generators/gencs.$(MODULE_EXT) src/syntax/parser.$(MODULE_EXT) libs/ilib/il.$(LIB_EXT)
 
 
-src/typing/matcher.$(MODULE_EXT): src/optimization/optimizer.$(MODULE_EXT) src/generators/codegen.$(MODULE_EXT) src/typing/typecore.$(MODULE_EXT) src/typing/type.$(MODULE_EXT) src/typing/typer.$(MODULE_EXT) src/typing/common.$(MODULE_EXT) src/syntax/ast.$(MODULE_EXT)
+# optimization
 
 
-src/main.$(MODULE_EXT): src/optimization/filters.$(MODULE_EXT) src/typing/matcher.$(MODULE_EXT) src/typing/typer.$(MODULE_EXT) src/typing/typeload.$(MODULE_EXT) src/typing/typecore.$(MODULE_EXT) src/typing/type.$(MODULE_EXT) src/syntax/parser.$(MODULE_EXT) src/optimization/optimizer.$(MODULE_EXT) src/syntax/lexer.$(MODULE_EXT) src/macro/interp.$(MODULE_EXT) src/generators/genxml.$(MODULE_EXT) src/generators/genswf.$(MODULE_EXT) src/generators/genphp.$(MODULE_EXT) src/generators/genneko.$(MODULE_EXT) src/generators/genjs.$(MODULE_EXT) src/generators/genlua.$(MODULE_EXT) src/generators/gencpp.$(MODULE_EXT) src/generators/genas3.$(MODULE_EXT) src/typing/common.$(MODULE_EXT) src/generators/codegen.$(MODULE_EXT) src/syntax/ast.$(MODULE_EXT) src/generators/gencommon.$(MODULE_EXT) src/generators/genjava.$(MODULE_EXT) src/generators/gencs.$(MODULE_EXT) src/generators/genpy.$(MODULE_EXT) src/generators/genhl.$(MODULE_EXT) src/version.$(MODULE_EXT) libs/ilib/il.$(LIB_EXT)
+src/optimization/analyzer.$(MODULE_EXT): src/syntax/ast.$(MODULE_EXT) src/typing/type.$(MODULE_EXT) src/typing/common.$(MODULE_EXT) src/optimization/analyzerConfig.$(MODULE_EXT) src/optimization/analyzerTypes.$(MODULE_EXT) src/optimization/analyzerTexpr.$(MODULE_EXT) src/optimization/analyzerTexprTransformer.$(MODULE_EXT) src/generators/codegen.$(MODULE_EXT)
+
+src/optimization/analyzerConfig.$(MODULE_EXT): src/syntax/ast.$(MODULE_EXT) src/typing/type.$(MODULE_EXT) src/typing/common.$(MODULE_EXT)
+
+src/optimization/analyzerTexpr.$(MODULE_EXT): src/syntax/ast.$(MODULE_EXT) src/typing/type.$(MODULE_EXT) src/typing/common.$(MODULE_EXT) src/generators/codegen.$(MODULE_EXT) src/optimization/analyzerConfig.$(MODULE_EXT) src/optimization/optimizer.$(MODULE_EXT)
+
+src/optimization/analyzerTexprTransformer.$(MODULE_EXT): src/syntax/ast.$(MODULE_EXT) src/typing/type.$(MODULE_EXT) src/typing/common.$(MODULE_EXT) src/generators/codegen.$(MODULE_EXT) src/optimization/analyzerConfig.$(MODULE_EXT) src/optimization/analyzerTypes.$(MODULE_EXT) src/optimization/analyzerTexpr.$(MODULE_EXT)
+
+src/optimization/analyzerTypes.$(MODULE_EXT): src/syntax/ast.$(MODULE_EXT) src/typing/type.$(MODULE_EXT) src/typing/common.$(MODULE_EXT) src/optimization/analyzerConfig.$(MODULE_EXT)
+
+src/optimization/dce.$(MODULE_EXT): src/syntax/ast.$(MODULE_EXT) src/typing/common.$(MODULE_EXT) src/generators/codegen.$(MODULE_EXT) src/typing/type.$(MODULE_EXT)
+
+src/optimization/filters.$(MODULE_EXT): src/syntax/ast.$(MODULE_EXT) src/optimization/analyzer.$(MODULE_EXT) src/typing/common.$(MODULE_EXT) src/typing/type.$(MODULE_EXT) src/optimization/dce.$(MODULE_EXT) src/generators/codegen.$(MODULE_EXT) src/typing/typecore.$(MODULE_EXT)
 
 
 src/optimization/optimizer.$(MODULE_EXT): src/typing/typecore.$(MODULE_EXT) src/typing/type.$(MODULE_EXT) src/syntax/parser.$(MODULE_EXT) src/typing/common.$(MODULE_EXT) src/syntax/ast.$(MODULE_EXT)
 src/optimization/optimizer.$(MODULE_EXT): src/typing/typecore.$(MODULE_EXT) src/typing/type.$(MODULE_EXT) src/syntax/parser.$(MODULE_EXT) src/typing/common.$(MODULE_EXT) src/syntax/ast.$(MODULE_EXT)
 
 
+# syntax
+
+src/syntax/ast.$(MODULE_EXT):
+
+src/syntax/lexer.$(MODULE_EXT): src/syntax/lexer.ml src/syntax/ast.$(MODULE_EXT)
+
 src/syntax/parser.$(MODULE_EXT): src/syntax/parser.ml src/syntax/lexer.$(MODULE_EXT) src/typing/common.$(MODULE_EXT) src/syntax/ast.$(MODULE_EXT)
 src/syntax/parser.$(MODULE_EXT): src/syntax/parser.ml src/syntax/lexer.$(MODULE_EXT) src/typing/common.$(MODULE_EXT) src/syntax/ast.$(MODULE_EXT)
 	$(CC_PARSER_CMD)
 	$(CC_PARSER_CMD)
 
 
+# typing
+
+src/typing/common.$(MODULE_EXT): src/typing/type.$(MODULE_EXT) src/syntax/ast.$(MODULE_EXT) libs/ilib/il.$(LIB_EXT)
+
+src/typing/matcher.$(MODULE_EXT): src/optimization/optimizer.$(MODULE_EXT) src/generators/codegen.$(MODULE_EXT) src/typing/typecore.$(MODULE_EXT) src/typing/type.$(MODULE_EXT) src/typing/typer.$(MODULE_EXT) src/typing/common.$(MODULE_EXT) src/syntax/ast.$(MODULE_EXT)
+
 src/typing/type.$(MODULE_EXT): src/syntax/ast.$(MODULE_EXT)
 src/typing/type.$(MODULE_EXT): src/syntax/ast.$(MODULE_EXT)
 
 
 src/typing/typecore.$(MODULE_EXT): src/typing/type.$(MODULE_EXT) src/typing/common.$(MODULE_EXT) src/syntax/ast.$(MODULE_EXT)
 src/typing/typecore.$(MODULE_EXT): src/typing/type.$(MODULE_EXT) src/typing/common.$(MODULE_EXT) src/syntax/ast.$(MODULE_EXT)
@@ -186,9 +208,9 @@ src/typing/typeload.$(MODULE_EXT): src/typing/typecore.$(MODULE_EXT) src/typing/
 src/typing/typer.$(MODULE_EXT): src/typing/typeload.$(MODULE_EXT) src/typing/typecore.$(MODULE_EXT) src/typing/type.$(MODULE_EXT) src/syntax/parser.$(MODULE_EXT) src/optimization/optimizer.$(MODULE_EXT) src/syntax/lexer.$(MODULE_EXT) src/macro/interp.$(MODULE_EXT) src/typing/common.$(MODULE_EXT) src/generators/codegen.$(MODULE_EXT) src/syntax/ast.$(MODULE_EXT) src/optimization/filters.$(MODULE_EXT) src/generators/gencommon.$(MODULE_EXT) src/generators/genjs.$(MODULE_EXT) src/generators/genlua.$(MODULE_EXT)
 src/typing/typer.$(MODULE_EXT): src/typing/typeload.$(MODULE_EXT) src/typing/typecore.$(MODULE_EXT) src/typing/type.$(MODULE_EXT) src/syntax/parser.$(MODULE_EXT) src/optimization/optimizer.$(MODULE_EXT) src/syntax/lexer.$(MODULE_EXT) src/macro/interp.$(MODULE_EXT) src/typing/common.$(MODULE_EXT) src/generators/codegen.$(MODULE_EXT) src/syntax/ast.$(MODULE_EXT) src/optimization/filters.$(MODULE_EXT) src/generators/gencommon.$(MODULE_EXT) src/generators/genjs.$(MODULE_EXT) src/generators/genlua.$(MODULE_EXT)
 
 
 
 
-src/syntax/lexer.$(MODULE_EXT): src/syntax/lexer.ml src/syntax/ast.$(MODULE_EXT)
+# main
 
 
-src/syntax/ast.$(MODULE_EXT):
+src/main.$(MODULE_EXT): src/optimization/filters.$(MODULE_EXT) src/typing/matcher.$(MODULE_EXT) src/typing/typer.$(MODULE_EXT) src/typing/typeload.$(MODULE_EXT) src/typing/typecore.$(MODULE_EXT) src/typing/type.$(MODULE_EXT) src/syntax/parser.$(MODULE_EXT) src/optimization/optimizer.$(MODULE_EXT) src/syntax/lexer.$(MODULE_EXT) src/macro/interp.$(MODULE_EXT) src/generators/genxml.$(MODULE_EXT) src/generators/genswf.$(MODULE_EXT) src/generators/genphp.$(MODULE_EXT) src/generators/genneko.$(MODULE_EXT) src/generators/genjs.$(MODULE_EXT) src/generators/genlua.$(MODULE_EXT) src/generators/gencpp.$(MODULE_EXT) src/generators/genas3.$(MODULE_EXT) src/typing/common.$(MODULE_EXT) src/generators/codegen.$(MODULE_EXT) src/syntax/ast.$(MODULE_EXT) src/generators/gencommon.$(MODULE_EXT) src/generators/genjava.$(MODULE_EXT) src/generators/gencs.$(MODULE_EXT) src/generators/genpy.$(MODULE_EXT) src/generators/genhl.$(MODULE_EXT) src/version.$(MODULE_EXT) libs/ilib/il.$(LIB_EXT)
 
 
 src/version.$(MODULE_EXT):
 src/version.$(MODULE_EXT):
 	$(MAKE) -f Makefile.version_extra -s --no-print-directory ADD_REVISION=$(ADD_REVISION) BRANCH=$(BRANCH) COMMIT_SHA=$(COMMIT_SHA) COMMIT_DATE=$(COMMIT_DATE) > src/version.ml
 	$(MAKE) -f Makefile.version_extra -s --no-print-directory ADD_REVISION=$(ADD_REVISION) BRANCH=$(BRANCH) COMMIT_SHA=$(COMMIT_SHA) COMMIT_DATE=$(COMMIT_DATE) > src/version.ml

+ 5 - 5
Makefile.win

@@ -33,7 +33,7 @@ endif
 
 
 ifdef FILTER
 ifdef FILTER
 CC_CMD=($(OCAMLOPT) $(CFLAGS) -c $< 2>tmp.cmi && $(FILTER)) || ($(FILTER) && exit 1)
 CC_CMD=($(OCAMLOPT) $(CFLAGS) -c $< 2>tmp.cmi && $(FILTER)) || ($(FILTER) && exit 1)
-CC_PARSER_CMD=($(OCAMLOPT) -pp camlp4o $(CFLAGS) -c parser.ml 2>tmp.cmi && $(FILTER)) || ($(FILTER) && exit 1)
+CC_PARSER_CMD=($(OCAMLOPT) -pp camlp4o $(CFLAGS) -c src/syntax/parser.ml 2>tmp.cmi && $(FILTER)) || ($(FILTER) && exit 1)
 endif
 endif
 
 
 package_bin:
 package_bin:
@@ -42,11 +42,11 @@ package_bin:
 	# Copy the package contents to $(PACKAGE_FILE_NAME)
 	# Copy the package contents to $(PACKAGE_FILE_NAME)
 	# Using poor man's cp (zip then unzip), because cp in cygwin is quite broken
 	# Using poor man's cp (zip then unzip), because cp in cygwin is quite broken
 	mkdir -p $(PACKAGE_FILE_NAME)
 	mkdir -p $(PACKAGE_FILE_NAME)
-	7za a -y -tzip -mx0 temp.zip $(OUTPUT) haxelib$(EXTENSION) std > log.txt || type log.txt
-	cd extra && 7za a -y -tzip -mx0 ../temp.zip LICENSE.txt CONTRIB.txt CHANGES.txt > log.txt || type log.txt
-	7za x -y temp.zip -o$(PACKAGE_FILE_NAME) > log.txt || type log.txt
+	7z a -y -tzip -mx0 temp.zip $(OUTPUT) haxelib$(EXTENSION) std > log.txt || type log.txt
+	cd extra && 7z a -y -tzip -mx0 ../temp.zip LICENSE.txt CONTRIB.txt CHANGES.txt > log.txt || type log.txt
+	7z x -y temp.zip -o$(PACKAGE_FILE_NAME) > log.txt || type log.txt
 	rm temp.zip
 	rm temp.zip
 	# archive
 	# archive
-	7za a -r -tzip out/$(PACKAGE_FILE_NAME)_bin.zip $(PACKAGE_FILE_NAME) > log.txt || type log.txt
+	7z a -r -tzip out/$(PACKAGE_FILE_NAME)_bin.zip $(PACKAGE_FILE_NAME) > log.txt || type log.txt
 	rm -r $(PACKAGE_FILE_NAME)
 	rm -r $(PACKAGE_FILE_NAME)
 	rm log.txt extra/log.txt
 	rm log.txt extra/log.txt

+ 0 - 2
appveyor.yml

@@ -28,7 +28,6 @@ skip_tags: true
 
 
 install:
 install:
     - 'git submodule update --init --recursive'
     - 'git submodule update --init --recursive'
-    - cinst 7zip.commandline -y
     # Install ocaml using wodi
     # Install ocaml using wodi
     - appveyor DownloadFile "http://cygwin.com/setup-%CYG_ARCH%.exe" -FileName "%CYG_ROOT%\setup.exe"
     - appveyor DownloadFile "http://cygwin.com/setup-%CYG_ARCH%.exe" -FileName "%CYG_ROOT%\setup.exe"
     - '%CYG_ROOT%/setup.exe -g -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++ -P git > log.txt || type log.txt'
     - '%CYG_ROOT%/setup.exe -g -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++ -P git > log.txt || type log.txt'
@@ -60,7 +59,6 @@ build_script:
     - '%CYG_ROOT%/bin/bash -lc "cd \"$OLDPWD\" && make -s -f Makefile.win"'
     - '%CYG_ROOT%/bin/bash -lc "cd \"$OLDPWD\" && make -s -f Makefile.win"'
     - 'set PATH=%PATH%;%APPVEYOR_BUILD_FOLDER%'
     - 'set PATH=%PATH%;%APPVEYOR_BUILD_FOLDER%'
     - 'set HAXEPATH=%APPVEYOR_BUILD_FOLDER%'
     - 'set HAXEPATH=%APPVEYOR_BUILD_FOLDER%'
-    - '%CYG_ROOT%/bin/bash -lc "cd \"$OLDPWD\" && make -s -f Makefile.win tools"'
     - '%CYG_ROOT%/bin/bash -lc "cd \"$OLDPWD\" && make -s -f Makefile.win package_bin"'
     - '%CYG_ROOT%/bin/bash -lc "cd \"$OLDPWD\" && make -s -f Makefile.win package_bin"'
     - dir %APPVEYOR_BUILD_FOLDER%\out
     - dir %APPVEYOR_BUILD_FOLDER%\out
     - cd %APPVEYOR_BUILD_FOLDER%/tests/
     - cd %APPVEYOR_BUILD_FOLDER%/tests/

+ 1 - 0
extra/extract.patch

@@ -1196,6 +1196,7 @@ flash.system.Worker.state : WorkerState;
 flash.system.MessageChannel.state : MessageChannelState;
 flash.system.MessageChannel.state : MessageChannelState;
 
 
 enum flash.system.WorkerState;
 enum flash.system.WorkerState;
+enum flash.system.MessageChannelState;
 
 
 
 
 // ---  11.6 API
 // ---  11.6 API

+ 92 - 1
haxe.hxproj

@@ -157,6 +157,97 @@
     <hidden path="genhl.cmx" />
     <hidden path="genhl.cmx" />
     <hidden path="genhl.obj" />
     <hidden path="genhl.obj" />
     <hidden path="genhl.cmi" />
     <hidden path="genhl.cmi" />
+    <hidden path="src\version.obj" />
+    <hidden path="src\version.cmi" />
+    <hidden path="src\version.cmx" />
+    <hidden path="src\main.obj" />
+    <hidden path="src\main.cmx" />
+    <hidden path="src\main.cmi" />
+    <hidden path="src\typing\typer.obj" />
+    <hidden path="src\typing\typer.cmx" />
+    <hidden path="src\typing\typer.cmi" />
+    <hidden path="src\typing\typeload.obj" />
+    <hidden path="src\typing\typeload.cmx" />
+    <hidden path="src\typing\typeload.cmi" />
+    <hidden path="src\typing\typecore.obj" />
+    <hidden path="src\typing\typecore.cmx" />
+    <hidden path="src\typing\typecore.cmi" />
+    <hidden path="src\typing\type.obj" />
+    <hidden path="src\typing\type.cmx" />
+    <hidden path="src\typing\type.cmi" />
+    <hidden path="src\typing\matcher.obj" />
+    <hidden path="src\typing\matcher.cmx" />
+    <hidden path="src\typing\matcher.cmi" />
+    <hidden path="src\typing\common.obj" />
+    <hidden path="src\typing\common.cmx" />
+    <hidden path="src\typing\common.cmi" />
+    <hidden path="src\syntax\parser.obj" />
+    <hidden path="src\syntax\parser.cmx" />
+    <hidden path="src\syntax\parser.cmi" />
+    <hidden path="src\syntax\lexer.obj" />
+    <hidden path="src\syntax\lexer.ml" />
+    <hidden path="src\syntax\lexer.cmx" />
+    <hidden path="src\syntax\lexer.cmi" />
+    <hidden path="src\syntax\ast.obj" />
+    <hidden path="src\syntax\ast.cmx" />
+    <hidden path="src\syntax\ast.cmi" />
+    <hidden path="src\optimization\optimizer.obj" />
+    <hidden path="src\optimization\optimizer.cmx" />
+    <hidden path="src\optimization\optimizer.cmi" />
+    <hidden path="src\optimization\filters.obj" />
+    <hidden path="src\optimization\filters.cmx" />
+    <hidden path="src\optimization\filters.cmi" />
+    <hidden path="src\optimization\dce.obj" />
+    <hidden path="src\optimization\dce.cmi" />
+    <hidden path="src\optimization\analyzer.obj" />
+    <hidden path="src\optimization\dce.cmx" />
+    <hidden path="src\optimization\analyzer.cmx" />
+    <hidden path="src\optimization\analyzer.cmi" />
+    <hidden path="src\macro\interp.obj" />
+    <hidden path="src\macro\interp.cmx" />
+    <hidden path="src\macro\interp.cmi" />
+    <hidden path="src\generators\genxml.obj" />
+    <hidden path="src\generators\genxml.cmx" />
+    <hidden path="src\generators\genxml.cmi" />
+    <hidden path="src\generators\genswf9.obj" />
+    <hidden path="src\generators\genswf9.cmi" />
+    <hidden path="src\generators\genswf9.cmx" />
+    <hidden path="src\generators\genswf.obj" />
+    <hidden path="src\generators\genswf.cmx" />
+    <hidden path="src\generators\genswf.cmi" />
+    <hidden path="src\generators\genpy.obj" />
+    <hidden path="src\generators\genpy.cmx" />
+    <hidden path="src\generators\genpy.cmi" />
+    <hidden path="src\generators\genphp.obj" />
+    <hidden path="src\generators\genphp.cmx" />
+    <hidden path="src\generators\genneko.obj" />
+    <hidden path="src\generators\genphp.cmi" />
+    <hidden path="src\generators\genneko.cmx" />
+    <hidden path="src\generators\genneko.cmi" />
+    <hidden path="src\generators\genjs.obj" />
+    <hidden path="src\generators\genjs.cmx" />
+    <hidden path="src\generators\genjs.cmi" />
+    <hidden path="src\generators\genjava.obj" />
+    <hidden path="src\generators\genjava.cmx" />
+    <hidden path="src\generators\genjava.cmi" />
+    <hidden path="src\generators\genhl.obj" />
+    <hidden path="src\generators\genhl.cmx" />
+    <hidden path="src\generators\genhl.cmi" />
+    <hidden path="src\generators\gencs.obj" />
+    <hidden path="src\generators\gencs.cmx" />
+    <hidden path="src\generators\gencs.cmi" />
+    <hidden path="src\generators\gencpp.obj" />
+    <hidden path="src\generators\gencpp.cmx" />
+    <hidden path="src\generators\gencpp.cmi" />
+    <hidden path="src\generators\gencommon.obj" />
+    <hidden path="src\generators\gencommon.cmx" />
+    <hidden path="src\generators\gencommon.cmi" />
+    <hidden path="src\generators\genas3.obj" />
+    <hidden path="src\generators\genas3.cmx" />
+    <hidden path="src\generators\genas3.cmi" />
+    <hidden path="src\generators\codegen.obj" />
+    <hidden path="src\generators\codegen.cmx" />
+    <hidden path="src\generators\codegen.cmi" />
   </hiddenPaths>
   </hiddenPaths>
   <!-- Executed before build -->
   <!-- Executed before build -->
   <preBuildCommand>make -j4 MSVC=1 FD_OUTPUT=1 -f Makefile.win kill haxe</preBuildCommand>
   <preBuildCommand>make -j4 MSVC=1 FD_OUTPUT=1 -f Makefile.win kill haxe</preBuildCommand>
@@ -165,7 +256,7 @@
   <!-- Other project options -->
   <!-- Other project options -->
   <options>
   <options>
     <option showHiddenPaths="False" />
     <option showHiddenPaths="False" />
-    <option testMovie="Default" />
+    <option testMovie="Custom" />
     <option testMovieCommand="" />
     <option testMovieCommand="" />
   </options>
   </options>
   <!-- Plugin storage -->
   <!-- Plugin storage -->

+ 0 - 562
src/generators/codegen.ml

@@ -134,447 +134,6 @@ let escape_res_name name allow_dirs =
 		else
 		else
 			"-x" ^ (string_of_int (Char.code chr))) name
 			"-x" ^ (string_of_int (Char.code chr))) name
 
 
-(* -------------------------------------------------------------------------- *)
-(* REMOTING PROXYS *)
-
-let extend_remoting ctx c t p async prot =
-	if c.cl_super <> None then error "Cannot extend several classes" p;
-	(* remove forbidden packages *)
-	let rules = ctx.com.package_rules in
-	ctx.com.package_rules <- PMap.foldi (fun key r acc -> match r with Forbidden -> acc | _ -> PMap.add key r acc) rules PMap.empty;
-	(* parse module *)
-	let path = (t.tpackage,t.tname) in
-	let new_name = (if async then "Async_" else "Remoting_") ^ t.tname in
-	(* check if the proxy already exists *)
-	let t = (try
-		Typeload.load_type_def ctx p { tpackage = fst path; tname = new_name; tparams = []; tsub = None }
-	with
-		Error (Module_not_found _,p2) when p == p2 ->
-	(* build it *)
-	Common.log ctx.com ("Building proxy for " ^ s_type_path path);
-	let file, decls = (try
-		Typeload.parse_module ctx path p
-	with
-		| Not_found -> ctx.com.package_rules <- rules; error ("Could not load proxy module " ^ s_type_path path ^ (if fst path = [] then " (try using absolute path)" else "")) p
-		| e -> ctx.com.package_rules <- rules; raise e) in
-	ctx.com.package_rules <- rules;
-	let base_fields = [
-		{ cff_name = "__cnx"; cff_pos = p; cff_doc = None; cff_meta = []; cff_access = []; cff_kind = FVar (Some (CTPath { tpackage = ["haxe";"remoting"]; tname = if async then "AsyncConnection" else "Connection"; tparams = []; tsub = None }),None) };
-		{ cff_name = "new"; cff_pos = p; cff_doc = None; cff_meta = []; cff_access = [APublic]; cff_kind = FFun { f_args = ["c",false,None,None]; f_type = None; f_expr = Some (EBinop (OpAssign,(EConst (Ident "__cnx"),p),(EConst (Ident "c"),p)),p); f_params = [] } };
-	] in
-	let tvoid = CTPath { tpackage = []; tname = "Void"; tparams = []; tsub = None } in
-	let build_field is_public acc f =
-		if f.cff_name = "new" then
-			acc
-		else match f.cff_kind with
-		| FFun fd when (is_public || List.mem APublic f.cff_access) && not (List.mem AStatic f.cff_access) ->
-			if List.exists (fun (_,_,t,_) -> t = None) fd.f_args then error ("Field " ^ f.cff_name ^ " type is not complete and cannot be used by RemotingProxy") p;
-			let eargs = [EArrayDecl (List.map (fun (a,_,_,_) -> (EConst (Ident a),p)) fd.f_args),p] in
-			let ftype = (match fd.f_type with Some (CTPath { tpackage = []; tname = "Void" }) -> None | _ -> fd.f_type) in
-			let fargs, eargs = if async then match ftype with
-				| Some tret -> fd.f_args @ ["__callb",true,Some (CTFunction ([tret],tvoid)),None], eargs @ [EConst (Ident "__callb"),p]
-				| _ -> fd.f_args, eargs @ [EConst (Ident "null"),p]
-			else
-				fd.f_args, eargs
-			in
-			let id = (EConst (String f.cff_name), p) in
-			let id = if prot then id else ECall ((EConst (Ident "__unprotect__"),p),[id]),p in
-			let expr = ECall (
-				(EField (
-					(ECall ((EField ((EConst (Ident "__cnx"),p),"resolve"),p),[id]),p),
-					"call")
-				,p),eargs),p
-			in
-			let expr = if async || ftype = None then expr else (EReturn (Some expr),p) in
-			let fd = {
-				f_params = fd.f_params;
-				f_args = fargs;
-				f_type = if async then None else ftype;
-				f_expr = Some (EBlock [expr],p);
-			} in
-			{ cff_name = f.cff_name; cff_pos = f.cff_pos; cff_doc = None; cff_meta = []; cff_access = [APublic]; cff_kind = FFun fd } :: acc
-		| _ -> acc
-	in
-	let decls = List.map (fun d ->
-		match d with
-		| EClass c, p when c.d_name = t.tname ->
-			let is_public = List.mem HExtern c.d_flags || List.mem HInterface c.d_flags in
-			let fields = List.rev (List.fold_left (build_field is_public) base_fields c.d_data) in
-			(EClass { c with d_flags = []; d_name = new_name; d_data = fields },p)
-		| _ -> d
-	) decls in
-	let m = Typeload.type_module ctx (t.tpackage,new_name) file decls p in
-	add_dependency ctx.m.curmod m;
-	try
-		List.find (fun tdecl -> snd (t_path tdecl) = new_name) m.m_types
-	with Not_found ->
-		error ("Module " ^ s_type_path path ^ " does not define type " ^ t.tname) p
-	) in
-	match t with
-	| 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
-
-(* -------------------------------------------------------------------------- *)
-(* HAXE.RTTI.GENERIC *)
-
-exception Generic_Exception of string * Ast.pos
-
-type generic_context = {
-	ctx : typer;
-	subst : (t * t) list;
-	name : string;
-	p : pos;
-	mutable mg : module_def option;
-}
-
-let make_generic ctx ps pt p =
-	let rec loop l1 l2 =
-		match l1, l2 with
-		| [] , [] -> []
-		| (x,TLazy f) :: l1, _ -> loop ((x,(!f)()) :: l1) l2
-		| (_,t1) :: l1 , t2 :: l2 -> (t1,t2) :: loop l1 l2
-		| _ -> assert false
-	in
-	let name =
-		String.concat "_" (List.map2 (fun (s,_) t ->
-			let s_type_path_underscore (p,s) = match p with [] -> s | _ -> String.concat "_" p ^ "_" ^ s in
-			let rec loop top t = match follow t with
-				| TInst(c,tl) -> (s_type_path_underscore c.cl_path) ^ (loop_tl tl)
-				| TEnum(en,tl) -> (s_type_path_underscore en.e_path) ^ (loop_tl tl)
-				| TAbstract(a,tl) -> (s_type_path_underscore a.a_path) ^ (loop_tl tl)
-				| _ when not top -> "_" (* allow unknown/incompatible types as type parameters to retain old behavior *)
-				| TMono _ -> raise (Generic_Exception (("Could not determine type for parameter " ^ s), p))
-				| TDynamic _ -> "Dynamic"
-				| t -> raise (Generic_Exception (("Type parameter must be a class or enum instance (found " ^ (s_type (print_context()) t) ^ ")"), p))
-			and loop_tl tl = match tl with
-				| [] -> ""
-				| tl -> "_" ^ String.concat "_" (List.map (loop false) tl)
-			in
-			loop true t
-		) ps pt)
-	in
-	{
-		ctx = ctx;
-		subst = loop ps pt;
-		name = name;
-		p = p;
-		mg = None;
-	}
-
-let rec generic_substitute_type gctx t =
-	match t with
-	| TInst ({ cl_kind = KGeneric } as c2,tl2) ->
-		(* maybe loop, or generate cascading generics *)
-		let _, _, f = gctx.ctx.g.do_build_instance gctx.ctx (TClassDecl c2) gctx.p in
-		let t = f (List.map (generic_substitute_type gctx) tl2) in
-		(match follow t,gctx.mg with TInst(c,_), Some m -> add_dependency m c.cl_module | _ -> ());
-		t
-	| _ ->
-		try
-			generic_substitute_type gctx (List.assq t gctx.subst)
-		with Not_found ->
-			Type.map (generic_substitute_type gctx) t
-
-let generic_substitute_expr gctx e =
-	let vars = Hashtbl.create 0 in
-	let build_var v =
-		try
-			Hashtbl.find vars v.v_id
-		with Not_found ->
-			let v2 = alloc_var v.v_name (generic_substitute_type gctx v.v_type) in
-			v2.v_meta <- v.v_meta;
-			Hashtbl.add vars v.v_id v2;
-			v2
-	in
-	let rec build_expr e =
-		match e.eexpr with
-		| TField(e1, FInstance({cl_kind = KGeneric} as c,tl,cf)) ->
-			let _, _, f = gctx.ctx.g.do_build_instance gctx.ctx (TClassDecl c) gctx.p in
-			let t = f (List.map (generic_substitute_type gctx) tl) in
-			let fa = try
-				quick_field t cf.cf_name
-			with Not_found ->
-				error (Printf.sprintf "Type %s has no field %s (possible typing order issue)" (s_type (print_context()) t) cf.cf_name) e.epos
-			in
-			build_expr {e with eexpr = TField(e1,fa)}
-		| TTypeExpr (TClassDecl ({cl_kind = KTypeParameter _;} as c)) when Meta.has Meta.Const c.cl_meta ->
-			let rec loop subst = match subst with
-				| (t1,t2) :: subst ->
-					begin match follow t1 with
-						| TInst(c2,_) when c == c2 -> t2
-						| _ -> loop subst
-					end
-				| [] -> raise Not_found
-			in
-			begin try
-				let t = loop gctx.subst in
-				begin match follow t with
-					| TInst({cl_kind = KExpr e},_) -> type_expr gctx.ctx e Value
-					| _ -> error "Only Const type parameters can be used as value" e.epos
-				end
-			with Not_found ->
-				e
-			end
-		| _ ->
-			map_expr_type build_expr (generic_substitute_type gctx) build_var e
-	in
-	build_expr e
-
-let has_ctor_constraint c = match c.cl_kind with
-	| KTypeParameter tl ->
-		List.exists (fun t -> match follow t with
-			| TAnon a when PMap.mem "new" a.a_fields -> true
-			| TAbstract({a_path=["haxe"],"Constructible"},_) -> true
-			| _ -> false
-		) tl;
-	| _ -> false
-
-let get_short_name =
-	let i = ref (-1) in
-	(fun () ->
-		incr i;
-		Printf.sprintf "Hx___short___hx_type_%i" !i
-	)
-
-let rec build_generic ctx c p tl =
-	let pack = fst c.cl_path in
-	let recurse = ref false in
-	let rec check_recursive t =
-		match follow t with
-		| TInst (c2,tl) ->
-			(match c2.cl_kind with
-			| KTypeParameter tl ->
-				if not (Typeload.is_generic_parameter ctx c2) && has_ctor_constraint c2 then
-					error "Type parameters with a constructor cannot be used non-generically" p;
-				recurse := true
-			| _ -> ());
-			List.iter check_recursive tl;
-		| _ ->
-			()
-	in
-	List.iter check_recursive tl;
-	if !recurse then begin
-		TInst (c,tl) (* build a normal instance *)
-	end else begin
-	let gctx = make_generic ctx c.cl_params tl p in
-	let name = (snd c.cl_path) ^ "_" ^ gctx.name in
-	try
-		Typeload.load_instance ctx { tpackage = pack; tname = name; tparams = []; tsub = None } p false
-	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
-		ignore(c.cl_build()); (* make sure the super class is already setup *)
-		let mg = {
-			m_id = alloc_mid();
-			m_path = (pack,name);
-			m_types = [];
-			m_extra = module_extra (s_type_path (pack,name)) m.m_extra.m_sign 0. MFake;
-		} in
-		gctx.mg <- Some mg;
-		let cg = mk_class mg (pack,name) c.cl_pos in
-		mg.m_types <- [TClassDecl cg];
-		Hashtbl.add ctx.g.modules mg.m_path mg;
-		add_dependency mg m;
-		add_dependency ctx.m.curmod mg;
-		(* ensure that type parameters are set in dependencies *)
-		let dep_stack = ref [] in
-		let rec loop t =
-			if not (List.memq t !dep_stack) then begin
-			dep_stack := t :: !dep_stack;
-			match t with
-			| TInst (c,tl) -> add_dep c.cl_module tl
-			| TEnum (e,tl) -> add_dep e.e_module tl
-			| TType (t,tl) -> add_dep t.t_module tl
-			| TAbstract (a,tl) -> add_dep a.a_module tl
-			| TMono r ->
-				(match !r with
-				| None -> ()
-				| Some t -> loop t)
-			| TLazy f ->
-				loop ((!f)());
-			| TDynamic t2 ->
-				if t == t2 then () else loop t2
-			| TAnon a ->
-				PMap.iter (fun _ f -> loop f.cf_type) a.a_fields
-			| TFun (args,ret) ->
-				List.iter (fun (_,_,t) -> loop t) args;
-				loop ret
-			end
-		and add_dep m tl =
-			add_dependency mg m;
-			List.iter loop tl
-		in
-		List.iter loop tl;
-		let build_field cf_old =
-			(* We have to clone the type parameters (issue #4672). We cannot substitute the constraints immediately because
-		       we need the full substitution list first. *)
-			let param_subst,params = List.fold_left (fun (subst,params) (s,t) -> match follow t with
-				| TInst(c,tl) as t ->
-					let t2 = TInst({c with cl_pos = c.cl_pos;},tl) in
-					(t,t2) :: subst,(s,t2) :: params
-				| _ -> assert false
-			) ([],[]) cf_old.cf_params in
-			let gctx = {gctx with subst = param_subst @ gctx.subst} in
-			let cf_new = {cf_old with cf_pos = cf_old.cf_pos} in (* copy *)
-			(* Type parameter constraints are substituted here. *)
-			cf_new.cf_params <- List.rev_map (fun (s,t) -> match follow t with
-				| TInst({cl_kind = KTypeParameter tl1} as c,_) ->
-					let tl1 = List.map (generic_substitute_type gctx) tl1 in
-					c.cl_kind <- KTypeParameter tl1;
-					s,t
-				| _ -> assert false
-			) params;
-			let f () =
-				let t = generic_substitute_type gctx cf_old.cf_type in
-				ignore (follow t);
-				begin try (match cf_old.cf_expr with
-					| None ->
-						begin match cf_old.cf_kind with
-							| Method _ when not c.cl_interface && not c.cl_extern ->
-								display_error ctx (Printf.sprintf "Field %s has no expression (possible typing order issue)" cf_new.cf_name) cf_new.cf_pos;
-								display_error ctx (Printf.sprintf "While building %s" (s_type_path cg.cl_path)) p;
-							| _ ->
-								()
-						end
-					| Some e ->
-						cf_new.cf_expr <- Some (generic_substitute_expr gctx e)
-				) with Unify_error l ->
-					error (error_msg (Unify l)) cf_new.cf_pos
-				end;
-				t
-			in
-			let r = exc_protect ctx (fun r ->
-				let t = mk_mono() in
-				r := (fun() -> t);
-				unify_raise ctx (f()) t p;
-				t
-			) "build_generic" in
-			delay ctx PForce (fun() -> ignore ((!r)()));
-			cf_new.cf_type <- TLazy r;
-			cf_new
-		in
-		if c.cl_init <> None || c.cl_dynamic <> None then error "This class can't be generic" p;
-		List.iter (fun cf -> match cf.cf_kind with
-			| Method MethMacro when not ctx.in_macro -> ()
-			| _ -> error "A generic class can't have static fields" cf.cf_pos
-		) c.cl_ordered_statics;
-		cg.cl_super <- (match c.cl_super with
-			| None -> None
-			| Some (cs,pl) ->
-				let find_class subst =
-					let rec loop subst = match subst with
-						| (TInst(c,[]),t) :: subst when c == cs -> t
-						| _ :: subst -> loop subst
-						| [] -> raise Not_found
-					in
-					try
-						if pl <> [] then raise Not_found;
-						let t = loop subst in
-						(* 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 ->
-								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
-									| _ -> ()
-								end;
-							| _,Some cf -> error "Generics extending type parameters cannot have constructors" cf.cf_pos
-							| _ -> ()
-						end;
-						t
-					with Not_found ->
-						apply_params c.cl_params tl (TInst(cs,pl))
-				in
-				let ts = follow (find_class gctx.subst) in
-				let cs,pl = Typeload.Inheritance.check_extends ctx c ts p in
-				match cs.cl_kind with
-				| KGeneric ->
-					(match build_generic ctx cs p pl with
-					| TInst (cs,pl) -> Some (cs,pl)
-					| _ -> assert false)
-				| _ -> Some(cs,pl)
-		);
-		Typeload.add_constructor ctx cg false p;
-		cg.cl_kind <- KGenericInstance (c,tl);
-		cg.cl_meta <- (Meta.NoDoc,[],p) :: cg.cl_meta;
-		if has_meta Meta.Keep c.cl_meta then cg.cl_meta <- (Meta.Keep,[],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)
-			| Some ctor, _, _ -> Some ctor
-			| None, None, None -> None
-			| _ -> error "Please define a constructor for this class in order to use it as generic" c.cl_pos
-		);
-		cg.cl_implements <- List.map (fun (i,tl) ->
-			(match follow (generic_substitute_type gctx (TInst (i, List.map (generic_substitute_type gctx) tl))) with
-			| TInst (i,tl) -> i, tl
-			| _ -> assert false)
-		) c.cl_implements;
-		cg.cl_ordered_fields <- List.map (fun f ->
-			let f = build_field f in
-			cg.cl_fields <- PMap.add f.cf_name f cg.cl_fields;
-			f
-		) c.cl_ordered_fields;
-		cg.cl_overrides <- List.map (fun f ->
-			try PMap.find f.cf_name cg.cl_fields with Not_found -> assert false
-		) c.cl_overrides;
-		(* 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
-			cg.cl_meta <- (Meta.Native,[EConst(String (n)),p],p) :: cg.cl_meta;
-		end;
-		TInst (cg,[])
-	end
-
-(* -------------------------------------------------------------------------- *)
-(* HAXE.XML.PROXY *)
-
-let extend_xml_proxy ctx c t file p =
-	let t = Typeload.load_complex_type ctx p t in
-	let file = (try Common.find_file ctx.com file with Not_found -> file) in
-	add_dependency c.cl_module (create_fake_module ctx file);
-	let used = ref PMap.empty in
-	let print_results() =
-		PMap.iter (fun id used ->
-			if not used then ctx.com.warning (id ^ " is not used") p;
-		) (!used)
-	in
-	let check_used = Common.defined ctx.com Define.CheckXmlProxy in
-	if check_used then ctx.g.hook_generate <- print_results :: ctx.g.hook_generate;
-	try
-		let rec loop = function
-			| Xml.Element (_,attrs,childs) ->
-				(try
-					let id = List.assoc "id" attrs in
-					if PMap.mem id c.cl_fields then error ("Duplicate id " ^ id) p;
-					let t = if not check_used then t else begin
-						used := PMap.add id false (!used);
-						let ft() = used := PMap.add id true (!used); t in
-						TLazy (ref ft)
-					end in
-					let f = {
-						cf_name = id;
-						cf_type = t;
-						cf_public = true;
-						cf_pos = p;
-						cf_doc = None;
-						cf_meta = no_meta;
-						cf_kind = Var { v_read = AccResolve; v_write = AccNo };
-						cf_params = [];
-						cf_expr = None;
-						cf_overloads = [];
-					} in
-					c.cl_fields <- PMap.add id f c.cl_fields;
-				with
-					Not_found -> ());
-				List.iter loop childs;
-			| Xml.PCData _ -> ()
-		in
-		loop (Xml.parse_file file)
-	with
-		| Xml.Error e -> error ("XML error " ^ Xml.error e) p
-		| Xml.File_not_found f -> error ("XML File not found : " ^ f) p
-
 (* -------------------------------------------------------------------------- *)
 (* -------------------------------------------------------------------------- *)
 (* BUILD META DATA OBJECT *)
 (* BUILD META DATA OBJECT *)
 
 
@@ -617,127 +176,6 @@ let build_metadata com t =
 		let meta_obj = (try ("obj", make_meta_field (List.assoc "" meta)) :: meta_obj with Not_found -> meta_obj) in
 		let meta_obj = (try ("obj", make_meta_field (List.assoc "" meta)) :: meta_obj with Not_found -> meta_obj) in
 		Some (mk (TObjectDecl meta_obj) t_dynamic p)
 		Some (mk (TObjectDecl meta_obj) t_dynamic p)
 
 
-(* -------------------------------------------------------------------------- *)
-(* MACRO TYPE *)
-
-let get_macro_path ctx e args p =
-	let rec loop e =
-		match fst e with
-		| EField (e,f) -> f :: loop e
-		| EConst (Ident i) -> [i]
-		| _ -> error "Invalid macro call" p
-	in
-	let path = match e with
-		| (EConst(Ident i)),_ ->
-			let path = try
-				if not (PMap.mem i ctx.curclass.cl_statics) then raise Not_found;
-				ctx.curclass.cl_path
-			with Not_found -> try
-				(t_infos (fst (PMap.find i ctx.m.module_globals))).mt_path
-			with Not_found ->
-				error "Invalid macro call" p
-			in
-			i :: (snd path) :: (fst path)
-		| _ ->
-			loop e
-	in
-	(match path with
-	| meth :: cl :: path -> (List.rev path,cl), meth, args
-	| _ -> error "Invalid macro call" p)
-
-let build_macro_type ctx pl p =
-	let path, field, args = (match pl with
-		| [TInst ({ cl_kind = KExpr (ECall (e,args),_) },_)]
-		| [TInst ({ cl_kind = KExpr (EArrayDecl [ECall (e,args),_],_) },_)] ->
-			get_macro_path ctx e args p
-		| _ ->
-			error "MacroType requires a single expression call parameter" p
-	) in
-	let old = ctx.ret in
-	let t = (match ctx.g.do_macro ctx MMacroType path field args p with
-		| None -> mk_mono()
-		| Some _ -> ctx.ret
-	) in
-	ctx.ret <- old;
-	t
-
-let build_macro_build ctx c pl cfl p =
-	let path, field, args = match Meta.get Meta.GenericBuild c.cl_meta with
-		| _,[ECall(e,args),_],_ -> get_macro_path ctx e args p
-		| _ -> error "genericBuild requires a single expression call parameter" p
-	in
-	let old = ctx.ret,ctx.g.get_build_infos in
-	ctx.g.get_build_infos <- (fun() -> Some (TClassDecl c, pl, cfl));
-	let t = (match ctx.g.do_macro ctx MMacroType path field args p with
-		| None -> mk_mono()
-		| Some _ -> ctx.ret
-	) in
-	ctx.ret <- fst old;
-	ctx.g.get_build_infos <- snd old;
-	t
-
-(* -------------------------------------------------------------------------- *)
-(* API EVENTS *)
-
-let build_instance ctx mtype p =
-	match mtype with
-	| TClassDecl c ->
-		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
-				r := (fun() -> t);
-				let tf = (f()) in
-				unify_raise ctx tf t p;
-				link_dynamic t tf;
-				t
-			) s in
-			delay ctx PForce (fun() -> ignore ((!r)()));
-			TLazy r
-		in
-		let ft = (fun pl ->
-			match c.cl_kind with
-			| KGeneric ->
-				build (fun () -> build_generic ctx c p pl) "build_generic"
-			| KMacroType ->
-				build (fun () -> build_macro_type ctx pl p) "macro_type"
-			| KGenericBuild cfl ->
-				build (fun () -> build_macro_build ctx c pl cfl p) "generic_build"
-			| _ ->
-				TInst (c,pl)
-		) in
-		c.cl_params , c.cl_path , ft
-	| TEnumDecl e ->
-		e.e_params , e.e_path , (fun t -> TEnum (e,t))
-	| TTypeDecl t ->
-		t.t_params , t.t_path , (fun tl -> TType(t,tl))
-	| TAbstractDecl a ->
-		a.a_params, a.a_path, (fun tl -> TAbstract(a,tl))
-
-let on_inherit ctx c p (is_extends,tp) =
-	if not is_extends then
-		true
-	else match tp with
-	| { tpackage = ["haxe";"remoting"]; tname = "Proxy"; tparams = [TPType(CTPath t)] } ->
-		extend_remoting ctx c t p false true;
-		false
-	| { tpackage = ["haxe";"remoting"]; tname = "AsyncProxy"; tparams = [TPType(CTPath t)] } ->
-		extend_remoting ctx c t p true true;
-		false
-	| { tpackage = ["haxe";"xml"]; tname = "Proxy"; tparams = [TPExpr(EConst (String file),p);TPType t] } ->
-		extend_xml_proxy ctx c t file p;
-		true
-	| _ ->
-		true
-
-let push_this ctx e = match e.eexpr with
-	| TConst ((TInt _ | TFloat _ | TString _ | TBool _) as ct) ->
-		(EConst (tconst_to_const ct),e.epos),fun () -> ()
-	| _ ->
-		ctx.this_stack <- e :: ctx.this_stack;
-		let er = EMeta((Meta.This,[],e.epos), (EConst(Ident "this"),e.epos)),e.epos in
-		er,fun () -> ctx.this_stack <- List.tl ctx.this_stack
-
 (* -------------------------------------------------------------------------- *)
 (* -------------------------------------------------------------------------- *)
 (* ABSTRACT CASTS *)
 (* ABSTRACT CASTS *)
 
 

+ 1 - 1
src/generators/genas3.ml

@@ -146,7 +146,7 @@ let valid_as3_ident s =
 
 
 let anon_field s =
 let anon_field s =
 	let s = s_ident s in
 	let s = s_ident s in
-	if not (valid_as3_ident s) then "\"" ^ s ^ "\"" else s
+	if not (valid_as3_ident s) then "\"" ^ (Ast.s_escape s) ^ "\"" else s
 
 
 let rec create_dir acc = function
 let rec create_dir acc = function
 	| [] -> ()
 	| [] -> ()

File diff suppressed because it is too large
+ 173 - 375
src/generators/gencpp.ml


+ 29 - 7
src/generators/genhl.ml

@@ -296,7 +296,7 @@ type access =
 	| AArray of reg * (ttype * ttype) * reg
 	| AArray of reg * (ttype * ttype) * reg
 	| AVirtualMethod of texpr * field index
 	| AVirtualMethod of texpr * field index
 	| ADynamic of texpr * string index
 	| ADynamic of texpr * string index
-	| AEnum of field index
+	| AEnum of tenum * field index
 	| ACaptured of field index
 	| ACaptured of field index
 
 
 let null_proto =
 let null_proto =
@@ -1374,7 +1374,7 @@ and get_access ctx e =
 			ADynamic (ethis, alloc_string ctx name)
 			ADynamic (ethis, alloc_string ctx name)
 		| FEnum (e,ef), _ ->
 		| FEnum (e,ef), _ ->
 			(match follow ef.ef_type with
 			(match follow ef.ef_type with
-			| TFun _ -> AEnum ef.ef_index
+			| TFun _ -> AEnum (e,ef.ef_index)
 			| t -> AGlobal (alloc_global ctx (efield_name e ef) (to_type ctx t))))
 			| t -> AGlobal (alloc_global ctx (efield_name e ef) (to_type ctx t))))
 	| TLocal v ->
 	| TLocal v ->
 		(match captured_index ctx v with
 		(match captured_index ctx v with
@@ -1815,17 +1815,22 @@ and eval_expr ctx e =
 			let ro = alloc_tmp ctx t in
 			let ro = alloc_tmp ctx t in
 			let rb = alloc_tmp ctx HBytes in
 			let rb = alloc_tmp ctx HBytes in
 			let ridx = reg_int ctx 0 in
 			let ridx = reg_int ctx 0 in
+			let has_len = (match t with HObj p -> PMap.mem "dataLen" p.pindex | _ -> assert false) in
 			iteri (fun i (k,v) ->
 			iteri (fun i (k,v) ->
 				op ctx (ONew ro);
 				op ctx (ONew ro);
 				op ctx (OString (rb,alloc_string ctx k));
 				op ctx (OString (rb,alloc_string ctx k));
 				op ctx (OSetField (ro,0,rb));
 				op ctx (OSetField (ro,0,rb));
 				op ctx (OBytes (rb,alloc_string ctx (v ^ "\x00"))); (* add a \x00 to prevent clashing with existing string *)
 				op ctx (OBytes (rb,alloc_string ctx (v ^ "\x00"))); (* add a \x00 to prevent clashing with existing string *)
 				op ctx (OSetField (ro,1,rb));
 				op ctx (OSetField (ro,1,rb));
-				op ctx (OSetField (ro,2,reg_int ctx (String.length v)));
+				if has_len then op ctx (OSetField (ro,2,reg_int ctx (String.length v)));
 				op ctx (OSetArray (arr,ridx,ro));
 				op ctx (OSetArray (arr,ridx,ro));
 				op ctx (OIncr ridx);
 				op ctx (OIncr ridx);
 			) res;
 			) res;
 			arr
 			arr
+		| "$rethrow", [v] ->
+			let r = alloc_tmp ctx HVoid in
+			op ctx (ORethrow (eval_to ctx v HDyn));
+			r
 		| "$allTypes", [] ->
 		| "$allTypes", [] ->
 			let r = alloc_tmp ctx (to_type ctx e.etype) in
 			let r = alloc_tmp ctx (to_type ctx e.etype) in
 			op ctx (OGetGlobal (r, alloc_global ctx "__types__" (rtype ctx r)));
 			op ctx (OGetGlobal (r, alloc_global ctx "__types__" (rtype ctx r)));
@@ -1876,7 +1881,7 @@ and eval_expr ctx e =
 		| AInstanceProto (ethis, fid) | AVirtualMethod (ethis, fid) ->
 		| AInstanceProto (ethis, fid) | AVirtualMethod (ethis, fid) ->
 			let el = eval_null_check ctx ethis :: el() in
 			let el = eval_null_check ctx ethis :: el() in
 			op ctx (OCallMethod (ret, fid, el))
 			op ctx (OCallMethod (ret, fid, el))
-		| AEnum index ->
+		| AEnum (_,index) ->
 			op ctx (OMakeEnum (ret, index, el()))
 			op ctx (OMakeEnum (ret, index, el()))
 		| AArray (a,t,idx) ->
 		| AArray (a,t,idx) ->
 			let r = array_read ctx a t idx ec.epos in
 			let r = array_read ctx a t idx ec.epos in
@@ -1918,8 +1923,25 @@ and eval_expr ctx e =
 		| ADynamic (ethis, f) ->
 		| ADynamic (ethis, f) ->
 			let robj = eval_null_check ctx ethis in
 			let robj = eval_null_check ctx ethis in
 			op ctx (ODynGet (r,robj,f))
 			op ctx (ODynGet (r,robj,f))
-		| AEnum index ->
-			op ctx (OMakeEnum (r,index,[]))
+		| AEnum (en,index) ->
+			let cur_fid = DynArray.length ctx.cfids.arr in
+			let name = List.nth en.e_names index in
+			let fid = alloc_fun_path ctx en.e_path name in
+			if fid = cur_fid then begin
+				let ef = PMap.find name en.e_constrs in
+				let eargs, et = (match follow ef.ef_type with TFun (args,ret) -> args, ret | _ -> assert false) in
+				let ct = ctx.com.basic in
+				let p = ef.ef_pos in
+				let eargs = List.map (fun (n,o,t) -> alloc_var n t, if o then Some TNull else None) eargs in
+				let ecall = mk (TCall (e,List.map (fun (v,_) -> mk (TLocal v) v.v_type p) eargs)) et p in
+				let f = {
+					tf_args = eargs;
+					tf_type = et;
+					tf_expr = mk (TReturn (Some ecall)) ct.tvoid p;
+				} in
+				ignore(make_fun ctx ("","") fid f None None);
+			end;
+			op ctx (OStaticClosure (r,fid));
 		| ANone | ALocal _ | AArray _ | ACaptured _ ->
 		| ANone | ALocal _ | AArray _ | ACaptured _ ->
 			error "Invalid access" e.epos);
 			error "Invalid access" e.epos);
 		unsafe_cast_to ctx r (to_type ctx e.etype) e.epos
 		unsafe_cast_to ctx r (to_type ctx e.etype) e.epos
@@ -2343,7 +2365,7 @@ and eval_expr ctx e =
 	| TMeta (_,e) ->
 	| TMeta (_,e) ->
 		eval_expr ctx e
 		eval_expr ctx e
 	| TFor _ ->
 	| TFor _ ->
-		assert false (* eliminated with pf_for_to_while *)
+		assert false (* eliminated by analyzer *)
 	| TSwitch (en,cases,def) ->
 	| TSwitch (en,cases,def) ->
 		let rt = to_type ctx e.etype in
 		let rt = to_type ctx e.etype in
 		let r = alloc_tmp ctx rt in
 		let r = alloc_tmp ctx rt in

+ 6 - 4
src/generators/genjs.ml

@@ -44,6 +44,7 @@ type ctx = {
 	smap : sourcemap;
 	smap : sourcemap;
 	js_modern : bool;
 	js_modern : bool;
 	js_flatten : bool;
 	js_flatten : bool;
+	es_version : int;
 	store_exception_stack : bool;
 	store_exception_stack : bool;
 	mutable current : tclass;
 	mutable current : tclass;
 	mutable statics : (tclass * string * texpr) list;
 	mutable statics : (tclass * string * texpr) list;
@@ -630,7 +631,7 @@ and gen_expr ctx e =
 	| TObjectDecl fields ->
 	| TObjectDecl fields ->
 		spr ctx "{ ";
 		spr ctx "{ ";
 		concat ctx ", " (fun (f,e) -> (match e.eexpr with
 		concat ctx ", " (fun (f,e) -> (match e.eexpr with
-			| TMeta((Meta.QuotedField,_,_),e) -> print ctx "'%s' : " f;
+			| TMeta((Meta.QuotedField,_,_),e) -> print ctx "'%s' : " (Ast.s_escape f);
 			| _ -> print ctx "%s : " (anon_field f));
 			| _ -> print ctx "%s : " (anon_field f));
 			gen_value ctx e
 			gen_value ctx e
 		) fields;
 		) fields;
@@ -1252,6 +1253,7 @@ let alloc_ctx com =
 		};
 		};
 		js_modern = not (Common.defined com Define.JsClassic);
 		js_modern = not (Common.defined com Define.JsClassic);
 		js_flatten = not (Common.defined com Define.JsUnflatten);
 		js_flatten = not (Common.defined com Define.JsUnflatten);
+		es_version = int_of_string (Common.defined_value com Define.JsEs);
 		store_exception_stack = if Common.has_dce com then (Common.has_feature com "haxe.CallStack.exceptionStack") else List.exists (function TClassDecl { cl_path=["haxe"],"CallStack" } -> true | _ -> false) com.types;
 		store_exception_stack = if Common.has_dce com then (Common.has_feature com "haxe.CallStack.exceptionStack") else List.exists (function TClassDecl { cl_path=["haxe"],"CallStack" } -> true | _ -> false) com.types;
 		statics = [];
 		statics = [];
 		inits = [];
 		inits = [];
@@ -1364,7 +1366,7 @@ let generate com =
 		closureArgs
 		closureArgs
 	in
 	in
 	(* Provide console for environments that may not have it. *)
 	(* Provide console for environments that may not have it. *)
-	let closureArgs = if (not (Common.defined com Define.JsEs5)) then
+	let closureArgs = if ctx.es_version < 5 then
 		var_console :: closureArgs
 		var_console :: closureArgs
 	else
 	else
 		closureArgs
 		closureArgs
@@ -1409,13 +1411,13 @@ let generate com =
 	) include_files;
 	) include_files;
 
 
 	(* If ctx.js_modern, console is defined in closureArgs. *)
 	(* If ctx.js_modern, console is defined in closureArgs. *)
-	if (not ctx.js_modern) && (not (Common.defined com Define.JsEs5)) then
+	if (not ctx.js_modern) && (ctx.es_version < 5) then
 		add_feature ctx "js.Lib.global"; (* console polyfill will check console from $global *)
 		add_feature ctx "js.Lib.global"; (* console polyfill will check console from $global *)
 
 
 	if (not ctx.js_modern) && (has_feature ctx "js.Lib.global") then
 	if (not ctx.js_modern) && (has_feature ctx "js.Lib.global") then
 		print ctx "var %s = %s;\n" (fst var_global) (snd var_global);
 		print ctx "var %s = %s;\n" (fst var_global) (snd var_global);
 
 
-	if (not ctx.js_modern) && (not (Common.defined com Define.JsEs5)) then
+	if (not ctx.js_modern) && (ctx.es_version < 5) then
 		spr ctx "var console = $global.console || {log:function(){}};\n";
 		spr ctx "var console = $global.console || {log:function(){}};\n";
 
 
 	(* TODO: fix $estr *)
 	(* TODO: fix $estr *)

+ 1 - 1
src/generators/genpy.ml

@@ -1686,7 +1686,7 @@ module Printer = struct
 			print_exprs pctx sep el
 			print_exprs pctx sep el
 
 
 	and print_exprs_named pctx sep fl =
 	and print_exprs_named pctx sep fl =
-		let args = String.concat sep (List.map (fun (s,e) -> Printf.sprintf "'%s': %s" (handle_keywords s) (print_expr pctx e)) fl) in
+		let args = String.concat sep (List.map (fun (s,e) -> Printf.sprintf "'%s': %s" (Ast.s_escape (handle_keywords s)) (print_expr pctx e)) fl) in
 		Printf.sprintf "{%s}" args
 		Printf.sprintf "{%s}" args
 	and print_params_named pctx sep fl =
 	and print_params_named pctx sep fl =
 		let args = String.concat sep (List.map (fun (s,e) -> Printf.sprintf "%s= %s" (handle_keywords s) (print_expr pctx e)) fl) in
 		let args = String.concat sep (List.map (fun (s,e) -> Printf.sprintf "%s= %s" (handle_keywords s) (print_expr pctx e)) fl) in

+ 24 - 4
src/main.ml

@@ -988,7 +988,7 @@ and do_connect host port args =
 
 
 and init ctx =
 and init ctx =
 	let usage = Printf.sprintf
 	let usage = Printf.sprintf
-		"Haxe Compiler %s - (C)2005-2016 Haxe Foundation\n Usage : haxe%s -main <class> [-swf|-js|-neko|-php|-cpp|-as3|-cs|-java|-python|-hl|-lua] <output> [options]\n Options :"
+		"Haxe Compiler %s - (C)2005-2016 Haxe Foundation\n Usage : haxe%s -main <class> [-swf|-js|-neko|-php|-cpp|-cppia|-as3|-cs|-java|-python|-hl|-lua] <output> [options]\n Options :"
 		s_version (if Sys.os_type = "Win32" then ".exe" else "")
 		s_version (if Sys.os_type = "Win32" then ".exe" else "")
 	in
 	in
 	let com = ctx.com in
 	let com = ctx.com in
@@ -1075,6 +1075,10 @@ try
 		("-cpp",Arg.String (fun dir ->
 		("-cpp",Arg.String (fun dir ->
 			set_platform Cpp dir;
 			set_platform Cpp dir;
 		),"<directory> : generate C++ code into target directory");
 		),"<directory> : generate C++ code into target directory");
+		("-cppia",Arg.String (fun file ->
+			set_platform Cpp file;
+			Common.define com Define.Cppia;
+		),"<file> : generate Cppia code into target file");
 		("-cs",Arg.String (fun dir ->
 		("-cs",Arg.String (fun dir ->
 			cp_libs := "hxcs" :: !cp_libs;
 			cp_libs := "hxcs" :: !cp_libs;
 			set_platform Cs dir;
 			set_platform Cs dir;
@@ -1403,7 +1407,7 @@ try
 				ignore(Str.search_forward r msg 0);
 				ignore(Str.search_forward r msg 0);
 				let s = Str.matched_group 1 msg in
 				let s = Str.matched_group 1 msg in
 				let sl = List.map (fun (s,_,_) -> s) all_args_spec in
 				let sl = List.map (fun (s,_,_) -> s) all_args_spec in
-				let msg = Typecore.string_error_raise s sl (Printf.sprintf "Invalid command: %s" s) in
+				let msg = StringError.string_error_raise s sl (Printf.sprintf "Invalid command: %s" s) in
 				raise (Arg.Bad msg)
 				raise (Arg.Bad msg)
 			with Not_found ->
 			with Not_found ->
 				raise exc);
 				raise exc);
@@ -1455,6 +1459,22 @@ try
 		| Js ->
 		| Js ->
 			if not (PMap.exists (fst (Define.infos Define.JqueryVer)) com.defines) then
 			if not (PMap.exists (fst (Define.infos Define.JqueryVer)) com.defines) then
 				Common.define_value com Define.JqueryVer "11202";
 				Common.define_value com Define.JqueryVer "11202";
+
+			let es_version =
+				try
+					int_of_string (Common.defined_value com Define.JsEs)
+				with
+				| Not_found ->
+					(Common.define_value com Define.JsEs "5"; 5)
+				| _ ->
+					0
+			in
+
+			if es_version < 3 || es_version = 4 then (* we don't support ancient and there's no 4th *)
+				failwith "Invalid -D js-es value";
+
+			if es_version >= 5 then Common.raw_define com "js-es5"; (* backward-compatibility *)
+
 			add_std "js";
 			add_std "js";
 			"js"
 			"js"
 		| Lua ->
 		| Lua ->
@@ -1464,7 +1484,7 @@ try
 			add_std "php";
 			add_std "php";
 			"php"
 			"php"
 		| Cpp ->
 		| Cpp ->
-			Common.define_value com Define.HxcppApiLevel (if Common.defined_value_safe com Define.CppAst <>"" then "330" else "321");
+			Common.define_value com Define.HxcppApiLevel "330";
 			add_std "cpp";
 			add_std "cpp";
 			if Common.defined com Define.Cppia then
 			if Common.defined com Define.Cppia then
 				classes := (make_path "cpp.cppia.HostClasses" ) :: !classes;
 				classes := (make_path "cpp.cppia.HostClasses" ) :: !classes;
@@ -1638,7 +1658,7 @@ with
 		message ctx msg p;
 		message ctx msg p;
 		List.iter (message ctx "Called from") l;
 		List.iter (message ctx "Called from") l;
 		error ctx "Aborted" Ast.null_pos;
 		error ctx "Aborted" Ast.null_pos;
-	| Codegen.Generic_Exception(m,p) ->
+	| Typeload.Generic_Exception(m,p) ->
 		error ctx m p
 		error ctx m p
 	| Arg.Bad msg ->
 	| Arg.Bad msg ->
 		error ctx ("Error: " ^ msg) Ast.null_pos
 		error ctx ("Error: " ^ msg) Ast.null_pos

File diff suppressed because it is too large
+ 9 - 1648
src/optimization/analyzer.ml


+ 119 - 0
src/optimization/analyzerConfig.ml

@@ -0,0 +1,119 @@
+(*
+	The Haxe Compiler
+	Copyright (C) 2005-2016  Haxe Foundation
+
+	This program is free software; you can redistribute it and/or
+	modify it under the terms of the GNU General Public License
+	as published by the Free Software Foundation; either version 2
+	of the License, or (at your option) any later version.
+
+	This program is distributed in the hope that it will be useful,
+	but WITHOUT ANY WARRANTY; without even the implied warranty of
+	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+	GNU General Public License for more details.
+
+	You should have received a copy of the GNU General Public License
+	along with this program; if not, write to the Free Software
+	Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *)
+
+open Ast
+open Type
+open Common
+
+type t = {
+	optimize : bool;
+	const_propagation : bool;
+	copy_propagation : bool;
+	code_motion : bool;
+	local_dce : bool;
+	fusion : bool;
+	purity_inference : bool;
+	dot_debug : bool;
+}
+
+let flag_const_propagation = "const_propagation"
+let flag_copy_propagation = "copy_propagation"
+let flag_code_motion = "code_motion"
+let flag_local_dce = "local_dce"
+let flag_fusion = "fusion"
+let flag_purity_inference = "purity_inference"
+let flag_ignore = "ignore"
+let flag_dot_debug = "dot_debug"
+
+let all_flags =
+	List.fold_left (fun acc flag ->
+		flag :: ("no_" ^ flag) :: acc
+	) [] [flag_const_propagation;flag_copy_propagation;flag_code_motion;flag_local_dce;flag_fusion;flag_purity_inference;flag_ignore;flag_dot_debug]
+
+let has_analyzer_option meta s =
+	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 s = s2 -> true
+						| _ -> false
+				) el then
+					true
+				else
+					loop ml
+			| _ :: ml ->
+				loop ml
+			| [] ->
+				false
+		in
+		loop meta
+	with Not_found ->
+		false
+
+let is_ignored meta =
+	has_analyzer_option meta flag_ignore
+
+let get_base_config com =
+	{
+		optimize = not (Common.defined com Define.NoAnalyzer);
+		const_propagation = not (Common.raw_defined com "analyzer-no-const-propagation");
+		copy_propagation = not (Common.raw_defined com "analyzer-no-copy-propagation");
+		code_motion = Common.raw_defined com "analyzer-code-motion";
+		local_dce = not (Common.raw_defined com "analyzer-no-local-dce");
+		fusion = not (Common.raw_defined com "analyzer-no-fusion") && (match com.platform with Flash | Java -> false | _ -> true);
+		purity_inference = not (Common.raw_defined com "analyzer-no-purity-inference");
+		dot_debug = false;
+	}
+
+let update_config_from_meta com config meta =
+	List.fold_left (fun config meta -> match meta with
+		| (Meta.Analyzer,el,_) ->
+			List.fold_left (fun config e -> match fst e with
+				| EConst (Ident s) when s = "no_" ^ flag_const_propagation -> { config with const_propagation = false}
+				| EConst (Ident s) when s = flag_const_propagation -> { config with const_propagation = true}
+				| EConst (Ident s) when s = "no_" ^ flag_copy_propagation -> { config with copy_propagation = false}
+				| EConst (Ident s) when s = flag_copy_propagation -> { config with copy_propagation = true}
+				| EConst (Ident s) when s = "no_" ^ flag_code_motion -> { config with code_motion = false}
+				| EConst (Ident s) when s = flag_code_motion -> { config with code_motion = true}
+				| EConst (Ident s) when s = "no_" ^ flag_local_dce -> { config with local_dce = false}
+				| EConst (Ident s) when s = flag_local_dce -> { config with local_dce = true}
+				| EConst (Ident s) when s = "no_" ^ flag_fusion -> { config with fusion = false}
+				| EConst (Ident s) when s = flag_fusion -> { config with fusion = true}
+				| EConst (Ident s) when s = "no_" ^ flag_purity_inference -> { config with purity_inference = false}
+				| EConst (Ident s) when s = flag_purity_inference -> { config with purity_inference = true}
+				| EConst (Ident s) when s = flag_dot_debug -> {config with dot_debug = true}
+				| _ ->
+					let s = Ast.s_expr e in
+					com.warning (StringError.string_error s all_flags ("Unrecognized analyzer option: " ^ s)) (pos e);
+					config
+			) config el
+		| (Meta.HasUntyped,_,_) ->
+			{config with optimize = false}
+		| _ ->
+			config
+	) config meta
+
+let get_class_config com c =
+	let config = get_base_config com in
+	update_config_from_meta com config c.cl_meta
+
+let get_field_config com c cf =
+	let config = get_class_config com c in
+	update_config_from_meta com config cf.cf_meta

+ 713 - 0
src/optimization/analyzerTexpr.ml

@@ -0,0 +1,713 @@
+(*
+	The Haxe Compiler
+	Copyright (C) 2005-2016  Haxe Foundation
+
+	This program is free software; you can redistribute it and/or
+	modify it under the terms of the GNU General Public License
+	as published by the Free Software Foundation; either version 2
+	of the License, or (at your option) any later version.
+
+	This program is distributed in the hope that it will be useful,
+	but WITHOUT ANY WARRANTY; without even the implied warranty of
+	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+	GNU General Public License for more details.
+
+	You should have received a copy of the GNU General Public License
+	along with this program; if not, write to the Free Software
+	Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *)
+
+open Ast
+open Type
+open Common
+
+let s_expr_pretty e = s_expr_pretty "" (s_type (print_context())) e
+
+let rec is_true_expr e1 = match e1.eexpr with
+	| TConst(TBool true) -> true
+	| TParenthesis e1 -> is_true_expr e1
+	| _ -> false
+
+let map_values ?(allow_control_flow=true) f e =
+	let branching = ref false in
+	let efinal = ref None in
+	let f e =
+		if !branching then
+			f e
+		else begin
+			efinal := Some e;
+			mk (TConst TNull) e.etype e.epos
+		end
+	in
+	let rec loop complex e = match e.eexpr with
+		| TIf(e1,e2,Some e3) ->
+			branching := true;
+			let e2 = loop true e2 in
+			let e3 = loop true e3 in
+			{e with eexpr = TIf(e1,e2,Some e3)}
+		| TSwitch(e1,cases,edef) ->
+			branching := true;
+			let cases = List.map (fun (el,e) -> el,loop true e) cases in
+			let edef = Option.map (loop true) edef in
+			{e with eexpr = TSwitch(e1,cases,edef)}
+		| TBlock [e1] ->
+			loop complex e1
+		| TBlock el ->
+			begin match List.rev el with
+			| e1 :: el ->
+				let e1 = loop true e1 in
+				let e = {e with eexpr = TBlock (List.rev (e1 :: el))} in
+				{e with eexpr = TMeta((Meta.MergeBlock,[],e.epos),e)}
+			| [] ->
+				f e
+			end
+		| TTry(e1,catches) ->
+			branching := true;
+			let e1 = loop true e1 in
+			let catches = List.map (fun (v,e) -> v,loop true e) catches in
+			{e with eexpr = TTry(e1,catches)}
+		| TMeta(m,e1) ->
+			{e with eexpr = TMeta(m,loop complex e1)}
+		| TParenthesis e1 ->
+			{e with eexpr = TParenthesis (loop complex e1)}
+		| TBreak | TContinue | TThrow _ | TReturn _ ->
+			if not allow_control_flow then raise Exit;
+			e
+		| _ ->
+			if not complex then raise Exit;
+			f e
+	in
+	let e = loop false e in
+	e,!efinal
+
+let can_throw e =
+	let rec loop e = match e.eexpr with
+		| TConst _ | TLocal _ | TTypeExpr _ | TFunction _ | TBlock _ -> ()
+		| TCall _ | TNew _ | TThrow _ | TCast(_,Some _) -> raise Exit
+		| TField _ | TArray _ -> raise Exit (* sigh *)
+		| _ -> Type.iter loop e
+	in
+	try
+		loop e; false
+	with Exit ->
+		true
+
+let rec can_be_inlined e = match e.eexpr with
+	| TConst _ -> true
+	| TParenthesis e1 | TMeta(_,e1) -> can_be_inlined e1
+	| _ -> false
+
+let target_handles_unops com = match com.platform with
+	| Lua | Python -> false
+	| _ -> true
+
+let target_handles_assign_ops com = match com.platform with
+	| Lua -> false
+	| _ -> true
+
+let rec can_be_used_as_value com e =
+	let rec loop e = match e.eexpr with
+		| TBlock [e] -> loop e
+		| TBlock _ | TSwitch _ | TTry _ -> raise Exit
+		| TCall({eexpr = TConst (TString "phi")},_) -> raise Exit
+		(* | TCall _ | TNew _ when (match com.platform with Cpp | Php -> true | _ -> false) -> raise Exit *)
+		| TReturn _ | TThrow _ | TBreak | TContinue -> raise Exit
+		| TUnop((Increment | Decrement),_,_) when target_handles_unops com -> raise Exit
+		| TNew _ when com.platform = Php -> raise Exit
+		| TFunction _ -> ()
+		| _ -> Type.iter loop e
+	in
+	try
+		loop e;
+		true
+	with Exit ->
+		false
+
+let has_pure_meta meta = Meta.has Meta.Pure meta
+
+let is_pure c cf = has_pure_meta c.cl_meta || has_pure_meta cf.cf_meta
+
+let wrap_meta s e =
+	mk (TMeta((Meta.Custom s,[],e.epos),e)) e.etype e.epos
+
+let is_really_unbound v =
+	v.v_name <> "`trace" && is_unbound v
+
+let r = Str.regexp "^\\([A-Za-z0-9_]\\)+$"
+let is_unbound_call_that_might_have_side_effects v el = match v.v_name,el with
+	| "__js__",[{eexpr = TConst (TString s)}] when Str.string_match r s 0 -> false
+	| _ -> true
+
+let is_ref_type = function
+	| TType({t_path = ["cs"],("Ref" | "Out")},_) -> true
+	| TAbstract({a_path=["hl";"types"],"Ref"},_) -> true
+	| _ -> false
+
+let type_change_ok com t1 t2 =
+	if t1 == t2 then
+		true
+	else begin
+		let rec map t = match t with
+			| TMono r -> (match !r with None -> t_dynamic | Some t -> map t)
+			| _ -> Type.map map t
+		in
+		let t1 = map t1 in
+		let t2 = map t2 in
+		let rec is_nullable_or_whatever = function
+			| TMono r ->
+				(match !r with None -> false | Some t -> is_nullable_or_whatever t)
+			| TType ({ t_path = ([],"Null") },[_]) ->
+				true
+			| TLazy f ->
+				is_nullable_or_whatever (!f())
+			| TType (t,tl) ->
+				is_nullable_or_whatever (apply_params t.t_params tl t.t_type)
+			| TFun _ ->
+				false
+			| TInst ({ cl_kind = KTypeParameter _ },_) ->
+				false
+			| TAbstract (a,_) when Meta.has Meta.CoreType a.a_meta ->
+				not (Meta.has Meta.NotNull a.a_meta)
+			| TAbstract (a,tl) ->
+				not (Meta.has Meta.NotNull a.a_meta) && is_nullable_or_whatever (apply_params a.a_params tl a.a_this)
+			| _ ->
+				true
+		in
+		(* Check equality again to cover cases where TMono became t_dynamic *)
+		t1 == t2 || match follow t1,follow t2 with
+			| TDynamic _,_ | _,TDynamic _ -> false
+			| _ ->
+				if com.config.pf_static && is_nullable_or_whatever t1 <> is_nullable_or_whatever t2 then false
+				else type_iseq t1 t2
+	end
+
+let dynarray_map f d =
+	DynArray.iteri (fun i e -> DynArray.unsafe_set d i (f e)) d
+
+let dynarray_mapi f d =
+	DynArray.iteri (fun i e -> DynArray.unsafe_set d i (f i e)) d
+
+(*
+	This module rewrites some expressions to reduce the amount of special cases for subsequent analysis. After analysis
+	it restores some of these expressions back to their original form.
+
+	The following expressions are removed from the AST after `apply` has run:
+	- OpBoolAnd and OpBoolOr binary operations are rewritten to TIf
+	- OpAssignOp on a variable is rewritten to OpAssign
+	- Prefix increment/decrement operations are rewritten to OpAssign
+	- Postfix increment/decrement operations are rewritten to a TBlock with OpAssign and OpAdd/OpSub
+	- `do {} while(true)` is rewritten to `while(true) {}`
+	- TWhile expressions are rewritten to `while (true)` with appropriate conditional TBreak
+	- TFor is rewritten to TWhile
+*)
+module TexprFilter = struct
+	let apply com e =
+		let rec loop e = match e.eexpr with
+		| TBinop(OpBoolAnd | OpBoolOr as op,e1,e2) ->
+			let e_then = e2 in
+			let e_if,e_else = if op = OpBoolOr then
+				mk (TUnop(Not,Prefix,e1)) com.basic.tbool e.epos,mk (TConst (TBool(true))) com.basic.tbool e.epos
+			else
+				e1,mk (TConst (TBool(false))) com.basic.tbool e.epos
+			in
+			loop (mk (TIf(e_if,e_then,Some e_else)) e.etype e.epos)
+		| TBinop(OpAssignOp op,({eexpr = TLocal _} as e1),e2) ->
+			let e = {e with eexpr = TBinop(op,e1,e2)} in
+			loop {e with eexpr = TBinop(OpAssign,e1,e)}
+		| TUnop((Increment | Decrement as op),flag,({eexpr = TLocal _} as e1)) ->
+			let e_one = mk (TConst (TInt (Int32.of_int 1))) com.basic.tint e1.epos in
+			let e = {e with eexpr = TBinop(OpAssignOp (if op = Increment then OpAdd else OpSub),e1,e_one)} in
+			let e = if flag = Prefix then
+				e
+			else
+				mk (TBlock [
+					{e with eexpr = TBinop(OpAssignOp (if op = Increment then OpAdd else OpSub),e1,e_one)};
+					{e with eexpr = TBinop((if op = Increment then OpSub else OpAdd),e1,e_one)};
+				]) e.etype e.epos
+			in
+			loop e
+		| TWhile(e1,e2,DoWhile) when is_true_expr e1 ->
+			loop {e with eexpr = TWhile(e1,e2,NormalWhile)}
+		| TWhile(e1,e2,flag) when not (is_true_expr e1) ->
+			let p = e.epos in
+			let e_break = mk TBreak t_dynamic p in
+			let e_not = mk (TUnop(Not,Prefix,Codegen.mk_parent e1)) e1.etype e1.epos in
+			let e_if eo = mk (TIf(e_not,e_break,eo)) com.basic.tvoid p in
+			let rec map_continue e = match e.eexpr with
+				| TContinue ->
+					Texpr.duplicate_tvars (e_if (Some e))
+				| TWhile _ | TFor _ ->
+					e
+				| _ ->
+					Type.map_expr map_continue e
+			in
+			let e2 = if flag = NormalWhile then e2 else map_continue e2 in
+			let e_if = e_if None in
+			let e_block = if flag = NormalWhile then Type.concat e_if e2 else Type.concat e2 e_if in
+			let e_true = mk (TConst (TBool true)) com.basic.tbool p in
+			let e = mk (TWhile(Codegen.mk_parent e_true,e_block,NormalWhile)) e.etype p in
+			loop e
+		| TFor(v,e1,e2) ->
+			let v' = alloc_var "tmp" e1.etype in
+			let ev' = mk (TLocal v') e1.etype e1.epos in
+			let t1 = (Abstract.follow_with_abstracts e1.etype) in
+			let ehasnext = mk (TField(ev',quick_field t1 "hasNext")) (tfun [] com.basic.tbool) e1.epos in
+			let ehasnext = mk (TCall(ehasnext,[])) com.basic.tbool ehasnext.epos in
+			let enext = mk (TField(ev',quick_field t1 "next")) (tfun [] v.v_type) e1.epos in
+			let enext = mk (TCall(enext,[])) v.v_type e1.epos in
+			let eassign = mk (TVar(v,Some enext)) com.basic.tvoid e.epos in
+			let ebody = Type.concat eassign e2 in
+			let e = mk (TBlock [
+				mk (TVar (v',Some e1)) com.basic.tvoid e1.epos;
+				mk (TWhile((mk (TParenthesis ehasnext) ehasnext.etype ehasnext.epos),ebody,NormalWhile)) com.basic.tvoid e1.epos;
+			]) com.basic.tvoid e.epos in
+			loop e
+		| _ ->
+			Type.map_expr loop e
+		in
+		loop e
+end
+
+module Fusion = struct
+
+	type interference_kind =
+		| IKVarMod of tvar list
+		| IKSideEffect
+		| IKNone
+
+	let get_interference_kind e =
+		let vars = ref [] in
+		let rec loop e = match e.eexpr with
+			| TMeta((Meta.Pure,_,_),_) ->
+				()
+			| TUnop((Increment | Decrement),_,{eexpr = TLocal v}) ->
+				vars := v :: !vars
+			| TBinop((OpAssign | OpAssignOp _),{eexpr = TLocal v},e2) ->
+				vars := v :: !vars;
+				loop e2
+			| TBinop((OpAssign | OpAssignOp _),_,_) | TUnop((Increment | Decrement),_,_) ->
+				raise Exit
+			| TCall({eexpr = TLocal v},el) when not (is_unbound_call_that_might_have_side_effects v el) ->
+				List.iter loop el
+			| TCall({eexpr = TField(_,FStatic(c,cf))},el) when is_pure c cf ->
+				List.iter loop el
+			| TNew(c,_,el) when (match c.cl_constructor with Some cf when is_pure c cf -> true | _ -> false) ->
+				List.iter loop el;
+			| TCall _ | TNew _ ->
+				raise Exit
+			| _ ->
+				Type.iter loop e
+		in
+		try
+			loop e;
+			begin match !vars with
+				| [] -> IKNone
+				| vars -> IKVarMod vars
+			end
+		with Exit ->
+			IKSideEffect
+
+	let apply com config e =
+		let rec block_element acc el = match el with
+			| {eexpr = TBinop((OpAssign | OpAssignOp _),_,_) | TUnop((Increment | Decrement),_,_)} as e1 :: el ->
+				block_element (e1 :: acc) el
+			| {eexpr = TLocal _} as e1 :: el when not config.AnalyzerConfig.local_dce ->
+				block_element (e1 :: acc) el
+			(* no-side-effect *)
+			| {eexpr = TEnumParameter _ | TFunction _ | TConst _ | TTypeExpr _ | TLocal _} :: el ->
+				block_element acc el
+			(* no-side-effect composites *)
+			| {eexpr = TParenthesis e1 | TMeta(_,e1) | TCast(e1,None) | TField(e1,_) | TUnop(_,_,e1)} :: el ->
+				block_element acc (e1 :: el)
+			| {eexpr = TArray(e1,e2) | TBinop(_,e1,e2)} :: el ->
+				block_element acc (e1 :: e2 :: el)
+			| {eexpr = TArrayDecl el1 | TCall({eexpr = TField(_,FEnum _)},el1)} :: el2 -> (* TODO: check e1 of FEnum *)
+				block_element acc (el1 @ el2)
+			| {eexpr = TObjectDecl fl} :: el ->
+				block_element acc ((List.map snd fl) @ el)
+			| {eexpr = TIf(e1,{eexpr = TBlock []},(Some {eexpr = TBlock []} | None))} :: el ->
+				block_element acc (e1 :: el)
+			| {eexpr = TBlock [e1]} :: el ->
+				block_element acc (e1 :: el)
+			| {eexpr = TBlock []} :: el ->
+				block_element acc el
+			| e1 :: el ->
+				block_element (e1 :: acc) el
+			| [] ->
+				acc
+		in
+		let changed = ref false in
+		let var_uses = Hashtbl.create 0 in
+		let var_writes = Hashtbl.create 0 in
+		let get_num_uses v =
+			try Hashtbl.find var_uses v.v_id with Not_found -> 0
+		in
+		let get_num_writes v =
+			try Hashtbl.find var_writes v.v_id with Not_found -> 0
+		in
+		let change map v delta =
+			Hashtbl.replace map v.v_id ((try Hashtbl.find map v.v_id with Not_found -> 0) + delta);
+		in
+		let change_num_uses v delta =
+			change var_uses v delta
+		in
+		let change_num_writes v delta =
+			change var_writes v delta
+		in
+		let rec loop e = match e.eexpr with
+			| TLocal v ->
+				change_num_uses v 1;
+			| TBinop(OpAssign,{eexpr = TLocal v},e2) ->
+				change_num_writes v 1;
+				loop e2
+			| _ ->
+				Type.iter loop e
+		in
+		loop e;
+		let can_be_fused v e =
+			let b = get_num_uses v <= 1 && get_num_writes v = 0 && can_be_used_as_value com e && (Meta.has Meta.CompilerGenerated v.v_meta || config.AnalyzerConfig.optimize && config.AnalyzerConfig.fusion && type_change_ok com v.v_type e.etype && v.v_extra = None) in
+			(* let st = s_type (print_context()) in *)
+			(* if e.epos.pfile = "src/Main.hx" then print_endline (Printf.sprintf "%s: %i %i %b %s %s (%b %b %b %b %b) -> %b" v.v_name (get_num_uses v) (get_num_writes v) (can_be_used_as_value com e) (st v.v_type) (st e.etype) (Meta.has Meta.CompilerGenerated v.v_meta) config.Config.optimize config.Config.fusion (type_change_ok com v.v_type e.etype) (v.v_extra = None) b); *)
+			b
+		in
+		let rec fuse acc el = match el with
+			| ({eexpr = TVar(v1,None)} as e1) :: {eexpr = TBinop(OpAssign,{eexpr = TLocal v2},e2)} :: el when v1 == v2 ->
+				changed := true;
+				let e1 = {e1 with eexpr = TVar(v1,Some e2)} in
+				change_num_writes v1 (-1);
+				fuse (e1 :: acc) el
+			| ({eexpr = TVar(v1,None)} as e1) :: ({eexpr = TIf(eif,_,Some _)} as e2) :: el when can_be_used_as_value com e2 && (match com.platform with Php -> false | Cpp when not (Common.defined com Define.Cppia) -> false | _ -> true) ->
+				begin try
+					let i = ref 0 in
+					let check_assign e = match e.eexpr with
+						| TBinop(OpAssign,{eexpr = TLocal v2},e2) when v1 == v2 -> incr i; e2
+						| _ -> raise Exit
+					in
+					let e,_ = map_values ~allow_control_flow:false check_assign e2 in
+					let e = match follow e.etype with
+						| TAbstract({a_path=[],"Void"},_) -> {e with etype = v1.v_type}
+						| _ -> e
+					in
+					let e1 = {e1 with eexpr = TVar(v1,Some e)} in
+					changed := true;
+					change_num_writes v1 (- !i);
+					fuse (e1 :: acc) el
+				with Exit ->
+					fuse (e1 :: acc) (e2 :: el)
+				end
+			| ({eexpr = TVar(v1,Some e1)} as ev) :: e2 :: el when can_be_fused v1 e1 ->
+				let found = ref false in
+				let affected = ref false in
+				let ik1 = get_interference_kind e1 in
+				let check_interference e2 =
+					let check ik e2 = match ik with
+						| IKNone -> ()
+						| IKSideEffect -> (* TODO: Could this miss a IKVarMod case? *)
+							let rec loop e = match e.eexpr with
+								| TMeta((Meta.Pure,_,_),_) ->
+									()
+								| TField _ when Optimizer.is_affected_type e.etype ->
+									raise Exit
+								| TCall({eexpr = TField(_,FStatic(c,cf))},el) when is_pure c cf ->
+									List.iter loop el
+								| TNew(c,_,el) when (match c.cl_constructor with Some cf when is_pure c cf -> true | _ -> false) ->
+									List.iter loop el
+								| TCall _ | TNew _ | TBinop((OpAssign | OpAssignOp _),_,_) | TUnop((Increment | Decrement),_,_) ->
+									raise Exit
+								| _ ->
+									Type.iter loop e
+							in
+							loop e2
+						| IKVarMod vl ->
+							let rec loop e = match e.eexpr with
+								| TLocal v when List.exists (fun v' -> v == v') vl -> raise Exit
+								| _ -> Type.iter loop e
+							in
+							loop e2
+					in
+					try
+						check ik1 e2;
+						check (get_interference_kind e2) e1
+					with Exit -> match com.platform with
+						| Cpp when not (Common.defined com Define.Cppia) -> raise Exit
+						| Php -> raise Exit (* They don't define evaluation order, so let's exit *)
+						| _ -> affected := true;
+				in
+				let rec replace e =
+					let e = match e.eexpr with
+						| TWhile _ | TFunction _ ->
+							e
+						| TIf(e1,e2,eo) ->
+							let e1 = replace e1 in
+							{e with eexpr = TIf(e1,e2,eo)}
+						| TSwitch(e1,cases,edef) ->
+							let e1 = replace e1 in
+							{e with eexpr = TSwitch(e1,cases,edef)}
+						| TLocal v2 when v1 == v2 && not !affected ->
+							found := true;
+							e1
+						| TBinop((OpAssign | OpAssignOp _ as op),({eexpr = TArray(e1,e2)} as ea),e3) ->
+							let e1 = replace e1 in
+							let e2 = replace e2 in
+							let ea = {ea with eexpr = TArray(e1,e2)} in
+							let e3 = replace e3 in
+							{e with eexpr = TBinop(op,ea,e3)}
+						| TBinop((OpAssign | OpAssignOp _ as op),e1,e2) ->
+							let e2 = replace e2 in
+							let e1 = match e1.eexpr with TLocal _ -> e1 | _ -> replace e1 in
+							{e with eexpr = TBinop(op,e1,e2)}
+						| TUnop((Increment | Decrement),_,{eexpr = TLocal _}) ->
+							e
+						| TCall({eexpr = TLocal v},_) when is_really_unbound v ->
+							e
+						| TCall(e1,el) when com.platform = Neko ->
+							(* Neko has this reversed at the moment (issue #4787) *)
+							let el = List.map replace el in
+							let e1 = replace e1 in
+							{e with eexpr = TCall(e1,el)}
+						| _ ->
+							Type.map_expr replace e
+					in
+					check_interference e;
+					e
+				in
+				begin try
+					let e = replace e2 in
+					if not !found then raise Exit;
+					changed := true;
+					change_num_uses v1 (-1);
+					fuse (e :: acc) el
+				with Exit ->
+					fuse (ev :: acc) (e2 :: el)
+				end
+			| {eexpr = TUnop((Increment | Decrement as op,Prefix,({eexpr = TLocal v} as ev)))} as e1 :: e2 :: el ->
+				begin try
+					let e2,f = match e2.eexpr with
+						| TReturn (Some e2) -> e2,(fun e -> {e2 with eexpr = TReturn (Some e)})
+						| TBinop(OpAssign,e21,e22) -> e22,(fun e -> {e2 with eexpr = TBinop(OpAssign,e21,e)})
+						| TVar(v,Some e2) -> e2,(fun e -> {e2 with eexpr = TVar(v,Some e)})
+						| _ -> raise Exit
+					in
+					let ops_match op1 op2 = match op1,op2 with
+						| Increment,OpSub
+						| Decrement,OpAdd ->
+							true
+						| _ ->
+							false
+					in
+					begin match e2.eexpr with
+						| TBinop(op2,{eexpr = TLocal v2},{eexpr = TConst (TInt i32)}) when v == v2 && Int32.to_int i32 = 1 && ops_match op op2 ->
+							changed := true;
+							change_num_uses v2 (-1);
+							let e = (f {e1 with eexpr = TUnop(op,Postfix,ev)}) in
+							fuse (e :: acc) el
+						| TLocal v2 when v == v2 ->
+							changed := true;
+							change_num_uses v2 (-1);
+							let e = (f {e1 with eexpr = TUnop(op,Prefix,ev)}) in
+							fuse (e :: acc) el
+						| _ ->
+							raise Exit
+					end
+				with Exit ->
+					fuse (e1 :: acc) (e2 :: el)
+				end
+			| e1 :: el ->
+				fuse (e1 :: acc) el
+			| [] ->
+				acc
+		in
+		let rec loop e = match e.eexpr with
+			| TBlock el ->
+				let el = List.map loop el in
+				(* fuse flips element order, but block_element doesn't care and flips it back *)
+				let el = fuse [] el in
+				let el = block_element [] el in
+				let rec fuse_loop el =
+					changed := false;
+					let el = fuse [] el in
+					let el = block_element [] el in
+					if !changed then fuse_loop el else el
+				in
+				let el = fuse_loop el in
+				{e with eexpr = TBlock el}
+			| TCall({eexpr = TLocal v},_) when is_really_unbound v ->
+				e
+			| _ ->
+				Type.map_expr loop e
+		in
+		let e = loop e in
+		e
+end
+
+module Cleanup = struct
+	let apply com e =
+		let if_or_op e e1 e2 e3 = match (Texpr.skip e1).eexpr,(Texpr.skip e3).eexpr with
+			| TUnop(Not,Prefix,e1),TConst (TBool true) -> Optimizer.optimize_binop {e with eexpr = TBinop(OpBoolOr,e1,e2)} OpBoolOr e1 e2
+			| _,TConst (TBool false) -> Optimizer.optimize_binop {e with eexpr = TBinop(OpBoolAnd,e1,e2)} OpBoolAnd e1 e2
+			| _,TBlock [] -> {e with eexpr = TIf(e1,e2,None)}
+			| _ -> match (Texpr.skip e2).eexpr with
+				| TBlock [] when com.platform <> Cs ->
+					let e1' = mk (TUnop(Not,Prefix,e1)) e1.etype e1.epos in
+					let e1' = Optimizer.optimize_unop e1' Not Prefix e1 in
+					{e with eexpr = TIf(e1',e3,None)}
+				| _ ->
+					{e with eexpr = TIf(e1,e2,Some e3)}
+		in
+		let rec loop e = match e.eexpr with
+			| 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;
+			| TBlock el ->
+				let el = List.map (fun e ->
+					let e = loop e in
+					match e.eexpr with
+					| TIf _ -> {e with etype = com.basic.tvoid}
+					| _ -> e
+				) el in
+				{e with eexpr = TBlock el}
+			| TWhile(e1,e2,NormalWhile) ->
+				let e1 = loop e1 in
+				let e2 = loop e2 in
+				begin match e2.eexpr with
+					| TBlock ({eexpr = TIf(e1,({eexpr = TBlock[{eexpr = TBreak}]} as eb),None)} :: el2) ->
+						let e1 = Texpr.skip e1 in
+						let e1 = match e1.eexpr with TUnop(_,_,e1) -> e1 | _ -> {e1 with eexpr = TUnop(Not,Prefix,e1)} in
+						{e with eexpr = TWhile(e1,{eb with eexpr = TBlock el2},NormalWhile)}
+					| TBlock el ->
+						let rec loop2 el = match el with
+							| {eexpr = TBreak | TContinue | TReturn _ | TThrow _} as e :: el ->
+								[e]
+							| e :: el ->
+								e :: (loop2 el)
+							| [] ->
+								[]
+						in
+						let el = loop2 el in
+						{e with eexpr = TWhile(e1,{e2 with eexpr = TBlock el},NormalWhile)}
+					| _ ->
+						{e with eexpr = TWhile(e1,e2,NormalWhile)}
+				end
+			| _ ->
+				Type.map_expr loop e
+		in
+		loop e
+
+	let rec reduce_control_flow ctx e =
+		Type.map_expr (reduce_control_flow ctx) (Optimizer.reduce_control_flow ctx e)
+end
+
+module Purity = struct
+	type purity =
+		| Pure
+		| NotPure
+		| MaybePure
+
+	type purity_node = {
+		pn_field : tclass_field;
+		mutable pn_purity : purity;
+		mutable pn_dependents : purity_node list;
+	}
+
+	let node_lut = Hashtbl.create 0
+
+	let get_field_id c cf = Printf.sprintf "%s.%s" (s_type_path c.cl_path) cf.cf_name
+
+	let get_node c cf =
+		try
+			Hashtbl.find node_lut (get_field_id c cf)
+		with Not_found ->
+			let node = {
+				pn_field = cf;
+				pn_purity = MaybePure;
+				pn_dependents = []
+			} in
+			Hashtbl.replace node_lut (get_field_id c cf) node;
+			node
+
+	let apply_to_field com is_ctor c cf =
+		let node = get_node c cf in
+		let rec taint node =
+			if node.pn_purity <> NotPure then begin
+				node.pn_purity <- NotPure;
+				List.iter taint node.pn_dependents
+			end
+		in
+		let taint_raise node =
+			taint node;
+			raise Exit;
+		in
+		let check_field c cf =
+			let node' = get_node c cf in
+			match node'.pn_purity with
+				| Pure -> ()
+				| NotPure -> taint_raise node;
+				| MaybePure -> node'.pn_dependents <- node :: node'.pn_dependents
+		in
+		let rec check_write e1 =
+			begin match e1.eexpr with
+				| TLocal v ->
+					() (* Writing to locals does not violate purity. *)
+				| TField({eexpr = TConst TThis},_) when is_ctor ->
+					() (* A constructor can write to its own fields without violating purity. *)
+				| _ ->
+					taint_raise node
+			end
+		and loop e = match e.eexpr with
+			| TMeta((Meta.Pure,_,_),_) ->
+				()
+			| TThrow _ ->
+				taint_raise node;
+			| TBinop((OpAssign | OpAssignOp _),e1,e2) ->
+				check_write e1;
+				loop e2;
+			| TUnop((Increment | Decrement),_,e1) ->
+				check_write e1;
+			| TCall({eexpr = TField(_,FStatic(c,cf))},el) ->
+				List.iter loop el;
+				check_field c cf;
+			| TNew(c,_,el) ->
+				List.iter loop el;
+				begin match c.cl_constructor with
+					| Some cf -> check_field c cf
+					| None -> taint_raise node
+				end
+			| TCall({eexpr = TLocal v},el) when not (is_unbound_call_that_might_have_side_effects v el) ->
+				List.iter loop el;
+			| TCall _ ->
+				taint_raise node
+			| _ ->
+				Type.iter loop e
+		in
+		match cf.cf_expr with
+		| None ->
+			taint node
+		| Some e ->
+			try
+				if (Meta.has (Meta.Custom ":impure")) cf.cf_meta then taint_raise node;
+				if is_pure c cf then raise Exit;
+				loop e;
+				node.pn_purity <- Pure;
+			with Exit ->
+				()
+
+	let apply_to_class com c =
+		List.iter (apply_to_field com false c) c.cl_ordered_fields;
+		List.iter (apply_to_field com false c) c.cl_ordered_statics;
+		(match c.cl_constructor with Some cf -> apply_to_field com true c cf | None -> ())
+
+	let infer com =
+		Hashtbl.clear node_lut;
+		List.iter (fun mt -> match mt with
+			| TClassDecl c -> apply_to_class com c
+			| _ -> ()
+		) com.types;
+		Hashtbl.fold (fun _ node acc ->
+			if node.pn_purity = Pure then begin
+				node.pn_field.cf_meta <- (Meta.Pure,[],node.pn_field.cf_pos) :: node.pn_field.cf_meta;
+				node.pn_field :: acc
+			end else acc
+		) node_lut [];
+end

+ 702 - 0
src/optimization/analyzerTexprTransformer.ml

@@ -0,0 +1,702 @@
+(*
+	The Haxe Compiler
+	Copyright (C) 2005-2016  Haxe Foundation
+
+	This program is free software; you can redistribute it and/or
+	modify it under the terms of the GNU General Public License
+	as published by the Free Software Foundation; either version 2
+	of the License, or (at your option) any later version.
+
+	This program is distributed in the hope that it will be useful,
+	but WITHOUT ANY WARRANTY; without even the implied warranty of
+	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+	GNU General Public License for more details.
+
+	You should have received a copy of the GNU General Public License
+	along with this program; if not, write to the Free Software
+	Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *)
+
+open Ast
+open Type
+open Common
+open AnalyzerConfig
+open AnalyzerTypes
+open AnalyzerTypes.BasicBlock
+open AnalyzerTypes.Graph
+open AnalyzerTexpr
+
+(*
+	Transforms an expression to a graph, and a graph back to an expression. This module relies on TexprFilter being
+	run first.
+
+	The created graph is intact and can immediately be transformed back to an expression, or used for analysis first.
+*)
+
+let rec func ctx bb tf t p =
+	let g = ctx.graph in
+	let create_node kind t p =
+		let bb = Graph.create_node g kind t p in
+		bb.bb_loop_groups <- ctx.loop_stack;
+		bb
+	in
+	let bb_root = create_node (BKFunctionBegin tf) tf.tf_expr.etype tf.tf_expr.epos in
+	let bb_exit = create_node BKFunctionEnd tf.tf_expr.etype tf.tf_expr.epos in
+	add_function g tf t p bb_root;
+	add_cfg_edge bb bb_root CFGFunction;
+	let make_block_meta b =
+		let e = mk (TConst (TInt (Int32.of_int b.bb_id))) ctx.com.basic.tint b.bb_pos in
+		wrap_meta ":block" e
+	in
+	let bb_breaks = ref [] in
+	let bb_continue = ref None in
+	let b_try_stack = ref [] in
+	let begin_loop bb_loop_pre bb_continue' =
+		let old = !bb_breaks,!bb_continue in
+		bb_breaks := [];
+		bb_continue := Some bb_continue';
+		let id = ctx.loop_counter in
+		g.g_loops <- IntMap.add id bb_loop_pre g.g_loops;
+		ctx.loop_stack <- id :: ctx.loop_stack;
+		bb_continue'.bb_loop_groups <- id :: bb_continue'.bb_loop_groups;
+		ctx.loop_counter <- id + 1;
+		(fun () ->
+			let breaks = !bb_breaks in
+			bb_breaks := fst old;
+			bb_continue := snd old;
+			ctx.loop_stack <- List.tl ctx.loop_stack;
+			breaks;
+		)
+	in
+	let begin_try b =
+		b_try_stack := b :: !b_try_stack;
+		(fun () ->
+			b_try_stack := List.tl !b_try_stack
+		)
+	in
+	let add_terminator bb e =
+		add_texpr bb e;
+		close_node g bb;
+		g.g_unreachable
+	in
+	let check_unbound_call v el =
+		if is_unbound_call_that_might_have_side_effects v el then ctx.has_unbound <- true
+	in
+	let no_void t p =
+		if ExtType.is_void (follow t) then error "Cannot use Void as value" p
+	in
+	let rec value bb e = match e.eexpr with
+		| TLocal v ->
+			bb,e
+		| TBinop(OpAssign,({eexpr = TLocal v} as e1),e2) ->
+			block_element bb e,e1
+		| TBlock [e1] ->
+			value bb e1
+		| TBlock _ | TIf _ | TSwitch _ | TTry _ ->
+			bind_to_temp bb false e
+		| TCall({eexpr = TLocal v},el) when is_really_unbound v ->
+			check_unbound_call v el;
+			bb,e
+		| TCall(e1,el) ->
+			call bb e e1 el
+		| TBinop((OpAssign | OpAssignOp _) as op,e1,e2) ->
+			let bb,e2 = value bb e2 in
+			let bb,e1 = value bb e1 in
+			bb,{e with eexpr = TBinop(op,e1,e2)}
+		| TBinop(op,e1,e2) ->
+			let bb,e1,e2 = match ordered_value_list bb [e1;e2] with
+				| bb,[e1;e2] -> bb,e1,e2
+				| _ -> assert false
+			in
+			bb,{e with eexpr = TBinop(op,e1,e2)}
+		| TUnop(op,flag,e1) ->
+			let bb,e1 = value bb e1 in
+			bb,{e with eexpr = TUnop(op,flag,e1)}
+		| TArrayDecl el ->
+			let bb,el = ordered_value_list bb el in
+			bb,{e with eexpr = TArrayDecl el}
+		| TObjectDecl fl ->
+			let el = List.map snd fl in
+			let bb,el = ordered_value_list bb el in
+			bb,{e with eexpr = TObjectDecl (List.map2 (fun (s,_) e -> s,e) fl el)}
+		| TField({eexpr = TTypeExpr _},fa) ->
+			bb,e
+		| TField(e1,fa) ->
+			let bb,e1 = value bb e1 in
+			bb,{e with eexpr = TField(e1,fa)}
+		| TArray(e1,e2) ->
+			let bb,e1,e2 = match ordered_value_list bb [e1;e2] with
+				| bb,[e1;e2] -> bb,e1,e2
+				| _ -> assert false
+			in
+			bb,{e with eexpr = TArray(e1,e2)}
+		| TMeta(m,e1) ->
+			let bb,e1 = value bb e1 in
+			bb,{e with eexpr = TMeta(m,e1)}
+		| TParenthesis e1 ->
+			let bb,e1 = value bb e1 in
+			bb,{e with eexpr = TParenthesis e1}
+		| TCast(e1,mto) ->
+			let bb,e1 = value bb e1 in
+			bb,{e with eexpr = TCast(e1,mto)}
+		| TNew(c,tl,el) ->
+			let bb,el = ordered_value_list bb el in
+			bb,{e with eexpr = TNew(c,tl,el)}
+		| TEnumParameter(e1,ef,ei) ->
+			let bb,e1 = value bb e1 in
+			bb,{e with eexpr = TEnumParameter(e1,ef,ei)}
+		| TFunction tf ->
+			let bb_func,bb_func_end = func ctx bb tf e.etype e.epos in
+			let e_fun = mk (TConst (TString "fun")) t_dynamic p in
+			let econst = mk (TConst (TInt (Int32.of_int bb_func.bb_id))) ctx.com.basic.tint e.epos in
+			let ec = mk (TCall(e_fun,[econst])) t_dynamic p in
+			let bb_next = create_node BKNormal bb.bb_type bb.bb_pos in
+			add_cfg_edge bb bb_next CFGGoto;
+			set_syntax_edge bb (SEMerge bb_next);
+			close_node g bb;
+			add_cfg_edge bb_func_end bb_next CFGGoto;
+			bb_next,ec
+		| TTypeExpr(TClassDecl {cl_kind = KAbstractImpl a}) when not (Meta.has Meta.RuntimeValue a.a_meta) ->
+			error "Cannot use abstract as value" e.epos
+		| TTypeExpr(TClassDecl c) ->
+			List.iter (fun cf -> if not (Meta.has Meta.MaybeUsed cf.cf_meta) then cf.cf_meta <- (Meta.MaybeUsed,[],cf.cf_pos) :: cf.cf_meta;) c.cl_ordered_statics;
+			bb,e
+		| TConst _ | TTypeExpr _ ->
+			bb,e
+		| TThrow _ | TReturn _ | TBreak | TContinue ->
+			let bb = block_element bb e in
+			bb,mk (TConst TNull) t_dynamic e.epos
+		| TVar _ | TFor _ | TWhile _ ->
+			error "Cannot use this expression as value" e.epos
+	and ordered_value_list bb el =
+		let might_be_affected,collect_modified_locals = Optimizer.create_affection_checker() in
+		let rec can_be_optimized e = match e.eexpr with
+			| TBinop _ | TArray _ | TCall _ -> true
+			| TParenthesis e1 -> can_be_optimized e1
+			| _ -> false
+		in
+		let _,el = List.fold_left (fun (had_side_effect,acc) e ->
+			if had_side_effect then
+				(true,(might_be_affected e || Optimizer.has_side_effect e,can_be_optimized e,e) :: acc)
+			else begin
+				let had_side_effect = Optimizer.has_side_effect e in
+				if had_side_effect then collect_modified_locals e;
+				let opt = can_be_optimized e in
+				(had_side_effect || opt,(false,opt,e) :: acc)
+			end
+		) (false,[]) (List.rev el) in
+		let bb,values = List.fold_left (fun (bb,acc) (aff,opt,e) ->
+			let bb,value = if aff || opt then bind_to_temp bb aff e else value bb e in
+			bb,(value :: acc)
+		) (bb,[]) el in
+		bb,List.rev values
+	and bind_to_temp bb sequential e =
+		let rec loop fl e = match e.eexpr with
+			| TField(e1,fa) when (match extract_field fa with Some {cf_kind = Method MethNormal} -> true | _ -> false) ->
+				loop ((fun e' -> {e with eexpr = TField(e',fa)}) :: fl) e1
+			| _ ->
+				fl,e
+		in
+		let fl,e = loop [] e in
+		let v = alloc_var ctx.temp_var_name e.etype in
+		begin match ctx.com.platform with
+			| Cpp when sequential && not (Common.defined ctx.com Define.Cppia) -> ()
+			| _ -> v.v_meta <- [Meta.CompilerGenerated,[],e.epos];
+		end;
+		let bb = declare_var_and_assign bb v e in
+		let e = {e with eexpr = TLocal v} in
+		let e = List.fold_left (fun e f -> f e) e (List.rev fl) in
+		bb,e
+	and declare_var_and_assign bb v e =
+		let rec loop bb e = match e.eexpr with
+			| TParenthesis e1 ->
+				loop bb e1
+			| TBlock el ->
+				let rec loop2 bb el = match el with
+					| [e] ->
+						bb,e
+					| e1 :: el ->
+						let bb = block_element bb e1 in
+						loop2 bb el
+					| [] ->
+						assert false
+				in
+				let bb,e = loop2 bb el in
+				loop bb e
+			| _ ->
+				bb,e
+		in
+		let bb,e = loop bb e in
+		no_void v.v_type e.epos;
+		let ev = mk (TLocal v) v.v_type e.epos in
+		let was_assigned = ref false in
+		let assign e =
+			if not !was_assigned then begin
+				was_assigned := true;
+				add_texpr bb (mk (TVar(v,None)) ctx.com.basic.tvoid ev.epos);
+			end;
+			mk (TBinop(OpAssign,ev,e)) ev.etype e.epos
+		in
+		begin try
+			block_element_plus bb (map_values assign e) (fun e -> mk (TVar(v,Some e)) ctx.com.basic.tvoid e.epos)
+		with Exit ->
+			let bb,e = value bb e in
+			add_texpr bb (mk (TVar(v,Some e)) ctx.com.basic.tvoid ev.epos);
+			bb
+		end
+	and block_element_plus bb (e,efinal) f =
+		let bb = block_element bb e in
+		let bb = match efinal with
+			| None -> bb
+			| Some e -> block_element bb (f e)
+		in
+		bb
+	and block_element_value bb e f =
+		let e,efinal = map_values f e in
+		block_element_plus bb (e,efinal) f
+	and call bb e e1 el =
+		begin match e1.eexpr with
+			| TConst TSuper when ctx.com.platform = Java || ctx.com.platform = Cs ->
+				bb,e
+			| _ ->
+				let check e t = match e.eexpr with
+					| TLocal v when is_ref_type t ->
+						v.v_capture <- true;
+						e
+					| _ ->
+						e
+				in
+				let el = Codegen.UnificationCallback.check_call check el e1.etype in
+				let bb,el = ordered_value_list bb (e1 :: el) in
+				match el with
+					| e1 :: el -> bb,{e with eexpr = TCall(e1,el)}
+					| _ -> assert false
+		end
+	and block_element bb e = match e.eexpr with
+		(* variables *)
+		| TVar(v,None) ->
+			add_texpr bb e;
+			bb
+		| TVar(v,Some e1) ->
+			declare_var_and_assign bb v e1
+		| TBinop(OpAssign,({eexpr = TLocal v} as e1),e2) ->
+			let assign e =
+				mk (TBinop(OpAssign,e1,e)) e.etype e.epos
+			in
+			begin try
+				block_element_value bb e2 assign
+			with Exit ->
+				let bb,e2 = value bb e2 in
+				add_texpr bb {e with eexpr = TBinop(OpAssign,e1,e2)};
+				bb
+			end
+		(* branching *)
+		| TMeta((Meta.MergeBlock,_,_),{eexpr = TBlock el}) ->
+			block_el bb el
+		| TBlock el ->
+			let bb_sub = create_node BKSub e.etype e.epos in
+			add_cfg_edge bb bb_sub CFGGoto;
+			close_node g bb;
+			let bb_sub_next = block_el bb_sub el in
+			if bb_sub_next != g.g_unreachable then begin
+				let bb_next = create_node BKNormal bb.bb_type bb.bb_pos in
+				set_syntax_edge bb (SESubBlock(bb_sub,bb_next));
+				add_cfg_edge bb_sub_next bb_next CFGGoto;
+				close_node g bb_sub_next;
+				bb_next;
+			end else begin
+				set_syntax_edge bb (SEMerge bb_sub);
+				close_node g bb_sub_next;
+				bb_sub_next
+			end
+		| TIf(e1,e2,None) ->
+			let bb,e1 = bind_to_temp bb false e1 in
+			let bb_then = create_node BKConditional e2.etype e2.epos in
+			add_texpr bb (wrap_meta ":cond-branch" e1);
+			add_cfg_edge bb bb_then (CFGCondBranch (mk (TConst (TBool true)) ctx.com.basic.tbool e2.epos));
+			let bb_then_next = block bb_then e2 in
+			let bb_next = create_node BKNormal bb.bb_type bb.bb_pos in
+			set_syntax_edge bb (SEIfThen(bb_then,bb_next));
+			add_cfg_edge bb bb_next CFGCondElse;
+			close_node g bb;
+			add_cfg_edge bb_then_next bb_next CFGGoto;
+			close_node g bb_then_next;
+			bb_next
+		| TIf(e1,e2,Some e3) ->
+			let bb,e1 = bind_to_temp bb false e1 in
+			let bb_then = create_node BKConditional e2.etype e2.epos in
+			let bb_else = create_node BKConditional e3.etype e3.epos in
+			add_texpr bb (wrap_meta ":cond-branch" e1);
+			add_cfg_edge bb bb_then (CFGCondBranch (mk (TConst (TBool true)) ctx.com.basic.tbool e2.epos));
+			add_cfg_edge bb bb_else CFGCondElse;
+			close_node g bb;
+			let bb_then_next = block bb_then e2 in
+			let bb_else_next = block bb_else e3 in
+			if bb_then_next == g.g_unreachable && bb_else_next == g.g_unreachable then begin
+				set_syntax_edge bb (SEIfThenElse(bb_then,bb_else,g.g_unreachable,e.etype));
+				g.g_unreachable
+			end else begin
+				let bb_next = create_node BKNormal bb.bb_type bb.bb_pos in
+				set_syntax_edge bb (SEIfThenElse(bb_then,bb_else,bb_next,e.etype));
+				add_cfg_edge bb_then_next bb_next CFGGoto;
+				add_cfg_edge bb_else_next bb_next CFGGoto;
+				close_node g bb_then_next;
+				close_node g bb_else_next;
+				bb_next
+			end
+		| TSwitch(e1,cases,edef) ->
+			let is_exhaustive = edef <> None || Optimizer.is_exhaustive e1 in
+			let bb,e1 = bind_to_temp bb false e1 in
+			add_texpr bb (wrap_meta ":cond-branch" e1);
+			let reachable = ref [] in
+			let make_case e =
+				let bb_case = create_node BKConditional e.etype e.epos in
+				let bb_case_next = block bb_case e in
+				if bb_case_next != g.g_unreachable then
+					reachable := bb_case_next :: !reachable;
+				close_node g bb_case_next;
+				bb_case
+			in
+			let cases = List.map (fun (el,e) ->
+				let bb_case = make_case e in
+				List.iter (fun e -> add_cfg_edge bb bb_case (CFGCondBranch e)) el;
+				el,bb_case
+			) cases in
+			let def = match edef with
+				| None ->
+					None
+				| Some e ->
+					let bb_case = make_case e in
+					add_cfg_edge bb bb_case (CFGCondElse);
+					Some (bb_case)
+			in
+			if is_exhaustive && !reachable = [] then begin
+				set_syntax_edge bb (SESwitch(cases,def,g.g_unreachable));
+				close_node g bb;
+				g.g_unreachable;
+			end else begin
+				let bb_next = create_node BKNormal bb.bb_type bb.bb_pos in
+				if not is_exhaustive then add_cfg_edge bb bb_next CFGGoto;
+				List.iter (fun bb -> add_cfg_edge bb bb_next CFGGoto) !reachable;
+				set_syntax_edge bb (SESwitch(cases,def,bb_next));
+				close_node g bb;
+				bb_next
+			end
+		| TWhile(e1,e2,NormalWhile) ->
+			let bb_loop_pre = create_node BKNormal e1.etype e1.epos in
+			add_cfg_edge bb bb_loop_pre CFGGoto;
+			set_syntax_edge bb (SEMerge bb_loop_pre);
+			close_node g bb;
+			let bb_loop_head = create_node BKLoopHead e1.etype e1.epos in
+			add_cfg_edge bb_loop_pre bb_loop_head CFGGoto;
+			let close = begin_loop bb bb_loop_head in
+			let bb_loop_body = create_node BKNormal e2.etype e2.epos in
+			let bb_loop_body_next = block bb_loop_body e2 in
+			let bb_breaks = close() in
+			let bb_next = if bb_breaks = [] then begin
+				(* The loop appears to be infinite, let's assume that something within it throws.
+				   Otherwise DCE's mark-pass won't see its body and removes everything. *)
+				add_cfg_edge bb_loop_body_next bb_exit CFGMaybeThrow;
+				g.g_unreachable
+			end else
+				create_node BKNormal bb.bb_type bb.bb_pos
+			in
+			List.iter (fun bb -> add_cfg_edge bb bb_next CFGGoto) bb_breaks;
+			set_syntax_edge bb_loop_pre (SEWhile(bb_loop_head,bb_loop_body,bb_next));
+			close_node g bb_loop_pre;
+			add_texpr bb_loop_pre {e with eexpr = TWhile(e1,make_block_meta bb_loop_body,NormalWhile)};
+			add_cfg_edge bb_loop_body_next bb_loop_head CFGGoto;
+			add_cfg_edge bb_loop_head bb_loop_body CFGGoto;
+			close_node g bb_loop_body_next;
+			close_node g bb_loop_head;
+			bb_next;
+		| TTry(e1,catches) ->
+			let bb_try = create_node BKNormal e1.etype e1.epos in
+			let bb_exc = create_node BKException t_dynamic e.epos in
+			add_cfg_edge bb bb_try CFGGoto;
+			let close = begin_try bb_exc in
+			let bb_try_next = block bb_try e1 in
+			close();
+			let bb_next = if bb_exc.bb_incoming = [] then
+				let bb_next = if bb_try_next == g.g_unreachable then
+					g.g_unreachable
+				else begin
+					let bb_next = create_node BKNormal bb.bb_type bb.bb_pos in
+					add_cfg_edge bb_try_next bb_next CFGGoto;
+					close_node g bb_try_next;
+					bb_next
+				end in
+				set_syntax_edge bb (SESubBlock(bb_try,bb_next));
+				bb_next
+			else begin
+				let is_reachable = ref (not (bb_try_next == g.g_unreachable)) in
+				let catches = List.map (fun (v,e) ->
+					let bb_catch = create_node (BKCatch v) e.etype e.epos in
+					add_cfg_edge bb_exc bb_catch CFGGoto;
+					let bb_catch_next = block bb_catch e in
+					is_reachable := !is_reachable || (not (bb_catch_next == g.g_unreachable));
+					v,bb_catch,bb_catch_next
+				) catches in
+				let bb_next = if !is_reachable then create_node BKNormal bb.bb_type bb.bb_pos else g.g_unreachable in
+				let catches = List.map (fun (v,bb_catch,bb_catch_next) ->
+					if bb_catch_next != g.g_unreachable then add_cfg_edge bb_catch_next bb_next CFGGoto;
+					close_node g bb_catch_next;
+					v,bb_catch
+				) catches in
+				set_syntax_edge bb (SETry(bb_try,bb_exc,catches,bb_next));
+				if bb_try_next != g.g_unreachable then add_cfg_edge bb_try_next bb_next CFGGoto;
+				close_node g bb_try_next;
+				bb_next
+			end in
+            close_node g bb_exc;
+            close_node g bb;
+			bb_next
+		(* control flow *)
+		| TReturn None ->
+			add_cfg_edge bb bb_exit CFGGoto;
+			add_terminator bb e
+		| TReturn (Some e1) ->
+			begin try
+				let mk_return e1 = mk (TReturn (Some e1)) t_dynamic e.epos in
+				block_element_value bb e1 mk_return
+			with Exit ->
+				let bb,e1 = value bb e1 in
+				add_cfg_edge bb bb_exit CFGGoto;
+				add_terminator bb {e with eexpr = TReturn(Some e1)};
+			end
+		| TBreak ->
+			bb_breaks := bb :: !bb_breaks;
+			add_terminator bb e
+		| TContinue ->
+			begin match !bb_continue with
+				| Some bb_continue -> add_cfg_edge bb bb_continue CFGGoto
+				| _ -> assert false
+			end;
+			add_terminator bb e
+		| TThrow e1 ->
+			begin try
+				let mk_throw e1 =
+					no_void e1.etype e1.epos;
+					mk (TThrow e1) t_dynamic e.epos
+				in
+				block_element_value bb e1 mk_throw
+			with Exit ->
+				let bb,e1 = value bb e1 in
+				begin match !b_try_stack with
+					| [] -> add_cfg_edge bb bb_exit CFGGoto
+					| _ -> List.iter (fun bb_exc -> add_cfg_edge bb bb_exc CFGGoto) !b_try_stack;
+				end;
+				no_void e1.etype e1.epos;
+				add_terminator bb {e with eexpr = TThrow e1};
+			end
+		(* side_effects *)
+		| TCall({eexpr = TLocal v},el) when is_really_unbound v ->
+			check_unbound_call v el;
+			add_texpr bb e;
+			bb
+		| TCall(e1,el) ->
+			let bb,e = call bb e e1 el in
+			add_texpr bb e;
+			bb
+		| TNew(c,tl,el) ->
+			let bb,el = ordered_value_list bb el in
+			add_texpr bb {e with eexpr = TNew(c,tl,el)};
+			bb
+		| TCast(e1,Some mt) ->
+			let b,e1 = value bb e1 in
+			add_texpr bb {e with eexpr = TCast(e1,Some mt)};
+			bb
+		| TBinop((OpAssign | OpAssignOp _) as op,({eexpr = TArray(e1,e2)} as ea),e3) ->
+			let bb,e1,e2,e3 = match ordered_value_list bb [e1;e2;e3] with
+				| bb,[e1;e2;e3] -> bb,e1,e2,e3
+				| _ -> assert false
+			in
+			add_texpr bb {e with eexpr = TBinop(op,{ea with eexpr = TArray(e1,e2)},e3)};
+			bb
+		| TBinop((OpAssign | OpAssignOp _ as op),e1,e2) ->
+			let bb,e1 = value bb e1 in
+			let bb,e2 = value bb e2 in
+			add_texpr bb {e with eexpr = TBinop(op,e1,e2)};
+			bb
+		| TUnop((Increment | Decrement as op),flag,e1) ->
+			let bb,e1 = value bb e1 in
+			add_texpr bb {e with eexpr = TUnop(op,flag,e1)};
+			bb
+		| TLocal _ when not ctx.config.AnalyzerConfig.local_dce ->
+			add_texpr bb e;
+			bb
+		(* no-side-effect *)
+		| TEnumParameter _ | TFunction _ | TConst _ | TTypeExpr _ | TLocal _ ->
+			bb
+		(* no-side-effect composites *)
+		| TParenthesis e1 | TMeta(_,e1) | TCast(e1,None) | TField(e1,_) | TUnop(_,_,e1) ->
+			block_element bb e1
+		| TArray(e1,e2) | TBinop(_,e1,e2) ->
+			let bb = block_element bb e1 in
+			block_element bb e2
+		| TArrayDecl el ->
+			block_el bb el
+		| TObjectDecl fl ->
+			block_el bb (List.map snd fl)
+		| TFor _ | TWhile(_,_,DoWhile) ->
+			assert false
+	and block_el bb el =
+		match !b_try_stack with
+		| [] ->
+			let rec loop bb el = match el with
+				| [] -> bb
+				| e :: el ->
+					let bb = block_element bb e in
+					if bb == g.g_unreachable then bb else loop bb el
+			in
+			loop bb el
+		| bbl ->
+			let rec loop bb el = match el with
+				| [] -> bb
+				| e :: el ->
+					let bb = if not (can_throw e) then
+						block_element bb e
+					else begin
+						let bb' = create_node BKNormal e.etype e.epos in
+						add_cfg_edge bb bb' CFGGoto;
+						List.iter (fun bb_exc -> add_cfg_edge bb bb_exc CFGMaybeThrow) bbl;
+						set_syntax_edge bb (SEMerge bb');
+						close_node g bb;
+						block_element bb' e
+					end in
+					if bb == g.g_unreachable then bb else loop bb el
+			in
+			loop bb el
+	and block bb e =
+		let el = match e.eexpr with
+			| TBlock el -> el
+			| _ -> [e]
+		in
+		block_el bb el
+	in
+	let bb_last = block bb_root tf.tf_expr in
+	close_node g bb_last;
+	add_cfg_edge bb_last bb_exit CFGGoto; (* implied return *)
+	close_node g bb_exit;
+	bb_root,bb_exit
+
+let from_texpr com config e =
+	let g = Graph.create e.etype e.epos in
+	let tf,is_real_function = match e.eexpr with
+		| TFunction tf ->
+			tf,true
+		| _ ->
+			(* Wrap expression in a function so we don't have to treat it as a special case throughout. *)
+			let e = mk (TReturn (Some e)) t_dynamic e.epos in
+			let tf = { tf_args = []; tf_type = e.etype; tf_expr = e; } in
+			tf,false
+	in
+	let ctx = {
+		com = com;
+		config = config;
+		graph = g;
+		(* For CPP we want to use variable names which are "probably" not used by users in order to
+		   avoid problems with the debugger, see https://github.com/HaxeFoundation/hxcpp/issues/365 *)
+		temp_var_name = (match com.platform with Cpp -> "_hx_tmp" | _ -> "tmp");
+		is_real_function = is_real_function;
+		entry = g.g_unreachable;
+		has_unbound = false;
+		loop_counter = 0;
+		loop_stack = [];
+	} in
+	let bb_func,bb_exit = func ctx g.g_root tf e.etype e.epos in
+	ctx.entry <- bb_func;
+	close_node g g.g_root;
+	g.g_exit <- bb_exit;
+	set_syntax_edge bb_exit SEEnd;
+	ctx
+
+let rec block_to_texpr_el ctx bb =
+	if bb.bb_dominator == ctx.graph.g_unreachable then
+		[]
+	else begin
+		let block bb = block_to_texpr ctx bb in
+		let rec loop bb se =
+			let el = List.rev (DynArray.to_list bb.bb_el) in
+			match el,se with
+			| el,SESubBlock(bb_sub,bb_next) ->
+				Some bb_next,(block bb_sub) :: el
+			| el,SEMerge bb_next ->
+				Some bb_next,el
+			| el,(SEEnd | SENone) ->
+				None,el
+			| {eexpr = TWhile(e1,_,flag)} as e :: el,(SEWhile(_,bb_body,bb_next)) ->
+				let e2 = block bb_body in
+				Some bb_next,{e with eexpr = TWhile(e1,e2,flag)} :: el
+			| el,SETry(bb_try,_,bbl,bb_next) ->
+				Some bb_next,(mk (TTry(block bb_try,List.map (fun (v,bb) -> v,block bb) bbl)) ctx.com.basic.tvoid bb_try.bb_pos) :: el
+			| e1 :: el,se ->
+				let e1 = Texpr.skip e1 in
+				let bb_next,e1_def,t = match se with
+					| SEIfThen(bb_then,bb_next) -> Some bb_next,TIf(e1,block bb_then,None),ctx.com.basic.tvoid
+					| SEIfThenElse(bb_then,bb_else,bb_next,t) -> Some bb_next,TIf(e1,block bb_then,Some (block bb_else)),t
+					| SESwitch(bbl,bo,bb_next) -> Some bb_next,TSwitch(e1,List.map (fun (el,bb) -> el,block bb) bbl,Option.map block bo),ctx.com.basic.tvoid
+					| _ -> error (Printf.sprintf "Invalid node exit: %s" (s_expr_pretty e1)) bb.bb_pos
+				in
+				bb_next,(mk e1_def t e1.epos) :: el
+			| [],_ ->
+				None,[]
+		in
+		let bb_next,el = loop bb bb.bb_syntax_edge in
+		let el = match bb_next with
+			| None -> el
+			| Some bb -> (block_to_texpr_el ctx bb) @ el
+		in
+		el
+	end
+
+and block_to_texpr ctx bb =
+	assert(bb.bb_closed);
+	let el = block_to_texpr_el ctx bb in
+	let e = mk (TBlock (List.rev el)) bb.bb_type bb.bb_pos in
+	e
+
+and func ctx i =
+	let bb,t,p,tf = Hashtbl.find ctx.graph.g_functions i in
+	let e = block_to_texpr ctx bb in
+	let rec loop e = match e.eexpr with
+		| TLocal v when not (is_unbound v) ->
+			{e with eexpr = TLocal (get_var_origin ctx.graph v)}
+		| TVar(v,eo) when not (is_unbound v) ->
+			let eo = Option.map loop eo in
+			let v' = get_var_origin ctx.graph v in
+			{e with eexpr = TVar(v',eo)}
+		| TBinop(OpAssign,e1,({eexpr = TBinop(op,e2,e3)} as e4)) when target_handles_assign_ops ctx.com ->
+			let e1 = loop e1 in
+			let e2 = loop e2 in
+			let e3 = loop e3 in
+			let is_valid_assign_op = function
+				| OpAdd | OpMult | OpDiv | OpSub | OpAnd
+				| OpOr | OpXor | OpShl | OpShr | OpUShr | OpMod ->
+					true
+				| OpAssignOp _ | OpInterval | OpArrow | OpAssign | OpEq
+				| OpNotEq | OpGt | OpGte | OpLt | OpLte | OpBoolAnd | OpBoolOr ->
+					false
+			in
+			begin match e1.eexpr,e2.eexpr with
+				| TLocal v1,TLocal v2 when v1 == v2 && is_valid_assign_op op ->
+					begin match op,e3.eexpr with
+						| OpAdd,TConst (TInt i32) when Int32.to_int i32 = 1 && target_handles_assign_ops ctx.com -> {e with eexpr = TUnop(Increment,Prefix,e1)}
+						| OpSub,TConst (TInt i32) when Int32.to_int i32 = 1 && target_handles_assign_ops ctx.com -> {e with eexpr = TUnop(Decrement,Prefix,e1)}
+						| _ -> {e with eexpr = TBinop(OpAssignOp op,e1,e3)}
+					end
+				| _ ->
+					{e with eexpr = TBinop(OpAssign,e1,{e4 with eexpr = TBinop(op,e2,e3)})}
+			end
+		| TCall({eexpr = TConst (TString "fun")},[{eexpr = TConst (TInt i32)}]) ->
+			func ctx (Int32.to_int i32)
+		| TCall({eexpr = TLocal v},_) when is_really_unbound v ->
+			e
+		| _ ->
+			Type.map_expr loop e
+	in
+	let e = loop e in
+	mk (TFunction {tf with tf_expr = e}) t p
+
+let to_texpr ctx =
+	func ctx ctx.entry.bb_id

+ 522 - 0
src/optimization/analyzerTypes.ml

@@ -0,0 +1,522 @@
+(*
+	The Haxe Compiler
+	Copyright (C) 2005-2016  Haxe Foundation
+
+	This program is free software; you can redistribute it and/or
+	modify it under the terms of the GNU General Public License
+	as published by the Free Software Foundation; either version 2
+	of the License, or (at your option) any later version.
+
+	This program is distributed in the hope that it will be useful,
+	but WITHOUT ANY WARRANTY; without even the implied warranty of
+	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+	GNU General Public License for more details.
+
+	You should have received a copy of the GNU General Public License
+	along with this program; if not, write to the Free Software
+	Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *)
+
+open Ast
+open Type
+open Common
+
+(*
+	A BasicBlock represents a node in the control flow. It has expression elements similar to TBlock in the AST,
+	but also holds additional information related to control flow and variables.
+
+	Basic blocks are created whenever it is relevant for control flow. They differ from TBlock in that only their
+	final element can be a control flow expression (the terminator). As a consequence, a given TBlock is split up
+	into several basic blocks when control flow expressions are encountered.
+*)
+module BasicBlock = struct
+	type block_kind =
+		| BKRoot                    (* The unique root block of the graph *)
+		| BKNormal                  (* A normal block *)
+		| BKFunctionBegin of tfunc  (* Entry block of a function *)
+		| BKFunctionEnd             (* Exit block of a function *)
+		| BKSub                     (* A sub block *)
+		| BKConditional             (* A "then", "else" or "case" block *)
+		| BKLoopHead                (* Header block of a loop *)
+		| BKException               (* Relay block for exceptions *)
+		| BKUnreachable             (* The unique unreachable block *)
+		| BKCatch of tvar           (* A catch block *)
+
+	type cfg_edge_Flag =
+		| FlagExecutable      (* Used by constant propagation to handle live edges *)
+		| FlagDce             (* Used by DCE to keep track of handled edges *)
+		| FlagCodeMotion      (* Used by code motion to track handled edges *)
+		| FlagCopyPropagation (* Used by copy propagation to track handled eges *)
+
+	type cfg_edge_kind =
+		| CFGGoto                (* An unconditional branch *)
+		| CFGFunction            (* Link to a function *)
+		| CFGMaybeThrow          (* The block may or may not throw an exception *)
+		| CFGCondBranch of texpr (* A conditional branch *)
+		| CFGCondElse            (* A conditional alternative (else,default) *)
+
+	and cfg_edge = {
+		cfg_from : t;                           (* The source block *)
+		cfg_to : t;                             (* The target block *)
+		cfg_kind : cfg_edge_kind;               (* The edge kind *)
+		mutable cfg_flags : cfg_edge_Flag list; (* Edge flags *)
+	}
+
+	and syntax_edge =
+		| SEIfThen of t * t                                (* `if` with "then" and "next" *)
+		| SEIfThenElse of t * t * t * Type.t               (* `if` with "then", "else" and "next" *)
+		| SESwitch of (texpr list * t) list * t option * t (* `switch` with cases, "default" and "next" *)
+		| SETry of t * t * (tvar * t) list * t             (* `try` with "exc", catches and "next" *)
+		| SEWhile of t * t * t                             (* `while` with "head", "body" and "next" *)
+		| SESubBlock of t * t                              (* "sub" with "next" *)
+		| SEMerge of t                                     (* Merge to same block *)
+		| SEEnd                                            (* End of syntax *)
+		| SENone                                           (* No syntax exit *)
+
+	and t = {
+		bb_id : int;                          (* The unique ID of the block *)
+		bb_type : Type.t;                     (* The block type *)
+		bb_pos : pos;                         (* The block position *)
+		bb_kind : block_kind;                 (* The block kind *)
+		mutable bb_closed : bool;             (* Whether or not the block has been closed *)
+		(* elements *)
+		bb_el : texpr DynArray.t;             (* The block expressions *)
+		bb_phi : texpr DynArray.t;            (* SSA-phi expressions *)
+		(* relations *)
+		mutable bb_outgoing : cfg_edge list;  (* Outgoing edges *)
+		mutable bb_incoming : cfg_edge list;  (* Incoming edges *)
+		mutable bb_dominator : t;             (* The block's dominator *)
+		mutable bb_dominated : t list;        (* The dominated blocks *)
+		mutable bb_df : t list;               (* The dominance frontier *)
+		mutable bb_syntax_edge : syntax_edge; (* The syntactic edge *)
+		mutable bb_loop_groups : int list;    (* The loop groups this block belongs to *)
+		mutable bb_scopes : int list;         (* The scopes this block belongs to *)
+		(* variables *)
+		mutable bb_var_writes : tvar list;    (* List of assigned variables *)
+	}
+
+	let s_block_kind = function
+		| BKRoot -> "BKRoot"
+		| BKNormal -> "BKNormal"
+		| BKFunctionBegin _ -> "BKFunctionBegin"
+		| BKFunctionEnd -> "BKFunctionEnd"
+		| BKSub -> "BKSub"
+		| BKConditional -> "BKConditional"
+		| BKLoopHead -> "BKLoopHead"
+		| BKException -> "BKException"
+		| BKUnreachable -> "BKUnreachable"
+		| BKCatch _ -> "BKCatch"
+
+	let s_cfg_edge_kind = function
+		| CFGGoto -> "CFGGoto"
+		| CFGFunction -> "CFGFunction"
+		| CFGMaybeThrow -> "CFGMaybeThrow"
+		| CFGCondBranch e -> "CFGCondBranch " ^ (s_expr_pretty "" (s_type (print_context())) e)
+		| CFGCondElse -> "CFGCondElse"
+
+	let has_flag edge flag =
+		List.mem flag edge.cfg_flags
+
+	(* expressions *)
+
+	let add_texpr bb e =
+		DynArray.add bb.bb_el e
+
+	let get_texpr bb is_phi i =
+		DynArray.get (if is_phi then bb.bb_phi else bb.bb_el) i
+
+	(* edges *)
+
+	let set_syntax_edge bb se =
+		bb.bb_syntax_edge <- se
+
+	let add_cfg_edge bb_from bb_to kind =
+		if bb_from.bb_kind <> BKUnreachable then begin
+			let edge = { cfg_from = bb_from; cfg_to = bb_to; cfg_kind = kind; cfg_flags = [] } in
+			bb_from.bb_outgoing <- edge :: bb_from.bb_outgoing;
+			bb_to.bb_incoming <- edge :: bb_to.bb_incoming;
+		end
+
+	let _create id kind t p =
+		let rec bb = {
+			bb_kind = kind;
+			bb_id = id;
+			bb_type = t;
+			bb_pos = p;
+			bb_closed = false;
+			bb_el = DynArray.create();
+			bb_phi = DynArray.create();
+			bb_outgoing = [];
+			bb_incoming = [];
+			bb_dominator = bb;
+			bb_dominated = [];
+			bb_df = [];
+			bb_syntax_edge = SENone;
+			bb_loop_groups = [];
+			bb_var_writes = [];
+			bb_scopes = [];
+		} in
+		bb
+
+	let in_scope bb bb' = match bb'.bb_scopes with
+		| [] -> error (Printf.sprintf "Scope-less block (kind: %s)" (s_block_kind bb'.bb_kind)) bb'.bb_pos
+		| scope :: _ -> List.mem scope bb.bb_scopes
+end
+
+(*
+	A Graph contains all relevant information for a given method. It is built from the field expression
+	and then refined in subsequent modules such as Ssa.
+*)
+module Graph = struct
+	open BasicBlock
+
+	type texpr_lookup = BasicBlock.t * bool * int
+	type tfunc_info = BasicBlock.t * Type.t * pos * tfunc
+	type var_write = BasicBlock.t list
+	type 'a itbl = (int,'a) Hashtbl.t
+
+	type var_info = {
+		vi_var : tvar;                            (* The variable itself *)
+		vi_extra : tvar_extra;                    (* The original v_extra *)
+		vi_bb_declare : BasicBlock.t;             (* The block where this variable was declared *)
+		mutable vi_origin : tvar;                 (* The origin variable of this variable *)
+		mutable vi_writes : var_write;            (* A list of blocks that assign to this variable *)
+		mutable vi_value : texpr_lookup option;   (* The value of this variable, if known *)
+		mutable vi_ssa_edges : texpr_lookup list; (* The expressions this variable influences *)
+		mutable vi_reaching_def : tvar option;    (* The current reaching definition variable of this variable *)
+	}
+
+	type t = {
+		mutable g_root : BasicBlock.t;             (* The unique root block *)
+		mutable g_exit : BasicBlock.t;             (* The unique exit block *)
+		mutable g_unreachable : BasicBlock.t;      (* The unique unreachable block *)
+		mutable g_functions : tfunc_info itbl;     (* A map of functions, indexed by their block IDs *)
+		mutable g_nodes : BasicBlock.t list;       (* A list of all blocks *)
+		g_var_infos : var_info DynArray.t;         (* A map of variable information *)
+		mutable g_loops : BasicBlock.t IntMap.t;   (* A map containing loop information *)
+	}
+
+	(* variables *)
+
+	let create_var_info g bb v =
+		let vi = {
+			vi_var = v;
+			vi_extra = v.v_extra;
+			vi_bb_declare = bb;
+			vi_origin = v;
+			vi_writes = [];
+			vi_value = None;
+			vi_ssa_edges = [];
+			vi_reaching_def = None;
+		} in
+		DynArray.add g.g_var_infos vi;
+		let i = DynArray.length g.g_var_infos - 1 in
+		v.v_extra <- Some([],Some (mk (TConst (TInt (Int32.of_int i))) t_dynamic null_pos))
+
+	let get_var_info g v = match v.v_extra with
+		| Some(_,Some {eexpr = TConst (TInt i32)}) -> DynArray.get g.g_var_infos (Int32.to_int i32)
+		| _ -> assert false
+
+	let declare_var g v bb =
+		create_var_info g bb v
+
+	let add_var_def g bb v =
+		if bb.bb_id > 0 then begin
+			bb.bb_var_writes <- v :: bb.bb_var_writes;
+			let vi = get_var_info g v in
+			vi.vi_writes <- bb :: vi.vi_writes;
+		end
+
+	let set_var_value g v bb is_phi i =
+		(get_var_info g v).vi_value <- Some (bb,is_phi,i)
+
+	let get_var_value g v =
+		let value = (get_var_info g v).vi_value in
+		let bb,is_phi,i = match value with
+			| None -> raise Not_found
+			| Some l -> l
+		in
+		match (get_texpr bb is_phi i).eexpr with
+		| TVar(_,Some e) | TBinop(OpAssign,_,e) -> e
+		| _ -> assert false
+
+	let add_var_origin g v v_origin =
+		(get_var_info g v).vi_origin <- v_origin
+
+	let get_var_origin g v =
+		(get_var_info g v).vi_origin
+
+	let add_ssa_edge g v bb is_phi i =
+		let vi = get_var_info g v in
+		vi.vi_ssa_edges <- (bb,is_phi,i) :: vi.vi_ssa_edges
+
+	(* nodes *)
+
+	let add_function g tf t p bb =
+		Hashtbl.add g.g_functions bb.bb_id (bb,t,p,tf)
+
+	let alloc_id =
+		let r = ref 1 in
+		(fun () ->
+			incr r;
+			!r
+		)
+
+	let create_node g kind t p =
+		let bb = BasicBlock._create (alloc_id()) kind t p in
+		g.g_nodes <- bb :: g.g_nodes;
+		bb
+
+	let close_node g bb =
+		if bb.bb_id > 0 then begin
+			assert(not bb.bb_closed);
+			bb.bb_closed <- true
+		end
+
+	let iter_dom_tree_from g bb f =
+		let rec loop bb =
+			f bb;
+			List.iter loop bb.bb_dominated
+		in
+		loop bb
+
+	let iter_dom_tree g f =
+		iter_dom_tree_from g g.g_root f
+
+	let iter_edges_from g bb f =
+		iter_dom_tree_from g bb (fun bb -> List.iter f bb.bb_outgoing)
+
+	let iter_edges g f =
+		iter_dom_tree g (fun bb -> List.iter f bb.bb_outgoing)
+
+	(* graph *)
+
+	let create t p =
+		let bb_root = BasicBlock._create 1 BKRoot t p; in
+		let bb_unreachable = BasicBlock._create 0 BKUnreachable t_dynamic null_pos in
+		{
+			g_root = bb_root;
+			g_exit = bb_unreachable;
+			g_unreachable = bb_unreachable;
+			g_functions = Hashtbl.create 0;
+			g_nodes = [bb_root];
+			g_var_infos = DynArray.create();
+			g_loops = IntMap.empty;
+		}
+
+	let check_integrity g =
+		List.iter (fun bb ->
+			List.iter (fun edge ->
+				if edge.cfg_to = g.g_unreachable then
+					prerr_endline (Printf.sprintf "Outgoing edge from %i to the unreachable block" bb.bb_id)
+				else if not (List.memq edge edge.cfg_to.bb_incoming) then
+					prerr_endline (Printf.sprintf "Outgoing edge %i -> %i has no matching incoming edge" edge.cfg_from.bb_id edge.cfg_to.bb_id)
+			) bb.bb_outgoing;
+			List.iter (fun edge ->
+				if edge.cfg_from == g.g_unreachable then
+					prerr_endline (Printf.sprintf "Incoming edge to %i from the unreachable block" bb.bb_id)
+				else if not (List.memq edge edge.cfg_from.bb_outgoing) then
+					prerr_endline (Printf.sprintf "Incoming edge %i <- %i has no matching outgoing edge" edge.cfg_to.bb_id edge.cfg_from.bb_id)
+			) bb.bb_incoming
+		) g.g_nodes
+
+	(* inference *)
+
+	type dom_bb_info = {
+		bb : BasicBlock.t;
+		parent : dom_bb_info;
+		mutable idom : dom_bb_info;
+		mutable semi : int;
+		mutable label : dom_bb_info;
+		mutable ancestor : dom_bb_info;
+		mutable bucket : dom_bb_info list;
+	}
+
+	(* Infers the immediate dominators for all reachable blocks. This function can be run multiple times
+	   in case an update is necessary. *)
+	let infer_immediate_dominators g =
+		let info = Hashtbl.create 0 in
+		let nodes = DynArray.create () in
+		let get_info i = Hashtbl.find info i in
+		let add_info bb bb_parent =
+			let rec bbi = {
+				bb = bb;
+				parent = bbi;
+				idom = bbi;
+				semi = DynArray.length nodes;
+				label = bbi;
+				ancestor = bbi;
+				bucket = [];
+			} in
+			let bbi = if bb == bb_parent then bbi else {bbi with parent = get_info bb_parent.bb_id} in
+			Hashtbl.add info bb.bb_id bbi;
+			DynArray.add nodes bbi;
+		in
+		let rec loop bb_parent bb =
+			bb.bb_dominated <- [];
+			add_info bb bb_parent;
+			List.iter (fun edge ->
+				let bb_to = edge.cfg_to in
+				if not (Hashtbl.mem info bb_to.bb_id) then
+					loop bb bb_to
+			) bb.bb_outgoing
+		in
+		loop g.g_root g.g_root;
+		let compress bbi =
+			let rec loop l bbi =
+				if bbi.ancestor == bbi then l else loop (bbi :: l) bbi.ancestor
+			in
+			let worklist = loop [bbi] bbi.ancestor in
+			match worklist with
+				| a :: worklist ->
+					ignore(List.fold_left (fun (a,min_semi) bbi_desc ->
+						let bbi = bbi_desc.label in
+						if bbi.semi > min_semi then begin
+							bbi_desc.label <- a.label;
+							(bbi_desc,min_semi)
+						end else
+							(bbi_desc,bbi.semi)
+					) (a,a.label.semi) worklist)
+				| [] ->
+					assert false
+		in
+		let eval v =
+			let bbi = get_info v in
+			if bbi.ancestor != bbi then begin
+				compress bbi;
+				bbi.label
+			end else
+				bbi
+		in
+		let rec loop nodes' = match nodes' with
+			| [_] -> ()
+			| [] -> assert false
+			| w :: nodes' ->
+				let semi = List.fold_left (fun acc v ->
+					min acc (eval v.cfg_from.bb_id).semi) w.semi w.bb.bb_incoming
+				in
+				w.semi <- semi;
+				let bbi = DynArray.get nodes semi in
+				bbi.bucket <- w :: bbi.bucket;
+				let bbi_p = w.parent in
+				w.ancestor <- bbi_p;
+				List.iter (fun v ->
+					let u = eval v.bb.bb_id in
+					if u.semi < v.semi then
+						v.idom <- u
+					else
+						v.idom <- bbi_p
+				) bbi_p.bucket;
+				bbi_p.bucket <- [];
+				loop nodes'
+		in
+		let l = DynArray.to_list nodes in
+		loop (List.rev l);
+		List.iter (fun w ->
+			if w.idom != (DynArray.get nodes w.semi) then w.idom <- w.idom.idom
+		) (List.tl l);
+		DynArray.iter (fun bbi ->
+			if bbi.idom != bbi then begin
+				let bb = bbi.bb in
+				let bb' = bbi.idom.bb in
+				if bb != bb' then begin
+					bb.bb_dominator <- bb';
+					bb'.bb_dominated <- bb :: bb'.bb_dominated
+				end
+			end
+		) nodes
+
+	(* Infers the dominance frontier for all reachable blocks. This function should only be run once. *)
+	let infer_dominance_frontier g =
+		iter_edges g (fun edge ->
+			let rec loop bb =
+				if bb != g.g_unreachable && bb != edge.cfg_to && bb != edge.cfg_to.bb_dominator then begin
+					if edge.cfg_to != g.g_exit then bb.bb_df <- edge.cfg_to :: bb.bb_df;
+					if bb.bb_dominator != bb then loop bb.bb_dominator
+				end
+			in
+			loop edge.cfg_from
+		)
+
+	(* Infers variable declarations and definitions. This function should only be run once. *)
+	let infer_var_writes g =
+		iter_dom_tree g (fun bb ->
+			begin match bb.bb_kind with
+				| BKCatch v ->
+					declare_var g v bb;
+					add_var_def g bb v
+				| BKFunctionBegin tf ->
+					List.iter (fun (v,_) ->
+						declare_var g v bb;
+						add_var_def g bb v
+					) tf.tf_args;
+				| _ ->
+					()
+			end;
+			DynArray.iter (fun e -> match e.eexpr with
+				| TVar(v,eo) when not (is_unbound v) ->
+					declare_var g v bb;
+					if eo <> None then add_var_def g bb v;
+				| TBinop(OpAssign,{eexpr = TLocal v},_) when not (is_unbound v) ->
+					add_var_def g bb v
+				| _ ->
+					()
+			) bb.bb_el
+		)
+
+	(* Infers the scopes of all reachable blocks. This function can be run multiple times
+	   in case an update is necessary *)
+	let infer_scopes g =
+		let next_scope_id = ref 0 in
+		let next_scope scopes =
+			incr next_scope_id;
+			!next_scope_id :: scopes
+		in
+		let rec loop scopes bb =
+			bb.bb_scopes <- scopes;
+			begin match bb.bb_syntax_edge with
+				| SEIfThen(bb_then,bb_next) ->
+					loop (next_scope scopes) bb_then;
+					loop scopes bb_next
+				| SEIfThenElse(bb_then,bb_else,bb_next,_) ->
+					loop (next_scope scopes) bb_then;
+					loop (next_scope scopes) bb_else;
+					loop scopes bb_next
+				| SESwitch(cases,bbo,bb_next) ->
+					List.iter (fun (_,bb_case) -> loop (next_scope scopes) bb_case) cases;
+					(match bbo with None -> () | Some bb -> loop (next_scope scopes) bb);
+					loop scopes bb_next;
+				| SETry(bb_try,bb_exc,catches,bb_next) ->
+					let scopes' = next_scope scopes in
+					loop scopes' bb_try;
+					loop scopes' bb_exc;
+					List.iter (fun (_,bb_catch) -> loop (next_scope scopes) bb_catch) catches;
+					loop scopes bb_next
+				| SEWhile(bb_head,bb_body,bb_next) ->
+					let scopes' = next_scope scopes in
+					loop scopes' bb_head;
+					loop scopes' bb_body;
+					loop scopes bb_next;
+				| SESubBlock(bb_sub,bb_next) ->
+					loop (next_scope scopes) bb_sub;
+					loop scopes bb_next
+				| SEMerge bb ->
+					loop scopes bb
+				| SEEnd | SENone ->
+					()
+			end
+		in
+		Hashtbl.iter (fun _ (bb,_,_,_) -> loop [0] bb) g.g_functions
+end
+
+type analyzer_context = {
+	com : Common.context;
+	config : AnalyzerConfig.t;
+	graph : Graph.t;
+	temp_var_name : string;
+	is_real_function : bool;
+	mutable entry : BasicBlock.t;
+	mutable has_unbound : bool;
+	mutable loop_counter : int;
+	mutable loop_stack : int list;
+}

+ 3 - 3
src/optimization/filters.ml

@@ -668,7 +668,7 @@ let rec is_removable_class c =
 			| _ -> false) ||
 			| _ -> false) ||
 		List.exists (fun (_,t) -> match follow t with
 		List.exists (fun (_,t) -> match follow t with
 			| TInst(c,_) ->
 			| TInst(c,_) ->
-				Codegen.has_ctor_constraint c || Meta.has Meta.Const c.cl_meta
+				has_ctor_constraint c || Meta.has Meta.Const c.cl_meta
 			| _ ->
 			| _ ->
 				false
 				false
 		) c.cl_params)
 		) c.cl_params)
@@ -868,7 +868,7 @@ let add_field_inits ctx t =
 				| _ ->
 				| _ ->
 					assert false
 					assert false
 			in
 			in
-			let config = Analyzer.Config.get_field_config ctx.com c cf in
+			let config = AnalyzerConfig.get_field_config ctx.com c cf in
 			Analyzer.Run.run_on_field ctx config c cf;
 			Analyzer.Run.run_on_field ctx config c cf;
 			(match cf.cf_expr with
 			(match cf.cf_expr with
 			| Some e ->
 			| Some e ->
@@ -1035,8 +1035,8 @@ let run com tctx main =
 	(* PASS 1: general expression filters *)
 	(* PASS 1: general expression filters *)
 	let filters = [
 	let filters = [
 		Codegen.AbstractCast.handle_abstract_casts tctx;
 		Codegen.AbstractCast.handle_abstract_casts tctx;
-		check_local_vars_init;
 		Optimizer.inline_constructors tctx;
 		Optimizer.inline_constructors tctx;
+		check_local_vars_init;
 		Optimizer.reduce_expression tctx;
 		Optimizer.reduce_expression tctx;
 		captured_vars com;
 		captured_vars com;
 	] in
 	] in

+ 19 - 14
src/optimization/optimizer.ml

@@ -179,10 +179,11 @@ let api_inline ctx c field params p = match c.cl_path, field, params with
 		| TTypeExpr (TAbstractDecl ({ a_path = [],"Bool" })) -> Some (typeof "boolean")
 		| TTypeExpr (TAbstractDecl ({ a_path = [],"Bool" })) -> Some (typeof "boolean")
 		| TTypeExpr (TAbstractDecl ({ a_path = [],"Float" })) -> Some (typeof "number")
 		| TTypeExpr (TAbstractDecl ({ a_path = [],"Float" })) -> Some (typeof "number")
 		| TTypeExpr (TAbstractDecl ({ a_path = [],"Int" })) when is_trivial o ->
 		| TTypeExpr (TAbstractDecl ({ a_path = [],"Int" })) when is_trivial o ->
-			(* generate (o|0) === o check *)
+			(* generate typeof(o) == "number" && (o|0) === o check *)
 			let teq = mk_local ctx "__strict_eq__" (tfun [tint; tint] tbool) p in
 			let teq = mk_local ctx "__strict_eq__" (tfun [tint; tint] tbool) p in
 			let lhs = mk (TBinop (Ast.OpOr, o, mk (TConst (TInt Int32.zero)) tint p)) tint p in
 			let lhs = mk (TBinop (Ast.OpOr, o, mk (TConst (TInt Int32.zero)) tint p)) tint p in
-			Some (mk (TCall (teq, [lhs; o])) tbool p)
+			let jscheck = mk (TCall (teq, [lhs; o])) tbool p in
+			Some(mk (TBinop (Ast.OpBoolAnd, typeof "number", jscheck)) tbool p)
 		| TTypeExpr (TClassDecl ({ cl_path = [],"Array" })) ->
 		| TTypeExpr (TClassDecl ({ cl_path = [],"Array" })) ->
 			(* generate (o instanceof Array) && o.__enum__ == null check *)
 			(* generate (o instanceof Array) && o.__enum__ == null check *)
 			let iof = mk_local ctx "__instanceof__" (tfun [o.etype;t.etype] tbool) p in
 			let iof = mk_local ctx "__instanceof__" (tfun [o.etype;t.etype] tbool) p in
@@ -1412,6 +1413,16 @@ let inline_constructors ctx e =
 		v.v_id <- -v.v_id;
 		v.v_id <- -v.v_id;
 		vars := IntMap.add v.v_id ii !vars;
 		vars := IntMap.add v.v_id ii !vars;
 	in
 	in
+	let get_field_var v s =
+		let ii = IntMap.find v.v_id !vars in
+		PMap.find s ii.ii_fields
+	in
+	let add_field_var v s t =
+		let ii = IntMap.find v.v_id !vars in
+		let v' = alloc_var (Printf.sprintf "%s_%s" v.v_name s) t in
+		ii.ii_fields <- PMap.add s v' ii.ii_fields;
+		v'
+	in
 	let int_field_name i =
 	let int_field_name i =
 		if i < 0 then "n" ^ (string_of_int (-i))
 		if i < 0 then "n" ^ (string_of_int (-i))
 		else (string_of_int i)
 		else (string_of_int i)
@@ -1476,7 +1487,9 @@ let inline_constructors ctx e =
 					()
 					()
 			in
 			in
 			loop [] e1
 			loop [] e1
-		| TBinop(OpAssign,{eexpr = TField({eexpr = TLocal v},_)},e2) when v.v_id < 0 ->
+		| TBinop(OpAssign,({eexpr = TField({eexpr = TLocal v},fa)} as e1),e2) when v.v_id < 0 ->
+			let s = field_name fa in
+			(try ignore(get_field_var v s) with Not_found -> ignore(add_field_var v s e1.etype));
 			find_locals e2
 			find_locals e2
 		| TField({eexpr = TLocal v},fa) when v.v_id < 0 ->
 		| TField({eexpr = TLocal v},fa) when v.v_id < 0 ->
 			begin match extract_field fa with
 			begin match extract_field fa with
@@ -1502,20 +1515,12 @@ let inline_constructors ctx e =
 	in
 	in
 	find_locals e;
 	find_locals e;
 	(* Pass 2 *)
 	(* Pass 2 *)
-	let get_field_var v s =
-		let ii = IntMap.find v.v_id !vars in
-		PMap.find s ii.ii_fields
-	in
-	let add_field_var v s t =
-		let ii = IntMap.find v.v_id !vars in
-		let v' = alloc_var (Printf.sprintf "%s_%s" v.v_name s) t in
-		ii.ii_fields <- PMap.add s v' ii.ii_fields;
-		v'
-	in
 	let inline v p =
 	let inline v p =
 		try
 		try
 			let ii = IntMap.find v.v_id !vars in
 			let ii = IntMap.find v.v_id !vars in
-			Some ii.ii_expr
+			let el = PMap.fold (fun v acc -> (mk (TVar(v,None)) ctx.t.tvoid p) :: acc) ii.ii_fields [] in
+			let e = {ii.ii_expr with eexpr = TBlock (el @ [ii.ii_expr])} in
+			Some e
 		with Not_found ->
 		with Not_found ->
 			None
 			None
 	in
 	in

+ 12 - 1
src/syntax/ast.ml

@@ -74,6 +74,7 @@ module Meta = struct
 		| FakeEnum
 		| FakeEnum
 		| File
 		| File
 		| Final
 		| Final
+		| Fixed
 		| FlatEnum
 		| FlatEnum
 		| Font
 		| Font
 		| Forward
 		| Forward
@@ -919,4 +920,14 @@ let full_dot_path mpath tpath =
 		(fst mpath) @ [snd mpath;snd tpath]
 		(fst mpath) @ [snd mpath;snd tpath]
 
 
 let safe_for_all2 f a b =
 let safe_for_all2 f a b =
-	try List.for_all2 f a b with _ -> false
+	try List.for_all2 f a b with _ -> false
+
+let rec remove_duplicates f l = match l with
+	| [] -> []
+	| x :: l -> x :: (remove_duplicates f (List.filter (fun x' -> f x x') l))
+
+module Expr = struct
+	let ensure_block e = match fst e with
+		| EBlock _ -> e
+		| _ -> (EBlock [e],pos e)
+end

+ 3 - 72
src/typing/common.ml

@@ -84,14 +84,10 @@ type platform_config = {
 	pf_add_final_return : bool;
 	pf_add_final_return : bool;
 	(** does the platform natively support overloaded functions *)
 	(** does the platform natively support overloaded functions *)
 	pf_overload : bool;
 	pf_overload : bool;
-	(** does the platform generator handle pattern matching *)
-	pf_pattern_matching : bool;
 	(** can the platform use default values for non-nullable arguments *)
 	(** can the platform use default values for non-nullable arguments *)
 	pf_can_skip_non_nullable_argument : bool;
 	pf_can_skip_non_nullable_argument : bool;
 	(** type paths that are reserved on the platform *)
 	(** type paths that are reserved on the platform *)
 	pf_reserved_type_paths : path list;
 	pf_reserved_type_paths : path list;
-	(** transform for in the corresponding while *)
-	pf_for_to_while : bool;
 }
 }
 
 
 type display_mode =
 type display_mode =
@@ -171,7 +167,6 @@ module Define = struct
 		| CheckXmlProxy
 		| CheckXmlProxy
 		| CoreApi
 		| CoreApi
 		| CoreApiSerialize
 		| CoreApiSerialize
-		| CppAst
 		| Cppia
 		| Cppia
 		| Dce
 		| Dce
 		| DceDebug
 		| DceDebug
@@ -201,7 +196,7 @@ module Define = struct
 		| JavaVer
 		| JavaVer
 		| JqueryVer
 		| JqueryVer
 		| JsClassic
 		| JsClassic
-		| JsEs5
+		| JsEs
 		| JsUnflatten
 		| JsUnflatten
 		| KeepOldOutput
 		| KeepOldOutput
 		| LoopUnrollMaxCost
 		| LoopUnrollMaxCost
@@ -261,7 +256,6 @@ module Define = struct
 		| CheckXmlProxy -> ("check_xml_proxy","Check the used fields of the xml proxy")
 		| CheckXmlProxy -> ("check_xml_proxy","Check the used fields of the xml proxy")
 		| CoreApi -> ("core_api","Defined in the core api context")
 		| CoreApi -> ("core_api","Defined in the core api context")
 		| CoreApiSerialize -> ("core_api_serialize","Mark some generated core api classes with the Serializable attribute on C#")
 		| CoreApiSerialize -> ("core_api_serialize","Mark some generated core api classes with the Serializable attribute on C#")
-		| CppAst -> ("cppast", "Generate experimental cpp code")
 		| Cppia -> ("cppia", "Generate cpp instruction assembly")
 		| Cppia -> ("cppia", "Generate cpp instruction assembly")
 		| Dce -> ("dce","<mode:std|full||no> Set the dead code elimination mode (default std)")
 		| Dce -> ("dce","<mode:std|full||no> Set the dead code elimination mode (default std)")
 		| DceDebug -> ("dce_debug","Show DCE log")
 		| DceDebug -> ("dce_debug","Show DCE log")
@@ -292,7 +286,7 @@ module Define = struct
 		| JavaVer -> ("java_ver", "<version:5-7> Sets the Java version to be targeted")
 		| JavaVer -> ("java_ver", "<version:5-7> Sets the Java version to be targeted")
 		| JqueryVer -> ("jquery_ver", "The jQuery version supported by js.jquery.*. The version is encoded as an interger. e.g. 1.11.3 is encoded as 11103")
 		| JqueryVer -> ("jquery_ver", "The jQuery version supported by js.jquery.*. The version is encoded as an interger. e.g. 1.11.3 is encoded as 11103")
 		| JsClassic -> ("js_classic","Don't use a function wrapper and strict mode in JS output")
 		| JsClassic -> ("js_classic","Don't use a function wrapper and strict mode in JS output")
-		| JsEs5 -> ("js_es5","Generate JS for ES5-compliant runtimes")
+		| JsEs -> ("js_es","Generate JS compilant with given ES standard version (default 5)")
 		| JsUnflatten -> ("js_unflatten","Generate nested objects for packages and types")
 		| 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)")
 		| 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)")
 		| LoopUnrollMaxCost -> ("loop_unroll_max_cost","Maximum cost (number of expressions * iterations) before loop unrolling is canceled (default 250)")
@@ -412,6 +406,7 @@ module MetaInfo = struct
 		| FakeEnum -> ":fakeEnum",("Treat enum as collection of values of the specified type",[HasParam "Type name";UsedOn TEnum])
 		| FakeEnum -> ":fakeEnum",("Treat enum as collection of values of the specified type",[HasParam "Type name";UsedOn TEnum])
 		| File -> ":file",("Includes a given binary file into the target Swf and associates it with the class (must extend flash.utils.ByteArray)",[HasParam "File path";UsedOn TClass;Platform Flash])
 		| File -> ":file",("Includes a given binary file into the target Swf and associates it with the class (must extend flash.utils.ByteArray)",[HasParam "File path";UsedOn TClass;Platform Flash])
 		| Final -> ":final",("Prevents a class from being extended",[UsedOn TClass])
 		| Final -> ":final",("Prevents a class from being extended",[UsedOn TClass])
+		| Fixed -> ":fixed",("Delcares an anonymous object to have fixed fields",[ (*UsedOn TObjectDecl(_)*)])
 		| FlatEnum -> ":flatEnum",("Internally used to mark an enum as being flat, i.e. having no function constructors",[UsedOn TEnum; Internal])
 		| FlatEnum -> ":flatEnum",("Internally used to mark an enum as being flat, i.e. having no function constructors",[UsedOn TEnum; Internal])
 		| Font -> ":font",("Embeds the given TrueType font into the class (must extend flash.text.Font)",[HasParam "TTF path";HasParam "Range String";UsedOn TClass])
 		| Font -> ":font",("Embeds the given TrueType font into the class (must extend flash.text.Font)",[HasParam "TTF path";HasParam "Range String";UsedOn TClass])
 		| Forward -> ":forward",("Forwards field access to underlying type",[HasParam "List of field names";UsedOn TAbstract])
 		| Forward -> ":forward",("Forwards field access to underlying type",[HasParam "List of field names";UsedOn TAbstract])
@@ -560,10 +555,8 @@ let default_config =
 		pf_pad_nulls = false;
 		pf_pad_nulls = false;
 		pf_add_final_return = false;
 		pf_add_final_return = false;
 		pf_overload = false;
 		pf_overload = false;
-		pf_pattern_matching = false;
 		pf_can_skip_non_nullable_argument = true;
 		pf_can_skip_non_nullable_argument = true;
 		pf_reserved_type_paths = [];
 		pf_reserved_type_paths = [];
-		pf_for_to_while = false;
 	}
 	}
 
 
 let get_config com =
 let get_config com =
@@ -577,62 +570,33 @@ let get_config com =
 			pf_static = false;
 			pf_static = false;
 			pf_sys = false;
 			pf_sys = false;
 			pf_capture_policy = CPLoopVars;
 			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;
 			pf_reserved_type_paths = [([],"Object");([],"Error")];
 			pf_reserved_type_paths = [([],"Object");([],"Error")];
 		}
 		}
 	| Lua ->
 	| Lua ->
 		{
 		{
 			default_config with
 			default_config with
 			pf_static = false;
 			pf_static = false;
-			pf_sys = true;
 			pf_capture_policy = CPLoopVars;
 			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;
-			pf_reserved_type_paths = [];
 		}
 		}
 	| Neko ->
 	| Neko ->
 		{
 		{
 			default_config with
 			default_config with
 			pf_static = false;
 			pf_static = false;
-			pf_sys = true;
-			pf_capture_policy = CPNone;
 			pf_pad_nulls = true;
 			pf_pad_nulls = true;
-			pf_add_final_return = false;
-			pf_overload = false;
-			pf_pattern_matching = false;
-			pf_can_skip_non_nullable_argument = true;
-			pf_reserved_type_paths = [];
 		}
 		}
 	| Flash when defined Define.As3 ->
 	| Flash when defined Define.As3 ->
 		{
 		{
 			default_config with
 			default_config with
-			pf_static = true;
 			pf_sys = false;
 			pf_sys = false;
 			pf_capture_policy = CPLoopVars;
 			pf_capture_policy = CPLoopVars;
-			pf_pad_nulls = false;
 			pf_add_final_return = true;
 			pf_add_final_return = true;
-			pf_overload = false;
-			pf_pattern_matching = false;
 			pf_can_skip_non_nullable_argument = false;
 			pf_can_skip_non_nullable_argument = false;
-			pf_reserved_type_paths = [];
 		}
 		}
 	| Flash ->
 	| Flash ->
 		{
 		{
 			default_config with
 			default_config with
-			pf_static = true;
 			pf_sys = false;
 			pf_sys = false;
 			pf_capture_policy = CPLoopVars;
 			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 = false;
 			pf_can_skip_non_nullable_argument = false;
 			pf_reserved_type_paths = [([],"Object");([],"Error")];
 			pf_reserved_type_paths = [([],"Object");([],"Error")];
 		}
 		}
@@ -640,66 +604,34 @@ let get_config com =
 		{
 		{
 			default_config with
 			default_config with
 			pf_static = false;
 			pf_static = false;
-			pf_sys = true;
-			pf_capture_policy = CPNone;
 			pf_pad_nulls = true;
 			pf_pad_nulls = true;
-			pf_add_final_return = false;
-			pf_overload = false;
-			pf_pattern_matching = false;
-			pf_can_skip_non_nullable_argument = true;
-			pf_reserved_type_paths = [];
 		}
 		}
 	| Cpp ->
 	| Cpp ->
 		{
 		{
 			default_config with
 			default_config with
-			pf_static = true;
-			pf_sys = true;
 			pf_capture_policy = CPWrapRef;
 			pf_capture_policy = CPWrapRef;
 			pf_pad_nulls = true;
 			pf_pad_nulls = true;
 			pf_add_final_return = true;
 			pf_add_final_return = true;
-			pf_overload = false;
-			pf_pattern_matching = false;
-			pf_can_skip_non_nullable_argument = true;
-			pf_reserved_type_paths = [];
 		}
 		}
 	| Cs ->
 	| Cs ->
 		{
 		{
 			default_config with
 			default_config with
-			pf_static = true;
-			pf_sys = true;
 			pf_capture_policy = CPWrapRef;
 			pf_capture_policy = CPWrapRef;
 			pf_pad_nulls = true;
 			pf_pad_nulls = true;
-			pf_add_final_return = false;
 			pf_overload = true;
 			pf_overload = true;
-			pf_pattern_matching = false;
-			pf_can_skip_non_nullable_argument = true;
-			pf_reserved_type_paths = [];
 		}
 		}
 	| Java ->
 	| Java ->
 		{
 		{
 			default_config with
 			default_config with
-			pf_static = true;
-			pf_sys = true;
 			pf_capture_policy = CPWrapRef;
 			pf_capture_policy = CPWrapRef;
 			pf_pad_nulls = true;
 			pf_pad_nulls = true;
-			pf_add_final_return = false;
 			pf_overload = true;
 			pf_overload = true;
-			pf_pattern_matching = false;
-			pf_can_skip_non_nullable_argument = true;
-			pf_reserved_type_paths = [];
 		}
 		}
 	| Python ->
 	| Python ->
 		{
 		{
 			default_config with
 			default_config with
 			pf_static = false;
 			pf_static = false;
-			pf_sys = true;
 			pf_capture_policy = CPLoopVars;
 			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;
-			pf_reserved_type_paths = [];
 		}
 		}
 	| Hl ->
 	| Hl ->
 		{
 		{
@@ -707,7 +639,6 @@ let get_config com =
 			pf_capture_policy = CPWrapRef;
 			pf_capture_policy = CPWrapRef;
 			pf_pad_nulls = true;
 			pf_pad_nulls = true;
 			pf_can_skip_non_nullable_argument = false;
 			pf_can_skip_non_nullable_argument = false;
-			pf_for_to_while = true;
 		}
 		}
 
 
 let memory_marker = [|Unix.time()|]
 let memory_marker = [|Unix.time()|]

+ 3 - 0
src/typing/matcher.ml

@@ -275,6 +275,9 @@ module Pattern = struct
 					| _ ->
 					| _ ->
 						handle_ident i
 						handle_ident i
 				end
 				end
+			| EVars([s,None,None]) ->
+				let v = add_local s in
+				PatVariable v
 			| ECall(e1,el) ->
 			| ECall(e1,el) ->
 				let e1 = type_expr ctx e1 (WithType t) in
 				let e1 = type_expr ctx e1 (WithType t) in
 				begin match e1.eexpr,follow e1.etype with
 				begin match e1.eexpr,follow e1.etype with

+ 79 - 2
src/typing/type.ml

@@ -327,6 +327,9 @@ let mk_block e =
 	| TBlock _ -> e
 	| TBlock _ -> e
 	| _ -> mk (TBlock [e]) e.etype e.epos
 	| _ -> mk (TBlock [e]) e.etype e.epos
 
 
+let is_unbound v =
+	Meta.has Meta.Unbound v.v_meta
+
 let mk_cast e t p = mk (TCast(e,None)) t p
 let mk_cast e t p = mk (TCast(e,None)) t p
 
 
 let null t p = mk (TConst TNull) t p
 let null t p = mk (TConst TNull) t p
@@ -703,6 +706,15 @@ let tconst_to_const = function
 	| TThis -> Ident "this"
 	| TThis -> Ident "this"
 	| TSuper -> Ident "super"
 	| TSuper -> Ident "super"
 
 
+let has_ctor_constraint c = match c.cl_kind with
+	| KTypeParameter tl ->
+		List.exists (fun t -> match follow t with
+			| TAnon a when PMap.mem "new" a.a_fields -> true
+			| TAbstract({a_path=["haxe"],"Constructible"},_) -> true
+			| _ -> false
+		) tl;
+	| _ -> false
+
 (* ======= Field utility ======= *)
 (* ======= Field utility ======= *)
 
 
 let field_name f =
 let field_name f =
@@ -1272,6 +1284,20 @@ module Printer = struct
 			"cl_ordered_fields",s_list "\n" s_tclass_field c.cl_ordered_fields;
 			"cl_ordered_fields",s_list "\n" s_tclass_field c.cl_ordered_fields;
 			"cl_ordered_statics",s_list "\n" s_tclass_field c.cl_ordered_statics;
 			"cl_ordered_statics",s_list "\n" s_tclass_field c.cl_ordered_statics;
 		]
 		]
+
+	let s_tvar_extra ve = match ve with
+		| None -> "None"
+		| Some(tl,eo) -> Printf.sprintf "Some(%s, %s)" (s_type_params tl) (match eo with None -> "None" | Some e -> s_expr_ast true "" s_type e)
+
+	let s_tvar v =
+		s_record_fields [
+			"v_id",string_of_int v.v_id;
+			"v_name",v.v_name;
+			"v_type",s_type v.v_type;
+			"v_capture",string_of_bool v.v_capture;
+			"v_extra",s_tvar_extra v.v_extra;
+			"v_meta",s_metadata v.v_meta;
+		]
 end
 end
 
 
 (* ======= Unification ======= *)
 (* ======= Unification ======= *)
@@ -2447,5 +2473,56 @@ module Texpr = struct
 		| _ -> e
 		| _ -> e
 end
 end
 
 
-let print_if b e =
-	if b then print_endline (s_expr_pretty "" (s_type (print_context())) e)
+module ExtType = struct
+	let is_void = function
+		| TAbstract({a_path=[],"Void"},_) -> true
+		| _ -> false
+end
+
+module StringError = struct
+	(* Source: http://en.wikibooks.org/wiki/Algorithm_implementation/Strings/Levenshtein_distance#OCaml *)
+	let levenshtein a b =
+		let x = Array.init (String.length a) (fun i -> a.[i]) in
+		let y = Array.init (String.length b) (fun i -> b.[i]) in
+		let minimum (x:int) y z =
+			let m' (a:int) b = if a < b then a else b in
+			m' (m' x y) z
+		in
+		let init_matrix n m =
+			let init_col = Array.init m in
+				Array.init n (function
+				| 0 -> init_col (function j -> j)
+				| i -> init_col (function 0 -> i | _ -> 0)
+			)
+		in
+		match Array.length x, Array.length y with
+			| 0, n -> n
+			| m, 0 -> m
+			| m, n ->
+				let matrix = init_matrix (m + 1) (n + 1) in
+				for i = 1 to m do
+					let s = matrix.(i) and t = matrix.(i - 1) in
+					for j = 1 to n do
+						let cost = abs (compare x.(i - 1) y.(j - 1)) in
+						s.(j) <- minimum (t.(j) + 1) (s.(j - 1) + 1) (t.(j - 1) + cost)
+					done
+				done;
+				matrix.(m).(n)
+
+	let string_error_raise s sl msg =
+		if sl = [] then msg else
+		let cl = List.map (fun s2 -> s2,levenshtein s s2) sl in
+		let cl = List.sort (fun (_,c1) (_,c2) -> compare c1 c2) cl in
+		let rec loop sl = match sl with
+			| (s2,i) :: sl when i <= (min (String.length s) (String.length s2)) / 3 -> s2 :: loop sl
+			| _ -> []
+		in
+		match loop cl with
+			| [] -> raise Not_found
+			| [s] -> Printf.sprintf "%s (Suggestion: %s)" msg s
+			| sl -> Printf.sprintf "%s (Suggestions: %s)" msg (String.concat ", " sl)
+
+	let string_error s sl msg =
+		try string_error_raise s sl msg
+		with Not_found -> msg
+end

+ 9 - 47
src/typing/typecore.ml

@@ -157,52 +157,6 @@ let get_constructor_ref : (typer -> tclass -> t list -> Ast.pos -> (t * tclass_f
 let cast_or_unify_ref : (typer -> t -> texpr -> Ast.pos -> texpr) ref = ref (fun _ _ _ _ -> assert false)
 let cast_or_unify_ref : (typer -> t -> texpr -> Ast.pos -> texpr) ref = ref (fun _ _ _ _ -> assert false)
 let find_array_access_raise_ref : (typer -> tabstract -> tparams -> texpr -> texpr option -> pos -> (tclass_field * t * t * texpr * texpr option)) ref = ref (fun _ _ _ _ _ _ -> assert false)
 let find_array_access_raise_ref : (typer -> tabstract -> tparams -> texpr -> texpr option -> pos -> (tclass_field * t * t * texpr * texpr option)) ref = ref (fun _ _ _ _ _ _ -> assert false)
 
 
-(* Source: http://en.wikibooks.org/wiki/Algorithm_implementation/Strings/Levenshtein_distance#OCaml *)
-let levenshtein a b =
-	let x = Array.init (String.length a) (fun i -> a.[i]) in
-	let y = Array.init (String.length b) (fun i -> b.[i]) in
-	let minimum (x:int) y z =
-		let m' (a:int) b = if a < b then a else b in
-		m' (m' x y) z
-	in
-	let init_matrix n m =
-		let init_col = Array.init m in
-			Array.init n (function
-			| 0 -> init_col (function j -> j)
-			| i -> init_col (function 0 -> i | _ -> 0)
-		)
-	in
-	match Array.length x, Array.length y with
-		| 0, n -> n
-		| m, 0 -> m
-		| m, n ->
-			let matrix = init_matrix (m + 1) (n + 1) in
-			for i = 1 to m do
-				let s = matrix.(i) and t = matrix.(i - 1) in
-				for j = 1 to n do
-					let cost = abs (compare x.(i - 1) y.(j - 1)) in
-					s.(j) <- minimum (t.(j) + 1) (s.(j - 1) + 1) (t.(j - 1) + cost)
-				done
-			done;
-			matrix.(m).(n)
-
-let string_error_raise s sl msg =
-	if sl = [] then msg else
-	let cl = List.map (fun s2 -> s2,levenshtein s s2) sl in
-	let cl = List.sort (fun (_,c1) (_,c2) -> compare c1 c2) cl in
-	let rec loop sl = match sl with
-		| (s2,i) :: sl when i <= (min (String.length s) (String.length s2)) / 3 -> s2 :: loop sl
-		| _ -> []
-	in
-	match loop cl with
-		| [] -> raise Not_found
-		| [s] -> Printf.sprintf "%s (Suggestion: %s)" msg s
-		| sl -> Printf.sprintf "%s (Suggestions: %s)" msg (String.concat ", " sl)
-
-let string_error s sl msg =
-	try string_error_raise s sl msg
-	with Not_found -> msg
-
 let string_source t = match follow t with
 let string_source t = match follow t with
 	| TInst(c,_) -> List.map (fun cf -> cf.cf_name) c.cl_ordered_fields
 	| TInst(c,_) -> List.map (fun cf -> cf.cf_name) c.cl_ordered_fields
 	| TAnon a -> PMap.fold (fun cf acc -> cf.cf_name :: acc) a.a_fields []
 	| TAnon a -> PMap.fold (fun cf acc -> cf.cf_name :: acc) a.a_fields []
@@ -219,7 +173,7 @@ let unify_error_msg ctx = function
 	| Invalid_field_type s ->
 	| Invalid_field_type s ->
 		"Invalid type for field " ^ s ^ " :"
 		"Invalid type for field " ^ s ^ " :"
 	| Has_no_field (t,n) ->
 	| Has_no_field (t,n) ->
-		string_error n (string_source t) (short_type ctx t ^ " has no field " ^ n)
+		StringError.string_error n (string_source t) (short_type ctx t ^ " has no field " ^ n)
 	| Has_no_runtime_field (t,n) ->
 	| Has_no_runtime_field (t,n) ->
 		s_type ctx t ^ "." ^ n ^ " is not accessible at runtime"
 		s_type ctx t ^ "." ^ n ^ " is not accessible at runtime"
 	| Has_extra_field (t,n) ->
 	| Has_extra_field (t,n) ->
@@ -425,6 +379,14 @@ let create_fake_module ctx file =
 	Hashtbl.replace ctx.g.modules mdep.m_path mdep;
 	Hashtbl.replace ctx.g.modules mdep.m_path mdep;
 	mdep
 	mdep
 
 
+let push_this ctx e = match e.eexpr with
+	| TConst ((TInt _ | TFloat _ | TString _ | TBool _) as ct) ->
+		(Ast.EConst (tconst_to_const ct),e.epos),fun () -> ()
+	| _ ->
+		ctx.this_stack <- e :: ctx.this_stack;
+		let er = Ast.EMeta((Ast.Meta.This,[],e.epos), (Ast.EConst(Ast.Ident "this"),e.epos)),e.epos in
+		er,fun () -> ctx.this_stack <- List.tl ctx.this_stack
+
 (* -------------- debug functions to activate when debugging typer passes ------------------------------- *)
 (* -------------- debug functions to activate when debugging typer passes ------------------------------- *)
 (*/*
 (*/*
 
 

+ 549 - 2
src/typing/typeload.ml

@@ -951,7 +951,7 @@ let rec return_flow ctx e =
 	in
 	in
 	let return_flow = return_flow ctx in
 	let return_flow = return_flow ctx in
 	let rec uncond e = match e.eexpr with
 	let rec uncond e = match e.eexpr with
-		| TIf _ | TWhile _ | TSwitch _ | TTry _ -> ()
+		| TIf _ | TWhile _ | TSwitch _ | TTry _ | TFunction _ -> ()
 		| TReturn _ | TThrow _ -> raise Exit
 		| TReturn _ | TThrow _ -> raise Exit
 		| _ -> Type.iter uncond e
 		| _ -> Type.iter uncond e
 	in
 	in
@@ -2879,7 +2879,7 @@ let init_module_type ctx context_init do_init (decl,p) =
 			let chk_private t p = if (t_infos t).mt_private then error "You can't import a private type" p in
 			let chk_private t p = if (t_infos t).mt_private then error "You can't import a private type" p in
 			let has_name name t = snd (t_infos t).mt_path = name in
 			let has_name name t = snd (t_infos t).mt_path = name in
 			let get_type tname =
 			let get_type tname =
-				let t = (try List.find (has_name tname) types with Not_found -> error (string_error tname (List.map (fun mt -> snd (t_infos mt).mt_path) types) ("Module " ^ s_type_path md.m_path ^ " does not define type " ^ tname)) p_type) in
+				let t = (try List.find (has_name tname) types with Not_found -> error (StringError.string_error tname (List.map (fun mt -> snd (t_infos mt).mt_path) types) ("Module " ^ s_type_path md.m_path ^ " does not define type " ^ tname)) p_type) in
 				chk_private t p_type;
 				chk_private t p_type;
 				t
 				t
 			in
 			in
@@ -3508,3 +3508,550 @@ let load_module ctx m p =
 
 
 ;;
 ;;
 type_function_params_rec := type_function_params
 type_function_params_rec := type_function_params
+
+(* former codegen.ml stuff starting here *)
+
+(* -------------------------------------------------------------------------- *)
+(* REMOTING PROXYS *)
+
+let extend_remoting ctx c t p async prot =
+	if c.cl_super <> None then error "Cannot extend several classes" p;
+	(* remove forbidden packages *)
+	let rules = ctx.com.package_rules in
+	ctx.com.package_rules <- PMap.foldi (fun key r acc -> match r with Forbidden -> acc | _ -> PMap.add key r acc) rules PMap.empty;
+	(* parse module *)
+	let path = (t.tpackage,t.tname) in
+	let new_name = (if async then "Async_" else "Remoting_") ^ t.tname in
+	(* check if the proxy already exists *)
+	let t = (try
+		load_type_def ctx p { tpackage = fst path; tname = new_name; tparams = []; tsub = None }
+	with
+		Error (Module_not_found _,p2) when p == p2 ->
+	(* build it *)
+	Common.log ctx.com ("Building proxy for " ^ s_type_path path);
+	let file, decls = (try
+		parse_module ctx path p
+	with
+		| Not_found -> ctx.com.package_rules <- rules; error ("Could not load proxy module " ^ s_type_path path ^ (if fst path = [] then " (try using absolute path)" else "")) p
+		| e -> ctx.com.package_rules <- rules; raise e) in
+	ctx.com.package_rules <- rules;
+	let base_fields = [
+		{ cff_name = "__cnx"; cff_pos = p; cff_doc = None; cff_meta = []; cff_access = []; cff_kind = FVar (Some (CTPath { tpackage = ["haxe";"remoting"]; tname = if async then "AsyncConnection" else "Connection"; tparams = []; tsub = None }),None) };
+		{ cff_name = "new"; cff_pos = p; cff_doc = None; cff_meta = []; cff_access = [APublic]; cff_kind = FFun { f_args = ["c",false,None,None]; f_type = None; f_expr = Some (EBinop (OpAssign,(EConst (Ident "__cnx"),p),(EConst (Ident "c"),p)),p); f_params = [] } };
+	] in
+	let tvoid = CTPath { tpackage = []; tname = "Void"; tparams = []; tsub = None } in
+	let build_field is_public acc f =
+		if f.cff_name = "new" then
+			acc
+		else match f.cff_kind with
+		| FFun fd when (is_public || List.mem APublic f.cff_access) && not (List.mem AStatic f.cff_access) ->
+			if List.exists (fun (_,_,t,_) -> t = None) fd.f_args then error ("Field " ^ f.cff_name ^ " type is not complete and cannot be used by RemotingProxy") p;
+			let eargs = [EArrayDecl (List.map (fun (a,_,_,_) -> (EConst (Ident a),p)) fd.f_args),p] in
+			let ftype = (match fd.f_type with Some (CTPath { tpackage = []; tname = "Void" }) -> None | _ -> fd.f_type) in
+			let fargs, eargs = if async then match ftype with
+				| Some tret -> fd.f_args @ ["__callb",true,Some (CTFunction ([tret],tvoid)),None], eargs @ [EConst (Ident "__callb"),p]
+				| _ -> fd.f_args, eargs @ [EConst (Ident "null"),p]
+			else
+				fd.f_args, eargs
+			in
+			let id = (EConst (String f.cff_name), p) in
+			let id = if prot then id else ECall ((EConst (Ident "__unprotect__"),p),[id]),p in
+			let expr = ECall (
+				(EField (
+					(ECall ((EField ((EConst (Ident "__cnx"),p),"resolve"),p),[id]),p),
+					"call")
+				,p),eargs),p
+			in
+			let expr = if async || ftype = None then expr else (EReturn (Some expr),p) in
+			let fd = {
+				f_params = fd.f_params;
+				f_args = fargs;
+				f_type = if async then None else ftype;
+				f_expr = Some (EBlock [expr],p);
+			} in
+			{ cff_name = f.cff_name; cff_pos = f.cff_pos; cff_doc = None; cff_meta = []; cff_access = [APublic]; cff_kind = FFun fd } :: acc
+		| _ -> acc
+	in
+	let decls = List.map (fun d ->
+		match d with
+		| EClass c, p when c.d_name = t.tname ->
+			let is_public = List.mem HExtern c.d_flags || List.mem HInterface c.d_flags in
+			let fields = List.rev (List.fold_left (build_field is_public) base_fields c.d_data) in
+			(EClass { c with d_flags = []; d_name = new_name; d_data = fields },p)
+		| _ -> d
+	) decls in
+	let m = type_module ctx (t.tpackage,new_name) file decls p in
+	add_dependency ctx.m.curmod m;
+	try
+		List.find (fun tdecl -> snd (t_path tdecl) = new_name) m.m_types
+	with Not_found ->
+		error ("Module " ^ s_type_path path ^ " does not define type " ^ t.tname) p
+	) in
+	match t with
+	| 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
+
+(* -------------------------------------------------------------------------- *)
+(* HAXE.RTTI.GENERIC *)
+
+exception Generic_Exception of string * Ast.pos
+
+type generic_context = {
+	ctx : typer;
+	subst : (t * t) list;
+	name : string;
+	p : pos;
+	mutable mg : module_def option;
+}
+
+let make_generic ctx ps pt p =
+	let rec loop l1 l2 =
+		match l1, l2 with
+		| [] , [] -> []
+		| (x,TLazy f) :: l1, _ -> loop ((x,(!f)()) :: l1) l2
+		| (_,t1) :: l1 , t2 :: l2 -> (t1,t2) :: loop l1 l2
+		| _ -> assert false
+	in
+	let name =
+		String.concat "_" (List.map2 (fun (s,_) t ->
+			let s_type_path_underscore (p,s) = match p with [] -> s | _ -> String.concat "_" p ^ "_" ^ s in
+			let rec loop top t = match follow t with
+				| TInst(c,tl) -> (s_type_path_underscore c.cl_path) ^ (loop_tl tl)
+				| TEnum(en,tl) -> (s_type_path_underscore en.e_path) ^ (loop_tl tl)
+				| TAbstract(a,tl) -> (s_type_path_underscore a.a_path) ^ (loop_tl tl)
+				| _ when not top -> "_" (* allow unknown/incompatible types as type parameters to retain old behavior *)
+				| TMono _ -> raise (Generic_Exception (("Could not determine type for parameter " ^ s), p))
+				| TDynamic _ -> "Dynamic"
+				| t -> raise (Generic_Exception (("Type parameter must be a class or enum instance (found " ^ (s_type (print_context()) t) ^ ")"), p))
+			and loop_tl tl = match tl with
+				| [] -> ""
+				| tl -> "_" ^ String.concat "_" (List.map (loop false) tl)
+			in
+			loop true t
+		) ps pt)
+	in
+	{
+		ctx = ctx;
+		subst = loop ps pt;
+		name = name;
+		p = p;
+		mg = None;
+	}
+
+let rec generic_substitute_type gctx t =
+	match t with
+	| TInst ({ cl_kind = KGeneric } as c2,tl2) ->
+		(* maybe loop, or generate cascading generics *)
+		let _, _, f = gctx.ctx.g.do_build_instance gctx.ctx (TClassDecl c2) gctx.p in
+		let t = f (List.map (generic_substitute_type gctx) tl2) in
+		(match follow t,gctx.mg with TInst(c,_), Some m -> add_dependency m c.cl_module | _ -> ());
+		t
+	| _ ->
+		try
+			generic_substitute_type gctx (List.assq t gctx.subst)
+		with Not_found ->
+			Type.map (generic_substitute_type gctx) t
+
+let generic_substitute_expr gctx e =
+	let vars = Hashtbl.create 0 in
+	let build_var v =
+		try
+			Hashtbl.find vars v.v_id
+		with Not_found ->
+			let v2 = alloc_var v.v_name (generic_substitute_type gctx v.v_type) in
+			v2.v_meta <- v.v_meta;
+			Hashtbl.add vars v.v_id v2;
+			v2
+	in
+	let rec build_expr e =
+		match e.eexpr with
+		| TField(e1, FInstance({cl_kind = KGeneric} as c,tl,cf)) ->
+			let _, _, f = gctx.ctx.g.do_build_instance gctx.ctx (TClassDecl c) gctx.p in
+			let t = f (List.map (generic_substitute_type gctx) tl) in
+			let fa = try
+				quick_field t cf.cf_name
+			with Not_found ->
+				error (Printf.sprintf "Type %s has no field %s (possible typing order issue)" (s_type (print_context()) t) cf.cf_name) e.epos
+			in
+			build_expr {e with eexpr = TField(e1,fa)}
+		| TTypeExpr (TClassDecl ({cl_kind = KTypeParameter _;} as c)) when Meta.has Meta.Const c.cl_meta ->
+			let rec loop subst = match subst with
+				| (t1,t2) :: subst ->
+					begin match follow t1 with
+						| TInst(c2,_) when c == c2 -> t2
+						| _ -> loop subst
+					end
+				| [] -> raise Not_found
+			in
+			begin try
+				let t = loop gctx.subst in
+				begin match follow t with
+					| TInst({cl_kind = KExpr e},_) -> type_expr gctx.ctx e Value
+					| _ -> error "Only Const type parameters can be used as value" e.epos
+				end
+			with Not_found ->
+				e
+			end
+		| _ ->
+			map_expr_type build_expr (generic_substitute_type gctx) build_var e
+	in
+	build_expr e
+
+let get_short_name =
+	let i = ref (-1) in
+	(fun () ->
+		incr i;
+		Printf.sprintf "Hx___short___hx_type_%i" !i
+	)
+
+let rec build_generic ctx c p tl =
+	let pack = fst c.cl_path in
+	let recurse = ref false in
+	let rec check_recursive t =
+		match follow t with
+		| TInst (c2,tl) ->
+			(match c2.cl_kind with
+			| KTypeParameter tl ->
+				if not (is_generic_parameter ctx c2) && has_ctor_constraint c2 then
+					error "Type parameters with a constructor cannot be used non-generically" p;
+				recurse := true
+			| _ -> ());
+			List.iter check_recursive tl;
+		| _ ->
+			()
+	in
+	List.iter check_recursive tl;
+	if !recurse then begin
+		TInst (c,tl) (* build a normal instance *)
+	end else begin
+	let gctx = make_generic ctx c.cl_params tl p in
+	let name = (snd c.cl_path) ^ "_" ^ gctx.name in
+	try
+		load_instance ctx { tpackage = pack; tname = name; tparams = []; tsub = None } p false
+	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
+		ignore(c.cl_build()); (* make sure the super class is already setup *)
+		let mg = {
+			m_id = alloc_mid();
+			m_path = (pack,name);
+			m_types = [];
+			m_extra = module_extra (s_type_path (pack,name)) m.m_extra.m_sign 0. MFake;
+		} in
+		gctx.mg <- Some mg;
+		let cg = mk_class mg (pack,name) c.cl_pos in
+		mg.m_types <- [TClassDecl cg];
+		Hashtbl.add ctx.g.modules mg.m_path mg;
+		add_dependency mg m;
+		add_dependency ctx.m.curmod mg;
+		(* ensure that type parameters are set in dependencies *)
+		let dep_stack = ref [] in
+		let rec loop t =
+			if not (List.memq t !dep_stack) then begin
+			dep_stack := t :: !dep_stack;
+			match t with
+			| TInst (c,tl) -> add_dep c.cl_module tl
+			| TEnum (e,tl) -> add_dep e.e_module tl
+			| TType (t,tl) -> add_dep t.t_module tl
+			| TAbstract (a,tl) -> add_dep a.a_module tl
+			| TMono r ->
+				(match !r with
+				| None -> ()
+				| Some t -> loop t)
+			| TLazy f ->
+				loop ((!f)());
+			| TDynamic t2 ->
+				if t == t2 then () else loop t2
+			| TAnon a ->
+				PMap.iter (fun _ f -> loop f.cf_type) a.a_fields
+			| TFun (args,ret) ->
+				List.iter (fun (_,_,t) -> loop t) args;
+				loop ret
+			end
+		and add_dep m tl =
+			add_dependency mg m;
+			List.iter loop tl
+		in
+		List.iter loop tl;
+		let build_field cf_old =
+			(* We have to clone the type parameters (issue #4672). We cannot substitute the constraints immediately because
+		       we need the full substitution list first. *)
+			let param_subst,params = List.fold_left (fun (subst,params) (s,t) -> match follow t with
+				| TInst(c,tl) as t ->
+					let t2 = TInst({c with cl_pos = c.cl_pos;},tl) in
+					(t,t2) :: subst,(s,t2) :: params
+				| _ -> assert false
+			) ([],[]) cf_old.cf_params in
+			let gctx = {gctx with subst = param_subst @ gctx.subst} in
+			let cf_new = {cf_old with cf_pos = cf_old.cf_pos} in (* copy *)
+			(* Type parameter constraints are substituted here. *)
+			cf_new.cf_params <- List.rev_map (fun (s,t) -> match follow t with
+				| TInst({cl_kind = KTypeParameter tl1} as c,_) ->
+					let tl1 = List.map (generic_substitute_type gctx) tl1 in
+					c.cl_kind <- KTypeParameter tl1;
+					s,t
+				| _ -> assert false
+			) params;
+			let f () =
+				let t = generic_substitute_type gctx cf_old.cf_type in
+				ignore (follow t);
+				begin try (match cf_old.cf_expr with
+					| None ->
+						begin match cf_old.cf_kind with
+							| Method _ when not c.cl_interface && not c.cl_extern ->
+								display_error ctx (Printf.sprintf "Field %s has no expression (possible typing order issue)" cf_new.cf_name) cf_new.cf_pos;
+								display_error ctx (Printf.sprintf "While building %s" (s_type_path cg.cl_path)) p;
+							| _ ->
+								()
+						end
+					| Some e ->
+						cf_new.cf_expr <- Some (generic_substitute_expr gctx e)
+				) with Unify_error l ->
+					error (error_msg (Unify l)) cf_new.cf_pos
+				end;
+				t
+			in
+			let r = exc_protect ctx (fun r ->
+				let t = mk_mono() in
+				r := (fun() -> t);
+				unify_raise ctx (f()) t p;
+				t
+			) "build_generic" in
+			delay ctx PForce (fun() -> ignore ((!r)()));
+			cf_new.cf_type <- TLazy r;
+			cf_new
+		in
+		if c.cl_init <> None || c.cl_dynamic <> None then error "This class can't be generic" p;
+		List.iter (fun cf -> match cf.cf_kind with
+			| Method MethMacro when not ctx.in_macro -> ()
+			| _ -> error "A generic class can't have static fields" cf.cf_pos
+		) c.cl_ordered_statics;
+		cg.cl_super <- (match c.cl_super with
+			| None -> None
+			| Some (cs,pl) ->
+				let find_class subst =
+					let rec loop subst = match subst with
+						| (TInst(c,[]),t) :: subst when c == cs -> t
+						| _ :: subst -> loop subst
+						| [] -> raise Not_found
+					in
+					try
+						if pl <> [] then raise Not_found;
+						let t = loop subst in
+						(* 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 ->
+								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
+									| _ -> ()
+								end;
+							| _,Some cf -> error "Generics extending type parameters cannot have constructors" cf.cf_pos
+							| _ -> ()
+						end;
+						t
+					with Not_found ->
+						apply_params c.cl_params tl (TInst(cs,pl))
+				in
+				let ts = follow (find_class gctx.subst) in
+				let cs,pl = Inheritance.check_extends ctx c ts p in
+				match cs.cl_kind with
+				| KGeneric ->
+					(match build_generic ctx cs p pl with
+					| TInst (cs,pl) -> Some (cs,pl)
+					| _ -> assert false)
+				| _ -> Some(cs,pl)
+		);
+		add_constructor ctx cg false p;
+		cg.cl_kind <- KGenericInstance (c,tl);
+		cg.cl_meta <- (Meta.NoDoc,[],p) :: cg.cl_meta;
+		if has_meta Meta.Keep c.cl_meta then cg.cl_meta <- (Meta.Keep,[],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)
+			| Some ctor, _, _ -> Some ctor
+			| None, None, None -> None
+			| _ -> error "Please define a constructor for this class in order to use it as generic" c.cl_pos
+		);
+		cg.cl_implements <- List.map (fun (i,tl) ->
+			(match follow (generic_substitute_type gctx (TInst (i, List.map (generic_substitute_type gctx) tl))) with
+			| TInst (i,tl) -> i, tl
+			| _ -> assert false)
+		) c.cl_implements;
+		cg.cl_ordered_fields <- List.map (fun f ->
+			let f = build_field f in
+			cg.cl_fields <- PMap.add f.cf_name f cg.cl_fields;
+			f
+		) c.cl_ordered_fields;
+		cg.cl_overrides <- List.map (fun f ->
+			try PMap.find f.cf_name cg.cl_fields with Not_found -> assert false
+		) c.cl_overrides;
+		(* 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
+			cg.cl_meta <- (Meta.Native,[EConst(String (n)),p],p) :: cg.cl_meta;
+		end;
+		TInst (cg,[])
+	end
+
+(* -------------------------------------------------------------------------- *)
+(* HAXE.XML.PROXY *)
+
+let extend_xml_proxy ctx c t file p =
+	let t = load_complex_type ctx p t in
+	let file = (try Common.find_file ctx.com file with Not_found -> file) in
+	add_dependency c.cl_module (create_fake_module ctx file);
+	let used = ref PMap.empty in
+	let print_results() =
+		PMap.iter (fun id used ->
+			if not used then ctx.com.warning (id ^ " is not used") p;
+		) (!used)
+	in
+	let check_used = Common.defined ctx.com Define.CheckXmlProxy in
+	if check_used then ctx.g.hook_generate <- print_results :: ctx.g.hook_generate;
+	try
+		let rec loop = function
+			| Xml.Element (_,attrs,childs) ->
+				(try
+					let id = List.assoc "id" attrs in
+					if PMap.mem id c.cl_fields then error ("Duplicate id " ^ id) p;
+					let t = if not check_used then t else begin
+						used := PMap.add id false (!used);
+						let ft() = used := PMap.add id true (!used); t in
+						TLazy (ref ft)
+					end in
+					let f = {
+						cf_name = id;
+						cf_type = t;
+						cf_public = true;
+						cf_pos = p;
+						cf_doc = None;
+						cf_meta = no_meta;
+						cf_kind = Var { v_read = AccResolve; v_write = AccNo };
+						cf_params = [];
+						cf_expr = None;
+						cf_overloads = [];
+					} in
+					c.cl_fields <- PMap.add id f c.cl_fields;
+				with
+					Not_found -> ());
+				List.iter loop childs;
+			| Xml.PCData _ -> ()
+		in
+		loop (Xml.parse_file file)
+	with
+		| Xml.Error e -> error ("XML error " ^ Xml.error e) p
+		| Xml.File_not_found f -> error ("XML File not found : " ^ f) p
+
+(* -------------------------------------------------------------------------- *)
+(* MACRO TYPE *)
+
+let get_macro_path ctx e args p =
+	let rec loop e =
+		match fst e with
+		| EField (e,f) -> f :: loop e
+		| EConst (Ident i) -> [i]
+		| _ -> error "Invalid macro call" p
+	in
+	let path = match e with
+		| (EConst(Ident i)),_ ->
+			let path = try
+				if not (PMap.mem i ctx.curclass.cl_statics) then raise Not_found;
+				ctx.curclass.cl_path
+			with Not_found -> try
+				(t_infos (fst (PMap.find i ctx.m.module_globals))).mt_path
+			with Not_found ->
+				error "Invalid macro call" p
+			in
+			i :: (snd path) :: (fst path)
+		| _ ->
+			loop e
+	in
+	(match path with
+	| meth :: cl :: path -> (List.rev path,cl), meth, args
+	| _ -> error "Invalid macro call" p)
+
+let build_macro_type ctx pl p =
+	let path, field, args = (match pl with
+		| [TInst ({ cl_kind = KExpr (ECall (e,args),_) },_)]
+		| [TInst ({ cl_kind = KExpr (EArrayDecl [ECall (e,args),_],_) },_)] ->
+			get_macro_path ctx e args p
+		| _ ->
+			error "MacroType requires a single expression call parameter" p
+	) in
+	let old = ctx.ret in
+	let t = (match ctx.g.do_macro ctx MMacroType path field args p with
+		| None -> mk_mono()
+		| Some _ -> ctx.ret
+	) in
+	ctx.ret <- old;
+	t
+
+let build_macro_build ctx c pl cfl p =
+	let path, field, args = match Meta.get Meta.GenericBuild c.cl_meta with
+		| _,[ECall(e,args),_],_ -> get_macro_path ctx e args p
+		| _ -> error "genericBuild requires a single expression call parameter" p
+	in
+	let old = ctx.ret,ctx.g.get_build_infos in
+	ctx.g.get_build_infos <- (fun() -> Some (TClassDecl c, pl, cfl));
+	let t = (match ctx.g.do_macro ctx MMacroType path field args p with
+		| None -> mk_mono()
+		| Some _ -> ctx.ret
+	) in
+	ctx.ret <- fst old;
+	ctx.g.get_build_infos <- snd old;
+	t
+
+(* -------------------------------------------------------------------------- *)
+(* API EVENTS *)
+
+let build_instance ctx mtype p =
+	match mtype with
+	| TClassDecl c ->
+		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
+				r := (fun() -> t);
+				let tf = (f()) in
+				unify_raise ctx tf t p;
+				link_dynamic t tf;
+				t
+			) s in
+			delay ctx PForce (fun() -> ignore ((!r)()));
+			TLazy r
+		in
+		let ft = (fun pl ->
+			match c.cl_kind with
+			| KGeneric ->
+				build (fun () -> build_generic ctx c p pl) "build_generic"
+			| KMacroType ->
+				build (fun () -> build_macro_type ctx pl p) "macro_type"
+			| KGenericBuild cfl ->
+				build (fun () -> build_macro_build ctx c pl cfl p) "generic_build"
+			| _ ->
+				TInst (c,pl)
+		) in
+		c.cl_params , c.cl_path , ft
+	| TEnumDecl e ->
+		e.e_params , e.e_path , (fun t -> TEnum (e,t))
+	| TTypeDecl t ->
+		t.t_params , t.t_path , (fun tl -> TType(t,tl))
+	| TAbstractDecl a ->
+		a.a_params, a.a_path, (fun tl -> TAbstract(a,tl))
+
+let on_inherit ctx c p (is_extends,tp) =
+	if not is_extends then
+		true
+	else match tp with
+	| { tpackage = ["haxe";"remoting"]; tname = "Proxy"; tparams = [TPType(CTPath t)] } ->
+		extend_remoting ctx c t p false true;
+		false
+	| { tpackage = ["haxe";"remoting"]; tname = "AsyncProxy"; tparams = [TPType(CTPath t)] } ->
+		extend_remoting ctx c t p true true;
+		false
+	| { tpackage = ["haxe";"xml"]; tname = "Proxy"; tparams = [TPExpr(EConst (String file),p);TPType t] } ->
+		extend_xml_proxy ctx c t file p;
+		true
+	| _ ->
+		true

+ 41 - 38
src/typing/typer.ml

@@ -817,8 +817,9 @@ let unify_field_call ctx fa el args ret p inline =
 		let candidates,failures = loop candidates in
 		let candidates,failures = loop candidates in
 		let fail () =
 		let fail () =
 			let failures = List.map (fun (cf,err,p) -> cf,error_msg err,p) failures in
 			let failures = List.map (fun (cf,err,p) -> cf,error_msg err,p) failures in
+			let failures = remove_duplicates (fun (_,msg1,_) (_,msg2,_) -> msg1 <> msg2) failures in
 			begin match failures with
 			begin match failures with
-			| (_,msg,p) :: failures when List.for_all (fun (_,msg2,_) -> msg = msg2) failures ->
+			| [_,msg,p] ->
 				error msg p
 				error msg p
 			| _ ->
 			| _ ->
 				display_error ctx "Could not find a suitable overload, reasons follow" p;
 				display_error ctx "Could not find a suitable overload, reasons follow" p;
@@ -845,7 +846,7 @@ let fast_enum_field e ef p =
 let rec type_module_type ctx t tparams p =
 let rec type_module_type ctx t tparams p =
 	match t with
 	match t with
 	| TClassDecl {cl_kind = KGenericBuild _} ->
 	| TClassDecl {cl_kind = KGenericBuild _} ->
-		let _,_,f = Codegen.build_instance ctx t p in
+		let _,_,f = Typeload.build_instance ctx t p in
 		let t = f (match tparams with None -> [] | Some tl -> tl) in
 		let t = f (match tparams with None -> [] | Some tl -> tl) in
 		let mt = try
 		let mt = try
 			module_type_of_type t
 			module_type_of_type t
@@ -1445,7 +1446,7 @@ and type_field ?(resume=false) ctx e i p mode =
 				(* the abstract field is not part of the field list, which is only true when it has no expression (issue #2344) *)
 				(* the abstract field is not part of the field list, which is only true when it has no expression (issue #2344) *)
 				display_error ctx ("Field " ^ i ^ " cannot be called directly because it has no expression") p;
 				display_error ctx ("Field " ^ i ^ " cannot be called directly because it has no expression") p;
 			| _ ->
 			| _ ->
-				display_error ctx (string_error i (string_source t) (s_type (print_context()) t ^ " has no field " ^ i)) p;
+				display_error ctx (StringError.string_error i (string_source t) (s_type (print_context()) t ^ " has no field " ^ i)) p;
 		end;
 		end;
 		AKExpr (mk (TField (e,FDynamic i)) (mk_mono()) p)
 		AKExpr (mk (TField (e,FDynamic i)) (mk_mono()) p)
 	in
 	in
@@ -1848,8 +1849,8 @@ let unify_int ctx e k =
 	end;
 	end;
 	let el = match using_param with None -> el | Some e -> e :: el in
 	let el = match using_param with None -> el | Some e -> e :: el in
 	(try
 	(try
-		let gctx = Codegen.make_generic ctx cf.cf_params monos p in
-		let name = cf.cf_name ^ "_" ^ gctx.Codegen.name in
+		let gctx = Typeload.make_generic ctx cf.cf_params monos p in
+		let name = cf.cf_name ^ "_" ^ gctx.Typeload.name in
 		let unify_existing_field tcf pcf = try
 		let unify_existing_field tcf pcf = try
 			unify_raise ctx tcf t p
 			unify_raise ctx tcf t p
 		with Error(Unify _,_) as err ->
 		with Error(Unify _,_) as err ->
@@ -1890,7 +1891,7 @@ let unify_int ctx e k =
 				| None ->
 				| None ->
 					display_error ctx "Recursive @:generic function" p; None;
 					display_error ctx "Recursive @:generic function" p; None;
 				| Some e ->
 				| Some e ->
-					let e = Codegen.generic_substitute_expr gctx e in
+					let e = Typeload.generic_substitute_expr gctx e in
 					check e;
 					check e;
 					Some e
 					Some e
 			);
 			);
@@ -1907,13 +1908,15 @@ let unify_int ctx e k =
 		let fa = if stat then FStatic (c,cf2) else FInstance (c,tl,cf2) in
 		let fa = if stat then FStatic (c,cf2) else FInstance (c,tl,cf2) in
 		let e = mk (TField(e,fa)) cf2.cf_type p in
 		let e = mk (TField(e,fa)) cf2.cf_type p in
 		make_call ctx e el ret p
 		make_call ctx e el ret p
-	with Codegen.Generic_Exception (msg,p) ->
+	with Typeload.Generic_Exception (msg,p) ->
 		error msg p)
 		error msg p)
 
 
-let call_to_string ctx c e =
-	let et = type_module_type ctx (TClassDecl c) None e.epos in
-	let cf = PMap.find "toString" c.cl_statics in
-	make_call ctx (mk (TField(et,FStatic(c,cf))) cf.cf_type e.epos) [e] ctx.t.tstring e.epos
+let call_to_string ctx e =
+	(* Ignore visibility of the toString field. *)
+	ctx.meta <- (Meta.PrivateAccess,[],e.epos) :: ctx.meta;
+	let acc = type_field ctx e "toString" e.epos MCall in
+	ctx.meta <- List.tl ctx.meta;
+	!build_call_ref ctx acc [] (WithType ctx.t.tstring) e.epos
 
 
 let get_next_stored_typed_expr_id =
 let get_next_stored_typed_expr_id =
 	let uid = ref 0 in
 	let uid = ref 0 in
@@ -2112,7 +2115,7 @@ and type_binop2 ctx op (e1 : texpr) (e2 : Ast.expr) is_assign_op wt p =
 	let to_string e =
 	let to_string e =
 		let rec loop t = match classify t with
 		let rec loop t = match classify t with
 			| KAbstract ({a_impl = Some c},_) when PMap.mem "toString" c.cl_statics ->
 			| KAbstract ({a_impl = Some c},_) when PMap.mem "toString" c.cl_statics ->
-				call_to_string ctx c e
+				call_to_string ctx e
 			| KInt | KFloat | KString -> e
 			| KInt | KFloat | KString -> e
 			| KUnk | KDyn | KParam _ | KOther ->
 			| KUnk | KDyn | KParam _ | KOther ->
 				let std = type_type ctx ([],"Std") e.epos in
 				let std = type_type ctx ([],"Std") e.epos in
@@ -2816,8 +2819,7 @@ and type_access ctx e p mode =
 	| _ ->
 	| _ ->
 		AKExpr (type_expr ctx (e,p) Value)
 		AKExpr (type_expr ctx (e,p) Value)
 
 
-and type_vars ctx vl p in_block =
-	let save = if in_block then (fun() -> ()) else save_locals ctx in
+and type_vars ctx vl p =
 	let vl = List.map (fun (v,t,e) ->
 	let vl = List.map (fun (v,t,e) ->
 		try
 		try
 			let t = Typeload.load_type_opt ctx p t in
 			let t = Typeload.load_type_opt ctx p t in
@@ -2835,8 +2837,6 @@ and type_vars ctx vl p in_block =
 				display_error ctx (error_msg e) p;
 				display_error ctx (error_msg e) p;
 				add_local ctx v t_dynamic, None
 				add_local ctx v t_dynamic, None
 	) vl in
 	) vl in
-	save();
-
 	match vl with
 	match vl with
 	| [v,eo] ->
 	| [v,eo] ->
 		mk (TVar (v,eo)) ctx.t.tvoid p
 		mk (TVar (v,eo)) ctx.t.tvoid p
@@ -2943,9 +2943,6 @@ and type_block ctx el with_type p =
 	in
 	in
 	let rec loop = function
 	let rec loop = function
 		| [] -> []
 		| [] -> []
-		| (EVars vl,p) :: l ->
-			let e = type_vars ctx vl p true in
-			merge e @ loop l
 		| [e] ->
 		| [e] ->
 			(try
 			(try
 				merge (type_expr ctx e with_type)
 				merge (type_expr ctx e with_type)
@@ -3104,10 +3101,10 @@ and type_new ctx t el with_type p =
 		ctx.call_argument_stack <- List.tl ctx.call_argument_stack;
 		ctx.call_argument_stack <- List.tl ctx.call_argument_stack;
 		(* Try to properly build @:generic classes here (issue #2016) *)
 		(* Try to properly build @:generic classes here (issue #2016) *)
 		begin match t with
 		begin match t with
-			| TInst({cl_kind = KGeneric } as c,tl) -> follow (Codegen.build_generic ctx c p tl)
+			| TInst({cl_kind = KGeneric } as c,tl) -> follow (Typeload.build_generic ctx c p tl)
 			| _ -> t
 			| _ -> t
 		end
 		end
-	with Codegen.Generic_Exception _ ->
+	with Typeload.Generic_Exception _ ->
 		(* Try to infer generic parameters from the argument list (issue #2044) *)
 		(* Try to infer generic parameters from the argument list (issue #2044) *)
 		match Typeload.resolve_typedef (Typeload.load_type_def ctx p t) with
 		match Typeload.resolve_typedef (Typeload.load_type_def ctx p t) with
 		| TClassDecl ({cl_constructor = Some cf} as c) ->
 		| TClassDecl ({cl_constructor = Some cf} as c) ->
@@ -3115,11 +3112,11 @@ and type_new ctx t el with_type p =
 			let ct, f = get_constructor ctx c monos p in
 			let ct, f = get_constructor ctx c monos p in
 			ignore (unify_constructor_call c monos f ct);
 			ignore (unify_constructor_call c monos f ct);
 			begin try
 			begin try
-				let t = Codegen.build_generic ctx c p monos in
+				let t = Typeload.build_generic ctx c p monos in
 				let map = apply_params c.cl_params monos in
 				let map = apply_params c.cl_params monos in
 				check_constraints ctx (s_type_path c.cl_path) c.cl_params monos map true p;
 				check_constraints ctx (s_type_path c.cl_path) c.cl_params monos map true p;
 				t
 				t
-			with Codegen.Generic_Exception _ as exc ->
+			with Typeload.Generic_Exception _ as exc ->
 				(* If we have an expected type, just use that (issue #3804) *)
 				(* If we have an expected type, just use that (issue #3804) *)
 				begin match with_type with
 				begin match with_type with
 					| WithType t ->
 					| WithType t ->
@@ -3175,7 +3172,7 @@ and type_new ctx t el with_type p =
 		error (s_type (print_context()) t ^ " cannot be constructed") p)
 		error (s_type (print_context()) t ^ " cannot be constructed") p)
 
 
 and type_try ctx e1 catches with_type p =
 and type_try ctx e1 catches with_type p =
-	let e1 = type_expr ctx e1 with_type in
+	let e1 = type_expr ctx (Expr.ensure_block e1) with_type in
 	let rec check_unreachable cases t p = match cases with
 	let rec check_unreachable cases t p = match cases with
 		| (v,e) :: cases ->
 		| (v,e) :: cases ->
 			let unreachable () =
 			let unreachable () =
@@ -3509,7 +3506,7 @@ and type_expr ctx (e,p) (with_type:with_type) =
 	| EArrayDecl el ->
 	| EArrayDecl el ->
 		type_array_decl ctx el with_type p
 		type_array_decl ctx el with_type p
 	| EVars vl ->
 	| EVars vl ->
-		type_vars ctx vl p false
+		type_vars ctx vl p
 	| EFor (it,e2) ->
 	| EFor (it,e2) ->
 		let i, pi, e1 = (match it with
 		let i, pi, e1 = (match it with
 			| (EIn ((EConst (Ident i),pi),e),_) -> i, pi, e
 			| (EIn ((EConst (Ident i),pi),e),_) -> i, pi, e
@@ -3519,6 +3516,7 @@ and type_expr ctx (e,p) (with_type:with_type) =
 		let old_loop = ctx.in_loop in
 		let old_loop = ctx.in_loop in
 		let old_locals = save_locals ctx in
 		let old_locals = save_locals ctx in
 		ctx.in_loop <- true;
 		ctx.in_loop <- true;
+		let e2 = Expr.ensure_block e2 in
 		let e = (match Optimizer.optimize_for_loop ctx (i,pi) e1 e2 p with
 		let e = (match Optimizer.optimize_for_loop ctx (i,pi) e1 e2 p with
 			| Some e -> e
 			| Some e -> e
 			| None ->
 			| None ->
@@ -3558,12 +3556,12 @@ and type_expr ctx (e,p) (with_type:with_type) =
 	| EIf (e,e1,e2) ->
 	| EIf (e,e1,e2) ->
 		let e = type_expr ctx e Value in
 		let e = type_expr ctx e Value in
 		let e = Codegen.AbstractCast.cast_or_unify ctx ctx.t.tbool e p in
 		let e = Codegen.AbstractCast.cast_or_unify ctx ctx.t.tbool e p in
-		let e1 = type_expr ctx e1 with_type in
+		let e1 = type_expr ctx (Expr.ensure_block e1) with_type in
 		(match e2 with
 		(match e2 with
 		| None ->
 		| None ->
 			mk (TIf (e,e1,None)) ctx.t.tvoid p
 			mk (TIf (e,e1,None)) ctx.t.tvoid p
 		| Some e2 ->
 		| Some e2 ->
-			let e2 = type_expr ctx e2 with_type in
+			let e2 = type_expr ctx (Expr.ensure_block e2) with_type in
 			let e1,e2,t = match with_type with
 			let e1,e2,t = match with_type with
 				| NoValue -> e1,e2,ctx.t.tvoid
 				| NoValue -> e1,e2,ctx.t.tvoid
 				| Value -> e1,e2,unify_min ctx [e1; e2]
 				| Value -> e1,e2,unify_min ctx [e1; e2]
@@ -3579,13 +3577,13 @@ and type_expr ctx (e,p) (with_type:with_type) =
 		let cond = type_expr ctx cond Value in
 		let cond = type_expr ctx cond Value in
 		let cond = Codegen.AbstractCast.cast_or_unify ctx ctx.t.tbool cond p in
 		let cond = Codegen.AbstractCast.cast_or_unify ctx ctx.t.tbool cond p in
 		ctx.in_loop <- true;
 		ctx.in_loop <- true;
-		let e = type_expr ctx e NoValue in
+		let e = type_expr ctx (Expr.ensure_block e) NoValue in
 		ctx.in_loop <- old_loop;
 		ctx.in_loop <- old_loop;
 		mk (TWhile (cond,e,NormalWhile)) ctx.t.tvoid p
 		mk (TWhile (cond,e,NormalWhile)) ctx.t.tvoid p
 	| EWhile (cond,e,DoWhile) ->
 	| EWhile (cond,e,DoWhile) ->
 		let old_loop = ctx.in_loop in
 		let old_loop = ctx.in_loop in
 		ctx.in_loop <- true;
 		ctx.in_loop <- true;
-		let e = type_expr ctx e NoValue in
+		let e = type_expr ctx (Expr.ensure_block e) NoValue in
 		ctx.in_loop <- old_loop;
 		ctx.in_loop <- old_loop;
 		let cond = type_expr ctx cond Value in
 		let cond = type_expr ctx cond Value in
 		let cond = Codegen.AbstractCast.cast_or_unify ctx ctx.t.tbool cond cond.epos in
 		let cond = Codegen.AbstractCast.cast_or_unify ctx ctx.t.tbool cond cond.epos in
@@ -3702,10 +3700,13 @@ and type_expr ctx (e,p) (with_type:with_type) =
 			| (Meta.ToString,_,_) ->
 			| (Meta.ToString,_,_) ->
 				let e = e() in
 				let e = e() in
 				(match follow e.etype with
 				(match follow e.etype with
-					| TAbstract({a_impl = Some c},_) when PMap.mem "toString" c.cl_statics -> call_to_string ctx c e
+					| TAbstract({a_impl = Some c},_) when PMap.mem "toString" c.cl_statics -> call_to_string ctx e
 					| _ -> e)
 					| _ -> e)
 			| (Meta.This,_,_) ->
 			| (Meta.This,_,_) ->
-				let e = List.hd ctx.this_stack in
+				let e = match ctx.this_stack with
+					| [] -> error "Cannot type @:this this here" p
+					| e :: _ -> e
+				in
 				let rec loop e = match e.eexpr with
 				let rec loop e = match e.eexpr with
 					| TConst TThis -> get_this ctx e.epos
 					| TConst TThis -> get_this ctx e.epos
 					| _ -> Type.map_expr loop e
 					| _ -> Type.map_expr loop e
@@ -3725,6 +3726,9 @@ and type_expr ctx (e,p) (with_type:with_type) =
 			| (Meta.NoPrivateAccess,_,_) ->
 			| (Meta.NoPrivateAccess,_,_) ->
 				ctx.meta <- List.filter (fun(m,_,_) -> m <> Meta.PrivateAccess) ctx.meta;
 				ctx.meta <- List.filter (fun(m,_,_) -> m <> Meta.PrivateAccess) ctx.meta;
 				e()
 				e()
+			| (Meta.Fixed,_,_) when ctx.com.platform=Cpp ->
+				let e = e() in
+				{e with eexpr = TMeta(m,e)}
 			| _ -> e()
 			| _ -> e()
 		in
 		in
 		ctx.meta <- old;
 		ctx.meta <- old;
@@ -4004,7 +4008,7 @@ and maybe_type_against_enum ctx f with_type p =
 			let e = try
 			let e = try
 				f()
 				f()
 			with Error (Unknown_ident n,_) ->
 			with Error (Unknown_ident n,_) ->
-				raise_or_display_message ctx (string_error n fields ("Identifier '" ^ n ^ "' is not part of " ^ s_type_path path)) p;
+				raise_or_display_message ctx (StringError.string_error n fields ("Identifier '" ^ n ^ "' is not part of " ^ s_type_path path)) p;
 				AKExpr (mk (TConst TNull) (mk_mono()) p)
 				AKExpr (mk (TConst TNull) (mk_mono()) p)
 			in
 			in
 			ctx.m.curmod.m_types <- old;
 			ctx.m.curmod.m_types <- old;
@@ -4036,7 +4040,7 @@ and type_call ctx e el (with_type:with_type) p =
 				begin match follow e.etype with
 				begin match follow e.etype with
 					| TInst({cl_path=[],"String"},_) -> raise Not_found
 					| TInst({cl_path=[],"String"},_) -> raise Not_found
 					| TMono _ -> raise Not_found
 					| TMono _ -> raise Not_found
-					| t when t == t_dynamic -> raise Not_found
+					| TDynamic _ -> raise Not_found
 					| _ -> ()
 					| _ -> ()
 				end;
 				end;
 				let acc = type_field ~resume:true ctx e "toString" p MCall in
 				let acc = type_field ~resume:true ctx e "toString" p MCall in
@@ -4127,7 +4131,7 @@ and build_call ctx acc el (with_type:with_type) p =
 		begin match ef.cf_kind with
 		begin match ef.cf_kind with
 		| Method MethMacro ->
 		| Method MethMacro ->
 			let ethis = type_module_type ctx (TClassDecl cl) None p in
 			let ethis = type_module_type ctx (TClassDecl cl) None p in
-			let eparam,f = Codegen.push_this ctx eparam in
+			let eparam,f = push_this ctx eparam in
 			let e = build_call ctx (AKMacro (ethis,ef)) (eparam :: el) with_type p in
 			let e = build_call ctx (AKMacro (ethis,ef)) (eparam :: el) with_type p in
 			f();
 			f();
 			e
 			e
@@ -4160,7 +4164,6 @@ and build_call ctx acc el (with_type:with_type) p =
 			(match ctx.g.do_macro ctx MExpr c.cl_path cf.cf_name el p with
 			(match ctx.g.do_macro ctx MExpr c.cl_path cf.cf_name el p with
 			| None -> (fun() -> type_expr ctx (EConst (Ident "null"),p) Value)
 			| None -> (fun() -> type_expr ctx (EConst (Ident "null"),p) Value)
 			| Some (EMeta((Meta.MergeBlock,_,_),(EBlock el,_)),_) -> (fun () -> let e = type_block ctx el with_type p in mk (TMeta((Meta.MergeBlock,[],p), e)) e.etype e.epos)
 			| Some (EMeta((Meta.MergeBlock,_,_),(EBlock el,_)),_) -> (fun () -> let e = type_block ctx el with_type p in mk (TMeta((Meta.MergeBlock,[],p), e)) e.etype e.epos)
-			| Some (EVars vl,p) -> (fun() -> type_vars ctx vl p true)
 			| Some e -> (fun() -> type_expr ctx e with_type))
 			| Some e -> (fun() -> type_expr ctx e with_type))
 		| _ ->
 		| _ ->
 			(* member-macro call : since we will make a static call, let's found the actual class and not its subclass *)
 			(* member-macro call : since we will make a static call, let's found the actual class and not its subclass *)
@@ -4168,7 +4171,7 @@ and build_call ctx acc el (with_type:with_type) p =
 			| TInst (c,_) ->
 			| TInst (c,_) ->
 				let rec loop c =
 				let rec loop c =
 					if PMap.mem cf.cf_name c.cl_fields then
 					if PMap.mem cf.cf_name c.cl_fields then
-						let eparam,f = Codegen.push_this ctx ethis in
+						let eparam,f = push_this ctx ethis in
 						ethis_f := f;
 						ethis_f := f;
 						let e = match ctx.g.do_macro ctx MExpr c.cl_path cf.cf_name (eparam :: el) p with
 						let e = match ctx.g.do_macro ctx MExpr c.cl_path cf.cf_name (eparam :: el) p with
 							| None -> (fun() -> type_expr ctx (EConst (Ident "null"),p) Value)
 							| None -> (fun() -> type_expr ctx (EConst (Ident "null"),p) Value)
@@ -5128,12 +5131,12 @@ let rec create com =
 			get_build_infos = (fun() -> None);
 			get_build_infos = (fun() -> None);
 			std = null_module;
 			std = null_module;
 			global_using = [];
 			global_using = [];
-			do_inherit = Codegen.on_inherit;
+			do_inherit = Typeload.on_inherit;
 			do_create = create;
 			do_create = create;
 			do_macro = type_macro;
 			do_macro = type_macro;
 			do_load_module = Typeload.load_module;
 			do_load_module = Typeload.load_module;
 			do_optimize = Optimizer.reduce_expression;
 			do_optimize = Optimizer.reduce_expression;
-			do_build_instance = Codegen.build_instance;
+			do_build_instance = Typeload.build_instance;
 		};
 		};
 		m = {
 		m = {
 			curmod = null_module;
 			curmod = null_module;

+ 3 - 0
std/Array.hx

@@ -22,6 +22,9 @@
 /**
 /**
 	An Array is a storage for values. You can access it using indexes or
 	An Array is a storage for values. You can access it using indexes or
 	with its API.
 	with its API.
+
+	@see http://haxe.org/manual/std-Array.html
+	@see http://haxe.org/manual/lf-array-comprehension.html
 **/
 **/
 extern class Array<T> {
 extern class Array<T> {
 
 

+ 2 - 0
std/Class.hx

@@ -23,6 +23,8 @@
 	An abstract type that represents a Class.
 	An abstract type that represents a Class.
 
 
 	See `Type` for the Haxe Reflection API.
 	See `Type` for the Haxe Reflection API.
+
+	@see http://haxe.org/manual/types-class-instance.html
 **/
 **/
 @:coreType @:runtimeValue abstract Class<T> {
 @:coreType @:runtimeValue abstract Class<T> {
 }
 }

+ 1 - 1
std/EReg.hx

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

+ 2 - 0
std/Enum.hx

@@ -26,6 +26,8 @@
 	The corresponding enum instance type is `EnumValue`.
 	The corresponding enum instance type is `EnumValue`.
 
 
 	See `Type` for the Haxe Reflection API.
 	See `Type` for the Haxe Reflection API.
+
+	@see http://haxe.org/manual/types-enum-instance.html
 **/
 **/
 @:coreType @:runtimeValue abstract Enum<T> {
 @:coreType @:runtimeValue abstract Enum<T> {
 }
 }

+ 2 - 0
std/EnumValue.hx

@@ -23,6 +23,8 @@
 /**
 /**
 	An abstract type that represents any enum value.
 	An abstract type that represents any enum value.
 	See `Type` for the Haxe Reflection API.
 	See `Type` for the Haxe Reflection API.
+
+	@see http://haxe.org/manual/types-enum-instance.html
 **/
 **/
 @:coreType abstract EnumValue {
 @:coreType abstract EnumValue {
 }
 }

+ 2 - 0
std/IntIterator.hx

@@ -30,6 +30,8 @@
 	field, it is worth noting that IntIterator does not reset after being used
 	field, it is worth noting that IntIterator does not reset after being used
 	in a for-loop. Subsequent uses of the same instance will then have no
 	in a for-loop. Subsequent uses of the same instance will then have no
 	effect.
 	effect.
+
+	@see http://haxe.org/manual/lf-iterators.html
 **/
 **/
 class IntIterator {
 class IntIterator {
 
 

+ 2 - 0
std/Lambda.hx

@@ -31,6 +31,8 @@
 
 
 	If the first argument to any of the methods is null, the result is
 	If the first argument to any of the methods is null, the result is
 	unspecified.
 	unspecified.
+
+	@see http://haxe.org/manual/std-Lambda.html
 **/
 **/
 class Lambda {
 class Lambda {
 
 

+ 2 - 0
std/List.hx

@@ -24,6 +24,8 @@
 	A linked-list of elements. The list is composed of element container objects
 	A linked-list of elements. The list is composed of element container objects
 	that are chained together. It is optimized so that adding or removing an
 	that are chained together. It is optimized so that adding or removing an
 	element does not imply copying the whole list content every time.
 	element does not imply copying the whole list content every time.
+
+	@see http://haxe.org/manual/std-List.html
 **/
 **/
 class List<T> {
 class List<T> {
 
 

+ 2 - 0
std/Map.hx

@@ -41,6 +41,8 @@ import haxe.Constraints.IMap;
 	Maps can also be created with `key1 => value1, key2 => value2` syntax.
 	Maps can also be created with `key1 => value1, key2 => value2` syntax.
 
 
 	Map is an abstract type, it is not available at runtime.
 	Map is an abstract type, it is not available at runtime.
+
+	@see http://haxe.org/manual/std-Map.html
 **/
 **/
 @:multiType(@:followWithAbstracts K)
 @:multiType(@:followWithAbstracts K)
 abstract Map<K,V>(IMap<K,V> ) {
 abstract Map<K,V>(IMap<K,V> ) {

+ 2 - 0
std/Math.hx

@@ -21,6 +21,8 @@
  */
  */
 /**
 /**
 	This class defines mathematical functions and constants.
 	This class defines mathematical functions and constants.
+
+	@see http://haxe.org/manual/std-math.html
 **/
 **/
 #if cpp @:include("hxMath.h") #end
 #if cpp @:include("hxMath.h") #end
 extern class Math
 extern class Math

+ 2 - 0
std/Reflect.hx

@@ -22,6 +22,8 @@
 /**
 /**
 	The Reflect API is a way to manipulate values dynamically through an
 	The Reflect API is a way to manipulate values dynamically through an
 	abstract interface in an untyped manner. Use with care.
 	abstract interface in an untyped manner. Use with care.
+
+	@see http://haxe.org/manual/std-reflection.html
 **/
 **/
 extern class Reflect {
 extern class Reflect {
 
 

+ 29 - 1
std/StdTypes.hx

@@ -23,6 +23,8 @@
 
 
 /**
 /**
 	The standard `Void` type. Only `null` values can be of the type `Void`.
 	The standard `Void` type. Only `null` values can be of the type `Void`.
+
+	@see http://haxe.org/manual/types-void.html
 **/
 **/
 @:coreType abstract Void { }
 @:coreType abstract Void { }
 
 
@@ -31,6 +33,12 @@
 
 
 	On static targets, `null` cannot be assigned to Float. If this is necessary,
 	On static targets, `null` cannot be assigned to Float. If this is necessary,
 	`Null<Float>` can be used instead.
 	`Null<Float>` can be used instead.
+
+	`Std.int` converts a `Float` to an `Int`, rounded towards 0.  
+	`Std.parseFloat` converts a `String` to a `Float`.
+
+	@see http://haxe.org/manual/types-basic-types.html
+	@see http://haxe.org/manual/types-nullability.html
 **/
 **/
 @:coreType @:notNull @:runtimeValue abstract Float { }
 @:coreType @:notNull @:runtimeValue abstract Float { }
 
 
@@ -39,6 +47,13 @@
 
 
 	On static targets, `null` cannot be assigned to `Int`. If this is necessary,
 	On static targets, `null` cannot be assigned to `Int`. If this is necessary,
 	`Null<Int>` can be used instead.
 	`Null<Int>` can be used instead.
+
+	`Std.int` converts a `Float` to an `Int`, rounded towards 0.  
+	`Std.parseInt` converts a `String` to an `Int`.
+
+	@see http://haxe.org/manual/types-basic-types.html
+	@see http://haxe.org/manual/std-math-integer-math.html
+	@see http://haxe.org/manual/types-nullability.html
 **/
 **/
 @:coreType @:notNull @:runtimeValue abstract Int to Float { }
 @:coreType @:notNull @:runtimeValue abstract Int to Float { }
 
 
@@ -51,6 +66,8 @@
 	that accept or can return a `null` value, or for the Flash compiler and AS3
 	that accept or can return a `null` value, or for the Flash compiler and AS3
 	generator to distinguish between base values that can be `null` and others that
 	generator to distinguish between base values that can be `null` and others that
 	can't.
 	can't.
+
+	@see http://haxe.org/manual/types-nullability.html
 **/
 **/
 typedef Null<T> = T
 typedef Null<T> = T
 
 
@@ -59,6 +76,9 @@ typedef Null<T> = T
 
 
 	On static targets, `null` cannot be assigned to `Bool`. If this is necessary,
 	On static targets, `null` cannot be assigned to `Bool`. If this is necessary,
 	`Null<Bool>` can be used instead.
 	`Null<Bool>` can be used instead.
+
+	@see http://haxe.org/manual/types-bool.html
+	@see http://haxe.org/manual/types-nullability.html
 **/
 **/
 @:coreType @:notNull @:runtimeValue abstract Bool {
 @:coreType @:notNull @:runtimeValue abstract Bool {
 }
 }
@@ -68,6 +88,8 @@ typedef Null<T> = T
 
 
 	Use of `Dynamic` should be minimized as it prevents several compiler
 	Use of `Dynamic` should be minimized as it prevents several compiler
 	checks and optimizations.
 	checks and optimizations.
+
+	@see http://haxe.org/manual/types-dynamic.html
 **/
 **/
 @:coreType @:runtimeValue abstract Dynamic<T> {
 @:coreType @:runtimeValue abstract Dynamic<T> {
 }
 }
@@ -78,6 +100,8 @@ typedef Null<T> = T
 	Any class with matching `hasNext()` and `next()` fields is considered an `Iterator`
 	Any class with matching `hasNext()` and `next()` fields is considered an `Iterator`
 	and can then be used e.g. in `for`-loops. This makes it easy to implement
 	and can then be used e.g. in `for`-loops. This makes it easy to implement
 	custom iterators.
 	custom iterators.
+
+	@see http://haxe.org/manual/lf-iterators.html
 **/
 **/
 typedef Iterator<T> = {
 typedef Iterator<T> = {
 
 
@@ -107,6 +131,8 @@ typedef Iterator<T> = {
 /**
 /**
 	An `Iterable` is a data structure which has an `iterator()` method.
 	An `Iterable` is a data structure which has an `iterator()` method.
 	See `Lambda` for generic functions on iterable structures.
 	See `Lambda` for generic functions on iterable structures.
+
+	@see http://haxe.org/manual/lf-iterators.html
 **/
 **/
 typedef Iterable<T> = {
 typedef Iterable<T> = {
 	function iterator() : Iterator<T>;
 	function iterator() : Iterator<T>;
@@ -118,6 +144,8 @@ typedef Iterable<T> = {
 
 
 	This interface should be used for externs only. Haxe does not support custom
 	This interface should be used for externs only. Haxe does not support custom
 	array access on classes. However, array access can be implemented for
 	array access on classes. However, array access can be implemented for
-	abstract types (see http://haxe.org/manual/types-abstract-array-access.html).
+	abstract types.
+
+	@see http://haxe.org/manual/types-abstract-array-access.html
 **/
 **/
 extern interface ArrayAccess<T> { }
 extern interface ArrayAccess<T> { }

+ 1 - 1
std/String.hx

@@ -168,5 +168,5 @@ extern class String {
 		If `code` is negative or has another invalid value, the result is
 		If `code` is negative or has another invalid value, the result is
 		unspecified.
 		unspecified.
 	**/
 	**/
-	static function fromCharCode( code : Int ) : String;
+	@:pure static function fromCharCode( code : Int ) : String;
 }
 }

+ 2 - 1
std/StringTools.hx

@@ -21,7 +21,8 @@
  */
  */
 /**
 /**
 	This class provides advanced methods on Strings. It is ideally used with
 	This class provides advanced methods on Strings. It is ideally used with
-	`using StringTools` and then acts as an extension to the String class.
+	`using StringTools` and then acts as an [extension](http://haxe.org/manual/lf-static-extension.html)
+	to the `String` class.
 
 
 	If the first argument to any of the methods is null, the result is
 	If the first argument to any of the methods is null, the result is
 	unspecified.
 	unspecified.

+ 4 - 0
std/Type.hx

@@ -19,6 +19,7 @@
  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * DEALINGS IN THE SOFTWARE.
  * DEALINGS IN THE SOFTWARE.
  */
  */
+
 /**
 /**
 	The diffent possible runtime types of a value.
 	The diffent possible runtime types of a value.
 **/
 **/
@@ -39,6 +40,9 @@ enum ValueType {
 
 
 	This class complements the more lightweight Reflect class, with a focus on
 	This class complements the more lightweight Reflect class, with a focus on
 	class and enum instances.
 	class and enum instances.
+
+	@see http://haxe.org/manual/types.html
+	@see http://haxe.org/manual/std-reflection.html
 **/
 **/
 extern class Type {
 extern class Type {
 
 

+ 6 - 2
std/UInt.hx

@@ -22,8 +22,10 @@
 
 
 #if ((flash || flash9doc || cs || hl) && !doc_gen)
 #if ((flash || flash9doc || cs || hl) && !doc_gen)
 /**
 /**
-	The unsigned Int type is only defined for Flash 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.
 	handled the same as a normal Int.
+
+	@see http://haxe.org/manual/types-basic-types.html
 **/
 **/
 @:coreType
 @:coreType
 @:notNull
 @:notNull
@@ -92,8 +94,10 @@ abstract UInt to Int from Int
 }
 }
 #else
 #else
 /**
 /**
-	The unsigned Int type is only defined for Flash and C#.
+	The unsigned `Int` type is only defined for Flash and C#.
 	Simulate it for other platforms.
 	Simulate it for other platforms.
+
+	@see http://haxe.org/manual/types-basic-types.html
 **/
 **/
 abstract UInt(Int) from Int to Int {
 abstract UInt(Int) from Int to Int {
 
 

+ 2 - 0
std/Xml.hx

@@ -22,6 +22,8 @@
 
 
 /**
 /**
 	Xml node types.
 	Xml node types.
+
+	@see http://haxe.org/manual/std-Xml.html
 **/
 **/
 @:enum abstract XmlType(Int) {
 @:enum abstract XmlType(Int) {
 	/**
 	/**

+ 0 - 1
std/cpp/ConstPointer.hx

@@ -22,7 +22,6 @@
  package cpp;
  package cpp;
 
 
 @:coreType @:include("cpp/Pointer.h") @:native("cpp.Pointer")
 @:coreType @:include("cpp/Pointer.h") @:native("cpp.Pointer")
-@:analyzer(no_simplification)
 extern class ConstPointer<T>
 extern class ConstPointer<T>
 {
 {
    // ptr actually returns the pointer - not strictly a 'T' - for pointers to smart pointers
    // ptr actually returns the pointer - not strictly a 'T' - for pointers to smart pointers

+ 0 - 1
std/cpp/Function.hx

@@ -22,7 +22,6 @@
  package cpp;
  package cpp;
 
 
 @:coreType @:structAccess @:include("cpp/Pointer.h")
 @:coreType @:structAccess @:include("cpp/Pointer.h")
-@:analyzer(no_simplification)
 extern class Function<T,ABI:cpp.abi.Abi>
 extern class Function<T,ABI:cpp.abi.Abi>
 {
 {
    public function new(d:Dynamic);
    public function new(d:Dynamic);

+ 0 - 1
std/cpp/Lib.hx

@@ -43,7 +43,6 @@ class Lib {
 		return untyped __global__.__hxcpp_unload_all_libraries();
 		return untyped __global__.__hxcpp_unload_all_libraries();
 	}
 	}
 
 
-   @:analyzer(no_simplification)
 	public static function _loadPrime( lib : String, prim : String, signature : String, quietFail = false ) : Dynamic {
 	public static function _loadPrime( lib : String, prim : String, signature : String, quietFail = false ) : Dynamic {
 		var factory:Callable< ConstCharStar -> Object > =
 		var factory:Callable< ConstCharStar -> Object > =
                untyped __global__.__hxcpp_cast_get_proc_address(lib, prim + "__prime", quietFail);
                untyped __global__.__hxcpp_cast_get_proc_address(lib, prim + "__prime", quietFail);

+ 64 - 0
std/cpp/NativeFile.hx

@@ -0,0 +1,64 @@
+package cpp;
+
+@:buildXml('<include name="${HXCPP}/src/hx/libs/std/Build.xml"/>')
+extern class NativeFile
+{
+   @:extern @:native("_hx_std_file_open")
+   public static function file_open(fname:String,r:String) : Dynamic return null;
+
+   @:extern @:native("_hx_std_file_close")
+   public static function file_close(handle:Dynamic) : Void { }
+
+
+   @:extern @:native("_hx_std_file_write")
+   public static function file_write(handle:Dynamic,s:haxe.io.BytesData,p:Int,n:Int) : Int return 0;
+
+
+   @:extern @:native("_hx_std_file_write_char")
+   public static function file_write_char(handle:Dynamic,c:Int) : Void { }
+
+
+   @:extern @:native("_hx_std_file_read")
+   public static function file_read(handle:Dynamic,s:haxe.io.BytesData,p:Int,n:Int) : Int return 0;
+
+
+   @:extern @:native("_hx_std_file_read_char")
+   public static function file_read_char(handle:Dynamic) : Int return 0;
+
+
+   @:extern @:native("_hx_std_file_seek")
+   public static function file_seek(handle:Dynamic,pos:Int,kind:Int) : Void { }
+
+
+   @:extern @:native("_hx_std_file_tell")
+   public static function file_tell(handle:Dynamic) : Int return 0;
+
+
+   @:extern @:native("_hx_std_file_eof")
+   public static function file_eof(handle:Dynamic) : Bool return false;
+
+
+   @:extern @:native("_hx_std_file_flush")
+   public static function file_flush(handle:Dynamic) : Void return null;
+
+
+   @:extern @:native("_hx_std_file_contents_string")
+   public static function file_contents_string(name:String) : String return null;
+
+
+   @:extern @:native("_hx_std_file_contents_bytes")
+   public static function file_contents_bytes(name:String) : haxe.io.BytesData return null;
+
+
+   @:extern @:native("_hx_std_file_stdin")
+   public static function file_stdin() : Dynamic return null;
+
+
+   @:extern @:native("_hx_std_file_stdout")
+   public static function file_stdout() : Dynamic return null;
+
+
+   @:extern @:native("_hx_std_file_stderr")
+   public static function file_stderr() : Dynamic return null;
+
+}

+ 38 - 0
std/cpp/NativeProcess.hx

@@ -0,0 +1,38 @@
+package cpp;
+
+@:buildXml('<include name="${HXCPP}/src/hx/libs/std/Build.xml"/>')
+extern class NativeProcess
+{
+
+   @:extern @:native("_hx_std_process_run")
+   public static function process_run(cmd:String,vargs:Array<String>) : Dynamic return null;
+
+
+   @:extern @:native("_hx_std_process_stdout_read")
+   public static function process_stdout_read(handle:Dynamic,buf:haxe.io.BytesData,pos:Int,len:Int) : Int return 0;
+
+
+   @:extern @:native("_hx_std_process_stderr_read")
+   public static function process_stderr_read(handle:Dynamic,buf:haxe.io.BytesData,pos:Int,len:Int) : Int return 0;
+
+
+   @:extern @:native("_hx_std_process_stdin_write")
+   public static function process_stdin_write(handle:Dynamic,buf:haxe.io.BytesData,pos:Int,len:Int) : Int return 0;
+
+
+   @:extern @:native("_hx_std_process_stdin_close")
+   public static function process_stdin_close(handle:Dynamic) : Void { }
+
+
+   @:extern @:native("_hx_std_process_exit")
+   public static function process_exit(handle:Dynamic) : Int return 0;
+
+
+   @:extern @:native("_hx_std_process_pid")
+   public static function process_pid(handle:Dynamic) : Int return 0;
+
+
+   @:extern @:native("_hx_std_process_close")
+   public static function process_close(handle:Dynamic) : Void { };
+
+}

+ 23 - 0
std/cpp/NativeRandom.hx

@@ -0,0 +1,23 @@
+package cpp;
+
+@:buildXml('<include name="${HXCPP}/src/hx/libs/std/Build.xml"/>')
+extern class NativeRandom
+{
+
+   @:extern @:native("_hx_std_random_new")
+   public static function random_new() : Dynamic return null;
+
+
+   @:extern @:native("_hx_std_random_set_seed")
+   public static function random_set_seed(handle:Dynamic,v:Int) : Void { }
+
+
+   @:extern @:native("_hx_std_random_int")
+   public static function random_int(handle:Dynamic,max:Int) : Int return 0;
+
+   @:extern @:native("_hx_std_random_float")
+   public static function random_float(handle:Dynamic) : Float return 0.0;
+
+
+}
+

+ 135 - 0
std/cpp/NativeSocket.hx

@@ -0,0 +1,135 @@
+package cpp;
+
+import sys.net.Socket;
+
+@:buildXml('<include name="${HXCPP}/src/hx/libs/std/Build.xml"/>')
+extern class NativeSocket
+{
+   @:extern @:native("_hx_std_socket_init")
+   public static function socket_init() : Void { }
+
+
+   @:extern @:native("_hx_std_socket_new")
+   public static function socket_new(udp:Bool) : Dynamic return null;
+
+
+   @:extern @:native("_hx_std_socket_close")
+   public static function socket_close(handle:Dynamic) : Void { }
+
+
+   @:extern @:native("_hx_std_socket_bind")
+   public static function socket_bind(o:Dynamic,host:Int,port:Int) : Void { }
+
+
+   @:extern @:native("_hx_std_socket_send_char")
+   public static function socket_send_char(o:Dynamic,c:Int) : Void { }
+
+
+   @:extern @:native("_hx_std_socket_send")
+   public static function socket_send(o:Dynamic,buf:haxe.io.BytesData,p:Int,l:Int) : Int return 0;
+
+
+   @:extern @:native("_hx_std_socket_recv")
+   public static function socket_recv(o:Dynamic,buf:haxe.io.BytesData,p:Int,l:Int) : Int return 0;
+
+
+   @:extern @:native("_hx_std_socket_recv_char")
+   public static function socket_recv_char(o:Dynamic) : Int return 0;
+
+
+   @:extern @:native("_hx_std_socket_write")
+   public static function socket_write(o:Dynamic,buf:haxe.io.BytesData) : Void { }
+
+
+   @:extern @:native("_hx_std_socket_read")
+   public static function socket_read(o:Dynamic) : haxe.io.BytesData return null;
+
+
+   @:extern @:native("_hx_std_host_resolve")
+   public static function host_resolve(host:String) : Int return 0;
+
+
+   @:extern @:native("_hx_std_host_to_string")
+   public static function host_to_string(ip:Int) : String return null;
+
+
+   @:extern @:native("_hx_std_host_reverse")
+   public static function host_reverse(host:Int) : String return null;
+
+
+   @:extern @:native("_hx_std_host_local")
+   public static function host_local() : String return null;
+
+
+   @:extern @:native("_hx_std_socket_connect")
+   public static function socket_connect(o:Dynamic,host:Int,port:Int) : Void { }
+
+
+   @:extern @:native("_hx_std_socket_listen")
+   public static function socket_listen(o:Dynamic,n:Int) : Void { }
+
+
+   @:extern @:native("_hx_std_socket_select")
+   public static function socket_select(rs:Array<Dynamic>,ws:Array<Dynamic>,es:Array<Dynamic>,timeout:Dynamic) : Array<Dynamic> return null;
+
+
+   @:extern @:native("_hx_std_socket_fast_select")
+   public static function socket_fast_select(rs:Array<Dynamic>,ws:Array<Dynamic>,es:Array<Dynamic>,timeout:Dynamic) : Void { }
+
+
+   @:extern @:native("_hx_std_socket_accept")
+   public static function socket_accept(o:Dynamic) : Dynamic return null;
+
+
+   @:extern @:native("_hx_std_socket_peer")
+   public static function socket_peer(o:Dynamic) : Array<Int> return null;
+
+
+   @:extern @:native("_hx_std_socket_host")
+   public static function socket_host(o:Dynamic) : Array<Int> return null;
+
+
+   @:extern @:native("_hx_std_socket_set_timeout")
+   public static function socket_set_timeout(o:Dynamic,t:Dynamic) : Void { }
+
+
+   @:extern @:native("_hx_std_socket_shutdown")
+   public static function socket_shutdown(o:Dynamic,r:Bool,w:Bool) : Void { }
+
+
+   @:extern @:native("_hx_std_socket_set_blocking")
+   public static function socket_set_blocking(o:Dynamic,b:Bool) : Void { }
+
+
+   @:extern @:native("_hx_std_socket_set_fast_send")
+   public static function socket_set_fast_send(o:Dynamic,b:Bool) : Void { }
+
+
+   @:extern @:native("_hx_std_socket_poll_alloc")
+   public static function socket_poll_alloc(nsocks:Int) : Dynamic return null;
+
+
+   @:extern @:native("_hx_std_socket_poll_prepare")
+   public static function socket_poll_prepare(pdata:Dynamic,rsocks:Array<Socket>,wsocks:Array<Socket>) : Array< Array<Int> > return null;
+
+
+   @:extern @:native("_hx_std_socket_poll_events")
+   public static function socket_poll_events(pdata:Dynamic,timeout:Float) : Void { }
+
+
+   @:extern @:native("_hx_std_socket_poll")
+   public static function socket_poll(socks:Array<Socket>,pdata:Dynamic,timeout:Float) : Array<Socket> return null;
+
+
+   @:extern @:native("_hx_std_socket_send_to")
+   public static function socket_send_to(o:Dynamic,buf:haxe.io.BytesData,p:Int,l:Int,inAddr:Dynamic) : Int return 0;
+
+
+   @:extern @:native("_hx_std_socket_recv_from")
+   public static function socket_recv_from(o:Dynamic,buf:haxe.io.BytesData,p:Int,l:Int,outAddr:Dynamic) : Int return 0;
+
+
+
+}
+
+

+ 108 - 0
std/cpp/NativeSys.hx

@@ -0,0 +1,108 @@
+package cpp;
+
+@:buildXml('<include name="${HXCPP}/src/hx/libs/std/Build.xml"/>')
+extern class NativeSys
+{
+
+   @:extern @:native("_hx_std_get_env")
+   public static function get_env(v:String) : String return null;
+
+
+   @:extern @:native("_hx_std_put_env")
+   public static function put_env(e:String,v:String) : Void { }
+
+
+   @:extern @:native("_hx_std_sys_sleep")
+   public static function sys_sleep(f:Float) : Void { }
+
+
+   @:extern @:native("_hx_std_set_time_locale")
+   public static function set_time_locale(l:String) : Bool return false;
+
+
+   @:extern @:native("_hx_std_get_cwd")
+   public static function get_cwd() : String return null;
+
+
+   @:extern @:native("_hx_std_set_cwd")
+   public static function set_cwd(d:String) : Void { }
+
+
+   @:extern @:native("_hx_std_sys_string")
+   public static function sys_string() : String return null;
+
+
+   @:extern @:native("_hx_std_sys_is64")
+   public static function sys_is64() : Bool return false;
+
+
+   @:extern @:native("_hx_std_sys_command")
+   public static function sys_command(cmd:String) : Int return 0;
+
+
+   @:extern @:native("_hx_std_sys_exit")
+   public static function sys_exit(code:Int) : Void { }
+
+
+   @:extern @:native("_hx_std_sys_exists")
+   public static function sys_exists(path:String) : Bool return false;
+
+
+   @:extern @:native("_hx_std_file_delete")
+   public static function file_delete(path:String) : Void { }
+
+
+   @:extern @:native("_hx_std_sys_rename")
+   public static function sys_rename(path:String,newname:String) : Bool return false;
+
+
+   @:extern @:native("_hx_std_sys_stat")
+   public static function sys_stat(path:String) : Dynamic return null;
+
+
+   @:extern @:native("_hx_std_sys_file_type")
+   public static function sys_file_type(path:String) : String return null;
+
+
+   @:extern @:native("_hx_std_sys_create_dir")
+   public static function sys_create_dir(path:String,mode:Int) : Bool return false;
+
+
+   @:extern @:native("_hx_std_sys_remove_dir")
+   public static function sys_remove_dir(path:String) : Void { }
+
+
+   @:extern @:native("_hx_std_sys_time")
+   public static function sys_time() : Float return 0;
+
+
+   @:extern @:native("_hx_std_sys_cpu_time")
+   public static function sys_cpu_time() : Float return 0;
+
+
+   @:extern @:native("_hx_std_sys_read_dir")
+   public static function sys_read_dir(p:String) : Array<String> return null;
+
+
+   @:extern @:native("_hx_std_file_full_path")
+   public static function file_full_path(path:String) : String return null;
+
+
+   @:extern @:native("_hx_std_sys_exe_path")
+   public static function sys_exe_path() : String return null;
+
+
+   @:extern @:native("_hx_std_sys_env")
+   public static function sys_env() : Array<String> return null;
+
+
+   @:extern @:native("_hx_std_sys_getch")
+   public static function sys_getch(b:Bool) : Int return 0;
+
+
+   @:extern @:native("_hx_std_sys_get_pid")
+   public static function sys_get_pid() : Int return 0;
+
+}
+
+

+ 466 - 399
std/cpp/NativeXml.hx

@@ -22,412 +22,479 @@
 package cpp;
 package cpp;
 
 
 @:enum abstract XmlType(Int) {
 @:enum abstract XmlType(Int) {
-	/**
-		Represents an XML element type.
-	**/
-	var Element = 0;
-	/**
-		Represents XML parsed character data type.
-	**/
-	var PCData = 1;
-	/**
-		Represents XML character data type.
-	**/
-	var CData = 2;
-	/**
-		Represents an XML comment type.
-	**/
-	var Comment = 3;
-	/**
-		Represents an XML doctype element type.
-	**/
-	var DocType = 4;
-	/**
-	 	Represents an XML processing instruction type.
-	**/
-	var ProcessingInstruction = 5;
-	/**
-		Represents an XML document type.
-	**/
-	var Document = 6;
+   /**
+      Represents an XML element type.
+   **/
+   var Element = 0;
+   /**
+      Represents XML parsed character data type.
+   **/
+   var PCData = 1;
+   /**
+      Represents XML character data type.
+   **/
+   var CData = 2;
+   /**
+      Represents an XML comment type.
+   **/
+   var Comment = 3;
+   /**
+      Represents an XML doctype element type.
+   **/
+   var DocType = 4;
+   /**
+       Represents an XML processing instruction type.
+   **/
+   var ProcessingInstruction = 5;
+   /**
+      Represents an XML document type.
+   **/
+   var Document = 6;
 }
 }
 
 
+class NativeXmlState
+{
+   var cur : Xml;
+
+   public function new(x:Xml)
+   {
+      x._children = new Array<Xml>();
+      cur = x;
+   }
+
+
+   @:keep
+   public function xml(name:String, att:Dynamic<String>)
+   {
+      var x = new Xml();
+      x._parent = cur;
+      x.nodeType = Xml.Element;
+      x._nodeName = name;
+      x._attributes = att;
+      x._children = new Array<Xml>();
+      cur.addChild(x);
+      cur = x;
+   }
+
+   @:keep
+   public function cdata(text:String)
+   {
+      var x = new Xml();
+      x._parent = cur;
+      x.nodeType = Xml.CData;
+      x._nodeValue = text;
+      cur.addChild(x);
+   }
+
+   @:keep
+   public function pcdata(text:String)
+   {
+      var x = new Xml();
+      x._parent = cur;
+      x.nodeType = Xml.PCData;
+      x._nodeValue = text;
+      cur.addChild(x);
+   }
+
+   @:keep
+   public function comment(text:String)
+   {
+      var x = new Xml();
+      x._parent = cur;
+      if( text.length>1 && StringTools.fastCodeAt(text,0) == 63 )
+      {
+         x.nodeType = Xml.ProcessingInstruction;
+         text = text.substr(1, text.length - 2);
+      }
+      else
+      {
+         x.nodeType = Xml.Comment;
+      }
+      x._nodeValue = text;
+      cur.addChild(x);
+   }
+
+   @:keep
+   public function doctype(text:String)
+   {
+      var x = new Xml();
+      x._parent = cur;
+      x.nodeType = Xml.DocType;
+      x._nodeValue = text.substr(1);
+      cur.addChild(x);
+   }
+   
+   @:keep
+   public function done()
+   {
+     cur = cur._parent;
+   }
+}
+
+private class NativeXmlIterator
+{
+   var cur = 0;
+   var children:Array<Xml>;
+
+   public function new(inChildren:Array<Xml>)
+   {
+      children = inChildren;
+      cur = 0;
+   }
+
+   public function hasNext() : Bool
+   {
+      var k = cur;
+      var l = children.length;
+      while( k < l )
+      {
+         if (children[k].nodeType == Xml.Element)
+            break;
+         k += 1;
+      }
+      cur = k;
+      return k < l;
+   }
+
+   public function next():Xml
+   {
+      var k = cur;
+      var l = children.length;
+      while( k < l )
+      {
+         var n = children[k];
+         k += 1;
+         if( n.nodeType == Xml.Element )
+         {
+            cur = k;
+            return n;
+         }
+      }
+      return null;
+   }
+}
+
+private class NativeXmlNamedIterator
+{
+   var cur = 0;
+   var children:Array<Xml>;
+   var name:String;
+
+   public function new(inChildren:Array<Xml>, inName:String)
+   {
+      children = inChildren;
+      name = inName;
+      cur = 0;
+   }
+
+
+   public function hasNext() : Bool
+   {
+      var k = cur;
+      var l = children.length;
+      while( k < l )
+      {
+         var n = children[k];
+         if( n.nodeType == Xml.Element && n._nodeName == name )
+            break;
+         k++;
+     }
+     cur = k;
+     return k < l;
+   }
+
+   public function next():Xml
+   {
+      var k = cur;
+      var l = children.length;
+      while( k < l )
+      {
+         var n = children[k];
+         k++;
+         if( n.nodeType == Xml.Element && n._nodeName == name ) {
+            cur = k;
+            return n;
+         }
+      }
+      return null;
+   }
+}
+
+
+
+
+@:cppInclude("./NativeXmlImport.cpp")
+@:allow(cpp.NativeXmlState) @:allow(cpp.NativeXmlIterator) @:allow(cpp.NativeXmlNamedIterator)
 class Xml {
 class Xml {
-	static inline var Element = XmlType.Element;
-	static inline var PCData = XmlType.PCData;
-	static inline var CData = XmlType.CData;
-	static inline var Comment = XmlType.Comment;
-	static inline var DocType = XmlType.DocType;
-	static inline var ProcessingInstruction = XmlType.ProcessingInstruction;
-	static inline var Document = XmlType.Document;
-
-
-	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";
+   static inline var Element = XmlType.Element;
+   static inline var PCData = XmlType.PCData;
+   static inline var CData = XmlType.CData;
+   static inline var Comment = XmlType.Comment;
+   static inline var DocType = XmlType.DocType;
+   static inline var ProcessingInstruction = XmlType.ProcessingInstruction;
+   static inline var Document = XmlType.Document;
+
+
+   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 {
+   }
+
+   @:extern @:native("parse_xml")
+   static function parse_xml(str:String, state:NativeXmlState) { }
+
+   public static function parse( str : String ) : Xml
+   {
+      var x = new Xml();
+      var state = new NativeXmlState(x);
+      parse_xml(str,state);
+      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();
       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 elements(): Iterator<Xml>
+   {
+      if( _children == null )
+         throw "bad nodetype";
+      return new NativeXmlIterator(_children);
+   }
+
+   public function elementsNamed( name : String ) : Iterator<Xml>
+   {
+      if( _children == null )
+         throw "bad nodetype";
+      return new NativeXmlNamedIterator(_children,name);
+   }
+
+   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 {
    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;
-	}
+      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 {
    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("?>");
-		}
-	}
+      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("?>");
+      }
+   }
 
 
 }
 }

+ 365 - 0
std/cpp/NativeXmlImport.cpp

@@ -0,0 +1,365 @@
+
+#ifdef EPPC
+#include <memory>
+#else
+#include <memory.h>
+#endif
+
+
+#ifndef HX_WINDOWS
+#  include <strings.h>
+#  undef strcmpi
+#  define strcmpi(a,b) strcasecmp(a,b)
+#else
+#   include <string.h>
+#endif
+
+
+// -------------- parsing --------------------------
+
+
+enum STATE {
+   IGNORE_SPACES,
+   BEGIN,
+   BEGIN_NODE,
+   TAG_NAME,
+   BODY,
+   ATTRIB_NAME,
+   EQUALS,
+   ATTVAL_BEGIN,
+   ATTRIB_VAL,
+   CHILDS,
+   CLOSE,
+   WAIT_END,
+   WAIT_END_RET,
+   PCDATA,
+   HEADER,
+   COMMENT,
+   DOCTYPE,
+   CDATA,
+};
+
+static void xml_error( const char *xml, const char *inWhere, int *line, String msg ) {
+   String b = HX_CSTRING("Xml parse error : ") + msg + HX_CSTRING(" at line ") + String(*line) + HX_CSTRING(" : ");
+   String where(inWhere);
+
+   int l = where.length;
+   int nchars = 30;
+   if( inWhere != xml )
+      b += HX_CSTRING("...");
+
+   if (where.length==0)
+      b+= HX_CSTRING("<eof>");
+   else if (where.length<nchars)
+      b+= where;
+   else
+      b+= where.substr(0,nchars) + HX_CSTRING("...");
+
+   hx::Throw(b);
+}
+
+#define ERRORSTR(msg)   xml_error(xml,p,line,msg);
+#define ERROR(msg)   xml_error(xml,p,line,HX_CSTRING(msg));
+
+static bool is_valid_char( int c ) {
+   return ( c >= 'a' && c <= 'z' ) || ( c >= 'A' && c <= 'Z' ) || ( c >= '0' && c <= '9' ) || c == ':' || c == '.' || c == '_' || c == '-';
+}
+
+static void do_parse_xml( const char *xml, const char **lp, int *line, cpp::NativeXmlState callb, String parentname )
+{
+   STATE state = BEGIN;
+   STATE next = BEGIN;
+   String aname;
+   hx::Anon attribs;
+   String nodename;
+
+   const char *start = NULL;
+   const char *p = *lp;
+   char c = *p;
+   int nsubs = 0, nbrackets = 0;
+   while( c ) {
+      switch( state ) {
+      case IGNORE_SPACES:
+         switch( c ) {
+         case '\n':
+         case '\r':
+         case '\t':
+         case ' ':
+            break;
+         default:
+            state = next;
+            continue;
+         }
+         break;
+      case BEGIN:
+         switch( c ) {
+         case '<':
+            state = IGNORE_SPACES;
+            next = BEGIN_NODE;
+            break;
+         default:
+            start = p;
+            state = PCDATA;
+            continue;
+         }
+         break;
+      case PCDATA:
+         if( c == '<' ) {
+            callb->pcdata(String(start,p-start).dup());
+            nsubs++;
+            state = IGNORE_SPACES;
+            next = BEGIN_NODE;
+         }
+         break;
+      case CDATA:
+         if( c == ']' && p[1] == ']' && p[2] == '>' ) {
+            callb->cdata(String(start,p-start).dup());
+            nsubs++;
+            p += 2;
+            state = BEGIN;
+         }
+         break;
+      case BEGIN_NODE:
+         switch( c ) {
+         case '!':
+            if( p[1] == '[' ) {
+               p += 2;
+               if( (p[0] != 'C' && p[0] != 'c') ||
+                  (p[1] != 'D' && p[1] != 'd') ||
+                  (p[2] != 'A' && p[2] != 'a') ||
+                  (p[3] != 'T' && p[3] != 't') ||
+                  (p[4] != 'A' && p[4] != 'a') ||
+                  (p[5] != '[') )
+                  ERROR("Expected <![CDATA[");
+               p += 5;
+               state = CDATA;
+               start = p + 1;
+               break;
+            }
+            if( p[1] == 'D' || p[1] == 'd' ) {
+               if( (p[2] != 'O' && p[2] != 'o') ||
+                  (p[3] != 'C' && p[3] != 'c') ||
+                  (p[4] != 'T' && p[4] != 't') ||
+                  (p[5] != 'Y' && p[5] != 'y') ||
+                  (p[6] != 'P' && p[6] != 'p') ||
+                  (p[7] != 'E' && p[7] != 'e') )
+                  ERROR("Expected <!DOCTYPE");
+               p += 7;
+               state = DOCTYPE;
+               start = p + 1;
+               break;
+            }
+            if( p[1] != '-' || p[2] != '-' )
+               ERROR("Expected <!--");
+            p += 2;
+            state = COMMENT;
+            start = p + 1;
+            break;
+         case '?':
+            state = HEADER;
+            start = p;
+            break;
+         case '/':
+            if( parentname.length==0 )
+               ERROR("Expected node name");
+            start = p + 1;
+            state = IGNORE_SPACES;
+            next = CLOSE;
+            break;
+         default:
+            state = TAG_NAME;
+            start = p;
+            continue;
+         }
+         break;
+      case TAG_NAME:
+         if( !is_valid_char(c) ) {
+            if( p == start )
+               ERROR("Expected node name");
+            nodename = String(start,p-start).dup();
+            attribs = hx::Anon_obj::Create();
+            state = IGNORE_SPACES;
+            next = BODY;
+            continue;
+         }
+         break;
+      case BODY:
+         switch( c ) {
+         case '/':
+            state = WAIT_END;
+            nsubs++;
+            callb->xml(nodename,attribs);
+            break;
+         case '>':
+            state = CHILDS;
+            nsubs++;
+            callb->xml(nodename,attribs);
+            break;
+         default:
+            state = ATTRIB_NAME;
+            start = p;
+            continue;
+         }
+         break;
+      case ATTRIB_NAME:
+         if( !is_valid_char(c) ) {
+            if( start == p )
+               ERROR("Expected attribute name");
+            aname = String(start,p-start).dup();
+            if( attribs->__Field(aname,hx::paccDynamic) != null() )
+               ERROR("Duplicate attribute");
+            state = IGNORE_SPACES;
+            next = EQUALS;
+            continue;
+         }
+         break;
+      case EQUALS:
+         switch( c ) {
+         case '=':
+            state = IGNORE_SPACES;
+            next = ATTVAL_BEGIN;
+            break;
+         default:
+            ERROR("Expected =");
+         }
+         break;
+      case ATTVAL_BEGIN:
+         switch( c ) {
+         case '"':
+         case '\'':
+            state = ATTRIB_VAL;
+            start = p;
+            break;
+         default:
+            ERROR("Expected \"");
+         }
+         break;
+      case ATTRIB_VAL:
+         if( c == *start ) {
+            attribs->Add( aname, String(start+1,p-start-1).dup() );
+            state = IGNORE_SPACES;
+            next = BODY;
+         }
+         break;
+      case CHILDS:
+         *lp = p;
+         do_parse_xml(xml,lp,line,callb,nodename);
+         p = *lp;
+         start = p;
+         state = BEGIN;
+         break;
+      case WAIT_END:
+         switch( c ) {
+         case '>':
+            callb->done();
+            state = BEGIN;
+            break;
+         default :
+            ERROR("Expected >");
+         }
+         break;
+      case WAIT_END_RET:
+         switch( c ) {
+         case '>':
+            if( nsubs == 0 )
+               callb->pcdata(HX_CSTRING(""));
+            *lp = p;
+            return;
+         default :
+            ERROR("Expected >");
+         }
+         break;
+      case CLOSE:
+         if( !is_valid_char(c) ) {
+            if( start == p )
+               ERROR("Expected node name");
+            {
+               String v = String(start,p - start).dup();
+               if( strcmpi(parentname.__s,v.__s) != 0 ) {
+                  ERRORSTR(HX_CSTRING("Expected </") + parentname + HX_CSTRING(">"));
+               }
+            }
+            state = IGNORE_SPACES;
+            next = WAIT_END_RET;
+            continue;
+         }
+         break;
+      case COMMENT:
+         if( c == '-' && p[1] == '-' && p[2] == '>' ) {
+            callb->comment(String(start,p-start).dup());
+            p += 2;
+            state = BEGIN;
+         }
+         break;
+      case DOCTYPE:
+         if( c == '[' )
+            nbrackets++;
+         else if( c == ']' )
+            nbrackets--;
+         else if( c == '>' && nbrackets == 0 ) {
+            callb->doctype(String(start,p-start).dup());
+            state = BEGIN;
+         }
+         break;
+      case HEADER:
+         if( c == '?' && p[1] == '>' ) {
+            p++;
+            callb->comment(String(start,p-start).dup());
+            state = BEGIN;
+         }
+         break;
+      }
+      c = *++p;
+      if( c == '\n' )
+         (*line)++;
+   }
+   if( state == BEGIN ) {
+      start = p;
+      state = PCDATA;
+   }
+   if( parentname.__s == 0 && state == PCDATA ) {
+      if( p != start || nsubs == 0 )
+         callb->pcdata(String(start,p-start).dup());
+      return;
+   }
+   ERROR("Unexpected end");
+}
+
+// ----------------------------------------------
+
+/**
+   <doc>
+   <h1>Xml</h1>
+   <p>
+   The standard event-driven XML parser.
+   </p>
+   </doc>
+**/
+
+/**
+   parse_xml : xml:string -> events:object -> void
+   <doc>
+   The [parse_xml] parse a string and for each parsed element call the
+   corresponding object method in [events] :
+   <ul>
+   <li>[void xml( name : string, attribs : object)] when an XML node is found</li>
+   <li>[void done()] when an XML node is closed</li>
+   <li>[void pcdata(string)] when PCData chars found</li>
+   <li>[void cdata(string)] when a CData session is found</li>
+   <li>[void comment(string)] when some comment or special header is found</li>
+   </ul>
+   You can then implement the events so they build the appropriate XML data
+   structure needed by your language.
+   </doc>
+**/
+static void parse_xml( String str, cpp::NativeXmlState state )
+{
+   int line = 0;
+   const char *p = str.__s;
+   // skip BOM
+   if( p[0] == (char)0xEF && p[1] == (char)0xBB && p[2] == (char)0xBF )
+      p += 3;
+   do_parse_xml(p,&p,&line,state,String());
+}
+
+

+ 19 - 0
std/cpp/ObjectType.hx

@@ -0,0 +1,19 @@
+package cpp;
+
+extern class ObjectType
+{
+   public inline static var vtUnknown = -1;
+   public inline static var vtInt = 0xff;
+   public inline static var vtNull = 0;
+   public inline static var vtFloat = 1;
+   public inline static var vtBool = 2;
+   public inline static var vtString = 3;
+   public inline static var vtObject = 4;
+   public inline static var vtArray = 5;
+   public inline static var vtFunction = 6;
+   public inline static var vtEnum = 7;
+   public inline static var vtClass = 8;
+   public inline static var vtInt64 = 9;
+   public inline static var vtAbstractBase = 0x100;
+}
+

+ 0 - 1
std/cpp/Pointer.hx

@@ -22,7 +22,6 @@
  package cpp;
  package cpp;
 
 
 @:coreType
 @:coreType
-@:analyzer(no_simplification)
 extern class Pointer<T> extends ConstPointer<T> implements ArrayAccess<T>
 extern class Pointer<T> extends ConstPointer<T> implements ArrayAccess<T>
 {
 {
    @:analyzer(no_simplification)
    @:analyzer(no_simplification)

+ 1 - 2
std/cpp/Prime.hx

@@ -32,7 +32,6 @@ class Prime {
 
 
    #if (!macro && cpp)
    #if (!macro && cpp)
 
 
-   @:analyzer(no_simplification)
 	public static function _loadPrime( lib : String, prim : String, signature : String, quietFail = false ) : Dynamic {
 	public static function _loadPrime( lib : String, prim : String, signature : String, quietFail = false ) : Dynamic {
 		var factory:Callable< ConstCharStar -> Object > =
 		var factory:Callable< ConstCharStar -> Object > =
                untyped __global__.__hxcpp_cast_get_proc_address(lib, prim + "__prime", quietFail);
                untyped __global__.__hxcpp_cast_get_proc_address(lib, prim + "__prime", quietFail);
@@ -76,7 +75,7 @@ class Prime {
       #if neko
       #if neko
       var init = neko.Lib.load(inModuleName, "neko_init", 5);
       var init = neko.Lib.load(inModuleName, "neko_init", 5);
 
 
-      if (init != null) 
+      if (init != null)
       {
       {
          init( function(s) return new String(s),
          init( function(s) return new String(s),
                function(len:Int) { var r = []; if (len > 0) r[len - 1] = null; return r; },
                function(len:Int) { var r = []; if (len > 0) r[len - 1] = null; return r; },

+ 4 - 9
std/cpp/Random.hx

@@ -26,24 +26,19 @@ class Random {
 	var r : Dynamic;
 	var r : Dynamic;
 
 
 	public function new() {
 	public function new() {
-		r = random_new();
+		r = cpp.NativeRandom.random_new();
 	}
 	}
 
 
 	public function setSeed( s : Int ) {
 	public function setSeed( s : Int ) {
-		random_set_seed(r,s);
+		cpp.NativeRandom.random_set_seed(r,s);
 	}
 	}
 
 
 	public function int( max : Int ) : Int {
 	public function int( max : Int ) : Int {
-		return random_int(r,max);
+		return cpp.NativeRandom.random_int(r,max);
 	}
 	}
 
 
 	public function float() : Float {
 	public function float() : Float {
-		return random_float(r);
+		return cpp.NativeRandom.random_float(r);
 	}
 	}
 
 
-	static var random_new = Lib.load("std","random_new",0);
-	static var random_set_seed = Lib.load("std","random_set_seed",2);
-	static var random_int = Lib.load("std","random_int",2);
-	static var random_float = Lib.load("std","random_float",1);
-
 }
 }

+ 27 - 17
std/cpp/_std/EReg.hx

@@ -19,6 +19,8 @@
  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * DEALINGS IN THE SOFTWARE.
  * DEALINGS IN THE SOFTWARE.
  */
  */
+
+@:buildXml('<include name="${HXCPP}/src/hx/libs/regexp/Build.xml"/>')
 @:coreApi class EReg {
 @:coreApi class EReg {
 
 
 	var r : Dynamic;
 	var r : Dynamic;
@@ -30,11 +32,11 @@
 			global = a.length > 1;
 			global = a.length > 1;
 			if( global )
 			if( global )
 				opt = a.join("");
 				opt = a.join("");
-			this.r = regexp_new_options(r, opt);
+			this.r = _hx_regexp_new_options(r, opt);
 	}
 	}
 
 
 	public function match( s : String ) : Bool {
 	public function match( s : String ) : Bool {
-			var p = regexp_match(r,s,0,s.length);
+			var p = _hx_regexp_match(r,s,0,s.length);
 			if( p )
 			if( p )
 				last = s;
 				last = s;
 			else
 			else
@@ -43,27 +45,27 @@
 	}
 	}
 
 
 	public function matched( n : Int ) : String {
 	public function matched( n : Int ) : String {
-			var m = regexp_matched(r,n);
+			var m = _hx_regexp_matched(r,n);
 			return m;
 			return m;
 	}
 	}
 
 
 	public function matchedLeft() : String {
 	public function matchedLeft() : String {
-			var p = regexp_matched_pos(r,0);
+			var p = _hx_regexp_matched_pos(r,0);
 			return last.substr(0,p.pos);
 			return last.substr(0,p.pos);
 	}
 	}
 
 
 	public function matchedRight() : String {
 	public function matchedRight() : String {
-			var p = regexp_matched_pos(r,0);
+			var p = _hx_regexp_matched_pos(r,0);
 			var sz = p.pos+p.len;
 			var sz = p.pos+p.len;
 			return last.substr(sz,last.length-sz);
 			return last.substr(sz,last.length-sz);
 	}
 	}
 
 
 	public function matchedPos() : { pos : Int, len : Int } {
 	public function matchedPos() : { pos : Int, len : Int } {
-			return regexp_matched_pos(r,0);
+			return _hx_regexp_matched_pos(r,0);
 	}
 	}
 
 
 	public function matchSub( s : String, pos : Int, len : Int = -1):Bool {
 	public function matchSub( s : String, pos : Int, len : Int = -1):Bool {
-			var p = regexp_match(r, s, pos, len < 0 ? s.length - pos : len);
+			var p = _hx_regexp_match(r, s, pos, len < 0 ? s.length - pos : len);
 			if (p)
 			if (p)
 				last = s;
 				last = s;
 			else
 			else
@@ -77,9 +79,9 @@
 			var a = new Array();
 			var a = new Array();
 			var first = true;
 			var first = true;
 			do {
 			do {
-				if( !regexp_match(r,s,pos,len) )
+				if( !_hx_regexp_match(r,s,pos,len) )
 					break;
 					break;
-				var p = regexp_matched_pos(r,0);
+				var p = _hx_regexp_matched_pos(r,0);
 				if( p.len == 0 && !first ) {
 				if( p.len == 0 && !first ) {
 					if( p.pos == s.length )
 					if( p.pos == s.length )
 						break;
 						break;
@@ -102,9 +104,9 @@
 			var a = by.split("$");
 			var a = by.split("$");
 			var first = true;
 			var first = true;
 			do {
 			do {
-				if( !regexp_match(r,s,pos,len) )
+				if( !_hx_regexp_match(r,s,pos,len) )
 					break;
 					break;
-				var p = regexp_matched_pos(r,0);
+				var p = _hx_regexp_matched_pos(r,0);
 				if( p.len == 0 && !first ) {
 				if( p.len == 0 && !first ) {
 					if( p.pos == s.length )
 					if( p.pos == s.length )
 						break;
 						break;
@@ -119,7 +121,7 @@
 					var c = k.charCodeAt(0);
 					var c = k.charCodeAt(0);
 					// 1...9
 					// 1...9
 					if( c >= 49 && c <= 57 ) {
 					if( c >= 49 && c <= 57 ) {
-						var p = try regexp_matched_pos(r,Std.int(c)-48) catch( e : String ) null;
+						var p = try _hx_regexp_matched_pos(r,Std.int(c)-48) catch( e : String ) null;
 						if( p == null ){
 						if( p == null ){
 							b.add("$");
 							b.add("$");
 							b.add(k);
 							b.add(k);
@@ -156,7 +158,7 @@
 				buf.add(s.substr(offset));
 				buf.add(s.substr(offset));
 				break;
 				break;
 			}
 			}
-			var p = regexp_matched_pos(r,0);
+			var p = _hx_regexp_matched_pos(r,0);
 			buf.add(s.substr(offset, p.pos - offset));
 			buf.add(s.substr(offset, p.pos - offset));
 			buf.add(f(this));
 			buf.add(f(this));
 			if (p.len == 0) {
 			if (p.len == 0) {
@@ -171,8 +173,16 @@
 		return buf.toString();
 		return buf.toString();
 	}
 	}
 
 
-	static var regexp_new_options : String -> String -> Dynamic = cpp.Lib.load("regexp","regexp_new_options",2);
-	static var regexp_match : Dynamic -> String -> Int -> Int -> Dynamic = cpp.Lib.load("regexp","regexp_match",4);
-	static var regexp_matched : Dynamic -> Int -> Dynamic = cpp.Lib.load("regexp","regexp_matched",2);
-	static var regexp_matched_pos : Dynamic -> Int -> { pos : Int, len : Int } = cpp.Lib.load("regexp","regexp_matched_pos",2);
+
+   @:extern @:native("_hx_regexp_new_options")
+	static function _hx_regexp_new_options(s:String, options:String) : Dynamic return null;
+
+   @:extern @:native("_hx_regexp_match")
+	static function _hx_regexp_match(handler: Dynamic, string:String, pos:Int, len:Int) : Bool return false;
+
+   @:extern @:native("_hx_regexp_matched")
+	static function _hx_regexp_matched(handle:Dynamic, pos:Int) : String return null;
+
+   @:extern @:native("_hx_regexp_matched_pos")
+	static function _hx_regexp_matched_pos(handle:Dynamic, match:Int) : {pos:Int, len:Int} return null;
 }
 }

+ 10 - 7
std/cpp/_std/Reflect.hx

@@ -19,6 +19,9 @@
  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * DEALINGS IN THE SOFTWARE.
  * DEALINGS IN THE SOFTWARE.
  */
  */
+
+import cpp.ObjectType;
+
 @:coreApi
 @:coreApi
 @:analyzer(ignore)
 @:analyzer(ignore)
 class Reflect {
 class Reflect {
@@ -46,7 +49,7 @@ class Reflect {
 	}
 	}
 
 
 	public static function callMethod( o : Dynamic, func : haxe.Constraints.Function, args : Array<Dynamic> ) : Dynamic untyped {
 	public static function callMethod( o : Dynamic, func : haxe.Constraints.Function, args : Array<Dynamic> ) : Dynamic untyped {
-			if (func!=null && func.__GetType()==__global__.vtString)
+			if (func!=null && func.__GetType()==ObjectType.vtString)
 				func = o.__Field(func,untyped __cpp__("hx::paccDynamic"));
 				func = o.__Field(func,untyped __cpp__("hx::paccDynamic"));
 			untyped func.__SetThis(o);
 			untyped func.__SetThis(o);
          return untyped func.__Run(args);
          return untyped func.__Run(args);
@@ -60,7 +63,7 @@ class Reflect {
 	}
 	}
 
 
 	public static function isFunction( f : Dynamic ) : Bool untyped {
 	public static function isFunction( f : Dynamic ) : Bool untyped {
-		return f!=null && f.__GetType() ==  __global__.vtFunction;
+		return f!=null && f.__GetType() ==  ObjectType.vtFunction;
 	}
 	}
 
 
 	public static function compare<T>( a : T, b : T ) : Int {
 	public static function compare<T>( a : T, b : T ) : Int {
@@ -78,12 +81,12 @@ class Reflect {
 	public static function isObject( v : Dynamic ) : Bool untyped {
 	public static function isObject( v : Dynamic ) : Bool untyped {
 		if (v==null) return false;
 		if (v==null) return false;
 		var t:Int = v.__GetType();
 		var t:Int = v.__GetType();
-		return t ==  __global__.vtObject || t==__global__.vtClass || t==__global__.vtString ||
-				t==__global__.vtArray;
+		return t ==  ObjectType.vtObject || t==ObjectType.vtClass || t==ObjectType.vtString ||
+				t==ObjectType.vtArray;
 	}
 	}
 
 
 	public static function isEnumValue( v : Dynamic ) : Bool untyped {
 	public static function isEnumValue( v : Dynamic ) : Bool untyped {
-		return v!=null && v.__GetType() == __global__.vtEnum;
+		return v!=null && v.__GetType() == ObjectType.vtEnum;
 	}
 	}
 
 
 	public static function deleteField( o : Dynamic, field : String ) : Bool untyped {
 	public static function deleteField( o : Dynamic, field : String ) : Bool untyped {
@@ -93,8 +96,8 @@ class Reflect {
 
 
 	public static function copy<T>( o : T ) : T {
 	public static function copy<T>( o : T ) : T {
 		if (o==null) return null;
 		if (o==null) return null;
-		if(untyped o.__GetType()==__global__.vtString ) return o;
-		if(untyped o.__GetType()==__global__.vtArray )
+		if(untyped o.__GetType()==ObjectType.vtString ) return o;
+		if(untyped o.__GetType()==ObjectType.vtArray )
 			return untyped o.__Field("copy", untyped __cpp__("hx::paccDynamic"))();
 			return untyped o.__Field("copy", untyped __cpp__("hx::paccDynamic"))();
 		var o2 : Dynamic = {};
 		var o2 : Dynamic = {};
 		for( f in Reflect.fields(o) )
 		for( f in Reflect.fields(o) )

+ 21 - 38
std/cpp/_std/Sys.hx

@@ -19,6 +19,8 @@
  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * DEALINGS IN THE SOFTWARE.
  * DEALINGS IN THE SOFTWARE.
  */
  */
+import cpp.NativeSys;
+
 @:coreApi class Sys {
 @:coreApi class Sys {
 
 
 	public static function print( v : Dynamic ) : Void {
 	public static function print( v : Dynamic ) : Void {
@@ -32,21 +34,21 @@
 
 
    @:access(sys.io.FileInput)
    @:access(sys.io.FileInput)
 	public static function stdin() : haxe.io.Input {
 	public static function stdin() : haxe.io.Input {
-		return new sys.io.FileInput(file_stdin());
+		return new sys.io.FileInput(cpp.NativeFile.file_stdin());
 	}
 	}
 
 
    @:access(sys.io.FileOutput)
    @:access(sys.io.FileOutput)
 	public static function stdout() : haxe.io.Output {
 	public static function stdout() : haxe.io.Output {
-		return new sys.io.FileOutput(file_stdout());
+		return new sys.io.FileOutput(cpp.NativeFile.file_stdout());
 	}
 	}
 
 
    @:access(sys.io.FileOutput)
    @:access(sys.io.FileOutput)
 	public static function stderr() : haxe.io.Output {
 	public static function stderr() : haxe.io.Output {
-		return new sys.io.FileOutput(file_stderr());
+		return new sys.io.FileOutput(cpp.NativeFile.file_stderr());
 	}
 	}
 
 
 	public static function getChar( echo : Bool ) : Int {
 	public static function getChar( echo : Bool ) : Int {
-		return getch(echo);
+		return NativeSys.sys_getch(echo);
 	}
 	}
 
 
 	public static function args() : Array<String> untyped {
 	public static function args() : Array<String> untyped {
@@ -54,39 +56,39 @@
 	}
 	}
 
 
 	public static function getEnv( s : String ):String {
 	public static function getEnv( s : String ):String {
-		var v = get_env(s);
+		var v = NativeSys.get_env(s);
 		if( v == null )
 		if( v == null )
 			return null;
 			return null;
 		return v;
 		return v;
 	}
 	}
 
 
 	public static function putEnv( s : String, v : String ) : Void {
 	public static function putEnv( s : String, v : String ) : Void {
-		put_env(s,v);
+		NativeSys.put_env(s,v);
 	}
 	}
 
 
 	public static function sleep( seconds : Float ) : Void {
 	public static function sleep( seconds : Float ) : Void {
-		_sleep(seconds);
+		NativeSys.sys_sleep(seconds);
 	}
 	}
 
 
 	public static function setTimeLocale( loc : String ) : Bool {
 	public static function setTimeLocale( loc : String ) : Bool {
-		return set_time_locale(loc);
+		return NativeSys.set_time_locale(loc);
 	}
 	}
 
 
 	public static function getCwd() : String {
 	public static function getCwd() : String {
-		return new String(get_cwd());
+		return NativeSys.get_cwd();
 	}
 	}
 
 
 	public static function setCwd( s : String ) : Void {
 	public static function setCwd( s : String ) : Void {
-		set_cwd(s);
+		NativeSys.set_cwd(s);
 	}
 	}
 
 
 	public static function systemName() : String {
 	public static function systemName() : String {
-		return sys_string();
+		return NativeSys.sys_string();
 	}
 	}
 
 
 	public static function command( cmd : String, ?args : Array<String> ) : Int {
 	public static function command( cmd : String, ?args : Array<String> ) : Int {
 		if (args == null) {
 		if (args == null) {
-			return sys_command(cmd);
+			return NativeSys.sys_command(cmd);
 		} else {
 		} else {
 			switch (systemName()) {
 			switch (systemName()) {
 				case "Windows":
 				case "Windows":
@@ -94,10 +96,10 @@
 						for (a in [StringTools.replace(cmd, "/", "\\")].concat(args))
 						for (a in [StringTools.replace(cmd, "/", "\\")].concat(args))
 						StringTools.quoteWinArg(a, true)
 						StringTools.quoteWinArg(a, true)
 					].join(" ");
 					].join(" ");
-					return sys_command(cmd);
+					return NativeSys.sys_command(cmd);
 				case _:
 				case _:
 					cmd = [cmd].concat(args).map(StringTools.quoteUnixArg).join(" ");
 					cmd = [cmd].concat(args).map(StringTools.quoteUnixArg).join(" ");
-					return sys_command(cmd);
+					return NativeSys.sys_command(cmd);
 			}
 			}
 		}
 		}
 	}
 	}
@@ -107,23 +109,23 @@
 	}
 	}
 
 
 	public static function time() : Float {
 	public static function time() : Float {
-		return sys_time();
+		return NativeSys.sys_time();
 	}
 	}
 
 
 	public static function cpuTime() : Float {
 	public static function cpuTime() : Float {
-		return sys_cpu_time();
+		return NativeSys.sys_cpu_time();
 	}
 	}
 
 
 	@:deprecated("Use programPath instead") public static function executablePath() : String {
 	@:deprecated("Use programPath instead") public static function executablePath() : String {
-		return new String(sys_exe_path());
+		return NativeSys.sys_exe_path();
 	}
 	}
 
 
 	public static function programPath() : String {
 	public static function programPath() : String {
-		return _programPath;
+		return NativeSys.sys_exe_path();
 	}
 	}
 
 
 	public static function environment() : Map<String,String> {
 	public static function environment() : Map<String,String> {
-		var vars:Array<String> = sys_env();
+		var vars:Array<String> = NativeSys.sys_env();
 		var result = new haxe.ds.StringMap<String>();
 		var result = new haxe.ds.StringMap<String>();
 		var i = 0;
 		var i = 0;
 		while(i<vars.length) {
 		while(i<vars.length) {
@@ -133,23 +135,4 @@
 		return result;
 		return result;
 	}
 	}
 
 
-	private static var get_env = cpp.Lib.load("std","get_env",1);
-	private static var put_env = cpp.Lib.load("std","put_env",2);
-	private static var _sleep = cpp.Lib.load("std","sys_sleep",1);
-	private static var set_time_locale = cpp.Lib.load("std","set_time_locale",1);
-	private static var get_cwd = cpp.Lib.load("std","get_cwd",0);
-	private static var set_cwd = cpp.Lib.load("std","set_cwd",1);
-	private static var sys_string = cpp.Lib.load("std","sys_string",0);
-	private static var sys_command = cpp.Lib.load("std","sys_command",1);
-	private static var sys_time = cpp.Lib.load("std","sys_time",0);
-	private static var sys_cpu_time = cpp.Lib.load("std","sys_cpu_time",0);
-	private static var sys_exe_path = cpp.Lib.load("std","sys_exe_path",0);
-	private static var _programPath = sys.FileSystem.fullPath(new String(sys_exe_path()));
-	private static var sys_env = cpp.Lib.load("std","sys_env",0);
-
-	private static var file_stdin = cpp.Lib.load("std","file_stdin",0);
-	private static var file_stdout = cpp.Lib.load("std","file_stdout",0);
-	private static var file_stderr = cpp.Lib.load("std","file_stderr",0);
-
-	private static var getch = cpp.Lib.load("std","sys_getch",1);
 }
 }

+ 15 - 6
std/cpp/_std/haxe/zip/Compress.hx

@@ -21,7 +21,7 @@
  */
  */
 package haxe.zip;
 package haxe.zip;
 
 
-@:coreApi
+@:coreApi @:buildXml('<include name="${HXCPP}/src/hx/libs/zlib/Build.xml" />')
 class Compress {
 class Compress {
 
 
 	var s : Dynamic;
 	var s : Dynamic;
@@ -53,10 +53,19 @@ class Compress {
 		return out.sub(0,r.write);
 		return out.sub(0,r.write);
 	}
 	}
 
 
-	static var _deflate_init = cpp.Lib.load("zlib","deflate_init",1);
-	static var _deflate_bound = cpp.Lib.load("zlib","deflate_bound",2);
-	static var _deflate_buffer = cpp.Lib.load("zlib","deflate_buffer",5);
-	static var _deflate_end = cpp.Lib.load("zlib","deflate_end",1);
-	static var _set_flush_mode = cpp.Lib.load("zlib","set_flush_mode",2);
+   @:extern @:native("_hx_deflate_init")
+	static function _deflate_init(level:Int) : Dynamic return null;
+
+   @:extern @:native("_hx_deflate_bound")
+	static function _deflate_bound(handle:Dynamic,length:Int):Int return 0;
+
+   @:extern @:native("_hx_deflate_buffer")
+	static function _deflate_buffer(handle:Dynamic, src:haxe.io.BytesData, srcPos:Int,  dest:haxe.io.BytesData, destPos:Int) : { done : Bool, read : Int, write : Int } return null;
+
+   @:extern @:native("_hx_deflate_end")
+	static function _deflate_end(handle:Dynamic) : Void { }
+
+   @:extern @:native("_hx_zip_set_flush_mode")
+	static function _set_flush_mode(handle:Dynamic, flushMode:String):Void { }
 
 
 }
 }

+ 12 - 5
std/cpp/_std/haxe/zip/Uncompress.hx

@@ -21,7 +21,7 @@
  */
  */
 package haxe.zip;
 package haxe.zip;
 
 
-@:coreApi
+@:coreApi @:buildXml('<include name="${HXCPP}/src/hx/libs/zlib/Build.xml"/>')
 class Uncompress {
 class Uncompress {
 	var s : Dynamic;
 	var s : Dynamic;
 
 
@@ -59,9 +59,16 @@ class Uncompress {
 		return b.getBytes();
 		return b.getBytes();
 	}
 	}
 
 
-	static var _inflate_init = cpp.Lib.load("zlib","inflate_init",1);
-	static var _inflate_buffer = cpp.Lib.load("zlib","inflate_buffer",5);
-	static var _inflate_end = cpp.Lib.load("zlib","inflate_end",1);
-	static var _set_flush_mode = cpp.Lib.load("zlib","set_flush_mode",2);
+   @:extern @:native("_hx_inflate_init")
+	static function _inflate_init(windowBits:Dynamic) : Dynamic return null;
+
+   @:extern @:native("_hx_inflate_buffer")
+	static function _inflate_buffer(handle:Dynamic, src:haxe.io.BytesData, srcPos:Int,  dest:haxe.io.BytesData, destPos:Int) : { done : Bool, read : Int, write : Int } return null;
+
+   @:extern @:native("_hx_inflate_end")
+	static function _inflate_end(handle:Dynamic):Void { }
+
+   @:extern @:native("_hx_zip_set_flush_mode")
+	static function _set_flush_mode(handle:Dynamic, flushMode:String):Void { }
 
 
 }
 }

+ 12 - 23
std/cpp/_std/sys/FileSystem.hx

@@ -21,26 +21,28 @@
  */
  */
 package sys;
 package sys;
 
 
+import cpp.NativeSys;
+
 private enum FileKind {
 private enum FileKind {
 	kdir;
 	kdir;
 	kfile;
 	kfile;
 	kother( k : String );
 	kother( k : String );
 }
 }
 
 
+@:buildXml('<include name="${HXCPP}/src/hx/libs/std/Build.xml"/>')
 @:coreApi
 @:coreApi
 class FileSystem {
 class FileSystem {
 
 
 	public static function exists( path : String ) : Bool {
 	public static function exists( path : String ) : Bool {
-		return sys_exists(makeCompatiblePath(path));
+		return NativeSys.sys_exists(makeCompatiblePath(path));
 	}
 	}
 
 
 	public static function rename( path : String, newPath : String ) : Void {
 	public static function rename( path : String, newPath : String ) : Void {
-		if (sys_rename(path,newPath)==null)
-         throw "Could not rename:" + path + " to " + newPath;
+		NativeSys.sys_rename(path,newPath);
 	}
 	}
 
 
 	public static function stat( path : String ) : FileStat {
 	public static function stat( path : String ) : FileStat {
-		var s : FileStat = sys_stat(makeCompatiblePath(path));
+		var s : FileStat = NativeSys.sys_stat(makeCompatiblePath(path));
 		if (s==null)
 		if (s==null)
 			return { gid:0, uid:0, atime:Date.fromTime(0), mtime:Date.fromTime(0), ctime:Date.fromTime(0), dev:0, ino:0, nlink:0, rdev:0, size:0, mode:0 };
 			return { gid:0, uid:0, atime:Date.fromTime(0), mtime:Date.fromTime(0), ctime:Date.fromTime(0), dev:0, ino:0, nlink:0, rdev:0, size:0, mode:0 };
 		s.atime = Date.fromTime(1000.0*(untyped s.atime));
 		s.atime = Date.fromTime(1000.0*(untyped s.atime));
@@ -50,7 +52,7 @@ class FileSystem {
 	}
 	}
 
 
 	public static function fullPath( relPath : String ) : String {
 	public static function fullPath( relPath : String ) : String {
-		return new String(file_full_path(relPath));
+		return NativeSys.file_full_path(relPath);
 	}
 	}
 
 
 	public static function absolutePath ( relPath : String ) : String {
 	public static function absolutePath ( relPath : String ) : String {
@@ -59,7 +61,7 @@ class FileSystem {
 	}
 	}
 
 
 	static function kind( path : String ) : FileKind {
 	static function kind( path : String ) : FileKind {
-		var k:String = sys_file_type(makeCompatiblePath(path));
+		var k:String = NativeSys.sys_file_type(makeCompatiblePath(path));
 		return switch(k) {
 		return switch(k) {
 		case "file": kfile;
 		case "file": kfile;
 		case "dir": kdir;
 		case "dir": kdir;
@@ -80,23 +82,21 @@ class FileSystem {
 			path = _p;
 			path = _p;
 		}
 		}
 		for (part in parts) {
 		for (part in parts) {
-			if (part.charCodeAt(part.length - 1) != ":".code && !exists(part) && sys_create_dir( part, 493 )==null)
+			if (part.charCodeAt(part.length - 1) != ":".code && !exists(part) && !NativeSys.sys_create_dir( part, 493 ))
 				throw "Could not create directory:" + part;
 				throw "Could not create directory:" + part;
 		}
 		}
 	}
 	}
 
 
 	public static function deleteFile( path : String ) : Void {
 	public static function deleteFile( path : String ) : Void {
-		if (file_delete(path)==null)
-         throw "Could not delete file:" + path;
+		NativeSys.file_delete(path);
 	}
 	}
 
 
 	public static function deleteDirectory( path : String ) : Void {
 	public static function deleteDirectory( path : String ) : Void {
-		if (sys_remove_dir(path)==null)
-         throw "Could not delete directory:" + path;
+		NativeSys.sys_remove_dir(path);
 	}
 	}
 
 
 	public static function readDirectory( path : String ) : Array<String> {
 	public static function readDirectory( path : String ) : Array<String> {
-		return sys_read_dir(path);
+		return NativeSys.sys_read_dir(path);
 	}
 	}
 
 
 	private static inline function makeCompatiblePath(path:String):String {
 	private static inline function makeCompatiblePath(path:String):String {
@@ -106,15 +106,4 @@ class FileSystem {
 			haxe.io.Path.removeTrailingSlashes(path);
 			haxe.io.Path.removeTrailingSlashes(path);
 		}
 		}
 	}
 	}
-
-	private static var sys_exists = cpp.Lib.load("std","sys_exists",1);
-	private static var file_delete = cpp.Lib.load("std","file_delete",1);
-	private static var sys_rename = cpp.Lib.load("std","sys_rename",2);
-	private static var sys_stat = cpp.Lib.load("std","sys_stat",1);
-	private static var sys_file_type = cpp.Lib.load("std","sys_file_type",1);
-	private static var sys_create_dir = cpp.Lib.load("std","sys_create_dir",2);
-	private static var sys_remove_dir = cpp.Lib.load("std","sys_remove_dir",1);
-	private static var sys_read_dir = cpp.Lib.load("std","sys_read_dir",1);
-	private static var file_full_path = cpp.Lib.load("std","file_full_path",1);
-
 }
 }

+ 42 - 21
std/cpp/_std/sys/db/Mysql.hx

@@ -21,26 +21,44 @@
  */
  */
 package sys.db;
 package sys.db;
 
 
+@:keep
 private class D {
 private class D {
 
 
-	static function load(fun,args) : Dynamic {
-		return cpp.Lib.load(lib,fun,args);
-	}
-
-	static var lib = "mysql5";
-	public static var connect = load("mysql_connect",1);
-	public static var select_db = load("select_db",2);
-	public static var request = load("request",2);
-	public static var close = load("close",1);
-	public static var escape = load("escape", 2);
-	public static var set_conv_funs = load("set_conv_funs", 4);
-	public static var result_get_length = load("result_get_length",1);
-	public static var result_get_nfields = load("result_get_nfields",1);
-	public static var result_next = load("result_next",1);
-	public static var result_get = load("result_get",2);
-	public static var result_get_int = load("result_get_int",2);
-	public static var result_get_float = load("result_get_float",2);
-	public static var result_fields_names = cpp.Lib.loadLazy(lib,"result_get_fields_names",1);
+   @:extern @:native("_hx_mysql_connect")
+	public static function connect(params:Dynamic):Dynamic return null;
+   @:extern @:native("_hx_mysql_select_db")
+	public static function select_db(handle:Dynamic, db:String):Void { }
+   @:extern @:native("_hx_mysql_request")
+	public static function request(handle:Dynamic,req:String):Dynamic return null;
+   @:extern @:native("_hx_mysql_close")
+	public static function close(handle:Dynamic):Dynamic return null;
+   @:extern @:native("_hx_mysql_escape")
+	public static function escape(handle:Dynamic,str:String):String return null;
+   @:extern @:native("_hx_mysql_result_get_length")
+	public static function result_get_length(handle:Dynamic):Int return 0;
+   @:extern @:native("_hx_mysql_result_get_nfields")
+	public static function result_get_nfields(handle:Dynamic):Int return 0;
+   @:extern @:native("_hx_mysql_result_next")
+	public static function result_next(handle:Dynamic):Dynamic return null;
+   @:extern @:native("_hx_mysql_result_get")
+	public static function result_get(handle:Dynamic,i:Int) : String return null;
+   @:extern @:native("_hx_mysql_result_get_int")
+	public static function result_get_int(handle:Dynamic,i:Int) : Int return 0;
+   @:extern @:native("_hx_mysql_result_get_float")
+	public static function result_get_float(handle:Dynamic,i:Int):Float return 0.0;
+   @:extern @:native("_hx_mysql_result_get_fields_names")
+	public static function result_fields_names(handle:Dynamic):Array<String> return null;
+
+   @:extern @:native("_hx_mysql_set_conversion")
+	public static function set_conv_funs(
+      charsToBytes: cpp.Callable< Dynamic -> Dynamic >,
+      intToDate: cpp.Callable< Float -> Dynamic > ) : Void {}
+
+   public static function charsToBytes(data:Dynamic) : Dynamic
+      return haxe.io.Bytes.ofData(data);
+
+   public static function secondsToDate(seconds:Float) : Dynamic
+      return Date.fromTime(seconds);
 
 
 }
 }
 
 
@@ -87,7 +105,7 @@ private class MysqlResultSet implements sys.db.ResultSet {
 	}
 	}
 
 
 	public function getResult( n : Int ) {
 	public function getResult( n : Int ) {
-		return new String(D.result_get(__r,n));
+		return D.result_get(__r,n);
 	}
 	}
 
 
 	public function getIntResult( n : Int ) : Int {
 	public function getIntResult( n : Int ) : Int {
@@ -111,7 +129,9 @@ private class MysqlConnection implements sys.db.Connection {
 
 
 	public function new(c) {
 	public function new(c) {
 		__c = c;
 		__c = c;
-		D.set_conv_funs(c, function(s) return new String(s), function(d) return untyped Date.new1(d), function(b) return haxe.io.Bytes.ofData(b));
+	 D.set_conv_funs( cpp.Function.fromStaticFunction(D.charsToBytes),
+                     cpp.Function.fromStaticFunction(D.secondsToDate) );
+    
 	}
 	}
 
 
 	public function request( s : String ) : sys.db.ResultSet {
 	public function request( s : String ) : sys.db.ResultSet {
@@ -124,7 +144,7 @@ private class MysqlConnection implements sys.db.Connection {
 	}
 	}
 
 
 	public function escape( s : String ) {
 	public function escape( s : String ) {
-		return new String(D.escape(__c,s));
+		return D.escape(__c,s);
 	}
 	}
 
 
 	public function quote( s : String ) {
 	public function quote( s : String ) {
@@ -174,6 +194,7 @@ private class MysqlConnection implements sys.db.Connection {
 	private static var __use_date = Date;
 	private static var __use_date = Date;
 }
 }
 
 
+@:buildXml('<include name="${HXCPP}/src/hx/libs/mysql/Build.xml"/>')
 @:coreApi class Mysql {
 @:coreApi class Mysql {
 
 
 	public static function connect( params : {
 	public static function connect( params : {

+ 32 - 13
std/cpp/_std/sys/db/Sqlite.hx

@@ -47,7 +47,12 @@ private class SqliteConnection implements Connection {
 
 
 	public function quote( s : String ) {
 	public function quote( s : String ) {
 		if( s.indexOf("\000") >= 0 )
 		if( s.indexOf("\000") >= 0 )
-			return "x'"+new String(_encode(s,"0123456789ABCDEF"))+"'";
+      {
+         var hexChars = new Array<String>();
+         for(i in 0...s.length)
+           hexChars.push( StringTools.hex( StringTools.fastCodeAt(s,i),2 ) );
+			return "x'"+ hexChars.join("") +"'";
+      }
 		return "'"+s.split("'").join("''")+"'";
 		return "'"+s.split("'").join("''")+"'";
 	}
 	}
 
 
@@ -68,7 +73,7 @@ private class SqliteConnection implements Connection {
 		}
 		}
 	}
 	}
 
 
-	public function lastInsertId() {
+	public function lastInsertId() : Int{
 		return _last_id(c);
 		return _last_id(c);
 	}
 	}
 
 
@@ -90,11 +95,16 @@ private class SqliteConnection implements Connection {
 		startTransaction(); // match mysql usage
 		startTransaction(); // match mysql usage
 	}
 	}
 
 
-	static var _encode = cpp.Lib.load("std","base_encode",2);
-	static var _connect = cpp.Lib.load("sqlite","sqlite_connect",1);
-	static var _close = cpp.Lib.load("sqlite","close",1);
-	static var _request = cpp.Lib.load("sqlite","request",2);
-	static var _last_id = cpp.Lib.load("sqlite","last_insert_id",1);
+
+   @:extern @:native("_hx_sqlite_connect")
+	public static function _connect(filename:String):Dynamic return null;
+   @:extern @:native("_hx_sqlite_request")
+	public static function _request(handle:Dynamic,req:String):Dynamic return null;
+   @:extern @:native("_hx_sqlite_close")
+	public static function _close(handle:Dynamic):Void { };
+   @:extern @:native("_hx_sqlite_last_insert_id")
+	public static function _last_id(handle:Dynamic):Int return 0;
+
 }
 }
 
 
 
 
@@ -170,15 +180,24 @@ private class SqliteResultSet implements ResultSet {
 		return null;
 		return null;
 	}
 	}
 
 
-	static var result_next = cpp.Lib.load("sqlite","result_next",1);
-	static var result_get_length = cpp.Lib.load("sqlite","result_get_length",1);
-	static var result_get_nfields = cpp.Lib.load("sqlite","result_get_nfields",1);
-	static var result_get = cpp.Lib.load("sqlite","result_get",2);
-	static var result_get_int = cpp.Lib.load("sqlite","result_get_int",2);
-	static var result_get_float = cpp.Lib.load("sqlite","result_get_float",2);
+
+
+   @:extern @:native("_hx_sqlite_result_next")
+	public static function result_next(handle:Dynamic):Dynamic return null;
+   @:extern @:native("_hx_sqlite_result_get_length")
+	public static function result_get_length(handle:Dynamic):Int return 0;
+   @:extern @:native("_hx_sqlite_result_get_nfields")
+	public static function result_get_nfields(handle:Dynamic):Int return 0;
+   @:extern @:native("_hx_sqlite_result_get")
+	public static function result_get(handle:Dynamic,i:Int) : String return null;
+   @:extern @:native("_hx_sqlite_result_get_int")
+	public static function result_get_int(handle:Dynamic,i:Int) : Int return 0;
+   @:extern @:native("_hx_sqlite_result_get_float")
+	public static function result_get_float(handle:Dynamic,i:Int):Float return 0.0;
 
 
 }
 }
 
 
+@:buildXml('<include name="${HXCPP}/src/hx/libs/sqlite/Build.xml"/>')
 @:coreApi class Sqlite {
 @:coreApi class Sqlite {
 
 
 	public static function open( file : String ) : Connection {
 	public static function open( file : String ) : Connection {

+ 7 - 10
std/cpp/_std/sys/io/File.hx

@@ -21,16 +21,17 @@
  */
  */
 package sys.io;
 package sys.io;
 
 
+import cpp.NativeFile;
+
 @:coreApi
 @:coreApi
 class File {
 class File {
 
 
 	public static function getContent( path : String ) : String {
 	public static function getContent( path : String ) : String {
-		var b = getBytes(path);
-		return b.toString();
+		return NativeFile.file_contents_string(path);
 	}
 	}
 
 
 	public static function getBytes( path : String ) : haxe.io.Bytes {
 	public static function getBytes( path : String ) : haxe.io.Bytes {
-		var data:haxe.io.BytesData = file_contents(path);
+		var data = NativeFile.file_contents_bytes(path);
 		return haxe.io.Bytes.ofData(data);
 		return haxe.io.Bytes.ofData(data);
 	}
 	}
 
 
@@ -47,15 +48,15 @@ class File {
 	}
 	}
 
 
 	public static function read( path : String, binary : Bool = true ) : FileInput {
 	public static function read( path : String, binary : Bool = true ) : FileInput {
-		return untyped new FileInput(file_open(path,(if( binary ) "rb" else "r")));
+		return untyped new FileInput(NativeFile.file_open(path,(if( binary ) "rb" else "r")));
 	}
 	}
 
 
 	public static function write( path : String, binary : Bool = true ) : FileOutput {
 	public static function write( path : String, binary : Bool = true ) : FileOutput {
-		return untyped new FileOutput(file_open(path,(if( binary ) "wb" else "w")));
+		return untyped new FileOutput(NativeFile.file_open(path,(if( binary ) "wb" else "w")));
 	}
 	}
 
 
 	public static function append( path : String, binary : Bool = true ) : FileOutput {
 	public static function append( path : String, binary : Bool = true ) : FileOutput {
-		return untyped new FileOutput(file_open(path,(if( binary ) "ab" else "a")));
+		return untyped new FileOutput(NativeFile.file_open(path,(if( binary ) "ab" else "a")));
 	}
 	}
 
 
 	public static function copy( srcPath : String, dstPath : String ) : Void {
 	public static function copy( srcPath : String, dstPath : String ) : Void {
@@ -66,8 +67,4 @@ class File {
 		d.close();
 		d.close();
 	}
 	}
 
 
-	private static var file_contents = cpp.Lib.load("std","file_contents",1);
-	private static var file_open = cpp.Lib.load("std","file_open",2);
-
-
 }
 }

+ 7 - 15
std/cpp/_std/sys/io/FileInput.hx

@@ -21,6 +21,7 @@
  */
  */
 package sys.io;
 package sys.io;
 import sys.io.FileSeek;
 import sys.io.FileSeek;
+import cpp.NativeFile;
 
 
 @:coreApi
 @:coreApi
 class FileInput extends haxe.io.Input {
 class FileInput extends haxe.io.Input {
@@ -33,7 +34,7 @@ class FileInput extends haxe.io.Input {
 
 
 	public override function readByte() : Int {
 	public override function readByte() : Int {
 		return try {
 		return try {
-			file_read_char(__f);
+			NativeFile.file_read_char(__f);
 		} catch( e : Dynamic ) {
 		} catch( e : Dynamic ) {
 			if( untyped e.__IsArray() )
 			if( untyped e.__IsArray() )
 				throw new haxe.io.Eof();
 				throw new haxe.io.Eof();
@@ -44,7 +45,7 @@ class FileInput extends haxe.io.Input {
 
 
 	public override function readBytes( s : haxe.io.Bytes, p : Int, l : Int ) : Int {
 	public override function readBytes( s : haxe.io.Bytes, p : Int, l : Int ) : Int {
 		return try {
 		return try {
-			file_read(__f,s.getData(),p,l);
+			NativeFile.file_read(__f,s.getData(),p,l);
 		} catch( e : Dynamic ) {
 		} catch( e : Dynamic ) {
 			if( untyped e.__IsArray() )
 			if( untyped e.__IsArray() )
 				throw new haxe.io.Eof();
 				throw new haxe.io.Eof();
@@ -55,29 +56,20 @@ class FileInput extends haxe.io.Input {
 
 
 	public override function close() : Void {
 	public override function close() : Void {
 		super.close();
 		super.close();
-		file_close(__f);
+		NativeFile.file_close(__f);
 	}
 	}
 
 
 	public function seek( p : Int, pos : FileSeek ) : Void {
 	public function seek( p : Int, pos : FileSeek ) : Void {
-		file_seek(__f,p,pos==SeekBegin ? 0 : pos==SeekCur ? 1 :  2 );
+		NativeFile.file_seek(__f,p,pos==SeekBegin ? 0 : pos==SeekCur ? 1 :  2 );
 	}
 	}
 
 
 	public function tell() : Int {
 	public function tell() : Int {
-		return file_tell(__f);
+		return NativeFile.file_tell(__f);
 	}
 	}
 
 
 
 
 	public function eof() : Bool {
 	public function eof() : Bool {
-		return file_eof(__f);
+		return NativeFile.file_eof(__f);
 	}
 	}
 
 
-	private static var file_eof = cpp.Lib.load("std","file_eof",1);
-
-	private static var file_read = cpp.Lib.load("std","file_read",4);
-	private static var file_read_char = cpp.Lib.load("std","file_read_char",1);
-
-	private static var file_close = cpp.Lib.load("std","file_close",1);
-	private static var file_seek = cpp.Lib.load("std","file_seek",3);
-	private static var file_tell = cpp.Lib.load("std","file_tell",1);
-
 }
 }

+ 7 - 14
std/cpp/_std/sys/io/FileOutput.hx

@@ -21,6 +21,7 @@
  */
  */
 package sys.io;
 package sys.io;
 import sys.io.FileSeek;
 import sys.io.FileSeek;
+import cpp.NativeFile;
 
 
 @:coreApi
 @:coreApi
 class FileOutput extends haxe.io.Output {
 class FileOutput extends haxe.io.Output {
@@ -32,36 +33,28 @@ class FileOutput extends haxe.io.Output {
 	}
 	}
 
 
 	public override function writeByte( c : Int ) : Void {
 	public override function writeByte( c : Int ) : Void {
-		try file_write_char(__f,c) catch( e : Dynamic ) throw haxe.io.Error.Custom(e);
+		try NativeFile.file_write_char(__f,c) catch( e : Dynamic ) throw haxe.io.Error.Custom(e);
 	}
 	}
 
 
 	public override function writeBytes( s : haxe.io.Bytes, p : Int, l : Int ) : Int {
 	public override function writeBytes( s : haxe.io.Bytes, p : Int, l : Int ) : Int {
-		return try file_write(__f,s.getData(),p,l) catch( e : Dynamic ) throw haxe.io.Error.Custom(e);
+		return try NativeFile.file_write(__f,s.getData(),p,l) catch( e : Dynamic ) throw haxe.io.Error.Custom(e);
 	}
 	}
 
 
 	public override function flush() : Void {
 	public override function flush() : Void {
-		file_flush(__f);
+		NativeFile.file_flush(__f);
 	}
 	}
 
 
 	public override function close() : Void {
 	public override function close() : Void {
 		super.close();
 		super.close();
-		file_close(__f);
+		NativeFile.file_close(__f);
 	}
 	}
 
 
 	public function seek( p : Int, pos : FileSeek ) : Void {
 	public function seek( p : Int, pos : FileSeek ) : Void {
-		file_seek(__f,p, pos == SeekBegin ? 0 : pos ==  SeekCur ? 1 : 2);
+		NativeFile.file_seek(__f,p, pos == SeekBegin ? 0 : pos ==  SeekCur ? 1 : 2);
 	}
 	}
 
 
 	public function tell() : Int {
 	public function tell() : Int {
-		return file_tell(__f);
+		return NativeFile.file_tell(__f);
 	}
 	}
 
 
-	private static var file_close = cpp.Lib.load("std","file_close",1);
-	private static var file_seek = cpp.Lib.load("std","file_seek",3);
-	private static var file_tell = cpp.Lib.load("std","file_tell",1);
-
-	private static var file_flush = cpp.Lib.load("std","file_flush",1);
-	private static var file_write = cpp.Lib.load("std","file_write",4);
-	private static var file_write_char = cpp.Lib.load("std","file_write_char",2);
-
 }
 }

+ 10 - 19
std/cpp/_std/sys/io/Process.hx

@@ -21,6 +21,8 @@
  */
  */
 package sys.io;
 package sys.io;
 
 
+import cpp.NativeProcess;
+
 private class Stdin extends haxe.io.Output {
 private class Stdin extends haxe.io.Output {
 
 
 	var p : Dynamic;
 	var p : Dynamic;
@@ -33,7 +35,7 @@ private class Stdin extends haxe.io.Output {
 
 
 	public override function close() {
 	public override function close() {
 		super.close();
 		super.close();
-		_stdin_close(p);
+		NativeProcess.process_stdin_close(p);
 	}
 	}
 
 
 	public override function writeByte(c) {
 	public override function writeByte(c) {
@@ -43,16 +45,13 @@ private class Stdin extends haxe.io.Output {
 
 
 	public override function writeBytes( buf : haxe.io.Bytes, pos : Int, len : Int ) : Int {
 	public override function writeBytes( buf : haxe.io.Bytes, pos : Int, len : Int ) : Int {
 		try {
 		try {
-			return _stdin_write(p,buf.getData(),pos,len);
+			return NativeProcess.process_stdin_write(p,buf.getData(),pos,len);
 		} catch( e : Dynamic ) {
 		} catch( e : Dynamic ) {
 			throw new haxe.io.Eof();
 			throw new haxe.io.Eof();
 		}
 		}
 		return 0;
 		return 0;
 	}
 	}
 
 
-	static var _stdin_write = cpp.Lib.load("std","process_stdin_write",4);
-	static var _stdin_close = cpp.Lib.load("std","process_stdin_close",1);
-
 }
 }
 
 
 private class Stdout extends haxe.io.Input {
 private class Stdout extends haxe.io.Input {
@@ -76,17 +75,14 @@ private class Stdout extends haxe.io.Input {
 	public override function readBytes( str : haxe.io.Bytes, pos : Int, len : Int ) : Int {
 	public override function readBytes( str : haxe.io.Bytes, pos : Int, len : Int ) : Int {
 		var result:Int;
 		var result:Int;
 		try {
 		try {
-			result = (out?_stdout_read:_stderr_read)(p,str.getData(),pos,len);
+			result = out? NativeProcess.process_stdout_read(p,str.getData(),pos,len) :
+                       NativeProcess.process_stderr_read(p,str.getData(),pos,len);
 		} catch( e : Dynamic ) {
 		} catch( e : Dynamic ) {
 			throw new haxe.io.Eof();
 			throw new haxe.io.Eof();
 		}
 		}
 		if (result==0)throw new haxe.io.Eof();
 		if (result==0)throw new haxe.io.Eof();
 		return result;
 		return result;
 	}
 	}
-
-	static var _stdout_read = cpp.Lib.load("std","process_stdout_read",4);
-	static var _stderr_read = cpp.Lib.load("std","process_stderr_read",4);
-
 }
 }
 
 
 @:coreApi
 @:coreApi
@@ -98,31 +94,26 @@ class Process {
 	public var stdin(default,null) : haxe.io.Output;
 	public var stdin(default,null) : haxe.io.Output;
 
 
 	public function new( cmd : String, ?args : Array<String> ) : Void {
 	public function new( cmd : String, ?args : Array<String> ) : Void {
-		p = try _run(cmd,args) catch( e : Dynamic ) throw "Process creation failure : "+cmd;
+		p = try NativeProcess.process_run(cmd,args) catch( e : Dynamic ) throw "Process creation failure : "+cmd;
 		stdin = new Stdin(p);
 		stdin = new Stdin(p);
 		stdout = new Stdout(p,true);
 		stdout = new Stdout(p,true);
 		stderr = new Stdout(p,false);
 		stderr = new Stdout(p,false);
 	}
 	}
 
 
 	public function getPid() : Int {
 	public function getPid() : Int {
-		return _pid(p);
+		return NativeProcess.process_pid(p);
 	}
 	}
 
 
 	public function exitCode() : Int {
 	public function exitCode() : Int {
-		return _exit(p);
+		return NativeProcess.process_exit(p);
 	}
 	}
 
 
 	public function close() : Void {
 	public function close() : Void {
-		_close(p);
+		NativeProcess.process_close(p);
 	}
 	}
 
 
 	public function kill() : Void {
 	public function kill() : Void {
 		throw "Not implemented";
 		throw "Not implemented";
 	}
 	}
 
 
-	static var _run = cpp.Lib.load("std","process_run",2);
-	static var _exit = cpp.Lib.load("std","process_exit",1);
-	static var _pid = cpp.Lib.load("std","process_pid",1);
-	static var _close = cpp.Lib.loadLazy("std","process_close",1);
-
 }
 }

+ 7 - 10
std/cpp/_std/sys/net/Host.hx

@@ -21,6 +21,8 @@
  */
  */
 package sys.net;
 package sys.net;
 
 
+import cpp.NativeSocket;
+
 @:coreApi
 @:coreApi
 class Host {
 class Host {
 
 
@@ -30,28 +32,23 @@ class Host {
 
 
 	public function new( name : String ) : Void {
 	public function new( name : String ) : Void {
 		host = name;
 		host = name;
-		ip = host_resolve(name);
+		ip = NativeSocket.host_resolve(name);
 	}
 	}
 
 
 	public function toString() : String {
 	public function toString() : String {
-		return new String(host_to_string(ip));
+		return NativeSocket.host_to_string(ip);
 	}
 	}
 
 
 	public function reverse() : String {
 	public function reverse() : String {
-		return new String(host_reverse(ip));
+		return NativeSocket.host_reverse(ip);
 	}
 	}
 
 
 	public static function localhost() : String {
 	public static function localhost() : String {
-		return new String(host_local());
+		return NativeSocket.host_local();
 	}
 	}
 
 
 	static function __init__() : Void {
 	static function __init__() : Void {
-		cpp.Lib.load("std","socket_init",0)();
+		NativeSocket.socket_init();
 	}
 	}
 
 
-	private static var host_resolve = cpp.Lib.load("std","host_resolve",1);
-	private static var host_reverse = cpp.Lib.load("std","host_reverse",1);
-	private static var host_to_string = cpp.Lib.load("std","host_to_string",1);
-	private static var host_local = cpp.Lib.load("std","host_local",0);
-
 }
 }

+ 24 - 47
std/cpp/_std/sys/net/Socket.hx

@@ -22,6 +22,7 @@
 package sys.net;
 package sys.net;
 
 
 import haxe.io.Error;
 import haxe.io.Error;
+import cpp.NativeSocket;
 
 
 private class SocketInput extends haxe.io.Input {
 private class SocketInput extends haxe.io.Input {
 
 
@@ -33,7 +34,7 @@ private class SocketInput extends haxe.io.Input {
 
 
 	public override function readByte() {
 	public override function readByte() {
 		return try {
 		return try {
-			socket_recv_char(__s);
+			NativeSocket.socket_recv_char(__s);
 		} catch( e : Dynamic ) {
 		} catch( e : Dynamic ) {
 			if( e == "Blocking" )
 			if( e == "Blocking" )
 				throw Blocked;
 				throw Blocked;
@@ -49,7 +50,7 @@ private class SocketInput extends haxe.io.Input {
 		if (__s==null)
 		if (__s==null)
 			throw "Invalid handle";
 			throw "Invalid handle";
 		try {
 		try {
-			r = socket_recv(__s,buf.getData(),pos,len);
+			r = NativeSocket.socket_recv(__s,buf.getData(),pos,len);
 		} catch( e : Dynamic ) {
 		} catch( e : Dynamic ) {
 			if( e == "Blocking" )
 			if( e == "Blocking" )
 				throw Blocked;
 				throw Blocked;
@@ -63,13 +64,9 @@ private class SocketInput extends haxe.io.Input {
 
 
 	public override function close() {
 	public override function close() {
 		super.close();
 		super.close();
-		if( __s != null ) socket_close(__s);
+		if( __s != null ) NativeSocket.socket_close(__s);
 	}
 	}
 
 
-	private static var socket_recv = cpp.Lib.load("std","socket_recv",4);
-	private static var socket_recv_char = cpp.Lib.load("std","socket_recv_char",1);
-	private static var socket_close = cpp.Lib.load("std","socket_close",1);
-
 }
 }
 
 
 private class SocketOutput extends haxe.io.Output {
 private class SocketOutput extends haxe.io.Output {
@@ -84,7 +81,7 @@ private class SocketOutput extends haxe.io.Output {
 		if (__s==null)
 		if (__s==null)
 			throw "Invalid handle";
 			throw "Invalid handle";
 		try {
 		try {
-			socket_send_char(__s, c);
+			NativeSocket.socket_send_char(__s, c);
 		} catch( e : Dynamic ) {
 		} catch( e : Dynamic ) {
 			if( e == "Blocking" )
 			if( e == "Blocking" )
 				throw Blocked;
 				throw Blocked;
@@ -95,7 +92,7 @@ private class SocketOutput extends haxe.io.Output {
 
 
 	public override function writeBytes( buf : haxe.io.Bytes, pos : Int, len : Int) : Int {
 	public override function writeBytes( buf : haxe.io.Bytes, pos : Int, len : Int) : Int {
 		return try {
 		return try {
-			socket_send(__s, buf.getData(), pos, len);
+			NativeSocket.socket_send(__s, buf.getData(), pos, len);
 		} catch( e : Dynamic ) {
 		} catch( e : Dynamic ) {
 			if( e == "Blocking" )
 			if( e == "Blocking" )
 				throw Blocked;
 				throw Blocked;
@@ -108,13 +105,9 @@ private class SocketOutput extends haxe.io.Output {
 
 
 	public override function close() {
 	public override function close() {
 		super.close();
 		super.close();
-		if( __s != null ) socket_close(__s);
+		if( __s != null ) NativeSocket.socket_close(__s);
 	}
 	}
 
 
-	private static var socket_close = cpp.Lib.load("std","socket_close",1);
-	private static var socket_send_char = cpp.Lib.load("std","socket_send_char",2);
-	private static var socket_send = cpp.Lib.load("std","socket_send",4);
-
 }
 }
 
 
 
 
@@ -127,13 +120,13 @@ class Socket {
 	public var custom : Dynamic;
 	public var custom : Dynamic;
 
 
 	public function new() : Void {
 	public function new() : Void {
-		__s = socket_new(false);
+		__s = NativeSocket.socket_new(false);
 		input = new SocketInput(__s);
 		input = new SocketInput(__s);
 		output = new SocketOutput(__s);
 		output = new SocketOutput(__s);
 	}
 	}
 
 
 	public function close() : Void {
 	public function close() : Void {
-		socket_close(__s);
+		NativeSocket.socket_close(__s);
 		untyped {
 		untyped {
 			var input : SocketInput = cast input;
 			var input : SocketInput = cast input;
 			var output : SocketOutput = cast output;
 			var output : SocketOutput = cast output;
@@ -145,20 +138,20 @@ class Socket {
 	}
 	}
 
 
 	public function read() : String {
 	public function read() : String {
-		var bytes:haxe.io.BytesData = socket_read(__s);
+		var bytes:haxe.io.BytesData = NativeSocket.socket_read(__s);
 		if (bytes==null) return "";
 		if (bytes==null) return "";
 		return bytes.toString();
 		return bytes.toString();
 	}
 	}
 
 
 	public function write( content : String ) : Void {
 	public function write( content : String ) : Void {
-		socket_write(__s, haxe.io.Bytes.ofString(content).getData() );
+		NativeSocket.socket_write(__s, haxe.io.Bytes.ofString(content).getData() );
 	}
 	}
 
 
 	public function connect(host : Host, port : Int) : Void {
 	public function connect(host : Host, port : Int) : Void {
 		try {
 		try {
-			socket_connect(__s, host.ip, port);
+			NativeSocket.socket_connect(__s, host.ip, port);
 		} catch( s : String ) {
 		} catch( s : String ) {
-			if( s == "std@socket_connect" )
+			if( s == "Invalid socket handle" )
 				throw "Failed to connect on "+host.toString()+":"+port;
 				throw "Failed to connect on "+host.toString()+":"+port;
 			else if (s == "Blocking") {
 			else if (s == "Blocking") {
 				// Do nothing, this is not a real error, it simply indicates
 				// Do nothing, this is not a real error, it simply indicates
@@ -170,19 +163,19 @@ class Socket {
 	}
 	}
 
 
 	public function listen(connections : Int) : Void {
 	public function listen(connections : Int) : Void {
-		socket_listen(__s, connections);
+		NativeSocket.socket_listen(__s, connections);
 	}
 	}
 
 
 	public function shutdown( read : Bool, write : Bool ) : Void {
 	public function shutdown( read : Bool, write : Bool ) : Void {
-		socket_shutdown(__s,read,write);
+		NativeSocket.socket_shutdown(__s,read,write);
 	}
 	}
 
 
 	public function bind(host : Host, port : Int) : Void {
 	public function bind(host : Host, port : Int) : Void {
-		socket_bind(__s, host.ip, port);
+		NativeSocket.socket_bind(__s, host.ip, port);
 	}
 	}
 
 
 	public function accept() : Socket {
 	public function accept() : Socket {
-		var c = socket_accept(__s);
+		var c = NativeSocket.socket_accept(__s);
 		var s = Type.createEmptyInstance(Socket);
 		var s = Type.createEmptyInstance(Socket);
 		s.__s = c;
 		s.__s = c;
 		s.input = new SocketInput(c);
 		s.input = new SocketInput(c);
@@ -191,7 +184,7 @@ class Socket {
 	}
 	}
 
 
 	public function peer() : { host : Host, port : Int } {
 	public function peer() : { host : Host, port : Int } {
-		var a : Dynamic = socket_peer(__s);
+		var a : Dynamic = NativeSocket.socket_peer(__s);
 		if (a == null) {
 		if (a == null) {
 			return null;
 			return null;
 		}
 		}
@@ -201,7 +194,7 @@ class Socket {
 	}
 	}
 
 
 	public function host() : { host : Host, port : Int } {
 	public function host() : { host : Host, port : Int } {
-		var a : Dynamic = socket_host(__s);
+		var a : Dynamic = NativeSocket.socket_host(__s);
 		if (a == null) {
 		if (a == null) {
 			return null;
 			return null;
 		}
 		}
@@ -211,7 +204,7 @@ class Socket {
 	}
 	}
 
 
 	public function setTimeout( timeout : Float ) : Void {
 	public function setTimeout( timeout : Float ) : Void {
-		socket_set_timeout(__s, timeout);
+		NativeSocket.socket_set_timeout(__s, timeout);
 	}
 	}
 
 
 	public function waitForRead() : Void {
 	public function waitForRead() : Void {
@@ -219,38 +212,22 @@ class Socket {
 	}
 	}
 
 
 	public function setBlocking( b : Bool ) : Void {
 	public function setBlocking( b : Bool ) : Void {
-		socket_set_blocking(__s,b);
+		NativeSocket.socket_set_blocking(__s,b);
 	}
 	}
 
 
 	public function setFastSend( b : Bool ) : Void {
 	public function setFastSend( b : Bool ) : Void {
-		socket_set_fast_send(__s,b);
+		NativeSocket.socket_set_fast_send(__s,b);
 	}
 	}
 
 
 	public static function select(read : Array<Socket>, write : Array<Socket>, others : Array<Socket>, ?timeout : Float ) : {read: Array<Socket>,write: Array<Socket>,others: Array<Socket>} {
 	public static function select(read : Array<Socket>, write : Array<Socket>, others : Array<Socket>, ?timeout : Float ) : {read: Array<Socket>,write: Array<Socket>,others: Array<Socket>} {
-		var neko_array = socket_select(read,write,others, timeout);
+		var neko_array = NativeSocket.socket_select(read,write,others, timeout);
 		if (neko_array==null)
 		if (neko_array==null)
 			throw "Select error";
 			throw "Select error";
-		return {
+		return @:fixed {
 			read: neko_array[0],
 			read: neko_array[0],
 			write: neko_array[1],
 			write: neko_array[1],
 			others: neko_array[2]
 			others: neko_array[2]
 		};
 		};
 	}
 	}
 
 
-	private static var socket_new = cpp.Lib.load("std","socket_new",1);
-	private static var socket_close = cpp.Lib.load("std","socket_close",1);
-	private static var socket_write = cpp.Lib.load("std","socket_write",2);
-	private static var socket_read = cpp.Lib.load("std","socket_read",1);
-	private static var socket_connect = cpp.Lib.load("std","socket_connect",3);
-	private static var socket_listen = cpp.Lib.load("std","socket_listen",2);
-	private static var socket_select = cpp.Lib.load("std","socket_select",4);
-	private static var socket_bind = cpp.Lib.load("std","socket_bind",3);
-	private static var socket_accept = cpp.Lib.load("std","socket_accept",1);
-	private static var socket_peer = cpp.Lib.load("std","socket_peer",1);
-	private static var socket_host = cpp.Lib.load("std","socket_host",1);
-	private static var socket_set_timeout = cpp.Lib.load("std","socket_set_timeout",2);
-	private static var socket_shutdown = cpp.Lib.load("std","socket_shutdown",3);
-	private static var socket_set_blocking = cpp.Lib.load("std","socket_set_blocking",2);
-	private static var socket_set_fast_send = cpp.Lib.loadLazy("std","socket_set_fast_send",2);
-
 }
 }

+ 4 - 6
std/cpp/_std/sys/net/UdpSocket.hx

@@ -21,18 +21,19 @@
  */
  */
 package sys.net;
 package sys.net;
 import haxe.io.Error;
 import haxe.io.Error;
+import cpp.NativeSocket;
 
 
 @:coreApi
 @:coreApi
 class UdpSocket extends Socket {
 class UdpSocket extends Socket {
 
 
 	public function new() : Void {
 	public function new() : Void {
-		__s = Socket.socket_new(true);
+		__s = NativeSocket.socket_new(true);
 		super();
 		super();
 	}
 	}
 
 
 	public function sendTo( buf : haxe.io.Bytes, pos : Int, len : Int, addr : Address ) : Int {
 	public function sendTo( buf : haxe.io.Bytes, pos : Int, len : Int, addr : Address ) : Int {
 		return try {
 		return try {
-			socket_send_to(__s, buf.getData(), pos, len, addr);
+			NativeSocket.socket_send_to(__s, buf.getData(), pos, len, addr);
 		} catch( e : Dynamic ) {
 		} catch( e : Dynamic ) {
 			if( e == "Blocking" )
 			if( e == "Blocking" )
 				throw Blocked;
 				throw Blocked;
@@ -44,7 +45,7 @@ class UdpSocket extends Socket {
 	public function readFrom( buf : haxe.io.Bytes, pos : Int, len : Int, addr : Address ) : Int {
 	public function readFrom( buf : haxe.io.Bytes, pos : Int, len : Int, addr : Address ) : Int {
 		var r;
 		var r;
 		try {
 		try {
-			r = socket_recv_from(__s,buf.getData(),pos,len,addr);
+			r = NativeSocket.socket_recv_from(__s,buf.getData(),pos,len,addr);
 		} catch( e : Dynamic ) {
 		} catch( e : Dynamic ) {
 			if( e == "Blocking" )
 			if( e == "Blocking" )
 				throw Blocked;
 				throw Blocked;
@@ -56,7 +57,4 @@ class UdpSocket extends Socket {
 		return r;
 		return r;
 	}
 	}
 
 
-	static var socket_recv_from = cpp.Lib.loadLazy("std", "socket_recv_from", 5);
-	static var socket_send_to = cpp.Lib.loadLazy("std", "socket_send_to", 5);
-
 }
 }

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

@@ -62,6 +62,7 @@ class HostClasses
    "sys.db.Object",
    "sys.db.Object",
    "sys.db.Manager",
    "sys.db.Manager",
    "sys.db.Connection",
    "sys.db.Connection",
+   "sys.db.Object",
    "sys.FileSystem",
    "sys.FileSystem",
    "sys.io.File",
    "sys.io.File",
    "sys.io.FileInput",
    "sys.io.FileInput",
@@ -91,6 +92,7 @@ class HostClasses
    "haxe.Template",
    "haxe.Template",
    "haxe.Utf8",
    "haxe.Utf8",
    "haxe.Log",
    "haxe.Log",
+   "haxe.zip.Compress",
    "haxe.zip.Uncompress",
    "haxe.zip.Uncompress",
 
 
    "haxe.crypto.BaseCode",
    "haxe.crypto.BaseCode",
@@ -187,6 +189,11 @@ class HostClasses
       externs.set("haxe._Int32.Int32_Impl_",true);
       externs.set("haxe._Int32.Int32_Impl_",true);
       externs.set("haxe._Int32.___Int32",true);
       externs.set("haxe._Int32.___Int32",true);
       // Hidded in implementation classes
       // Hidded in implementation classes
+      externs.set("sys.db.RecordType",true);
+      externs.set("sys.db._Sqlite.SqliteConnection",true);
+      externs.set("sys.db._Sqlite.SqliteResultSet",true);
+      externs.set("sys.db._Mysql.MysqlConnection",true);
+      externs.set("sys.db._Mysql.MysqlResultSet",true);
       externs.set("haxe.ds.TreeNode",true);
       externs.set("haxe.ds.TreeNode",true);
       externs.set("haxe.xml.XmlParserException",true);
       externs.set("haxe.xml.XmlParserException",true);
       for(e in classes)
       for(e in classes)

+ 7 - 19
std/cpp/net/Poll.hx

@@ -21,46 +21,34 @@
  */
  */
 package cpp.net;
 package cpp.net;
 import sys.net.Socket;
 import sys.net.Socket;
+import cpp.NativeSocket;
 
 
 class Poll {
 class Poll {
 
 
 	var mPollHandle : Dynamic;
 	var mPollHandle : Dynamic;
-	public var readIndexes : Array<Dynamic>;
-	public var writeIndexes : Array<Dynamic>;
+	public var readIndexes : Array<Int>;
+	public var writeIndexes : Array<Int>;
 
 
 	public function new( n : Int ) {
 	public function new( n : Int ) {
-		mPollHandle = socket_poll_alloc(n);
+		mPollHandle = NativeSocket.socket_poll_alloc(n);
 		readIndexes = [];
 		readIndexes = [];
 		writeIndexes = [];
 		writeIndexes = [];
 	}
 	}
 
 
 	public function prepare( read : Array<Socket>, write : Array<Socket> ) {
 	public function prepare( read : Array<Socket>, write : Array<Socket> ) {
-		var k = socket_poll_prepare(mPollHandle,read,write);
+		var k = NativeSocket.socket_poll_prepare(mPollHandle,read,write);
 		readIndexes = k[0];
 		readIndexes = k[0];
 		writeIndexes = k[1];
 		writeIndexes = k[1];
 	}
 	}
 
 
 	public function events( ?t : Float ) {
 	public function events( ?t : Float ) {
 		if (t==null) t=-1.0;
 		if (t==null) t=-1.0;
-		socket_poll_events(mPollHandle,t);
+		NativeSocket.socket_poll_events(mPollHandle,t);
 	}
 	}
 
 
 	public function poll( a : Array<Socket>, ?t : Float ) : Array<Socket> {
 	public function poll( a : Array<Socket>, ?t : Float ) : Array<Socket> {
 		if (t==null) t=-1.0;
 		if (t==null) t=-1.0;
-		var read:Array<Dynamic> = socket_poll(a,mPollHandle,t);
-		// Convert to array of sockets...
-		var result = new Array<Socket>();
-		if (read!=null && read.length>0) {
-			result[read.length-1]=null;
-			for(i in 0...read.length)
-				result[i] = read[i];
-		}
-		return result;
+		return NativeSocket.socket_poll(a,mPollHandle,t);
 	}
 	}
 
 
-	static var socket_poll_alloc = cpp.Lib.load("std","socket_poll_alloc",1);
-	static var socket_poll = cpp.Lib.load("std","socket_poll",3);
-	static var socket_poll_prepare = cpp.Lib.loadLazy("std","socket_poll_prepare",3);
-	static var socket_poll_events = cpp.Lib.loadLazy("std","socket_poll_events",2);
-
 }
 }

+ 16 - 16
std/haxe/EnumTools.hx

@@ -34,7 +34,7 @@ extern class EnumTools {
 
 
 		If `e` has no package, the enum name is returned.
 		If `e` has no package, the enum name is returned.
 
 
-		If `e` is null, the result is unspecified.
+		If `e` is `null`, the result is unspecified.
 
 
 		The enum name does not include any type parameters.
 		The enum name does not include any type parameters.
 	**/
 	**/
@@ -46,7 +46,7 @@ extern class EnumTools {
 		Creates an instance of enum `e` by calling its constructor `constr` with
 		Creates an instance of enum `e` by calling its constructor `constr` with
 		arguments `params`.
 		arguments `params`.
 
 
-		If `e` or `constr` is null, or if enum `e` has no constructor named
+		If `e` or `constr` is `null`, or if enum `e` has no constructor named
 		`constr`, or if the number of elements in `params` does not match the
 		`constr`, or if the number of elements in `params` does not match the
 		expected number of constructor arguments, or if any argument has an
 		expected number of constructor arguments, or if any argument has an
 		invalid type, the result is unspecified.
 		invalid type, the result is unspecified.
@@ -62,7 +62,7 @@ extern class EnumTools {
 		The constructor indices are preserved from haxe syntax, so the first
 		The constructor indices are preserved from haxe syntax, so the first
 		declared is index 0, the next index 1 etc.
 		declared is index 0, the next index 1 etc.
 
 
-		If `e` or `index` is null, or if enum `e` has no constructor
+		If `e` or `index` is `null`, or if enum `e` has no constructor
 		corresponding to index `index`, or if the number of elements in `params`
 		corresponding to index `index`, or if the number of elements in `params`
 		does not match the expected number of constructor arguments, or if any
 		does not match the expected number of constructor arguments, or if any
 		argument has an invalid type, the result is unspecified.
 		argument has an invalid type, the result is unspecified.
@@ -82,7 +82,7 @@ extern class EnumTools {
 		argument constructors is returned, in the order of the constructor
 		argument constructors is returned, in the order of the constructor
 		declaration.
 		declaration.
 
 
-		If `e` is null, the result is unspecified.
+		If `e` is `null`, the result is unspecified.
 	**/
 	**/
 	static public inline function createAll<T>(e:Enum<T>):Array<T> {
 	static public inline function createAll<T>(e:Enum<T>):Array<T> {
 		return Type.allEnums(e);
 		return Type.allEnums(e);
@@ -94,7 +94,7 @@ extern class EnumTools {
 		The order of the constructor names in the returned Array is preserved
 		The order of the constructor names in the returned Array is preserved
 		from the original syntax.
 		from the original syntax.
 
 
-		If `c` is null, the result is unspecified.
+		If `c` is `null`, the result is unspecified.
 	**/
 	**/
 	static public inline function getConstructors<T>(e:Enum<T>):Array<String> {
 	static public inline function getConstructors<T>(e:Enum<T>):Array<String> {
 		return Type.getEnumConstructs(e);
 		return Type.getEnumConstructs(e);
@@ -107,9 +107,9 @@ extern class EnumValueTools {
 		Recursively compares two enum instances `a` and `b` by value.
 		Recursively compares two enum instances `a` and `b` by value.
 
 
 		Unlike `a == b`, this function performs a deep equality check on the
 		Unlike `a == b`, this function performs a deep equality check on the
-		arguments of the constructors, if exists.
+		arguments of the constructors (if there are any).
 
 
-		If `a` or `b` are null, the result is unspecified.
+		If `a` or `b` are `null`, the result is unspecified.
 	**/
 	**/
 	static public inline function equals<T:EnumValue>(a:T, b:T):Bool {
 	static public inline function equals<T:EnumValue>(a:T, b:T):Bool {
 		return Type.enumEq(a, b);
 		return Type.enumEq(a, b);
@@ -120,7 +120,7 @@ extern class EnumValueTools {
 
 
 		The result String does not contain any constructor arguments.
 		The result String does not contain any constructor arguments.
 
 
-		If `e` is null, the result is unspecified.
+		If `e` is `null`, the result is unspecified.
 	**/
 	**/
 	static public inline function getName(e:EnumValue):String {
 	static public inline function getName(e:EnumValue):String {
 		return Type.enumConstructor(e);
 		return Type.enumConstructor(e);
@@ -129,12 +129,12 @@ extern class EnumValueTools {
 	/**
 	/**
 		Returns a list of the constructor arguments of enum instance `e`.
 		Returns a list of the constructor arguments of enum instance `e`.
 
 
-		If `e` has no arguments, the result is [].
+		If `e` has no arguments, the result is `[]`.
 
 
 		Otherwise the result are the values that were used as arguments to `e`,
 		Otherwise the result are the values that were used as arguments to `e`,
 		in the order of their declaration.
 		in the order of their declaration.
 
 
-		If `e` is null, the result is unspecified.
+		If `e` is `null`, the result is unspecified.
 	**/
 	**/
 	static public inline function getParameters(e:EnumValue):Array<Dynamic> {
 	static public inline function getParameters(e:EnumValue):Array<Dynamic> {
 		return Type.enumParameters(e);
 		return Type.enumParameters(e);
@@ -146,19 +146,19 @@ extern class EnumValueTools {
 		This corresponds to the original syntactic position of `e`. The index of
 		This corresponds to the original syntactic position of `e`. The index of
 		the first declared constructor is 0, the next one is 1 etc.
 		the first declared constructor is 0, the next one is 1 etc.
 
 
-		If `e` is null, the result is unspecified.
+		If `e` is `null`, the result is unspecified.
 	**/
 	**/
 	static public inline function getIndex(e:EnumValue):Int {
 	static public inline function getIndex(e:EnumValue):Int {
 		return Type.enumIndex(e);
 		return Type.enumIndex(e);
 	}
 	}
 
 
 	/**
 	/**
-		Matches enum instance `e` against pattern `pattern`, returning true if
-		matching succeeded and false otherwise.
+		Matches enum instance `e` against pattern `pattern`, returning `true` if
+		matching succeeded and `false` otherwise.
 
 
 		Example usage:
 		Example usage:
 
 
-		```
+		```haxe
 		if (e.match(pattern)) {
 		if (e.match(pattern)) {
 			// codeIfTrue
 			// codeIfTrue
 		} else {
 		} else {
@@ -168,7 +168,7 @@ extern class EnumValueTools {
 
 
 		This is equivalent to the following code:
 		This is equivalent to the following code:
 
 
-		```
+		```haxe
 		switch (e) {
 		switch (e) {
 			case pattern:
 			case pattern:
 				// codeIfTrue
 				// codeIfTrue
@@ -183,4 +183,4 @@ extern class EnumValueTools {
 	static public function match(e:EnumValue, pattern:Dynamic):Bool {
 	static public function match(e:EnumValue, pattern:Dynamic):Bool {
 		return false;
 		return false;
 	}
 	}
-}
+}

+ 9 - 3
std/haxe/Json.hx

@@ -22,9 +22,11 @@
 package haxe;
 package haxe;
 
 
 /**
 /**
-	Crossplatform JSON API : it will automatically use the optimized native API if available.
-	Use -D haxeJSON to force usage of the Haxe implementation even if a native API is found : this will provide
-	extra encoding features such as enums (replaced by their index) and StringMaps.
+	Crossplatform JSON API: it will automatically use the optimized native API if available.
+	Use `-D haxeJSON` to force usage of the Haxe implementation even if a native API is found: 
+	this will provide extra encoding features such as enums (replaced by their index) and StringMaps.
+	=
+	@see http://haxe.org/manual/std-Json.html
 **/
 **/
 class Json {
 class Json {
 
 
@@ -35,6 +37,8 @@ class Json {
 		are parsed into Array<Dynamic>.
 		are parsed into Array<Dynamic>.
 
 
 		If given `text` is not valid JSON, an exception will be thrown.
 		If given `text` is not valid JSON, an exception will be thrown.
+
+		@see http://haxe.org/manual/std-Json-parsing.html
 	**/
 	**/
 	public static inline function parse( text : String ) : Dynamic {
 	public static inline function parse( text : String ) : Dynamic {
 		return haxe.format.JsonParser.parse(text);
 		return haxe.format.JsonParser.parse(text);
@@ -49,6 +53,8 @@ class Json {
 		
 		
 		If `space` is given and is not null, the result will be pretty-printed.
 		If `space` is given and is not null, the result will be pretty-printed.
 		Successive levels will be indented by this string.
 		Successive levels will be indented by this string.
+
+		@see http://haxe.org/manual/std-Json-encoding.html
 	**/
 	**/
 	public static inline function stringify( value : Dynamic, ?replacer:Dynamic -> Dynamic -> Dynamic, ?space : String ) : String {
 	public static inline function stringify( value : Dynamic, ?replacer:Dynamic -> Dynamic -> Dynamic, ?space : String ) : String {
 		return haxe.format.JsonPrinter.print(value, replacer, space);
 		return haxe.format.JsonPrinter.print(value, replacer, space);

+ 6 - 6
std/haxe/Serializer.hx

@@ -22,22 +22,22 @@
 package haxe;
 package haxe;
 
 
 /**
 /**
-	The Serializer class can be used to encode values and objects into a String,
-	from which the Unserializer class can recreate the original representation.
+	The Serializer class can be used to encode values and objects into a `String`,
+	from which the `Unserializer` class can recreate the original representation.
 
 
 	This class can be used in two ways:
 	This class can be used in two ways:
 
 
-	- create a new Serializer() instance, call its serialize() method with
+	- create a `new Serializer()` instance, call its serialize() method with
 		any argument and finally retrieve the String representation from
 		any argument and finally retrieve the String representation from
-		toString()
-	- call Serializer.run() to obtain the serialized representation of a
+		`toString()`
+	- call `Serializer.run()` to obtain the serialized representation of a
 		single argument
 		single argument
 
 
 	Serialization is guaranteed to work for all haxe-defined classes, but may
 	Serialization is guaranteed to work for all haxe-defined classes, but may
 	or may not work for instances of external/native classes.
 	or may not work for instances of external/native classes.
 
 
 	The specification of the serialization format can be found here:
 	The specification of the serialization format can be found here:
-	`http://haxe.org/manual/serialization/format`
+	<http://haxe.org/manual/serialization/format>
 **/
 **/
 class Serializer {
 class Serializer {
 
 

+ 1 - 1
std/haxe/Template.hx

@@ -47,7 +47,7 @@ private typedef ExprToken = {
 	String, and to have some basic logic.
 	String, and to have some basic logic.
 
 
 	A complete documentation of the supported syntax is available at:
 	A complete documentation of the supported syntax is available at:
-	<a href="http://haxe.org/manual/std-template.html">http://haxe.org/manual/std-template.html</a>
+	<http://haxe.org/manual/std-template.html>
 **/
 **/
 class Template {
 class Template {
 
 

+ 10 - 7
std/haxe/Unserializer.hx

@@ -28,16 +28,19 @@ typedef TypeResolver = {
 }
 }
 
 
 /**
 /**
-	The Unserializer class is the complement to the Serializer class. It parses
-	a serialization String and creates objects from the contained data.
+	The `Unserializer` class is the complement to the `Serializer` class. It parses
+	a serialization `String` and creates objects from the contained data.
 
 
 	This class can be used in two ways:
 	This class can be used in two ways:
 
 
-	- create a new Unserializer() instance with a given serialization
-		String, then call its unserialize() method until all values are
+	- create a `new Unserializer()` instance with a given serialization
+		String, then call its `unserialize()` method until all values are
 		extracted
 		extracted
-	- call Unserializer.run() to unserialize a single value from a given
+	- call `Unserializer.run()`  to unserialize a single value from a given
 		String
 		String
+
+	The specification of the serialization format can be found here:
+	<http://haxe.org/manual/serialization/format>
 **/
 **/
 class Unserializer {
 class Unserializer {
 
 
@@ -119,7 +122,7 @@ class Unserializer {
 		If `r` is null, a special resolver is used which returns null for all
 		If `r` is null, a special resolver is used which returns null for all
 		input values.
 		input values.
 
 
-		See DEFAULT_RESOLVER for more information on type resolvers.
+		See `DEFAULT_RESOLVER` for more information on type resolvers.
 	**/
 	**/
  	public function setResolver( r ) {
  	public function setResolver( r ) {
 		if( r == null )
 		if( r == null )
@@ -131,7 +134,7 @@ class Unserializer {
 	/**
 	/**
 		Gets the type resolver of `this` Unserializer instance.
 		Gets the type resolver of `this` Unserializer instance.
 
 
-		See DEFAULT_RESOLVER for more information on type resolvers.
+		See `DEFAULT_RESOLVER` for more information on type resolvers.
 	**/
 	**/
  	public function getResolver() {
  	public function getResolver() {
 		return resolver;
 		return resolver;

+ 2 - 0
std/haxe/ds/GenericStack.hx

@@ -53,6 +53,8 @@ private class GenericStackIterator<T> extends cpp.FastIterator<T> {
 
 
 	The generated name is an implementation detail and should not be relied
 	The generated name is an implementation detail and should not be relied
 	upon.
 	upon.
+
+	@see http://haxe.org/manual/std-GenericStack.html
 **/
 **/
 #if (flash || cpp)
 #if (flash || cpp)
 @:generic
 @:generic

+ 34 - 0
std/haxe/ds/HashMap.hx

@@ -21,27 +21,61 @@
  */
  */
 package haxe.ds;
 package haxe.ds;
 
 
+/**
+	HashMap allows mapping of hashable objects to arbitrary values.
+
+	See `Map` for documentation details.
+
+	@see http://haxe.org/manual/std-Map.html
+**/
 abstract HashMap<K:{ function hashCode():Int; }, V >(HashMapData<K,V>) {
 abstract HashMap<K:{ function hashCode():Int; }, V >(HashMapData<K,V>) {
+	/**
+		Creates a new HashMap.
+	**/
 	public inline function new() {
 	public inline function new() {
 		this = new HashMapData();
 		this = new HashMapData();
 	}
 	}
+
+	/**
+		See `Map.set`
+	**/
 	public inline function set(k:K, v:V) {
 	public inline function set(k:K, v:V) {
 		this.keys.set(k.hashCode(), k);
 		this.keys.set(k.hashCode(), k);
 		this.values.set(k.hashCode(), v);
 		this.values.set(k.hashCode(), v);
 	}
 	}
+
+	/**
+		See `Map.get`
+	**/
 	public inline function get(k:K) {
 	public inline function get(k:K) {
 		return this.values.get(k.hashCode());
 		return this.values.get(k.hashCode());
 	}
 	}
+
+	/**
+		See `Map.exists`
+	**/
 	public inline function exists(k:K) {
 	public inline function exists(k:K) {
 		return this.values.exists(k.hashCode());
 		return this.values.exists(k.hashCode());
 	}
 	}
+
+	/**
+		See `Map.remove`
+	**/
 	public inline function remove(k:K) {
 	public inline function remove(k:K) {
 		this.values.remove(k.hashCode());
 		this.values.remove(k.hashCode());
 		return this.keys.remove(k.hashCode());
 		return this.keys.remove(k.hashCode());
 	}
 	}
+
+	/**
+		See `Map.keys`
+	**/
 	public inline function keys() {
 	public inline function keys() {
 		return this.keys.iterator();
 		return this.keys.iterator();
 	}
 	}
+
+	/**
+		See `Map.iterator`
+	**/
 	public inline function iterator() {
 	public inline function iterator() {
 		return this.values.iterator();
 		return this.values.iterator();
 	}
 	}

+ 2 - 0
std/haxe/ds/IntMap.hx

@@ -25,6 +25,8 @@ package haxe.ds;
 	IntMap allows mapping of Int keys to arbitrary values.
 	IntMap allows mapping of Int keys to arbitrary values.
 
 
 	See `Map` for documentation details.
 	See `Map` for documentation details.
+
+	@see http://haxe.org/manual/std-Map.html
 **/
 **/
 extern class IntMap<T> implements haxe.Constraints.IMap<Int,T> {
 extern class IntMap<T> implements haxe.Constraints.IMap<Int,T> {
 
 

+ 1 - 1
std/haxe/ds/ListSort.hx

@@ -24,7 +24,7 @@ package haxe.ds;
 
 
 /**
 /**
 	ListSort provides a stable implementation of merge sort through its `sort`
 	ListSort provides a stable implementation of merge sort through its `sort`
-	method. It has a O(N.log(N)) complexity and does not require additional memory allocation
+	method. It has a O(N.log(N)) complexity and does not require additional memory allocation.
 **/
 **/
 class ListSort {
 class ListSort {
 
 

+ 2 - 0
std/haxe/ds/ObjectMap.hx

@@ -29,6 +29,8 @@ package haxe.ds;
 	to `haxe.ds.WeakMap` for a weak reference version.
 	to `haxe.ds.WeakMap` for a weak reference version.
 
 
 	See `Map` for documentation details.
 	See `Map` for documentation details.
+
+	@see http://haxe.org/manual/std-Map.html
 **/
 **/
 extern class ObjectMap < K: { }, V > implements haxe.Constraints.IMap<K,V> {
 extern class ObjectMap < K: { }, V > implements haxe.Constraints.IMap<K,V> {
 
 

+ 2 - 0
std/haxe/ds/Option.hx

@@ -25,6 +25,8 @@ package haxe.ds;
 /**
 /**
 	An Option is a wrapper type which can either have a value (Some) or not a
 	An Option is a wrapper type which can either have a value (Some) or not a
 	value (None).
 	value (None).
+
+	@see http://haxe.org/manual/std-Option.html
 **/
 **/
 enum Option<T> {
 enum Option<T> {
 	Some(v:T);
 	Some(v:T);

+ 2 - 0
std/haxe/ds/StringMap.hx

@@ -26,6 +26,8 @@ package haxe.ds;
 	StringMap allows mapping of String keys to arbitrary values.
 	StringMap allows mapping of String keys to arbitrary values.
 
 
 	See `Map` for documentation details.
 	See `Map` for documentation details.
+
+	@see http://haxe.org/manual/std-Map.html
 **/
 **/
 extern class StringMap<T> implements haxe.Constraints.IMap<String,T> {
 extern class StringMap<T> implements haxe.Constraints.IMap<String,T> {
 
 

+ 2 - 0
std/haxe/ds/Vector.hx

@@ -40,6 +40,8 @@ private typedef VectorData<T> = #if flash10
 /**
 /**
 	A Vector is a storage of fixed size. It can be faster than Array on some
 	A Vector is a storage of fixed size. It can be faster than Array on some
 	targets, and is never slower.
 	targets, and is never slower.
+
+	@see http://haxe.org/manual/std-vector.html
 **/
 **/
 abstract Vector<T>(VectorData<T>) {
 abstract Vector<T>(VectorData<T>) {
 	/**
 	/**

+ 2 - 0
std/haxe/ds/WeakMap.hx

@@ -28,6 +28,8 @@ package haxe.ds;
 	The keys are considered to be weak references on static targets.
 	The keys are considered to be weak references on static targets.
 
 
 	See `Map` for documentation details.
 	See `Map` for documentation details.
+
+	@see http://haxe.org/manual/std-Map.html
 **/
 **/
 class WeakMap<K: { },V> implements haxe.Constraints.IMap<K,V> {
 class WeakMap<K: { },V> implements haxe.Constraints.IMap<K,V> {
 
 

+ 3 - 1
std/haxe/format/JsonParser.hx

@@ -26,6 +26,8 @@ package haxe.format;
 
 
 	This class is used by `haxe.Json` when native JSON implementation
 	This class is used by `haxe.Json` when native JSON implementation
 	is not available.
 	is not available.
+
+	@see http://haxe.org/manual/std-Json-parsing.html
 **/
 **/
 class JsonParser {
 class JsonParser {
 
 
@@ -33,7 +35,7 @@ class JsonParser {
 		Parses given JSON-encoded `str` and returns the resulting object.
 		Parses given JSON-encoded `str` and returns the resulting object.
 
 
 		JSON objects are parsed into anonymous structures and JSON arrays
 		JSON objects are parsed into anonymous structures and JSON arrays
-		are parsed into Array<Dynamic>.
+		are parsed into `Array<Dynamic>`.
 
 
 		If given `str` is not valid JSON, an exception will be thrown.
 		If given `str` is not valid JSON, an exception will be thrown.
 
 

+ 2 - 0
std/haxe/format/JsonPrinter.hx

@@ -26,6 +26,8 @@ package haxe.format;
 
 
 	This class is used by `haxe.Json` when native JSON implementation
 	This class is used by `haxe.Json` when native JSON implementation
 	is not available.
 	is not available.
+
+	@see http://haxe.org/manual/std-Json-encoding.html
 **/
 **/
 class JsonPrinter {
 class JsonPrinter {
 
 

+ 0 - 3
std/haxe/io/Input.hx

@@ -312,9 +312,6 @@ class Input {
 	static function __init__() untyped {
 	static function __init__() untyped {
 		Input.prototype.bigEndian = false;
 		Input.prototype.bigEndian = false;
 	}
 	}
-#elseif cpp
-	static var _float_of_bytes = cpp.Lib.load("std","float_of_bytes",2);
-	static var _double_of_bytes = cpp.Lib.load("std","double_of_bytes",2);
 #end
 #end
 
 
 #if (flash || js || python)
 #if (flash || js || python)

+ 5 - 8
std/haxe/io/Path.hx

@@ -208,11 +208,9 @@ class Path {
 		If `path` is null, the result is unspecified.
 		If `path` is null, the result is unspecified.
 	**/
 	**/
 	public static function normalize(path : String) : String {
 	public static function normalize(path : String) : String {
-		var slash = '/';
-		path = path.split("\\").join("/");
-		if( path == null || path == slash ) {
-			return slash;
-		}
+		var slash = "/";
+		path = path.split("\\").join(slash);
+		if (path == slash) return slash;
 
 
 		var target = [];
 		var target = [];
 
 
@@ -235,7 +233,7 @@ class Path {
 				case ":".code:
 				case ":".code:
 					acc.add(":");
 					acc.add(":");
 					colon = true;
 					colon = true;
-				case "/".code if (colon == false):
+				case "/".code if (!colon):
 					slashes = true;
 					slashes = true;
 				case i:
 				case i:
 					colon = false;
 					colon = false;
@@ -246,8 +244,7 @@ class Path {
 					acc.add(String.fromCharCode(i));
 					acc.add(String.fromCharCode(i));
 			}
 			}
 		}
 		}
-		var result = acc.toString();
-		return result;
+		return acc.toString();
 	}
 	}
 
 
 	/**
 	/**

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

@@ -68,7 +68,7 @@ class HttpConnection implements Connection implements Dynamic<Connection> {
 		return new haxe.Unserializer(data).unserialize();
 		return new haxe.Unserializer(data).unserialize();
 	}
 	}
 
 
-	#if (js || neko || php)
+	#if !flash
 
 
 	public static function urlConnect( url : String ) {
 	public static function urlConnect( url : String ) {
 		return new HttpConnection(url,[]);
 		return new HttpConnection(url,[]);

+ 1 - 0
std/hl/types/Api.hx

@@ -2,6 +2,7 @@ package hl.types;
 
 
 extern class Api {
 extern class Api {
 
 
+	static inline function rethrow( v : Dynamic ) : Void { untyped $rethrow(v); }
 	@:hlNative("std","obj_get_field") static function getField( obj : Dynamic, hash : Int ) : Dynamic;
 	@:hlNative("std","obj_get_field") static function getField( obj : Dynamic, hash : Int ) : Dynamic;
 	@:hlNative("std","obj_set_field") static function setField( obj : Dynamic, hash : Int, value : Dynamic ) : Void;
 	@:hlNative("std","obj_set_field") static function setField( obj : Dynamic, hash : Int, value : Dynamic ) : Void;
 	@:hlNative("std","obj_has_field") static function hasField( obj : Dynamic, hash : Int ) : Bool;
 	@:hlNative("std","obj_has_field") static function hasField( obj : Dynamic, hash : Int ) : Bool;

+ 1 - 1
std/js/Boot.hx

@@ -191,7 +191,7 @@ class Boot {
 			return false;
 			return false;
 		switch( cl ) {
 		switch( cl ) {
 		case Int:
 		case Int:
-			return (untyped __js__("(o|0) === o"));
+			return (untyped __js__("typeof"))(o) == "number" && untyped __js__("(o|0) === o");
 		case Float:
 		case Float:
 			return (untyped __js__("typeof"))(o) == "number";
 			return (untyped __js__("typeof"))(o) == "number";
 		case Bool:
 		case Bool:

+ 1 - 1
std/js/Promise.hx

@@ -40,7 +40,7 @@ extern class Promise<T>
 	/** @throws DOMError */
 	/** @throws DOMError */
 	function new( init : (T -> Void) -> (Dynamic -> Void) -> Void ) : Void;
 	function new( init : (T -> Void) -> (Dynamic -> Void) -> Void ) : Void;
 
 
-	function then<TOut>( ?fulfillCallback : PromiseCallback<T, TOut>, ?rejectCallback : EitherType<Dynamic -> Void, PromiseCallback<Dynamic, TOut>> ) : Promise<TOut>;
+	function then<TOut>( fulfillCallback : Null<PromiseCallback<T, TOut>>, ?rejectCallback : EitherType<Dynamic -> Void, PromiseCallback<Dynamic, TOut>> ) : Promise<TOut>;
 
 
 	@:native("catch")
 	@:native("catch")
 	function catchError<TOut>( rejectCallback : EitherType<Dynamic -> Void, PromiseCallback<Dynamic, TOut>> ) : Promise<TOut>;
 	function catchError<TOut>( rejectCallback : EitherType<Dynamic -> Void, PromiseCallback<Dynamic, TOut>> ) : Promise<TOut>;

+ 1 - 1
std/js/_std/Array.hx

@@ -45,7 +45,7 @@ extern class Array<T> {
 		return @:privateAccess HxOverrides.remove(this,x);
 		return @:privateAccess HxOverrides.remove(this,x);
 	}
 	}
 
 
-#if js_es5
+#if (js_es >= 5)
 	function indexOf( x : T, ?fromIndex:Int ) : Int;
 	function indexOf( x : T, ?fromIndex:Int ) : Int;
 	function lastIndexOf( x : T, ?fromIndex:Int ) : Int;
 	function lastIndexOf( x : T, ?fromIndex:Int ) : Int;
 
 

Some files were not shown because too many files changed in this diff