Explorar o código

Merge remote-tracking branch 'origin/development' into mono-fix

frabbit %!s(int64=7) %!d(string=hai) anos
pai
achega
227f35ee2a
Modificáronse 100 ficheiros con 3090 adicións e 4941 borrados
  1. 6 0
      .gitignore
  2. 75 112
      .travis.yml
  3. 13 0
      .vscode/settings.json
  4. 1 1
      CONTRIBUTING.md
  5. 73 31
      Makefile
  6. 31 0
      Makefile.win
  7. 11 11
      README.md
  8. 28 18
      appveyor.yml
  9. 114 4
      extra/CHANGES.txt
  10. 21 15
      extra/ImportAll.hx
  11. 0 6
      extra/all.hxml
  12. 16 0
      extra/build-haxesetup.xml
  13. 1 1
      extra/choco/haxe.nuspec
  14. 60 0
      extra/doc.hxml
  15. 1 1
      extra/haxelib_src
  16. BIN=BIN
      extra/mac-installer/installer-structure.pkg
  17. 13 0
      extra/mac-installer/scripts/haxe-postinstall.sh
  18. 8 0
      extra/mac-installer/scripts/haxe-preinstall.sh
  19. 18 0
      extra/mac-installer/scripts/install.sh
  20. 19 0
      extra/mac-installer/scripts/neko-postinstall.sh
  21. 3 0
      extra/mac-installer/scripts/neko-preinstall.sh
  22. 10 24
      extra/release-checklist.txt
  23. 1 1
      libs
  24. 24 0
      opam
  25. 10 317
      src/codegen/codegen.ml
  26. 13 12
      src/codegen/dotnet.ml
  27. 0 0
      src/codegen/gencommon/abstractImplementationFix.ml
  28. 0 0
      src/codegen/gencommon/arrayDeclSynf.ml
  29. 3 3
      src/codegen/gencommon/castDetect.ml
  30. 0 0
      src/codegen/gencommon/classInstance.ml
  31. 9 8
      src/codegen/gencommon/closuresToClass.ml
  32. 0 0
      src/codegen/gencommon/dynamicFieldAccess.ml
  33. 7 6
      src/codegen/gencommon/dynamicOperators.ml
  34. 6 5
      src/codegen/gencommon/enumToClass.ml
  35. 14 14
      src/codegen/gencommon/enumToClass2.ml
  36. 1 1
      src/codegen/gencommon/expressionUnwrap.ml
  37. 0 0
      src/codegen/gencommon/filterClosures.ml
  38. 2 2
      src/codegen/gencommon/fixOverrides.ml
  39. 13 13
      src/codegen/gencommon/gencommon.ml
  40. 1 1
      src/codegen/gencommon/hardNullableSynf.ml
  41. 3 2
      src/codegen/gencommon/initFunction.ml
  42. 0 0
      src/codegen/gencommon/intDivisionSynf.ml
  43. 0 0
      src/codegen/gencommon/interfaceProps.ml
  44. 0 0
      src/codegen/gencommon/interfaceVarsDeleteModf.ml
  45. 1 1
      src/codegen/gencommon/normalize.ml
  46. 0 0
      src/codegen/gencommon/objectDeclMap.ml
  47. 2 2
      src/codegen/gencommon/overloadingConstructor.ml
  48. 6 5
      src/codegen/gencommon/realTypeParams.ml
  49. 18 17
      src/codegen/gencommon/reflectionCFs.ml
  50. 0 0
      src/codegen/gencommon/renameTypeParameters.ml
  51. 0 0
      src/codegen/gencommon/setHXGen.ml
  52. 1 1
      src/codegen/gencommon/switchToIf.ml
  53. 0 0
      src/codegen/gencommon/tArrayTransform.ml
  54. 0 0
      src/codegen/gencommon/unnecessaryCastsRemoval.ml
  55. 1 1
      src/codegen/gencommon/unreachableCodeEliminationSynf.ml
  56. 10 8
      src/codegen/genxml.ml
  57. 6 6
      src/codegen/java.ml
  58. 2 2
      src/codegen/overloads.ml
  59. 3 3
      src/codegen/swfLoader.ml
  60. 4 3
      src/compiler/displayOutput.ml
  61. 40 67
      src/compiler/main.ml
  62. 29 113
      src/compiler/server.ml
  63. 67 426
      src/context/common.ml
  64. 0 182
      src/context/display.ml
  65. 182 0
      src/context/displayToplevel.ml
  66. 0 0
      src/context/displayTypes.ml
  67. 0 0
      src/context/sourcemaps.ml
  68. 27 12
      src/context/typecore.ml
  69. 1 1
      src/core/abstract.ml
  70. 32 6
      src/core/ast.ml
  71. 291 0
      src/core/define.ml
  72. 0 0
      src/core/error.ml
  73. 0 0
      src/core/globals.ml
  74. 0 0
      src/core/json.ml
  75. 9 13
      src/core/meta.ml
  76. 74 0
      src/core/numeric.ml
  77. 47 1
      src/core/path.ml
  78. 388 0
      src/core/texpr.ml
  79. 167 0
      src/core/timer.ml
  80. 120 246
      src/core/type.ml
  81. 1 1
      src/filters/capturedVars.ml
  82. 2 2
      src/filters/defaultArguments.ml
  83. 6 118
      src/filters/filters.ml
  84. 70 0
      src/filters/filtersCommon.ml
  85. 209 0
      src/filters/jsExceptions.ml
  86. 4 4
      src/filters/tryCatchWrapper.ml
  87. 36 0
      src/filters/varLazifier.ml
  88. 4 4
      src/generators/genas3.ml
  89. 31 27
      src/generators/gencpp.ml
  90. 16 13
      src/generators/gencs.ml
  91. 55 66
      src/generators/genhl.ml
  92. 7 7
      src/generators/genjava.ml
  93. 197 217
      src/generators/genjs.ml
  94. 102 90
      src/generators/genlua.ml
  95. 4 4
      src/generators/genneko.ml
  96. 0 2437
      src/generators/genphp.ml
  97. 164 199
      src/generators/genphp7.ml
  98. 18 11
      src/generators/genpy.ml
  99. 2 2
      src/generators/genswf.ml
  100. 5 14
      src/generators/genswf9.ml

+ 6 - 0
.gitignore

@@ -9,6 +9,7 @@
 *.exe
 *.exe
 .*.swp
 .*.swp
 /out
 /out
+/installer
 
 
 /extra/hxclasses
 /extra/hxclasses
 /extra/*.swf
 /extra/*.swf
@@ -18,6 +19,7 @@
 /extra/deploy_key
 /extra/deploy_key
 /extra/*_sec.gpg
 /extra/*_sec.gpg
 /extra/*_ssh
 /extra/*_ssh
+/extra/doc/
 
 
 /src/version.ml
 /src/version.ml
 /haxe
 /haxe
@@ -68,6 +70,7 @@ build.bat
 /.vscode
 /.vscode
 tests/unit/compile.php.hxml
 tests/unit/compile.php.hxml
 /extra/*.xml
 /extra/*.xml
+!/extra/build-haxesetup.xml
 tests/optimization/testopt.js
 tests/optimization/testopt.js
 tests/misc/pythonImport/native_python/__pycache__
 tests/misc/pythonImport/native_python/__pycache__
 tests/unit/unit.py
 tests/unit/unit.py
@@ -107,3 +110,6 @@ tests/server/test/cases/
 tests/server/test.js
 tests/server/test.js
 
 
 tests/unit/pypy3-*
 tests/unit/pypy3-*
+tmp.tmp
+
+dev-display.hxml

+ 75 - 112
.travis.yml

@@ -22,38 +22,17 @@ before_cache:
 
 
 env:
 env:
   global:
   global:
+    - OPAMYES=1
     # make variables
     # make variables
     - ADD_REVISION=1
     - ADD_REVISION=1
     # nightly builds submit
     # nightly builds submit
     - secure: "UoGjYvQqt66GWmeLC4Pih1iue5AufVgW8XQOd2Bx839NN/2mQQ9bD1HuONJe+taWBJ+PHInkAjYROYYaiCQUA7B1SXs3oQD7Og6arVcR7kY7XOdAQ2t8ZkxJHTnuYGWW/2gNFBESv+3H17bkXG4rzaSn2LV5PJLOxSjw0ziBUMY="
     - secure: "UoGjYvQqt66GWmeLC4Pih1iue5AufVgW8XQOd2Bx839NN/2mQQ9bD1HuONJe+taWBJ+PHInkAjYROYYaiCQUA7B1SXs3oQD7Og6arVcR7kY7XOdAQ2t8ZkxJHTnuYGWW/2gNFBESv+3H17bkXG4rzaSn2LV5PJLOxSjw0ziBUMY="
     - secure: "ugpxt+zeYiAiMYKLK96f5TLSxbQAtmDWiumdwaLHl88fIUeefxJJPIF1Xm0AHeYEJE7sD8dLE1dMbRSzOpXFfTmJoQZv19Wjv+2N5B+DaabKjGj1nZG7q3blGa3nUYzWVfFNFiIpM9c5fvW8yiUFzacZE5itEY8+lZQeGsNh+WQ="
     - secure: "ugpxt+zeYiAiMYKLK96f5TLSxbQAtmDWiumdwaLHl88fIUeefxJJPIF1Xm0AHeYEJE7sD8dLE1dMbRSzOpXFfTmJoQZv19Wjv+2N5B+DaabKjGj1nZG7q3blGa3nUYzWVfFNFiIpM9c5fvW8yiUFzacZE5itEY8+lZQeGsNh+WQ="
-    # SauceLabs
-    # - secure: SjyKefmjUEXi0IKHGGpcbLAajU0mLHONg8aA8LoY7Q9nAkSN6Aql+fzS38Boq7w1jWn+2FOpr+4jy0l6wVd/bftsF+huFfYpFJmdh8BlKmE0K71zZAral0H1c7YxkuQpPiJCIFGXqtkvev7SWTy0z31u7kuuQeEyW27boXe5cDA=
-    # - secure: sUvWUjCyPuWht4seNa4f2VG9DkvXkhZyLZfjJO9TUAHB2JndS16E2j/qrvKEjycyH6w8tU/B9vnjDRvvGrYXxEXcBEwsJVfkorFnRl9uwGCGIYrzjMhssEl3fMYZK7P304f+gAp5ULrDBX2gIaKeSa8lUNRtz2PsZOieE4kMdhk=
-    # Bintray
-    # - secure: "ETbwZaeRq8wIVZVyUk1IsNctYVuQa/U2biRkF9pQkz3MEXpaneynclVzNjm8rnm8JqfKcjUDUvQJBP1KYrJYq3tAJFhl31YUnS0FsF3sgLIcnHkhbRA24xJdIlCwHP6QUPoiyPbkec43NRwrF0071KOMD51vgUToXRtAe3o/15g="
-    # - secure: "Fcrrge2f4jFYDOopig2rwkQvgJw6Ra8UK6OwTVk08wecytzVaOJK1TcB22PSvZ+h0ZLJs34T+pXHFjlNuSWm4+CwGSvnltRD1/svjS8zOqK7RzuUdzHz87yruz9PFqV63HTas6qtmgLqp8n/Q6AhtDLF39BTZPyDzEbi9qkwRuI="
-    # - secure: "VBJDQNJ9uvdt0aszo7oU3txuRvjkuLmuHZGOkrd4wE/5B4sX5jzx/+dnrKcNTXJCmQ/rVLuMu9GyxqVjNHlzce678voxdQNOtNkNgpkr1qN9/A9rRnCp77hH27ErdthpWxbmcnE62hAJ83TIKSvn//5lAkx4sMCKS1NXEWQ5qec="
-    # PPA configs
-    - PPA="ppa:haxe/snapshots"
-    - DEBFULLNAME="Haxe CI Bot"
-    - DEBEMAIL="[email protected]"
 
 
 sudo: required
 sudo: required
 dist: trusty
 dist: trusty
-addons: &addons
-  ssh_known_hosts:
-    - haxe.org
-    - api.haxe.org
 
 
 install_linux: &install_linux
 install_linux: &install_linux
-  - if [ ! -d "$HOME/neko" ]; then
-      export CACHE_AVAILABLE=0;
-    elif [ ! -d "$HOME/neko/.git" ]; then
-      export CACHE_AVAILABLE=0;
-    else
-      export CACHE_AVAILABLE=1;
-    fi
   # Install dependencies
   # Install dependencies
   - export APT_CACHE_DIR=~/apt-cache && mkdir -pv $APT_CACHE_DIR
   - export APT_CACHE_DIR=~/apt-cache && mkdir -pv $APT_CACHE_DIR
   - sudo apt-get install --reinstall ca-certificates # workaround for "Cannot add PPA: 'ppa:haxe/ocaml'. Please check that the PPA name or format is correct."
   - sudo apt-get install --reinstall ca-certificates # workaround for "Cannot add PPA: 'ppa:haxe/ocaml'. Please check that the PPA name or format is correct."
@@ -63,7 +42,6 @@ install_linux: &install_linux
       ocaml
       ocaml
       ocaml-native-compilers
       ocaml-native-compilers
       ocaml-findlib
       ocaml-findlib
-      camlp4
       libpcre3-dev
       libpcre3-dev
       zlib1g-dev
       zlib1g-dev
       libgtk2.0-dev
       libgtk2.0-dev
@@ -71,38 +49,36 @@ install_linux: &install_linux
       awscli
       awscli
       $JOB_DEPENDENCIES
       $JOB_DEPENDENCIES
   - wget https://raw.github.com/ocaml/opam/master/shell/opam_installer.sh -O - | sh -s /usr/local/bin system
   - wget https://raw.github.com/ocaml/opam/master/shell/opam_installer.sh -O - | sh -s /usr/local/bin system
-  - export OPAMYES=1
-  - opam install sedlex xml-light extlib rope ptmap
-  # check if we need to install neko
-  - export REF_CHANGED=1;
-  - if [ ! -d "$HOME/neko" ]; then
-      mkdir $HOME/neko;
-      pushd $HOME/neko;
-      git clone https://github.com/HaxeFoundation/neko.git .;
-      git submodule update --init --recursive;
+  - opam update
+  - opam pin add haxe . --no-action
+  - opam install haxe --deps-only
+  # install neko
+  - if [ ! $DEPLOY_NIGHTLIES ]; then
+      sudo add-apt-repository ppa:haxe/snapshots -y;
+      sudo apt-get -o dir::cache::archives="$APT_CACHE_DIR" install -y neko neko-dev;
     else
     else
-      pushd $HOME/neko;
-      if [ ! -d "$HOME/neko/.git" ]; then
+      if [ ! -d "$HOME/neko" ]; then
+        mkdir $HOME/neko;
+        pushd $HOME/neko;
         git clone https://github.com/HaxeFoundation/neko.git .;
         git clone https://github.com/HaxeFoundation/neko.git .;
         git submodule update --init --recursive;
         git submodule update --init --recursive;
       else
       else
-        git fetch --all;
-        export REF_CUR=`git rev-list master | head -n 1`;
-        export REF_REMOTE=`git rev-list origin/master | head -n 1`;
-        export REF_CHANGED=`(test $REF_CUR != $REF_REMOTE && echo 1) || echo 0`;
-        if [ $REF_CHANGED = 1 ]; then
+        pushd $HOME/neko;
+        if [ ! -d "$HOME/neko/.git" ]; then
+          git clone https://github.com/HaxeFoundation/neko.git .;
+          git submodule update --init --recursive;
+        else
+          git fetch --all;
           git reset --hard origin/master;
           git reset --hard origin/master;
           git submodule update --init --recursive;
           git submodule update --init --recursive;
         fi;
         fi;
       fi;
       fi;
-    fi;
-  - env
-  - test $REF_CHANGED = 0 || cmake . -DSTATIC_DEPS=all -G Ninja || (git clean -dfx && export CACHE_AVAILABLE=0 && cmake . -DSTATIC_DEPS=all -G Ninja)
-  # download static dependencies before actual build, with 3 chances to deal with network issues
-  - test $REF_CHANGED = 0 || ninja download_static_deps || ninja download_static_deps || ninja download_static_deps
-  - test $REF_CHANGED = 0 || (ninja -j 4)
-  - sudo cmake -P cmake_install.cmake
-  - popd
+      cmake . -DSTATIC_DEPS=all -G Ninja || (git clean -dfx && cmake . -DSTATIC_DEPS=all -G Ninja);
+      ninja download_static_deps || ninja download_static_deps || ninja download_static_deps;
+      ninja -j 4;
+      sudo ninja install;
+      popd;
+    fi
   # Setup JDK
   # Setup JDK
   - jdk_switcher use oraclejdk7
   - jdk_switcher use oraclejdk7
   - java -version
   - java -version
@@ -119,58 +95,43 @@ install_linux: &install_linux
   - export HAXE_STD_PATH="$TRAVIS_BUILD_DIR/std"
   - export HAXE_STD_PATH="$TRAVIS_BUILD_DIR/std"
 
 
 install_osx: &install_osx
 install_osx: &install_osx
-  - if [ ! -d "$HOME/neko" ]; then
-      export CACHE_AVAILABLE=0;
-    elif [ ! -d "$HOME/neko/.git" ]; then
-      export CACHE_AVAILABLE=0;
-    else
-      export CACHE_AVAILABLE=1;
-    fi
   # Install dependencies
   # Install dependencies
   - travis_retry brew update --merge
   - travis_retry brew update --merge
   - brew uninstall --force brew-cask # https://github.com/caskroom/homebrew-cask/pull/15381
   - brew uninstall --force brew-cask # https://github.com/caskroom/homebrew-cask/pull/15381
   - travis_retry brew tap Homebrew/bundle
   - travis_retry brew tap Homebrew/bundle
   - travis_retry brew bundle --file=tests/Brewfile
   - travis_retry brew bundle --file=tests/Brewfile
-  - export OPAMYES=1
   - opam init
   - opam init
   - eval `opam config env`
   - eval `opam config env`
-  - opam install camlp4 sedlex ocamlfind xml-light extlib rope
-  # Install a patched ptmap. See https://github.com/backtracking/ptmap/issues/3
-  - opam install obuild qtest
-  - git clone https://github.com/andyli/ptmap.git --branch 4.05 ~/ptmap
-  - pushd ~/ptmap
-  - make && sudo make install
-  - popd
-  # check if we need to install neko
-  - export REF_CHANGED=1;
-  - if [ ! -d "$HOME/neko" ]; then
-      mkdir $HOME/neko;
-      pushd $HOME/neko;
-      git clone https://github.com/HaxeFoundation/neko.git .;
-      git submodule update --init --recursive;
+  - opam update
+  - opam pin add ptmap https://github.com/andyli/ptmap.git#ocaml406 --no-action # https://github.com/backtracking/ptmap/pull/8
+  - opam pin add haxe . --no-action
+  - opam install haxe --deps-only
+  # install neko
+  - if [ ! $DEPLOY_NIGHTLIES ]; then
+      brew install neko --HEAD;
     else
     else
-      pushd $HOME/neko;
-      if [ ! -d "$HOME/neko/.git" ]; then
+      if [ ! -d "$HOME/neko" ]; then
+        mkdir $HOME/neko;
+        pushd $HOME/neko;
         git clone https://github.com/HaxeFoundation/neko.git .;
         git clone https://github.com/HaxeFoundation/neko.git .;
         git submodule update --init --recursive;
         git submodule update --init --recursive;
       else
       else
-        git fetch --all;
-        export REF_CUR=`git rev-list master | head -n 1`;
-        export REF_REMOTE=`git rev-list origin/master | head -n 1`;
-        export REF_CHANGED=`(test $REF_CUR != $REF_REMOTE && echo 1) || echo 0`;
-        if [ $REF_CHANGED = 1 ]; then
+        pushd $HOME/neko;
+        if [ ! -d "$HOME/neko/.git" ]; then
+          git clone https://github.com/HaxeFoundation/neko.git .;
+          git submodule update --init --recursive;
+        else
+          git fetch --all;
           git reset --hard origin/master;
           git reset --hard origin/master;
           git submodule update --init --recursive;
           git submodule update --init --recursive;
         fi;
         fi;
       fi;
       fi;
+      cmake . -DSTATIC_DEPS=all -G Ninja || (git clean -dfx && cmake . -DSTATIC_DEPS=all -G Ninja);
+      ninja download_static_deps || ninja download_static_deps || ninja download_static_deps;
+      ninja -j 4;
+      sudo ninja install;
+      popd;
     fi
     fi
-  - env
-  - test $REF_CHANGED = 0 || cmake . -DSTATIC_DEPS=all -G Ninja || (git clean -dfx && export CACHE_AVAILABLE=0 && cmake . -DSTATIC_DEPS=all -G Ninja)
-  # download static dependencies before actual build, with 3 chances to deal with network issues
-  - test $REF_CHANGED = 0 || ninja download_static_deps || ninja download_static_deps || ninja download_static_deps
-  - test $REF_CHANGED = 0 || (ninja -j 4)
-  - sudo cmake -P cmake_install.cmake
-  - popd
   # Build haxe
   # Build haxe
   - make -s STATICLINK=1 "LIB_PARAMS=/usr/local/opt/zlib/lib/libz.a /usr/local/lib/libpcre.a" libs
   - make -s STATICLINK=1 "LIB_PARAMS=/usr/local/opt/zlib/lib/libz.a /usr/local/lib/libpcre.a" libs
   - make -s -j STATICLINK=1 "LIB_PARAMS=/usr/local/opt/zlib/lib/libz.a /usr/local/lib/libpcre.a" haxe
   - make -s -j STATICLINK=1 "LIB_PARAMS=/usr/local/opt/zlib/lib/libz.a /usr/local/lib/libpcre.a" haxe
@@ -189,43 +150,57 @@ matrix:
     #########
     #########
     - os: linux
     - os: linux
       env:
       env:
-        - TEST=macro,neko,js,php,php7,flash9,as3,java,cs,python,hl,lua
+        - TEST=neko
         - DEPLOY_API_DOCS=1
         - DEPLOY_API_DOCS=1
         - DEPLOY_NIGHTLIES=1
         - DEPLOY_NIGHTLIES=1
-        # - SAUCE=1
         # haxeci_decrypt (Deploy source package to ppa:haxe/snapshots.)
         # haxeci_decrypt (Deploy source package to ppa:haxe/snapshots.)
         - secure: "Mw3p6bDZuqVQ6u7GrwLQfje5hhIOA4+mdqqLXYHP79UKdhgqb91Dn6IbG9vQ1VXVe64W4YZbQAMBMMRX5kEPDl6JvTVGSBhg00Mi69oO5qrCMcBI6f9FntG72YaVvLf+PA7co+vKrnJzaP2M9pe4SH9Ztbhy0YNxULp7NQ8FLsM="
         - secure: "Mw3p6bDZuqVQ6u7GrwLQfje5hhIOA4+mdqqLXYHP79UKdhgqb91Dn6IbG9vQ1VXVe64W4YZbQAMBMMRX5kEPDl6JvTVGSBhg00Mi69oO5qrCMcBI6f9FntG72YaVvLf+PA7co+vKrnJzaP2M9pe4SH9Ztbhy0YNxULp7NQ8FLsM="
-        # deploy_key_decrypt (Deploy doc to api.haxe.org.)
-        - secure: "A75uYqU0Xz6plIgSewEs0QQWe472dCMb9kf3j7Hx0DS7dApXgx8++189sw9Sv0wam5KPtbcIM292MucjGCb5zocVj9xCUVgajhEA0QpTuDMBjk/cg3ClWCGjfybaCl2E5LLdUs7Zy4b4oNWtVikOWLWJ4sC1kaarR9p6kv8yYZg="
-      # addons:
-      #   <<: *addons
-      #  sauce_connect: true
+      addons:
+        ssh_known_hosts:
+          - haxe.org
+          - api.haxe.org
+      before_install:
+        - eval `ssh-agent -s` # for deployment to haxe.org
+      install: *install_linux
+
+    - os: linux
+      env:
+        - TEST=macro,js,php,flash9,as3,java,cs,python,lua
+        - SAUCE=1
+      addons:
+        sauce_connect: true
       before_install:
       before_install:
         - "export DISPLAY=:99.0"
         - "export DISPLAY=:99.0"
         - "sh -e /etc/init.d/xvfb start"
         - "sh -e /etc/init.d/xvfb start"
         - "export AUDIODEV=null"
         - "export AUDIODEV=null"
       install: *install_linux
       install: *install_linux
+
     - os: linux
     - os: linux
       env:
       env:
         - TEST=cpp
         - TEST=cpp
         - HXCPP_COMPILE_THREADS=4
         - HXCPP_COMPILE_THREADS=4
         - HXCPP_COMPILE_CACHE=~/hxcache
         - HXCPP_COMPILE_CACHE=~/hxcache
-      before_install:
-        - export JOB_DEPENDENCIES="gcc-multilib g++-multilib"
+        - JOB_DEPENDENCIES="gcc-multilib g++-multilib"
       install: *install_linux
       install: *install_linux
 
 
     #######
     #######
     # osx #
     # osx #
     #######
     #######
     - os: osx
     - os: osx
-      osx_image: xcode6.4 # to compile binaries that support older versions of Mac
+      osx_image: xcode7.3 # to compile binaries that support older versions of Mac, and 10.11 is the min version that brew provides bottles
       env:
       env:
-        - TEST=macro,neko,js,php,python,hl,lua
+        - TEST=neko
         - DEPLOY_NIGHTLIES=1
         - DEPLOY_NIGHTLIES=1
       install: *install_osx
       install: *install_osx
 
 
     - os: osx
     - os: osx
-      osx_image: xcode8.3 # to compile C++ faster
+      osx_image: xcode9.1 # to compile faster
+      env:
+        - TEST=macro,java,cs,lua,js,php,flash9,python
+      install: *install_osx
+
+    - os: osx
+      osx_image: xcode9.1 # to compile faster
       env:
       env:
         - TEST=cpp
         - TEST=cpp
         - HXCPP_COMPILE_CACHE=~/hxcache
         - HXCPP_COMPILE_CACHE=~/hxcache
@@ -233,23 +208,11 @@ matrix:
       install: *install_osx
       install: *install_osx
 
 
 script:
 script:
-  - eval `ssh-agent -s` # for deployment to haxe.org
-  - export CAN_BUILD=`(test $CACHE_AVAILABLE = 1 || test $TRAVIS_OS_NAME = 'linux') && echo 1`
-  - if [ ! $CAN_BUILD ]; then
-      echo "No cache available, but initial cache created, please try restarting this job";
-    fi
-  - test $CAN_BUILD && pushd tests
-  - test $CAN_BUILD && mkdir ~/haxelib && haxelib setup ~/haxelib
-  - test $CAN_BUILD && haxe -version
-  - test $CAN_BUILD && haxe RunCi.hxml
-  - test $CAN_BUILD && neko RunCi.n
-  - test $CAN_BUILD && popd
-
-branches:
-  except:
-    # A hack to prevent building for tags, assuming they all start with a number.
-    # https://github.com/travis-ci/travis-ci/issues/1532
-    - /^[0-9]/
+  - pushd tests
+  - mkdir ~/haxelib && haxelib setup ~/haxelib
+  - haxe -version
+  - haxe RunCi.hxml
+  - popd
 
 
 notifications:
 notifications:
   webhooks:
   webhooks:

+ 13 - 0
.vscode/settings.json

@@ -0,0 +1,13 @@
+{
+	"files.associations": {
+		"*.mly": "ocaml",
+		"*.ml": "ocaml"
+	},
+	"[ocaml]": {
+		"editor.tabSize": 4
+	},
+	"files.exclude": {
+		"**/_build": true
+	},
+	"reason.server.languages": ["ocaml"]
+}

+ 1 - 1
CONTRIBUTING.md

@@ -12,7 +12,7 @@ This repository is about the Haxe compiler itself and the Haxe standard library.
 * The haxelib command line tool or lib.haxe.org: <https://github.com/HaxeFoundation/haxelib/issues>
 * 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 on try.haxe.org: <https://github.com/clemos/try-haxe/issues>
 * Something under haxe.org/manual: <https://github.com/HaxeFoundation/HaxeManual/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 on api.haxe.org: For content this is probably the right repository. If it's about the representation, try <https://github.com/HaxeFoundation/dox/issues> instead.
 * Something else on haxe.org: <https://github.com/HaxeFoundation/haxe.org/issues>
 * Something else on haxe.org: <https://github.com/HaxeFoundation/haxe.org/issues>
 
 
 ## Other remarks:
 ## Other remarks:

+ 73 - 31
Makefile

@@ -15,6 +15,7 @@ INSTALL_BIN_DIR=$(INSTALL_DIR)/bin
 INSTALL_LIB_DIR=$(INSTALL_DIR)/lib/haxe
 INSTALL_LIB_DIR=$(INSTALL_DIR)/lib/haxe
 INSTALL_STD_DIR=$(INSTALL_DIR)/share/haxe/std
 INSTALL_STD_DIR=$(INSTALL_DIR)/share/haxe/std
 PACKAGE_OUT_DIR=out
 PACKAGE_OUT_DIR=out
+INSTALLER_TMP_DIR=installer
 PACKAGE_SRC_EXTENSION=.tar.gz
 PACKAGE_SRC_EXTENSION=.tar.gz
 
 
 MAKEFILENAME?=Makefile
 MAKEFILENAME?=Makefile
@@ -27,9 +28,13 @@ STATICLINK?=0
 
 
 # Configuration
 # Configuration
 
 
-HAXE_DIRECTORIES=compiler context generators generators/gencommon macro filters macro/eval optimization syntax typing display
+HAXE_DIRECTORIES=core syntax context codegen codegen/gencommon generators optimization filters macro macro/eval typing compiler
 EXTLIB_LIBS=extlib-leftovers extc neko javalib swflib ttflib ilib objsize pcre ziplib
 EXTLIB_LIBS=extlib-leftovers extc neko javalib swflib ttflib ilib objsize pcre ziplib
-FINDLIB_LIBS=unix str threads sedlex xml-light extlib rope ptmap dynlink
+OCAML_LIBS=unix str threads dynlink
+OPAM_LIBS=sedlex xml-light extlib rope ptmap
+
+FINDLIB_LIBS=$(OCAML_LIBS)
+FINDLIB_LIBS+=$(OPAM_LIBS)
 
 
 # Includes, packages and compiler
 # Includes, packages and compiler
 
 
@@ -40,6 +45,8 @@ FINDLIB_PACKAGES=$(FINDLIB_LIBS:%=-package %)
 CFLAGS=
 CFLAGS=
 ALL_CFLAGS=-bin-annot -safe-string -thread -g -w -3 $(CFLAGS) $(ALL_INCLUDES) $(FINDLIB_PACKAGES)
 ALL_CFLAGS=-bin-annot -safe-string -thread -g -w -3 $(CFLAGS) $(ALL_INCLUDES) $(FINDLIB_PACKAGES)
 
 
+MESSAGE_FILTER=sed -e 's/_build\/src\//src\//' tmp.tmp
+
 ifeq ($(BYTECODE),1)
 ifeq ($(BYTECODE),1)
 	TARGET_FLAG = bytecode
 	TARGET_FLAG = bytecode
 	COMPILER = ocamlfind ocamlc
 	COMPILER = ocamlfind ocamlc
@@ -54,7 +61,7 @@ else
 	OCAMLDEP_FLAGS = -native
 	OCAMLDEP_FLAGS = -native
 endif
 endif
 
 
-CC_CMD = $(COMPILER) $(ALL_CFLAGS) -c $<
+CC_CMD = ($(COMPILER) $(ALL_CFLAGS) -c $< 2>tmp.tmp && $(MESSAGE_FILTER)) || ($(MESSAGE_FILTER) && exit 1)
 
 
 # Meta information
 # Meta information
 
 
@@ -111,7 +118,7 @@ _build/%:%
 build_dirs:
 build_dirs:
 	@mkdir -p $(BUILD_DIRECTORIES)
 	@mkdir -p $(BUILD_DIRECTORIES)
 
 
-_build/src/syntax/parser.ml:src/syntax/parser.mly
+_build/src/syntax/grammar.ml:src/syntax/grammar.mly
 	camlp4o -impl $< -o $@
 	camlp4o -impl $< -o $@
 
 
 _build/src/compiler/version.ml: FORCE
 _build/src/compiler/version.ml: FORCE
@@ -121,7 +128,7 @@ else
 	echo let version_extra = None > _build/src/compiler/version.ml
 	echo let version_extra = None > _build/src/compiler/version.ml
 endif
 endif
 
 
-build_src: | $(BUILD_SRC) _build/src/syntax/parser.ml _build/src/compiler/version.ml
+build_src: | $(BUILD_SRC) _build/src/syntax/grammar.ml _build/src/compiler/version.ml
 
 
 haxe: build_src
 haxe: build_src
 	$(MAKE) -f $(MAKEFILENAME) build_pass_1
 	$(MAKE) -f $(MAKEFILENAME) build_pass_1
@@ -155,7 +162,7 @@ quickcpp: build_src build_pass_4 copy_haxetoolkit
 
 
 CPP_OS := $(shell uname)
 CPP_OS := $(shell uname)
 ifeq ($(CPP_OS),Linux)
 ifeq ($(CPP_OS),Linux)
-copy_haxetoolkit: 
+copy_haxetoolkit:
 	sudo cp haxe /usr/bin/haxe
 	sudo cp haxe /usr/bin/haxe
 else
 else
 copy_haxetoolkit: /cygdrive/c/HaxeToolkit/haxe/haxe.exe
 copy_haxetoolkit: /cygdrive/c/HaxeToolkit/haxe/haxe.exe
@@ -196,6 +203,10 @@ uninstall:
 	else \
 	else \
 		rm -rf $(INSTALL_LIB_DIR); \
 		rm -rf $(INSTALL_LIB_DIR); \
 	fi
 	fi
+	rm -rf  $(INSTALL_STD_DIR)
+
+opam_install:
+	opam install $(OPAM_LIBS) camlp4 ocamlfind --yes
 
 
 # Dependencies
 # Dependencies
 
 
@@ -222,32 +233,63 @@ package_unix:
 
 
 package_bin: package_$(PLATFORM)
 package_bin: package_$(PLATFORM)
 
 
-install_dox:
-	haxelib git hxparse https://github.com/Simn/hxparse master src
-	haxelib git hxtemplo https://github.com/Simn/hxtemplo
-	haxelib git hxargs https://github.com/Simn/hxargs
-	haxelib git markdown https://github.com/dpeek/haxe-markdown master src
-	haxelib git hxcpp https://github.com/HaxeFoundation/hxcpp
-	haxelib git hxjava https://github.com/HaxeFoundation/hxjava
-	haxelib git hxcs https://github.com/HaxeFoundation/hxcs
-	haxelib git dox https://github.com/HaxeFoundation/dox
-
-package_doc:
-	mkdir -p $(PACKAGE_OUT_DIR)
-	$(eval OUTFILE := $(shell pwd)/$(PACKAGE_OUT_DIR)/$(PACKAGE_FILE_NAME)_doc.zip)
+xmldoc:
+	haxelib path hxcpp  || haxelib git hxcpp  https://github.com/HaxeFoundation/hxcpp
+	haxelib path hxjava || haxelib git hxjava https://github.com/HaxeFoundation/hxjava
+	haxelib path hxcs   || haxelib git hxcs   https://github.com/HaxeFoundation/hxcs
+	cd extra && haxe doc.hxml
+
+$(INSTALLER_TMP_DIR):
+	mkdir -p $(INSTALLER_TMP_DIR)
+
+$(INSTALLER_TMP_DIR)/neko-osx64.tar.gz: $(INSTALLER_TMP_DIR)
+	wget http://nekovm.org/media/neko-2.1.0-osx64.tar.gz -O installer/neko-osx64.tar.gz
+
+# Installer
+
+package_installer_mac: $(INSTALLER_TMP_DIR)/neko-osx64.tar.gz package_unix
+	$(eval OUTFILE := $(shell pwd)/$(PACKAGE_OUT_DIR)/$(PACKAGE_FILE_NAME)_installer.tar.gz)
+	$(eval PACKFILE := $(shell pwd)/$(PACKAGE_OUT_DIR)/$(PACKAGE_FILE_NAME)_bin.tar.gz)
 	$(eval VERSION := $(shell haxe -version 2>&1))
 	$(eval VERSION := $(shell haxe -version 2>&1))
-	cd $$(haxelib path dox | head -n 1) && \
-		haxe run.hxml && \
-		haxe gen.hxml && \
-		haxe -lib hxtemplo -lib hxparse -lib hxargs -lib markdown \
-		-cp src -dce no --run dox.Dox -theme haxe_api -D website "http://haxe.org/" \
-		--title "Haxe API" -o $(OUTFILE) \
-		-D version "$(VERSION)" -i bin/xml -ex microsoft -ex javax -ex cs.internal \
-		-D source-path https://github.com/HaxeFoundation/haxe/blob/$(BRANCH)/std/
-
-deploy_doc:
-	scp $(PACKAGE_OUT_DIR)/$(PACKAGE_FILE_NAME)_doc.zip [email protected]:/data/haxeapi/www/v/dev/api-latest.zip
-	ssh [email protected] "cd /data/haxeapi/www/v/dev && find . ! -name 'api-latest.zip' -maxdepth 1 -mindepth 1 -exec rm -rf {} + && unzip -q -o api-latest.zip"
+	$(eval NEKOVER := $(shell neko -version 2>&1))
+	bash -c "rm -rf $(INSTALLER_TMP_DIR)/{resources,pkg,tgz,haxe.tar.gz}"
+	mkdir $(INSTALLER_TMP_DIR)/resources
+	# neko - unpack to change the dir name
+	cd $(INSTALLER_TMP_DIR)/resources && tar -zxvf ../neko-osx64.tar.gz
+	mv $(INSTALLER_TMP_DIR)/resources/neko* $(INSTALLER_TMP_DIR)/resources/neko
+	cd $(INSTALLER_TMP_DIR)/resources && tar -zcvf neko.tar.gz neko
+	# haxe - unpack to change the dir name
+	cd $(INSTALLER_TMP_DIR)/resources && tar -zxvf $(PACKFILE)
+	mv $(INSTALLER_TMP_DIR)/resources/haxe* $(INSTALLER_TMP_DIR)/resources/haxe
+	cd $(INSTALLER_TMP_DIR)/resources && tar -zcvf haxe.tar.gz haxe
+	# scripts
+	cp -rf extra/mac-installer/* $(INSTALLER_TMP_DIR)/resources
+	cd $(INSTALLER_TMP_DIR)/resources && tar -zcvf scripts.tar.gz scripts
+	# installer structure
+	mkdir -p $(INSTALLER_TMP_DIR)/pkg
+	cd $(INSTALLER_TMP_DIR)/pkg && xar -xf ../resources/installer-structure.pkg .
+	mkdir $(INSTALLER_TMP_DIR)/tgz; mv $(INSTALLER_TMP_DIR)/resources/*.tar.gz $(INSTALLER_TMP_DIR)/tgz
+	cd $(INSTALLER_TMP_DIR)/tgz; find . | cpio -o --format odc | gzip -c > ../pkg/files.pkg/Payload
+	cd $(INSTALLER_TMP_DIR)/pkg/files.pkg && bash -c "INSTKB=$$(du -sk ../../tgz | awk '{print $$1;}'); \
+	du -sk ../../tgz; \
+	echo $$INSTKB ; \
+	INSTKBH=`expr $$INSTKB - 4`; \
+	echo $$INSTKBH ;\
+	sed -i '' 's/%%INSTKB%%/$$INSTKBH/g' PackageInfo ;\
+	sed -i '' 's/%%VERSION%%/$(VERSION)/g' PackageInfo ;\
+	sed -i '' 's/%%VERSTRING%%/$(VERSION)/g' PackageInfo ;\
+	sed -i '' 's/%%VERLONG%%/$(VERSION)/g' PackageInfo ;\
+	sed -i '' 's/%%NEKOVER%%/$(NEKOVER)/g' PackageInfo ;\
+	cd .. ;\
+	sed -i '' 's/%%VERSION%%/$(VERSION)/g' Distribution ;\
+	sed -i '' 's/%%VERSTRING%%/$(VERSION)/g' Distribution ;\
+	sed -i '' 's/%%VERLONG%%/$(VERSION)/g' Distribution ;\
+	sed -i '' 's/%%NEKOVER%%/$(NEKOVER)/g' Distribution ;\
+	sed -i '' 's/%%INSTKB%%/$$INSTKBH/g' Distribution"
+	# repackage
+	cd $(INSTALLER_TMP_DIR)/pkg; xar --compression none -cf ../$(PACKAGE_FILE_NAME).pkg *
+	# tar
+	cd $(INSTALLER_TMP_DIR); tar -zcvf $(OUTFILE) $(PACKAGE_FILE_NAME).pkg
 
 
 # Clean
 # Clean
 
 

+ 31 - 0
Makefile.win

@@ -60,3 +60,34 @@ package_choco:
 	cd out/choco && choco pack
 	cd out/choco && choco pack
 	mv out/choco/haxe.*.nupkg out
 	mv out/choco/haxe.*.nupkg out
 	rm -rf out/choco
 	rm -rf out/choco
+
+$(INSTALLER_TMP_DIR)/neko-win.zip: $(INSTALLER_TMP_DIR)
+	wget http://nekovm.org/media/neko-2.1.0-win.zip -O installer/neko-win.zip
+
+package_installer_win: $(INSTALLER_TMP_DIR)/neko-win.zip package_win
+	$(eval OUTFILE := $(PACKAGE_OUT_DIR)/$(PACKAGE_FILE_NAME)_installer.zip)
+	$(eval VERSION := $(shell haxe -version 2>&1 | cut -d ' ' -f1))
+	rm -rf $(INSTALLER_TMP_DIR)/resources
+	# neko
+	mkdir $(INSTALLER_TMP_DIR)/resources
+	cd $(INSTALLER_TMP_DIR) && 7z x -y neko-win.zip
+	rm $(INSTALLER_TMP_DIR)/neko-win.zip
+	mv $(INSTALLER_TMP_DIR)/neko* $(INSTALLER_TMP_DIR)/resources/neko
+	# haxe
+	7z x -y $(PACKAGE_OUT_DIR)/$(PACKAGE_FILE_NAME)_bin.zip -o$(INSTALLER_TMP_DIR)/resources
+	mv $(INSTALLER_TMP_DIR)/resources/haxe* $(INSTALLER_TMP_DIR)/resources/haxe
+	# haxesetup.exe
+	haxelib path hxcpp || haxelib install hxcpp
+	cd extra; haxelib run hxcpp build-haxesetup.xml
+	cp extra/haxesetup.exe $(INSTALLER_TMP_DIR)/resources/haxe
+	# extra
+	cp extra/*.nsi $(INSTALLER_TMP_DIR)
+	cp extra/*.nsh $(INSTALLER_TMP_DIR)
+	cp -rf extra/images $(INSTALLER_TMP_DIR)
+	# nsis
+	sed -i "s/%%VERSION%%/$(VERSION)/g" $(INSTALLER_TMP_DIR)/installer.nsi
+	sed -i "s/%%VERSTRING%%/$(VERSION)/g" $(INSTALLER_TMP_DIR)/installer.nsi
+	sed -i "s/%%VERLONG%%/$(VERSION)/g" $(INSTALLER_TMP_DIR)/installer.nsi
+	cd $(INSTALLER_TMP_DIR) && makensis installer.nsi
+	7z a -r -tzip $(OUTFILE) $(INSTALLER_TMP_DIR)/*.exe
+	dir $(PACKAGE_OUT_DIR)

+ 11 - 11
README.md

@@ -13,17 +13,17 @@ Haxe is an open source toolkit that allows you to easily build cross-platform to
 
 
 Haxe allows you to compile for the following targets:
 Haxe allows you to compile for the following targets:
 
 
- * ActionScript 3
+ * JavaScript
  * C++
  * C++
  * C#
  * C#
- * Flash
  * [HashLink](http://hashlink.haxe.org/)
  * [HashLink](http://hashlink.haxe.org/)
  * Java
  * Java
- * JavaScript
  * Lua
  * Lua
- * [NekoVM](http://nekovm.org/)
  * PHP
  * PHP
  * Python 3
  * Python 3
+ * [NekoVM](http://nekovm.org/)
+ * Flash
+ * ActionScript 3
 
 
 You can try Haxe directly from your browser at [try.haxe.org](https://try.haxe.org)!
 You can try Haxe directly from your browser at [try.haxe.org](https://try.haxe.org)!
 
 
@@ -68,20 +68,20 @@ For information on on using Haxe, consult the [Haxe documentation](https://haxe.
 
 
  * [Haxe Introduction](https://haxe.org/documentation/introduction/), an introduction to the Haxe toolkit
  * [Haxe Introduction](https://haxe.org/documentation/introduction/), an introduction to the Haxe toolkit
  * [The Haxe Manual](https://haxe.org/manual/), the reference manual for the Haxe language
  * [The Haxe Manual](https://haxe.org/manual/), the reference manual for the Haxe language
- * [Haxe Code Cookbook](http://code.haxe.org), code snippets / learning resource
- * [Haxe API](http://api.haxe.org), documentation for the Haxe standard and native APIs
- * [Haxelib](https://lib.haxe.org), a repository of Haxe libraries for a variety of needs
+ * [Haxe Code Cookbook](https://code.haxe.org), code snippets / learning resource
+ * [Haxe API](https://api.haxe.org), documentation for the Haxe standard and native APIs
+ * [Haxelib](https://lib.haxe.org), Haxelib is the package manager for the Haxe Toolkit.
 
 
 ## Community
 ## Community
 
 
 You can get help and talk with fellow Haxers from around the world via:
 You can get help and talk with fellow Haxers from around the world via:
 
 
+ * [Haxe Community Forum](http://community.haxe.org)
  * [Haxe on Stack Overflow](https://stackoverflow.com/questions/tagged/haxe)
  * [Haxe on Stack Overflow](https://stackoverflow.com/questions/tagged/haxe)
- * the [official Haxe Google Group](https://groups.google.com/forum/#!forum/haxelang)
- * [#Haxe on Twitter](https://twitter.com/hashtag/haxe?src=hash)
- * the [Haxe IRC chatroom](https://unic0rn.github.io/tiramisu/haxe/), #haxe on chat.freenode.net
+ * [Haxe Gittr chatroom](https://gitter.im/HaxeFoundation/haxe/)
+ * [#haxe on Twitter](https://twitter.com/hashtag/haxe?src=hash)
 
 
-:+1: Get notified of the latest Haxe news, follow us on [Twitter](https://twitter.com/haxelang), [Facebook](https://www.facebook.com/haxe.org) or [Google+](https://plus.google.com/+HaxeOrg)
+:+1: Get notified of the latest Haxe news, follow us on [Twitter](https://twitter.com/haxelang), [Facebook](https://www.facebook.com/haxe.org) and don't forget to read the [Haxe roundups](https://haxe.io/).
 
 
 ## Version compatibility
 ## Version compatibility
 
 

+ 28 - 18
appveyor.yml

@@ -13,41 +13,52 @@ environment:
         HXBUILDS_AWS_SECRET_ACCESS_KEY:
         HXBUILDS_AWS_SECRET_ACCESS_KEY:
           secure: ewwkKcjnSKl/Vtrz1SXmI6XKk1ENmJDyzm5YaR2wi03foRhTke29TvymB21rDTSl
           secure: ewwkKcjnSKl/Vtrz1SXmI6XKk1ENmJDyzm5YaR2wi03foRhTke29TvymB21rDTSl
     matrix:
     matrix:
-        - TEST: "neko,python,cs,java,php7,php,macro"
+        - ARCH: 64
+          TEST: "neko,python,cs,java,php,macro"
+          DEPLOY_NIGHTLIES: 1
+        - ARCH: 64
+          TEST: "cpp"
+        - ARCH: 32
+          TEST: "macro"
           DEPLOY_NIGHTLIES: 1
           DEPLOY_NIGHTLIES: 1
-        - TEST: "cpp"
-
-skip_tags: true
 
 
 cache:
 cache:
-    - opam64.tar.xz -> appveyor.yml
+    - opam.tar.xz -> appveyor.yml
 
 
 install:
 install:
     - 'git submodule update --init --recursive'
     - 'git submodule update --init --recursive'
     - '%CYG_ROOT%/bin/bash -lc "echo initialize"'
     - '%CYG_ROOT%/bin/bash -lc "echo initialize"'
-    - choco install curl
+    # http://help.appveyor.com/discussions/problems/5616-not-able-to-build-due-to-problem-in-chocolateyinstallps1
+    - ps: Set-Service wuauserv -StartupType Manual
+    - choco install curl nsis.portable wget awscli -y
     # Install ocaml
     # Install ocaml
     - curl -fsSL -o cygwin-setup.exe --retry 3 https://cygwin.com/setup-x86_64.exe
     - curl -fsSL -o cygwin-setup.exe --retry 3 https://cygwin.com/setup-x86_64.exe
-    - 'cygwin-setup.exe -g -q -R "%CYG_ROOT%" -P make -P git -P mingw64-x86_64-zlib -P rsync -P patch -P diffutils -P curl -P unzip -P m4 -P perl -P mingw64-x86_64-gcc-core -P mingw64-x86_64-pcre'
-    - if not exist "opam64.tar.xz" (
-        curl -fsSL -o opam64.tar.xz --retry 3 https://github.com/fdopen/opam-repository-mingw/releases/download/0.0.0.1/opam64.tar.xz
+    - 'cygwin-setup.exe -g -q -R "%CYG_ROOT%" -P make -P git -P mingw64-x86_64-zlib -P mingw64-i686-zlib -P rsync -P patch -P diffutils -P curl -P unzip -P m4 -P perl -P mingw64-x86_64-gcc-core -P mingw64-i686-gcc-core -P mingw64-x86_64-pcre -P mingw64-i686-pcre'
+    - if not exist "opam.tar.xz" (
+        curl -fsSL -o "opam.tar.xz" --retry 3 https://github.com/fdopen/opam-repository-mingw/releases/download/0.0.0.1/opam%ARCH%.tar.xz
       )
       )
-    - 7z x "opam64.tar.xz" -so | 7z x -aoa -si -ttar
-    - '%CYG_ROOT%/bin/bash -lc "cd \"$OLDPWD\" && bash opam64/install.sh"'
-    - '%CYG_ROOT%/bin/bash -lc "opam init mingw \"https://github.com/fdopen/opam-repository-mingw.git\" --comp 4.02.3+mingw64c --switch 4.02.3+mingw64c --auto-setup --yes"'
-    - '%CYG_ROOT%/bin/bash -lc "opam install camlp4 sedlex ocamlfind xml-light extlib rope ptmap --yes"'
+    - 7z x "opam.tar.xz" -so | 7z x -aoa -si -ttar
+    - '%CYG_ROOT%/bin/bash -lc "cd \"$OLDPWD\" && bash opam${ARCH}/install.sh"'
+    - '%CYG_ROOT%/bin/bash -lc "opam init mingw \"https://github.com/fdopen/opam-repository-mingw.git\" --comp 4.02.3+mingw${ARCH}c --switch 4.02.3+mingw${ARCH}c --auto-setup --yes"'
+    - '%CYG_ROOT%/bin/bash -lc "opam update --yes"'
+    - '%CYG_ROOT%/bin/bash -lc "opam pin add haxe \"$APPVEYOR_BUILD_FOLDER\" --no-action --yes"'
+    - '%CYG_ROOT%/bin/bash -lc "opam install haxe --deps-only --yes"'
     # Install neko
     # Install neko
     - choco install neko --prerelease --ignore-dependencies -s 'https://ci.appveyor.com/nuget/neko' -y
     - choco install neko --prerelease --ignore-dependencies -s 'https://ci.appveyor.com/nuget/neko' -y
-    - choco install chocolatey-core.extension php --ignore-dependencies -y
+    # Install php
+    - choco install php -y
     - echo extension=php_openssl.dll >> C:\tools\php71\php.ini
     - echo extension=php_openssl.dll >> C:\tools\php71\php.ini
     - RefreshEnv
     - RefreshEnv
-    - neko -version
     # setup python
     # setup python
     - cmd: mklink C:\Python34-x64\python3.exe C:\Python34-x64\python.exe
     - cmd: mklink C:\Python34-x64\python3.exe C:\Python34-x64\python.exe
     - set PATH=%PATH%;C:\Python34-x64
     - set PATH=%PATH%;C:\Python34-x64
     # expose the dll files
     # expose the dll files
-    - set "PATH=%CYG_ROOT%/usr/x86_64-w64-mingw32/sys-root/mingw/bin;%PATH%"
-    - choco install awscli
+    - if "%ARCH%" EQU "32" (
+        set "PATH=%CYG_ROOT%/usr/i686-w64-mingw32/sys-root/mingw/bin;%PATH%"
+      ) else (
+        set "PATH=%CYG_ROOT%/usr/x86_64-w64-mingw32/sys-root/mingw/bin;%PATH%"
+      )
+    - neko -version
 
 
 build_script:
 build_script:
     - 'cd %APPVEYOR_BUILD_FOLDER%'
     - 'cd %APPVEYOR_BUILD_FOLDER%'
@@ -66,7 +77,6 @@ test_script:
     - cd %APPVEYOR_BUILD_FOLDER%/tests/
     - cd %APPVEYOR_BUILD_FOLDER%/tests/
     - haxe -version
     - haxe -version
     - haxe RunCi.hxml
     - haxe RunCi.hxml
-    - neko RunCi.n
 
 
 artifacts:
 artifacts:
     - path: 'out/*.zip'
     - path: 'out/*.zip'

+ 114 - 4
extra/CHANGES.txt

@@ -1,4 +1,84 @@
-????-??-??: 4.0.0
+????-??-??: 4.0.0-preview.3
+
+	New features:
+
+	all : added new function type notation (#6645)
+
+	General improvements and optimizations:
+
+	all : made all non-warning/non-error compiler messages output to stdout (#4480)
+	php : implemented direct method comparison. No need to use `Reflect.compareMethods()`
+	php : added `php.Syntax.code()` instead of deprecated `untyped __php__()` (#6708)
+	php : added methods to `php.Syntax` for each php operator: `??`, `?:`, `**` etc. (#6708)
+
+	Removals:
+
+	php : removed `php.Syntax.binop()` (#6708)
+
+	Deprecations:
+
+	php : deprecated support for `untyped __php__`, `untyped __call__` etc. Use `php.Syntax` instead.
+
+	Bugfixes:
+
+	js : fixed saving setter to `tmp` var before invocation (#6672)
+	php : don't fail on generating import aliases for classes with the similar names (#6680)
+	php : fixed `Sys.environment()` to also return variables set by `Sys.putEnv()`
+	php : fixed `sys.net.Socket.bind()` (#6693)
+	php : fixed appending "sqlite:" prefix to the names of files created by `sys.db.Sqlite.open()` (#6692)
+	php : made php.Lib.objectOfAssociativeArray() recursive (#6698)
+	php : fixed php error on parsing expressions like `a == b == c` (#6720)
+
+2017-10-08: 4.0.0-preview.2
+
+	New features:
+
+	all : added final keyword (#6596)
+	all : added new function type notation (#6645)
+
+	General improvements and optimizations:
+
+	all : replaced some occurrences of List with Array
+	all : changed haxe.xml.Fast to an abstract
+	all : improved optimization when comparing against `null`
+	all : added support for `case var x` syntax and detect possible typos (#6608)
+	php : changed `--php-prefix`, `--php-front` and `--php-lib` to `-D php-prefix=`, `-D php-front=` and `-D php-lib=` respectively
+
+	Removals:
+
+	all : moved haxe.unit to hx3compat
+	all : moved haxe.web.Request to hx3compat
+	php : dropped php5 support; minimum supported php version is 7.0 now
+
+	Bugfixes:
+
+	all : fixed issue with various functions not being displayed in macro context (#6000)
+	all : fixed invalid  static extension lookup on `super` (#3607)
+	all : fixed typing error when constructing enums with abstracts over functions (#6609)
+	all : fixed bug that skipped checking @:from typing in some cases (#6564)
+	all : fixed Int64 parsing of negative numbers that end in a zero (#5493)
+	all : fixed top-down inference when constructing enums (#6606)
+	eval : fixed bug with equality handling
+	eval : fixed issue with file creation not defaulting to binary
+	eval : fixed invalid override detection (#6583)
+	eval : fixed infinite recursion when printing arrays/vectors
+	cs/java : fixed DCE bug that would lose toString method of thrown objects
+	php/python : fixed some bit operators for Int32 (#5938)
+	php : fixed accessing `static inline var` via reflection (#6630)
+	php : fixed Math.min() and Math.max() for NAN on PHP 7.1.9 and 7.1.10
+	js : fixed js syntax error for `value.iterator--` (#6637)
+
+	Standard Library:
+
+	macro : added have.display.Position and PositionTools.toRange (#6599)
+	all : moved List to haxe.ds (#6610)
+
+2017-09-12: 4.0.0-preview.1
+
+	New features:
+
+	all : reworked macro interpreter
+	all : added support for arrow functions
 
 
 	General improvements and optimizations:
 	General improvements and optimizations:
 
 
@@ -35,6 +115,36 @@
 	all : added `EReg.escape` (#5098)
 	all : added `EReg.escape` (#5098)
 	all : `BalancedTree implements `haxe.Constraints.IMap` (#6231)
 	all : `BalancedTree implements `haxe.Constraints.IMap` (#6231)
 
 
+2017-10-08: 3.4.4
+
+	Bugfixes:
+
+	flash : fixed flash target broken when compiled with OCaml 4.05 (#6589)
+	php7 : fixed accessing `static inline var` via reflection (#6630)
+	js : fixed js syntax error for `value.iterator--` (#6637)
+	cpp : fixed evaluation order problem when constructing enums (#6643)
+
+2017-09-10: 3.4.3
+
+	Bugfixes:
+
+	all : fixed DCE issue with interface fields (#6502)
+	cpp : fixed return typing for embedded closures (#6121)
+	php7: fixed `@:enum abstract` generation  without `-dce full` (#6175)
+	php7: fixed using enum constructor with arguments as a call argument (#6177)
+	php7: fixed accessing methods on dynamic values (#6211)
+	php7: fixed `null` property access (#6281)
+	php7: fixed setting values in a map stored in another map (#6257)
+	php7: implemented `php.Lib.mail()`
+	php7: implemented `php.Lib.loadLib()`
+	php7: implemented `php.Lib.getClasses()` (#6384)
+	php7: fixed exception on `Reflect.getProperty(o, field)` if requested field does not exist (#6559)
+	php/php7: fixed accessing enum constructors on enum type stored to a variable (#6159)
+	php/php7: fixed "cannot implement previously implemented interface" (#6208)
+	php: fixed invoking functions stored in dynamic static vars (#6158)
+	php: fixed field access on `new MyClass()` expressions wrapped in a `cast` (#6294)
+	macro : fixed bug in addClassPath that overwrites macro class paths with context class paths
+
 2017-03-20: 3.4.2
 2017-03-20: 3.4.2
 
 
 	Bugfixes:
 	Bugfixes:
@@ -908,7 +1018,7 @@
 	cpp : Fix socket sellect passing _s
 	cpp : Fix socket sellect passing _s
 	cpp : Throw error when match count does not match regex
 	cpp : Throw error when match count does not match regex
 	cpp : Improve register capture in GC
 	cpp : Improve register capture in GC
-	cpp : Fix Dynamic interger compare
+	cpp : Fix Dynamic integer compare
 	cpp : Implement makeVarArgs
 	cpp : Implement makeVarArgs
 	cpp : Fix toString for nulls in Enums and Arrays
 	cpp : Fix toString for nulls in Enums and Arrays
 	cpp : Added initial Android support
 	cpp : Added initial Android support
@@ -1142,7 +1252,7 @@
 	set all private+protected names from SWF lib to public (allow override+reflect)
 	set all private+protected names from SWF lib to public (allow override+reflect)
 	flash9 : use findprop instead of findpropstrict for 'this' access (allow dynamic)
 	flash9 : use findprop instead of findpropstrict for 'this' access (allow dynamic)
 	don't allow nullness changes in overrided/implemented
 	don't allow nullness changes in overrided/implemented
-	prevent typing hole with overriden polymorphic methods
+	prevent typing hole with overridden polymorphic methods
 	added neko.vm.Mutex and neko.vm.Deque (included in neko 1.7.1)
 	added neko.vm.Mutex and neko.vm.Deque (included in neko 1.7.1)
 	added package remapping using --remap
 	added package remapping using --remap
 
 
@@ -1399,7 +1509,7 @@
 2007-01-28: 1.11
 2007-01-28: 1.11
 	changed StringBuf.add implementation
 	changed StringBuf.add implementation
 	added haxe.Firebug
 	added haxe.Firebug
-	allowed variable return type for overriden/implemented methods
+	allowed variable return type for overridden/implemented methods
 	display error position in front of each error line
 	display error position in front of each error line
 	improved error messages when optional arguments not matched
 	improved error messages when optional arguments not matched
 	added neko.io.Path
 	added neko.io.Path

+ 21 - 15
extra/ImportAll.hx

@@ -1,5 +1,5 @@
 /*
 /*
- * Copyright (C)2005-2016 Haxe Foundation
+ * Copyright (C)2005-2017 Haxe Foundation
  *
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
  * copy of this software and associated documentation files (the "Software"),
@@ -23,16 +23,23 @@ import haxe.macro.Context;
 
 
 class ImportAll {
 class ImportAll {
 
 
+	static function isSysTarget() {
+		return Context.defined("neko") || Context.defined("php") || Context.defined("cpp") ||
+		       Context.defined("java") || Context.defined("python") ||
+		       Context.defined("lua") || Context.defined("hl") || Context.defined("eval"); // TODO: have to add cs here, SPOD gets in the way at the moment
+	}
+
 	public static function run( ?pack ) {
 	public static function run( ?pack ) {
 		if( pack == null ) {
 		if( pack == null ) {
 			pack = "";
 			pack = "";
 			haxe.macro.Compiler.define("doc_gen");
 			haxe.macro.Compiler.define("doc_gen");
 		}
 		}
+		if (Context.defined("interp")) {
+			haxe.macro.Compiler.define("macro");
+		}
 		switch( pack ) {
 		switch( pack ) {
-		case "php7":
-			if( !Context.defined("php7") ) return;
 		case "php":
 		case "php":
-			if( !Context.defined("php") || Context.defined("php7") ) return;
+			if( !Context.defined("php") ) return;
 		case "neko":
 		case "neko":
 			if( !Context.defined("neko") ) return;
 			if( !Context.defined("neko") ) return;
 		case "js":
 		case "js":
@@ -41,8 +48,10 @@ class ImportAll {
 			if( !Context.defined("cpp") ) return;
 			if( !Context.defined("cpp") ) return;
 		case "flash":
 		case "flash":
 			if( !Context.defined("flash9") ) return;
 			if( !Context.defined("flash9") ) return;
+		case "mt","mtwin":
+			return;
 		case "sys":
 		case "sys":
-			if( !Context.defined("neko") && !Context.defined("php") && !Context.defined("cpp") ) return;
+			if(!isSysTarget()) return;
 		case "java":
 		case "java":
 			if( !Context.defined("java") ) return;
 			if( !Context.defined("java") ) return;
 		case "cs":
 		case "cs":
@@ -55,10 +64,9 @@ class ImportAll {
 			if( !Context.defined("lua") ) return;
 			if( !Context.defined("lua") ) return;
 		case "eval":
 		case "eval":
 			if( !Context.defined("eval") ) return;
 			if( !Context.defined("eval") ) return;
-		case "tools":
-			return;
-		case "build-tool":
-			return;
+		case "ssl":
+			if (!Context.defined("neko") && !Context.defined("cpp")) return;
+		case "tools", "build-tool": return;
 		}
 		}
 		for( p in Context.getClassPath() ) {
 		for( p in Context.getClassPath() ) {
 			if( p == "/" )
 			if( p == "/" )
@@ -80,15 +88,13 @@ class ImportAll {
 					switch( cl ) {
 					switch( cl ) {
 					case "ImportAll", "neko.db.MacroManager": continue;
 					case "ImportAll", "neko.db.MacroManager": continue;
 					case "haxe.TimerQueue": if( Context.defined("neko") || Context.defined("php") || Context.defined("cpp") ) continue;
 					case "haxe.TimerQueue": if( Context.defined("neko") || Context.defined("php") || Context.defined("cpp") ) continue;
-					case "Sys": if( !(Context.defined("neko") || Context.defined("php") || Context.defined("cpp")) ) continue;
+					case "Sys": if(!isSysTarget()) continue;
 					case "haxe.web.Request": if( !(Context.defined("neko") || Context.defined("php") || Context.defined("js")) ) continue;
 					case "haxe.web.Request": if( !(Context.defined("neko") || Context.defined("php") || Context.defined("js")) ) continue;
-					case "haxe.macro.ExampleJSGenerator","haxe.macro.Context", "haxe.macro.Compiler": if( !Context.defined("neko") ) continue;
+					case "haxe.macro.ExampleJSGenerator","haxe.macro.Context", "haxe.macro.Compiler": if( !Context.defined("eval") ) continue;
 					case "haxe.remoting.SocketWrapper": if( !Context.defined("flash") ) continue;
 					case "haxe.remoting.SocketWrapper": if( !Context.defined("flash") ) continue;
 					case "haxe.remoting.SyncSocketConnection": if( !(Context.defined("neko") || Context.defined("php") || Context.defined("cpp")) ) continue;
 					case "haxe.remoting.SyncSocketConnection": if( !(Context.defined("neko") || Context.defined("php") || Context.defined("cpp")) ) continue;
-					case "sys.db.Sqlite" | "sys.db.Mysql" | "cs.db.AdoNet": continue;
-					}
-					if( Context.defined("php7") && cl.indexOf("php7.") == 0 ) {
-						cl = "php." + cl.substr("php7.".length);
+					case "neko.vm.Ui" | "sys.db.Sqlite" | "sys.db.Mysql" if ( Context.defined("interp") ): continue;
+					case "sys.db.Sqlite" | "sys.db.Mysql" | "cs.db.AdoNet" if ( Context.defined("cs") ): continue;
 					}
 					}
 					Context.getModule(cl);
 					Context.getModule(cl);
 				} else if( sys.FileSystem.isDirectory(p + "/" + file) )
 				} else if( sys.FileSystem.isDirectory(p + "/" + file) )

+ 0 - 6
extra/all.hxml

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

+ 16 - 0
extra/build-haxesetup.xml

@@ -0,0 +1,16 @@
+<xml>
+
+<include name="${HXCPP}/build-tool/BuildCommon.xml"/>
+<set name="static_link" value="1" />
+<set name="no_console" value="1" />
+
+<files id="haxesetup">
+  <file name="setup.cpp" />
+</files>
+
+<target id="default" output="haxesetup" tool="linker" toolid="exe">
+  <lib name="advapi32.lib" />
+  <files id="haxesetup" />
+</target>
+
+</xml>

+ 1 - 1
extra/choco/haxe.nuspec

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

+ 60 - 0
extra/doc.hxml

@@ -0,0 +1,60 @@
+--no-output
+--macro ImportAll.run()
+-dce no
+-D doc-gen
+
+--each
+
+-neko all.n
+-xml doc/neko.xml
+
+--next
+
+-js all.js
+-xml doc/js.xml
+
+--next
+
+-swf all9.swf
+-xml doc/flash.xml
+-swf-version 11.4
+
+--next
+
+-php all_php
+-xml doc/php.xml
+
+--next
+
+-cpp all_cpp
+-xml doc/cpp.xml
+-D xmldoc
+-D HXCPP_MULTI_THREADED
+
+--next
+-java all_java
+-xml doc/java.xml
+-D xmldoc
+
+--next
+-cs all_cs
+-D unsafe
+-xml doc/cs.xml
+-D xmldoc
+
+--next
+-python all_py
+-xml doc/python.xml
+-D xmldoc
+
+--next
+--interp
+-xml doc/macro.xml
+
+--next
+-lua all_lua
+-xml doc/lua.xml
+
+--next
+-hl all_hl
+-xml doc/hl.xml

+ 1 - 1
extra/haxelib_src

@@ -1 +1 @@
-Subproject commit b0b6057d24cac4fc4464b259f269e6d80bd9bf9d
+Subproject commit 93f6a205bdf4012a2615957b766e7a34efe9f0b6

BIN=BIN
extra/mac-installer/installer-structure.pkg


+ 13 - 0
extra/mac-installer/scripts/haxe-postinstall.sh

@@ -0,0 +1,13 @@
+#!/bin/sh
+rm -f /usr/bin/haxe
+rm -f /usr/local/bin/haxe
+rm -f /usr/bin/haxedoc
+rm -f /usr/local/bin/haxedoc
+rm -f /usr/bin/haxelib
+rm -f /usr/local/bin/haxelib
+rm -f ~/.haxelib
+rm -f $HOME/.haxelib 
+ln -s /usr/local/lib/haxe/haxe /usr/local/bin/haxe
+cp /usr/local/lib/haxe/haxelib /usr/local/bin/haxelib
+mkdir -p /usr/local/lib/haxe/lib
+chmod 777 /usr/local/lib/haxe/lib

+ 8 - 0
extra/mac-installer/scripts/haxe-preinstall.sh

@@ -0,0 +1,8 @@
+#!/bin/sh
+
+#ensure no conflicting version is left there
+rm -rf /usr/lib/haxe/std
+rm -rf /usr/lib/haxe/doc
+rm -f /usr/lib/haxe/haxe
+rm -rf /usr/local/lib/haxe/std
+rm -rf /usr/local/lib/haxe/doc

+ 18 - 0
extra/mac-installer/scripts/install.sh

@@ -0,0 +1,18 @@
+#!/bin/sh
+cd $(dirname $0)
+# haxe
+chmod +x *
+./haxe-preinstall.sh
+rm -f /usr/lib/haxe
+rm -f /usr/local/lib/haxe
+mkdir -p /usr/local/lib/haxe
+mkdir -p /usr/local/bin
+cp -Rf ../haxe/* /usr/local/lib/haxe
+./haxe-postinstall.sh
+./neko-preinstall.sh
+rm -f /usr/local/lib/neko
+mkdir -p /usr/local/lib/neko
+cp -Rf ../neko/* /usr/local/lib/neko
+./neko-postinstall.sh
+cd ../
+rm -Rf /tmp/haxe

+ 19 - 0
extra/mac-installer/scripts/neko-postinstall.sh

@@ -0,0 +1,19 @@
+#!/bin/sh
+rm -f /usr/bin/neko
+rm -f /usr/bin/nekoc
+rm -f /usr/bin/nekoml
+rm -f /usr/bin/nekotools
+rm -f /usr/lib/libneko.dylib
+rm -f /usr/local/bin/neko
+rm -f /usr/local/bin/nekoc
+rm -f /usr/local/bin/nekoml
+rm -f /usr/local/bin/nekotools
+rm -f /usr/local/lib/libneko*.dylib
+
+ln -s /usr/local/lib/neko/neko /usr/local/bin/neko
+ln -s /usr/local/lib/neko/nekoc /usr/local/bin/nekoc
+ln -s /usr/local/lib/neko/nekoml /usr/local/bin/nekoml
+ln -s /usr/local/lib/neko/nekotools /usr/local/bin/nekotools
+ln -s /usr/local/lib/neko/libneko.dylib /usr/local/lib/libneko.dylib
+ln -s /usr/local/lib/neko/libneko.2.dylib /usr/local/lib/libneko.2.dylib
+ln -s /usr/local/lib/neko/libneko.2.1.0.dylib /usr/local/lib/libneko.2.1.0.dylib

+ 3 - 0
extra/mac-installer/scripts/neko-preinstall.sh

@@ -0,0 +1,3 @@
+#!/bin/sh
+rm -rf /usr/lib/neko
+rm -rf /usr/local/lib/neko

+ 10 - 24
extra/release-checklist.txt

@@ -4,32 +4,18 @@
 - Make sure to update the haxelib submodule
 - Make sure to update the haxelib submodule
 - Check that the run-time haxelibs are ready for release: hxcpp, hxjava, hxcs
 - Check that the run-time haxelibs are ready for release: hxcpp, hxjava, hxcs
 
 
-# Building the binaries and installers
-
-- Make sure CHANGES.txt has a proper date set!
-- Make sure `version` in globals.ml has the correct value.
-- Update README.md:
-  - Version compatibility: add/update the Haxe/Neko version
-- Merge development branch into master.
-- Wait for Travis to greenlight master.
-- Tag master as MAJOR.MINOR.PATCH.
-- Wait for builds.haxe.org to build master.
-- Get https://github.com/waneck/hxbuilds/tree/master/release-helper
-- Run it with the fileName corresponding to the latest master file name on builds.haxe.org.
-
 # Making the release
 # Making the release
 
 
-- Regenerate API documentation (check --title and -D version values).
-- Make a GitHub release in https://github.com/HaxeFoundation/haxe/releases with
-  - the generated binaries and installers
-  - the API documentation
-- Update haxe.org
-  - Copy relevant changelog part to downloads/$version/CHANGES.md.
-  - Write announcement post in downloads/$version/RELEASE.md.
-  - Update downloads/versions.json.
-  - Push to staging, check https://staging.haxe.org/.
-  - Merge staging to master, check https://haxe.org/.
+- Make sure CHANGES.txt has a proper date set!
+- Make sure `version` in globals.ml has the correct value
+- Wait for the CI to build (check https://builds.haxe.org)
+- Make an empty GitHub release in https://github.com/HaxeFoundation/haxe/releases
+- Get https://github.com/simn/hxgithub
+- Run it with something like this: `neko release.n -t personal_access_token -h 4.0.0-preview.2 -u -uw -ur -doc --dry`
+- Write the announcement to `./haxe-version/RELEASE.md`
+- If everything was working, run the command again without `--dry`
+- Update https://github.com/HaxeFoundation/haxe.org/blob/staging/downloads/versions.json
 
 
 # Announcing the release
 # Announcing the release
 
 
-- Post announcement post to haxelang.
+- Post announcement post to haxelang

+ 1 - 1
libs

@@ -1 +1 @@
-Subproject commit ba1679cb1ed1e74ccd5068755642dc1353780ded
+Subproject commit c368bdc1c7b7dc4fb85613ffcc08578e23f40a6a

+ 24 - 0
opam

@@ -0,0 +1,24 @@
+opam-version: "1.2"
+name: "haxe"
+version: "4.0.0"
+maintainer: ["Haxe Foundation <[email protected]>" "Andy Li <[email protected]>"]
+author: "Haxe Foundation <[email protected]>"
+homepage: "https://haxe.org/"
+bug-reports: "https://github.com/HaxeFoundation/haxe/issues"
+license: ["GPL2+" "MIT"]
+dev-repo: "https://github.com/HaxeFoundation/haxe"
+build: [
+  [make]
+]
+install: [make "install" "INSTALL_DIR=%{prefix}%"]
+remove: [make "uninstall" "INSTALL_DIR=%{prefix}%"]
+depends: [
+  "ocamlfind" {build}
+  "camlp4"    {build}
+  "sedlex"    {build}
+  "xml-light" {build}
+  "extlib"    {build & >= "1.7"}
+  "rope"      {build}
+  "ptmap"     {build}
+]
+available: [ ocaml-version > "4.02" ]

+ 10 - 317
src/generators/codegen.ml → src/codegen/codegen.ml

@@ -26,110 +26,6 @@ open Globals
 (* -------------------------------------------------------------------------- *)
 (* -------------------------------------------------------------------------- *)
 (* TOOLS *)
 (* TOOLS *)
 
 
-(* Collection of functions that return expressions *)
-module ExprBuilder = struct
-	let make_static_this c p =
-		let ta = TAnon { a_fields = c.cl_statics; a_status = ref (Statics c) } in
-		mk (TTypeExpr (TClassDecl c)) ta p
-
-	let make_typeexpr mt pos =
-		let t =
-			match mt with
-			| TClassDecl c -> TAnon { a_fields = c.cl_statics; a_status = ref (Statics c) }
-			| TEnumDecl e -> TAnon { a_fields = PMap.empty; a_status = ref (EnumStatics e) }
-			| TAbstractDecl a -> TAnon { a_fields = PMap.empty; a_status = ref (AbstractStatics a) }
-			| _ -> assert false
-		in
-		mk (TTypeExpr mt) t pos
-
-	let make_static_field c cf p =
-		let e_this = make_static_this c p in
-		mk (TField(e_this,FStatic(c,cf))) cf.cf_type p
-
-	let make_throw e p =
-		mk (TThrow e) t_dynamic p
-
-	let make_int com i p =
-		mk (TConst (TInt (Int32.of_int i))) com.basic.tint p
-
-	let make_float com f p =
-		mk (TConst (TFloat f)) com.basic.tfloat p
-
-	let make_bool com b p =
-		mk (TConst(TBool b)) com.basic.tbool p
-
-	let make_string com s p =
-		mk (TConst (TString s)) com.basic.tstring p
-
-	let make_null t p =
-		mk (TConst TNull) t p
-
-	let make_local v p =
-		mk (TLocal v) v.v_type p
-
-	let make_const_texpr com ct p = match ct with
-		| TString s -> mk (TConst (TString s)) com.basic.tstring p
-		| TInt i -> mk (TConst (TInt i)) com.basic.tint p
-		| TFloat f -> mk (TConst (TFloat f)) com.basic.tfloat p
-		| TBool b -> mk (TConst (TBool b)) com.basic.tbool p
-		| TNull -> mk (TConst TNull) (com.basic.tnull (mk_mono())) p
-		| _ -> error "Unsupported constant" p
-end
-
-let field e name t p =
-	mk (TField (e,try quick_field e.etype name with Not_found -> assert false)) t p
-
-let fcall e name el ret p =
-	let ft = tfun (List.map (fun e -> e.etype) el) ret in
-	mk (TCall (field e name ft p,el)) ret p
-
-let mk_parent e =
-	mk (TParenthesis e) e.etype e.epos
-
-let mk_return e =
-	mk (TReturn (Some e)) t_dynamic e.epos
-
-let binop op a b t p =
-	mk (TBinop (op,a,b)) t p
-
-let index com e index t p =
-	mk (TArray (e,mk (TConst (TInt (Int32.of_int index))) com.basic.tint p)) t p
-
-let maybe_cast e t =
-	try
-		type_eq EqDoNotFollowNull e.etype t;
-		e
-	with
-		Unify_error _ -> mk (TCast(e,None)) t e.epos
-
-let type_constant com c p =
-	let t = com.basic in
-	match c with
-	| Int s ->
-		if String.length s > 10 && String.sub s 0 2 = "0x" then error "Invalid hexadecimal integer" p;
-		(try mk (TConst (TInt (Int32.of_string s))) t.tint p
-		with _ -> mk (TConst (TFloat s)) t.tfloat p)
-	| Float f -> mk (TConst (TFloat f)) t.tfloat p
-	| String s -> mk (TConst (TString s)) t.tstring p
-	| Ident "true" -> mk (TConst (TBool true)) t.tbool p
-	| Ident "false" -> mk (TConst (TBool false)) t.tbool p
-	| Ident "null" -> mk (TConst TNull) (t.tnull (mk_mono())) p
-	| Ident t -> error ("Invalid constant :  " ^ t) p
-	| Regexp _ -> error "Invalid constant" p
-
-let rec type_constant_value com (e,p) =
-	match e with
-	| EConst c ->
-		type_constant com c p
-	| EParenthesis e ->
-		type_constant_value com e
-	| EObjectDecl el ->
-		mk (TObjectDecl (List.map (fun ((n,_),e) -> n, type_constant_value com e) el)) (TAnon { a_fields = PMap.empty; a_status = ref Closed }) p
-	| EArrayDecl el ->
-		mk (TArrayDecl (List.map (type_constant_value com) el)) (com.basic.tarray t_dynamic) p
-	| _ ->
-		error "Constant value expected" p
-
 let rec has_properties c =
 let rec has_properties c =
 	List.exists (fun f ->
 	List.exists (fun f ->
 		match f.cf_kind with
 		match f.cf_kind with
@@ -160,7 +56,7 @@ let add_property_field com c =
 	| _ ->
 	| _ ->
 		let fields,values = List.fold_left (fun (fields,values) (n,v) ->
 		let fields,values = List.fold_left (fun (fields,values) (n,v) ->
 			let cf = mk_field n com.basic.tstring p null_pos in
 			let cf = mk_field n com.basic.tstring p null_pos in
-			PMap.add n cf fields,(n, ExprBuilder.make_string com v p) :: values
+			PMap.add n cf fields,((n,null_pos,NoQuotes),Texpr.Builder.make_string com.basic v p) :: values
 		) (PMap.empty,[]) props in
 		) (PMap.empty,[]) props in
 		let t = mk_anon fields in
 		let t = mk_anon fields in
 		let e = mk (TObjectDecl values) t p in
 		let e = mk (TObjectDecl values) t p in
@@ -178,48 +74,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
 
 
-(* -------------------------------------------------------------------------- *)
-(* BUILD META DATA OBJECT *)
-
-let build_metadata com t =
-	let api = com.basic in
-	let p, meta, fields, statics = (match t with
-		| TClassDecl c ->
-			let fields = List.map (fun f -> f.cf_name,f.cf_meta) (c.cl_ordered_fields @ (match c.cl_constructor with None -> [] | Some f -> [{ f with cf_name = "_" }])) in
-			let statics =  List.map (fun f -> f.cf_name,f.cf_meta) c.cl_ordered_statics in
-			(c.cl_pos, ["",c.cl_meta],fields,statics)
-		| TEnumDecl e ->
-			(e.e_pos, ["",e.e_meta],List.map (fun n -> n, (PMap.find n e.e_constrs).ef_meta) e.e_names, [])
-		| TTypeDecl t ->
-			(t.t_pos, ["",t.t_meta],(match follow t.t_type with TAnon a -> PMap.fold (fun f acc -> (f.cf_name,f.cf_meta) :: acc) a.a_fields [] | _ -> []),[])
-		| TAbstractDecl a ->
-			(a.a_pos, ["",a.a_meta],[],[])
-	) in
-	let filter l =
-		let l = List.map (fun (n,ml) -> n, ExtList.List.filter_map (fun (m,el,p) -> match m with Meta.Custom s when String.length s > 0 && s.[0] <> ':' -> Some (s,el,p) | _ -> None) ml) l in
-		List.filter (fun (_,ml) -> ml <> []) l
-	in
-	let meta, fields, statics = filter meta, filter fields, filter statics in
-	let make_meta_field ml =
-		let h = Hashtbl.create 0 in
-		mk (TObjectDecl (List.map (fun (f,el,p) ->
-			if Hashtbl.mem h f then error ("Duplicate metadata '" ^ f ^ "'") p;
-			Hashtbl.add h f ();
-			f, mk (match el with [] -> TConst TNull | _ -> TArrayDecl (List.map (type_constant_value com) el)) (api.tarray t_dynamic) p
-		) ml)) t_dynamic p
-	in
-	let make_meta l =
-		mk (TObjectDecl (List.map (fun (f,ml) -> f,make_meta_field ml) l)) t_dynamic p
-	in
-	if meta = [] && fields = [] && statics = [] then
-		None
-	else
-		let meta_obj = [] in
-		let meta_obj = (if fields = [] then meta_obj else ("fields",make_meta fields) :: meta_obj) in
-		let meta_obj = (if statics = [] then meta_obj else ("statics",make_meta statics) :: 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)
-
 let update_cache_dependencies t =
 let update_cache_dependencies t =
 	let rec check_t m t = match t with
 	let rec check_t m t = match t with
 		| TInst(c,tl) ->
 		| TInst(c,tl) ->
@@ -244,7 +98,7 @@ let update_cache_dependencies t =
 			| Some t -> check_t m t
 			| Some t -> check_t m t
 			| _ -> ())
 			| _ -> ())
 		| TLazy f ->
 		| TLazy f ->
-			check_t m (!f())
+			check_t m (lazy_type f)
 		| TDynamic t ->
 		| TDynamic t ->
 			if t == t_dynamic then
 			if t == t_dynamic then
 				()
 				()
@@ -261,114 +115,12 @@ let update_cache_dependencies t =
 		| _ ->
 		| _ ->
 			()
 			()
 
 
-(* -------------------------------------------------------------------------- *)
-(* STACK MANAGEMENT EMULATION *)
-
-type stack_context = {
-	stack_var : string;
-	stack_exc_var : string;
-	stack_pos_var : string;
-	stack_pos : pos;
-	stack_expr : texpr;
-	stack_pop : texpr;
-	stack_save_pos : texpr;
-	stack_restore : texpr list;
-	stack_push : tclass -> string -> texpr;
-	stack_return : texpr -> texpr;
-}
-
-let stack_context_init com stack_var exc_var pos_var tmp_var use_add p =
-	let t = com.basic in
-	let st = t.tarray t.tstring in
-	let stack_var = alloc_var stack_var st p in
-	let exc_var = alloc_var exc_var st p in
-	let pos_var = alloc_var pos_var t.tint p in
-	let stack_e = mk (TLocal stack_var) st p in
-	let exc_e = mk (TLocal exc_var) st p in
-	let stack_pop = fcall stack_e "pop" [] t.tstring p in
-	let stack_push c m =
-		fcall stack_e "push" [
-			if use_add then
-				binop OpAdd (ExprBuilder.make_string com (s_type_path c.cl_path ^ "::") p) (ExprBuilder.make_string com m p) t.tstring p
-			else
-				ExprBuilder.make_string com (s_type_path c.cl_path ^ "::" ^ m) p
-		] t.tvoid p
-	in
-	let stack_return e =
-		let tmp = alloc_var tmp_var e.etype e.epos in
-		mk (TBlock [
-			mk (TVar (tmp, Some e)) t.tvoid e.epos;
-			stack_pop;
-			mk (TReturn (Some (mk (TLocal tmp) e.etype e.epos))) e.etype e.epos
-		]) e.etype e.epos
-	in
-	{
-		stack_var = stack_var.v_name;
-		stack_exc_var = exc_var.v_name;
-		stack_pos_var = pos_var.v_name;
-		stack_pos = p;
-		stack_expr = stack_e;
-		stack_pop = stack_pop;
-		stack_save_pos = mk (TVar (pos_var, Some (field stack_e "length" t.tint p))) t.tvoid p;
-		stack_push = stack_push;
-		stack_return = stack_return;
-		stack_restore = [
-			binop OpAssign exc_e (mk (TArrayDecl []) st p) st p;
-			mk (TWhile (
-				mk_parent (binop OpGte (field stack_e "length" t.tint p) (mk (TLocal pos_var) t.tint p) t.tbool p),
-				fcall exc_e "unshift" [fcall stack_e "pop" [] t.tstring p] t.tvoid p,
-				NormalWhile
-			)) t.tvoid p;
-			fcall stack_e "push" [index com exc_e 0 t.tstring p] t.tvoid p
-		];
-	}
-
-let stack_init com use_add =
-	stack_context_init com "$s" "$e" "$spos" "$tmp" use_add null_pos
-
-let rec stack_block_loop ctx e =
-	match e.eexpr with
-	| TFunction _ ->
-		e
-	| TReturn None | TReturn (Some { eexpr = TConst _ }) | TReturn (Some { eexpr = TLocal _ }) ->
-		mk (TBlock [
-			ctx.stack_pop;
-			e;
-		]) e.etype e.epos
-	| TReturn (Some e) ->
-		ctx.stack_return (stack_block_loop ctx e)
-	| TTry (v,cases) ->
-		let v = stack_block_loop ctx v in
-		let cases = List.map (fun (v,e) ->
-			let e = stack_block_loop ctx e in
-			let e = (match (mk_block e).eexpr with
-				| TBlock l -> mk (TBlock (ctx.stack_restore @ l)) e.etype e.epos
-				| _ -> assert false
-			) in
-			v , e
-		) cases in
-		mk (TTry (v,cases)) e.etype e.epos
-	| _ ->
-		map_expr (stack_block_loop ctx) e
-
-let stack_block ctx c m e =
-	match (mk_block e).eexpr with
-	| TBlock l ->
-		mk (TBlock (
-			ctx.stack_push c m ::
-			ctx.stack_save_pos ::
-			List.map (stack_block_loop ctx) l
-			@ [ctx.stack_pop]
-		)) e.etype e.epos
-	| _ ->
-		assert false
-
 (* -------------------------------------------------------------------------- *)
 (* -------------------------------------------------------------------------- *)
 (* FIX OVERRIDES *)
 (* FIX OVERRIDES *)
 
 
 (*
 (*
 	on some platforms which doesn't support type parameters, we must have the
 	on some platforms which doesn't support type parameters, we must have the
-	exact same type for overriden/implemented function as the original one
+	exact same type for overridden/implemented function as the original one
 *)
 *)
 
 
 let rec find_field com c f =
 let rec find_field com c f =
@@ -499,68 +251,24 @@ let rec is_volatile t =
 		| Some t -> is_volatile t
 		| Some t -> is_volatile t
 		| _ -> false)
 		| _ -> false)
 	| TLazy f ->
 	| TLazy f ->
-		is_volatile (!f())
+		is_volatile (lazy_type f)
 	| TType (t,tl) ->
 	| TType (t,tl) ->
 		(match t.t_path with
 		(match t.t_path with
 		| _ -> is_volatile (apply_params t.t_params tl t.t_type))
 		| _ -> is_volatile (apply_params t.t_params tl t.t_type))
 	| _ ->
 	| _ ->
 		false
 		false
 
 
-let set_default ctx a c p =
-	let t = a.v_type in
-	let ve = mk (TLocal a) t p in
-	let cond =  TBinop (OpEq,ve,mk (TConst TNull) t p) in
-	mk (TIf (mk_parent (mk cond ctx.basic.tbool p), mk (TBinop (OpAssign,ve,mk (TConst c) t p)) t p,None)) ctx.basic.tvoid p
-
 let bytes_serialize data =
 let bytes_serialize data =
 	let b64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/" in
 	let b64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/" in
 	let tbl = Array.init (String.length b64) (fun i -> String.get b64 i) in
 	let tbl = Array.init (String.length b64) (fun i -> String.get b64 i) in
 	Bytes.unsafe_to_string (Base64.str_encode ~tbl data)
 	Bytes.unsafe_to_string (Base64.str_encode ~tbl data)
 
 
-(*
-	Tells if the constructor might be called without any issue whatever its parameters
-*)
-let rec constructor_side_effects e =
-	match e.eexpr with
-	| TBinop (op,_,_) when op <> OpAssign ->
-		true
-	| TField (_,FEnum _) ->
-		false
-	| TUnop _ | TArray _ | TField _ | TEnumParameter _ | TEnumIndex _ | TCall _ | TNew _ | TFor _ | TWhile _ | TSwitch _ | TReturn _ | TThrow _ ->
-		true
-	| TBinop _ | TTry _ | TIf _ | TBlock _ | TVar _
-	| TFunction _ | TArrayDecl _ | TObjectDecl _
-	| TParenthesis _ | TTypeExpr _ | TLocal _ | TMeta _
-	| TConst _ | TContinue | TBreak | TCast _ | TIdent _ ->
-		try
-			Type.iter (fun e -> if constructor_side_effects e then raise Exit) e;
-			false;
-		with Exit ->
-			true
-
 module Dump = struct
 module Dump = struct
-	let make_valid_filename s =
-		let r = Str.regexp "[^A-Za-z0-9_\\-\\.,]" in
-		Str.global_substitute r (fun s -> "_") s
-
-	let rec create_file ext acc = function
-		| [] -> assert false
-		| d :: [] ->
-			let d = make_valid_filename d in
-			let maxlen = 200 - String.length ext in
-			let d = if String.length d > maxlen then String.sub d 0 maxlen else d in
-			let ch = open_out (String.concat "/" (List.rev (d :: acc)) ^ ext) in
-			ch
-		| d :: l ->
-			let dir = String.concat "/" (List.rev (d :: acc)) in
-			if not (Sys.file_exists dir) then Unix.mkdir dir 0o755;
-			create_file ext (d :: acc) l
-
 	(*
 	(*
 		Make a dump of the full typed AST of all types
 		Make a dump of the full typed AST of all types
 	*)
 	*)
 	let create_dumpfile acc l =
 	let create_dumpfile acc l =
-		let ch = create_file ".dump" acc l in
+		let ch = Path.create_file false ".dump" acc l in
 		let buf = Buffer.create 0 in
 		let buf = Buffer.create 0 in
 		buf, (fun () ->
 		buf, (fun () ->
 			output_string ch (Buffer.contents buf);
 			output_string ch (Buffer.contents buf);
@@ -742,7 +450,7 @@ let default_cast ?(vtmp="$t") com e texpr t p =
 	let is = mk (TField (std,fis)) (tfun [t_dynamic;t_dynamic] api.tbool) p in
 	let is = mk (TField (std,fis)) (tfun [t_dynamic;t_dynamic] api.tbool) p in
 	let is = mk (TCall (is,[vexpr;texpr])) api.tbool p in
 	let is = mk (TCall (is,[vexpr;texpr])) api.tbool p in
 	let exc = mk (TThrow (mk (TConst (TString "Class cast error")) api.tstring p)) t p in
 	let exc = mk (TThrow (mk (TConst (TString "Class cast error")) api.tstring p)) t p in
-	let check = mk (TIf (mk_parent is,mk (TCast (vexpr,None)) t p,Some exc)) t p in
+	let check = mk (TIf (Texpr.Builder.mk_parent is,mk (TCast (vexpr,None)) t p,Some exc)) t p in
 	mk (TBlock [var;check;vexpr]) t p
 	mk (TBlock [var;check;vexpr]) t p
 
 
 module UnificationCallback = struct
 module UnificationCallback = struct
@@ -801,14 +509,14 @@ module UnificationCallback = struct
 			| TObjectDecl fl ->
 			| TObjectDecl fl ->
 				begin match follow e.etype with
 				begin match follow e.etype with
 					| TAnon an ->
 					| TAnon an ->
-						let fl = List.map (fun (n,e) ->
+						let fl = List.map (fun ((n,p,qs),e) ->
 							let e = try
 							let e = try
 								let t = (PMap.find n an.a_fields).cf_type in
 								let t = (PMap.find n an.a_fields).cf_type in
 								f e t
 								f e t
 							with Not_found ->
 							with Not_found ->
 								e
 								e
 							in
 							in
-							n,e
+							(n,p,qs),e
 						) fl in
 						) fl in
 						{ e with eexpr = TObjectDecl fl }
 						{ e with eexpr = TObjectDecl fl }
 					| _ -> e
 					| _ -> e
@@ -883,23 +591,8 @@ module ExtClass = struct
 			| Some e' -> c.cl_init <- Some (concat e' e)
 			| Some e' -> c.cl_init <- Some (concat e' e)
 
 
 	let add_static_init c cf e p =
 	let add_static_init c cf e p =
-		let ethis = ExprBuilder.make_static_this c p in
+		let ethis = Texpr.Builder.make_static_this c p in
 		let ef1 = mk (TField(ethis,FStatic(c,cf))) cf.cf_type p in
 		let ef1 = mk (TField(ethis,FStatic(c,cf))) cf.cf_type p in
 		let e_assign = mk (TBinop(OpAssign,ef1,e)) e.etype p in
 		let e_assign = mk (TBinop(OpAssign,ef1,e)) e.etype p in
 		add_cl_init c e_assign
 		add_cl_init c e_assign
-end
-
-let for_remap com v e1 e2 p =
-	let v' = alloc_var v.v_name e1.etype e1.epos 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 p in
-	let ebody = Type.concat eassign e2 in
-	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 p
+end

+ 13 - 12
src/typing/dotnet.ml → src/codegen/dotnet.ml

@@ -318,7 +318,7 @@ let convert_ilfield ctx p field =
 		| CInitOnly | CLiteral -> true, acc
 		| CInitOnly | CLiteral -> true, acc
 		| _ -> readonly,acc
 		| _ -> readonly,acc
 	) (false,[cff_access]) field.fflags.ff_contract in
 	) (false,[cff_access]) field.fflags.ff_contract in
-	if PMap.mem "net_loader_debug" ctx.ncom.defines then
+	if PMap.mem "net_loader_debug" ctx.ncom.defines.Define.values then
 		Printf.printf "\t%sfield %s : %s\n" (if List.mem AStatic acc then "static " else "") cff_name (IlMetaDebug.ilsig_s field.fsig.ssig);
 		Printf.printf "\t%sfield %s : %s\n" (if List.mem AStatic acc then "static " else "") cff_name (IlMetaDebug.ilsig_s field.fsig.ssig);
 	let kind = match readonly with
 	let kind = match readonly with
 		| true ->
 		| true ->
@@ -358,7 +358,7 @@ let convert_ilevent ctx p ev =
 			else
 			else
 				acc
 				acc
 	in
 	in
-	if PMap.mem "net_loader_debug" ctx.ncom.defines then
+	if PMap.mem "net_loader_debug" ctx.ncom.defines.Define.values then
 		Printf.printf "\tevent %s : %s\n" name (IlMetaDebug.ilsig_s ev.esig.ssig);
 		Printf.printf "\tevent %s : %s\n" name (IlMetaDebug.ilsig_s ev.esig.ssig);
 	let acc = add_m acc ev.eadd in
 	let acc = add_m acc ev.eadd in
 	let acc = add_m acc ev.eremove in
 	let acc = add_m acc ev.eremove in
@@ -381,6 +381,7 @@ let convert_ilmethod ctx p m is_explicit_impl =
 	let cff_name = match m.mname with
 	let cff_name = match m.mname with
 		| ".ctor" -> "new"
 		| ".ctor" -> "new"
 		| ".cctor"-> raise Exit (* __init__ field *)
 		| ".cctor"-> raise Exit (* __init__ field *)
+		| "Finalize" -> raise Exit (* destructor (~ClassName) *)
 		| "Equals" | "GetHashCode" -> raise Exit
 		| "Equals" | "GetHashCode" -> raise Exit
 		| name when String.length name > 5 ->
 		| name when String.length name > 5 ->
 				(match String.sub name 0 5 with
 				(match String.sub name 0 5 with
@@ -397,7 +398,7 @@ let convert_ilmethod ctx p m is_explicit_impl =
 			APrivate, meta
 			APrivate, meta
 		| FAPublic -> APublic, meta
 		| FAPublic -> APublic, meta
 		| _ ->
 		| _ ->
-			if PMap.mem "net_loader_debug" ctx.ncom.defines then
+			if PMap.mem "net_loader_debug" ctx.ncom.defines.Define.values then
 				Printf.printf "\tmethod %s (skipped) : %s\n" cff_name (IlMetaDebug.ilsig_s m.msig.ssig);
 				Printf.printf "\tmethod %s (skipped) : %s\n" cff_name (IlMetaDebug.ilsig_s m.msig.ssig);
 			raise Exit
 			raise Exit
 	in
 	in
@@ -408,7 +409,7 @@ let convert_ilmethod ctx p m is_explicit_impl =
 		| CMFinal -> acc, Some true
 		| CMFinal -> acc, Some true
 		| _ -> acc, is_final
 		| _ -> acc, is_final
 	) ([acc],None) m.mflags.mf_contract in
 	) ([acc],None) m.mflags.mf_contract in
-	if PMap.mem "net_loader_debug" ctx.ncom.defines then
+	if PMap.mem "net_loader_debug" ctx.ncom.defines.Define.values then
 		Printf.printf "\t%smethod %s : %s\n" (if !is_static then "static " else "") cff_name (IlMetaDebug.ilsig_s m.msig.ssig);
 		Printf.printf "\t%smethod %s : %s\n" (if !is_static then "static " else "") cff_name (IlMetaDebug.ilsig_s m.msig.ssig);
 
 
 	let meta = match is_final with
 	let meta = match is_final with
@@ -546,7 +547,7 @@ let convert_ilprop ctx p prop is_explicit_impl =
 			| _ -> "never");
 			| _ -> "never");
 		| Some _ -> "set"
 		| Some _ -> "set"
 	in
 	in
-	if PMap.mem "net_loader_debug" ctx.ncom.defines then
+	if PMap.mem "net_loader_debug" ctx.ncom.defines.Define.values then
 		Printf.printf "\tproperty %s (%s,%s) : %s\n" prop.pname get set (IlMetaDebug.ilsig_s prop.psig.ssig);
 		Printf.printf "\tproperty %s (%s,%s) : %s\n" prop.pname get set (IlMetaDebug.ilsig_s prop.psig.ssig);
 	let ilsig = match prop.psig.snorm with
 	let ilsig = match prop.psig.snorm with
 		| LMethod (_,ret,[]) -> ret
 		| LMethod (_,ret,[]) -> ret
@@ -712,7 +713,7 @@ let convert_ilclass ctx p ?(delegate=false) ilcls = match ilcls.csuper with
 	| _ ->
 	| _ ->
 		let flags = ref [HExtern] in
 		let flags = ref [HExtern] in
 		(* todo: instead of CsNative, use more specific definitions *)
 		(* todo: instead of CsNative, use more specific definitions *)
-		if PMap.mem "net_loader_debug" ctx.ncom.defines then begin
+		if PMap.mem "net_loader_debug" ctx.ncom.defines.Define.values then begin
 			let sup = match ilcls.csuper with | None -> [] | Some c -> [IlMetaDebug.ilsig_s c.ssig] in
 			let sup = match ilcls.csuper with | None -> [] | Some c -> [IlMetaDebug.ilsig_s c.ssig] in
 			let sup = sup @ List.map (fun i -> IlMetaDebug.ilsig_s i.ssig) ilcls.cimplements in
 			let sup = sup @ List.map (fun i -> IlMetaDebug.ilsig_s i.ssig) ilcls.cimplements in
 			print_endline ("converting " ^ ilpath_s ilcls.cpath ^ " : " ^ (String.concat ", " sup))
 			print_endline ("converting " ^ ilpath_s ilcls.cpath ^ " : " ^ (String.concat ", " sup))
@@ -1124,20 +1125,20 @@ let add_net_lib com file std =
 					failwith (".NET lib " ^ file ^ " not found")
 					failwith (".NET lib " ^ file ^ " not found")
 			in
 			in
 			real_file := file;
 			real_file := file;
-			let r = PeReader.create_r (open_in_bin file) com.defines in
+			let r = PeReader.create_r (open_in_bin file) com.defines.Define.values in
 			let ctx = PeReader.read r in
 			let ctx = PeReader.read r in
 			let clr_header = PeReader.read_clr_header ctx in
 			let clr_header = PeReader.read_clr_header ctx in
 			let cache = IlMetaReader.create_cache () in
 			let cache = IlMetaReader.create_cache () in
 			let meta = IlMetaReader.read_meta_tables ctx clr_header cache in
 			let meta = IlMetaReader.read_meta_tables ctx clr_header cache in
 			close_in (r.PeReader.ch);
 			close_in (r.PeReader.ch);
-			if PMap.mem "net_loader_debug" com.defines then
+			if PMap.mem "net_loader_debug" com.defines.Define.values then
 				print_endline ("for lib " ^ file);
 				print_endline ("for lib " ^ file);
 			let il_typedefs = Hashtbl.copy meta.il_typedefs in
 			let il_typedefs = Hashtbl.copy meta.il_typedefs in
 			Hashtbl.clear meta.il_typedefs;
 			Hashtbl.clear meta.il_typedefs;
 
 
 			Hashtbl.iter (fun _ td ->
 			Hashtbl.iter (fun _ td ->
 				let path = IlMetaTools.get_path (TypeDef td) in
 				let path = IlMetaTools.get_path (TypeDef td) in
-				if PMap.mem "net_loader_debug" com.defines then
+				if PMap.mem "net_loader_debug" com.defines.Define.values then
 					Printf.printf "found %s\n" (s_type_path (netpath_to_hx path));
 					Printf.printf "found %s\n" (s_type_path (netpath_to_hx path));
 				Hashtbl.replace com.net_path_map (netpath_to_hx path) path;
 				Hashtbl.replace com.net_path_map (netpath_to_hx path) path;
 				Hashtbl.replace meta.il_typedefs path td
 				Hashtbl.replace meta.il_typedefs path td
@@ -1174,7 +1175,7 @@ let add_net_lib com file std =
 		let pack = match fst path with | ["haxe";"root"] -> [] | p -> p in
 		let pack = match fst path with | ["haxe";"root"] -> [] | p -> p in
 		let cp = ref [] in
 		let cp = ref [] in
 		let rec build path = try
 		let rec build path = try
-			if PMap.mem "net_loader_debug" com.defines then
+			if PMap.mem "net_loader_debug" com.defines.Define.values then
 				Printf.printf "looking up %s\n" (s_type_path path);
 				Printf.printf "looking up %s\n" (s_type_path path);
 			match lookup path with
 			match lookup path with
 			| Some({csuper = Some{snorm = LClass( (["System"],[],("Delegate"|"MulticastDelegate")),_)}} as cls)
 			| Some({csuper = Some{snorm = LClass( (["System"],[],("Delegate"|"MulticastDelegate")),_)}} as cls)
@@ -1214,7 +1215,7 @@ let add_net_lib com file std =
 let before_generate com =
 let before_generate com =
 	(* net version *)
 	(* net version *)
 	let net_ver = try
 	let net_ver = try
-			int_of_string (PMap.find "net_ver" com.defines)
+			int_of_string (PMap.find "net_ver" com.defines.Define.values)
 		with | Not_found ->
 		with | Not_found ->
 			Common.define_value com Define.NetVer "20";
 			Common.define_value com Define.NetVer "20";
 			20
 			20
@@ -1235,7 +1236,7 @@ let before_generate com =
 
 
 	(* net target *)
 	(* net target *)
 	let net_target = try
 	let net_target = try
-			String.lowercase (PMap.find "net_target" com.defines)
+			String.lowercase (PMap.find "net_target" com.defines.Define.values)
 		with | Not_found ->
 		with | Not_found ->
 			"net"
 			"net"
 	in
 	in

+ 0 - 0
src/generators/gencommon/abstractImplementationFix.ml → src/codegen/gencommon/abstractImplementationFix.ml


+ 0 - 0
src/generators/gencommon/arrayDeclSynf.ml → src/codegen/gencommon/arrayDeclSynf.ml


+ 3 - 3
src/generators/gencommon/castDetect.ml → src/codegen/gencommon/castDetect.ml

@@ -81,10 +81,10 @@ struct
 				let ret_type = match !current_ret_type with | Some(s) -> s | None -> gen.gcon.error "Invalid return outside function declaration." e.epos; assert false in
 				let ret_type = match !current_ret_type with | Some(s) -> s | None -> gen.gcon.error "Invalid return outside function declaration." e.epos; assert false in
 				(match eopt with
 				(match eopt with
 				| None when not (ExtType.is_void ret_type) ->
 				| None when not (ExtType.is_void ret_type) ->
-					mk_return (null ret_type e.epos)
+					Texpr.Builder.mk_return (null ret_type e.epos)
 				| None -> e
 				| None -> e
 				| Some eret ->
 				| Some eret ->
-					mk_return (handle (run eret) ret_type eret.etype))
+					Texpr.Builder.mk_return (handle (run eret) ret_type eret.etype))
 			| TFunction(tfunc) ->
 			| TFunction(tfunc) ->
 				let last_ret = !current_ret_type in
 				let last_ret = !current_ret_type in
 				current_ret_type := Some(tfunc.tf_type);
 				current_ret_type := Some(tfunc.tf_type);
@@ -623,7 +623,7 @@ let choose_ctor gen cl tparams etl maybe_empty_t p =
 			unify et t;
 			unify et t;
 			check_arg arglist elist
 			check_arg arglist elist
 		with | Unify_error el ->
 		with | Unify_error el ->
-			(* List.iter (fun el -> gen.gcon.warning (Typecore.unify_error_msg (print_context()) el) p) el; *)
+			(* List.iter (fun el -> gen.gcon.warning (Error.unify_error_msg (print_context()) el) p) el; *)
 			false)
 			false)
 		| _ ->
 		| _ ->
 			false
 			false

+ 0 - 0
src/generators/gencommon/classInstance.ml → src/codegen/gencommon/classInstance.ml


+ 9 - 8
src/generators/gencommon/closuresToClass.ml → src/codegen/gencommon/closuresToClass.ml

@@ -20,6 +20,7 @@ open Option
 open Common
 open Common
 open Globals
 open Globals
 open Codegen
 open Codegen
+open Texpr.Builder
 open Ast
 open Ast
 open Type
 open Type
 open Gencommon
 open Gencommon
@@ -691,7 +692,7 @@ struct
 			if arity >= max_arity then begin
 			if arity >= max_arity then begin
 				let varray = match changed_args with | [v,_] -> v | _ -> assert false in
 				let varray = match changed_args with | [v,_] -> v | _ -> assert false in
 				let varray_local = mk_local varray pos in
 				let varray_local = mk_local varray pos in
-				let mk_varray i = { eexpr = TArray(varray_local, ExprBuilder.make_int gen.gcon i pos); etype = t_dynamic; epos = pos } in
+				let mk_varray i = { eexpr = TArray(varray_local, make_int gen.gcon.basic i pos); etype = t_dynamic; epos = pos } in
 				let el =
 				let el =
 					snd (List.fold_left (fun (count,acc) (v,const) ->
 					snd (List.fold_left (fun (count,acc) (v,const) ->
 						(count + 1, (mk (TVar(v, Some(mk_const const (mk_varray count) v.v_type))) basic.tvoid pos) :: acc)
 						(count + 1, (mk (TVar(v, Some(mk_const const (mk_varray count) v.v_type))) basic.tvoid pos) :: acc)
@@ -794,8 +795,8 @@ struct
 			invoke_field.cf_expr <- Some invoke_fun;
 			invoke_field.cf_expr <- Some invoke_fun;
 
 
 			invoke_field, [
 			invoke_field, [
-				ExprBuilder.make_int gen.gcon arity pos;
-				ExprBuilder.make_int gen.gcon type_number pos;
+				make_int gen.gcon.basic arity pos;
+				make_int gen.gcon.basic type_number pos;
 			]
 			]
 		in
 		in
 
 
@@ -1028,7 +1029,7 @@ struct
 			let pos = cl.cl_pos in
 			let pos = cl.cl_pos in
 
 
 			let rec mk_dyn_call arity api =
 			let rec mk_dyn_call arity api =
-				let zero = ExprBuilder.make_float gen.gcon "0.0" pos in
+				let zero = make_float gen.gcon.basic "0.0" pos in
 				let rec loop i acc =
 				let rec loop i acc =
 					if i = 0 then
 					if i = 0 then
 						acc
 						acc
@@ -1046,7 +1047,7 @@ struct
 			let mk_invoke_switch i api =
 			let mk_invoke_switch i api =
 				let t = TFun (func_sig_i i, t_dynamic) in
 				let t = TFun (func_sig_i i, t_dynamic) in
 				(* case i: return this.invokeX_o(0, 0, 0, 0, 0, ... arg[0], args[1]....); *)
 				(* case i: return this.invokeX_o(0, 0, 0, 0, 0, ... arg[0], args[1]....); *)
-				[ExprBuilder.make_int gen.gcon i pos], mk_return (mk (TCall(mk_this (iname i false) t, mk_dyn_call i api)) t_dynamic pos)
+				[make_int gen.gcon.basic i pos], mk_return (mk (TCall(mk_this (iname i false) t, mk_dyn_call i api)) t_dynamic pos)
 			in
 			in
 			let rec loop_cases api arity acc =
 			let rec loop_cases api arity acc =
 				if arity < 0 then
 				if arity < 0 then
@@ -1067,8 +1068,8 @@ struct
 				in
 				in
 				{
 				{
 					eexpr = TIf(
 					eexpr = TIf(
-						mk (TBinop (Ast.OpNotEq, mk_this type_name basic.tint, (ExprBuilder.make_int gen.gcon (if is_float then 0 else 1) pos))) basic.tbool pos,
-						ExprBuilder.make_throw (mk_arg_exception "Wrong number of arguments" pos) pos,
+						mk (TBinop (Ast.OpNotEq, mk_this type_name basic.tint, (make_int gen.gcon.basic (if is_float then 0 else 1) pos))) basic.tbool pos,
+						make_throw (mk_arg_exception "Wrong number of arguments" pos) pos,
 						Some (mk_return call_expr)
 						Some (mk_return call_expr)
 					);
 					);
 					etype = t_dynamic;
 					etype = t_dynamic;
@@ -1099,7 +1100,7 @@ struct
 						eexpr = TSwitch(
 						eexpr = TSwitch(
 							switch_cond,
 							switch_cond,
 							loop_cases api !max_arity [],
 							loop_cases api !max_arity [],
-							Some(ExprBuilder.make_throw (mk_arg_exception "Too many arguments" pos) pos));
+							Some(make_throw (mk_arg_exception "Too many arguments" pos) pos));
 						etype = basic.tvoid;
 						etype = basic.tvoid;
 						epos = pos;
 						epos = pos;
 					}
 					}

+ 0 - 0
src/generators/gencommon/dynamicFieldAccess.ml → src/codegen/gencommon/dynamicFieldAccess.ml


+ 7 - 6
src/generators/gencommon/dynamicOperators.ml → src/codegen/gencommon/dynamicOperators.ml

@@ -20,6 +20,7 @@ open Common
 open Ast
 open Ast
 open Type
 open Type
 open Codegen
 open Codegen
+open Texpr.Builder
 open Gencommon
 open Gencommon
 
 
 (* ******************************************* *)
 (* ******************************************* *)
@@ -65,9 +66,9 @@ open Gencommon
 let init com handle_strings (should_change:texpr->bool) (equals_handler:texpr->texpr->texpr) (dyn_plus_handler:texpr->texpr->texpr->texpr) (compare_handler:Ast.binop->texpr->texpr->texpr->texpr) =
 let init com handle_strings (should_change:texpr->bool) (equals_handler:texpr->texpr->texpr) (dyn_plus_handler:texpr->texpr->texpr->texpr) (compare_handler:Ast.binop->texpr->texpr->texpr->texpr) =
 	let get_etype_one e =
 	let get_etype_one e =
 		if like_int e.etype then
 		if like_int e.etype then
-			ExprBuilder.make_int com 1 e.epos
+			make_int com.basic 1 e.epos
 		else
 		else
-			ExprBuilder.make_float com "1.0" e.epos
+			make_float com.basic "1.0" e.epos
 	in
 	in
 	let rec run e =
 	let rec run e =
 		match e.eexpr with
 		match e.eexpr with
@@ -144,21 +145,21 @@ let init com handle_strings (should_change:texpr->bool) (equals_handler:texpr->t
 					| TField (fexpr, field) ->
 					| TField (fexpr, field) ->
 						let tmp = mk_temp "getvar" fexpr.etype in
 						let tmp = mk_temp "getvar" fexpr.etype in
 						let var = mk (TVar (tmp, Some (run fexpr))) com.basic.tvoid e.epos in
 						let var = mk (TVar (tmp, Some (run fexpr))) com.basic.tvoid e.epos in
-						([var], mk (TField (ExprBuilder.make_local tmp fexpr.epos, field)) etype e1.epos)
+						([var], mk (TField (make_local tmp fexpr.epos, field)) etype e1.epos)
 					| _ ->
 					| _ ->
 						([], e1)
 						([], e1)
 				in
 				in
 				match flag with
 				match flag with
 				| Prefix ->
 				| Prefix ->
 					vars @ [
 					vars @ [
-						mk_cast etype { e with eexpr = TBinop(OpAssign, getvar, Codegen.binop op (mk_cast etype getvar) one etype e.epos); etype = getvar.etype }
+						mk_cast etype { e with eexpr = TBinop(OpAssign, getvar, binop op (mk_cast etype getvar) one etype e.epos); etype = getvar.etype }
 					]
 					]
 				| Postfix ->
 				| Postfix ->
 					let ret = mk_temp "ret" etype in
 					let ret = mk_temp "ret" etype in
-					let retlocal = ExprBuilder.make_local ret e.epos in
+					let retlocal = make_local ret e.epos in
 					vars @ [
 					vars @ [
 						mk (TVar (ret, Some (mk_cast etype getvar))) com.basic.tvoid e.epos;
 						mk (TVar (ret, Some (mk_cast etype getvar))) com.basic.tvoid e.epos;
-						{ e with eexpr = TBinop (OpAssign, getvar, Codegen.binop op retlocal one getvar.etype e.epos) };
+						{ e with eexpr = TBinop (OpAssign, getvar, binop op retlocal one getvar.etype e.epos) };
 						retlocal
 						retlocal
 					]
 					]
 			in
 			in

+ 6 - 5
src/generators/gencommon/enumToClass.ml → src/codegen/gencommon/enumToClass.ml

@@ -21,6 +21,7 @@ open Globals
 open Ast
 open Ast
 open Type
 open Type
 open Codegen
 open Codegen
+open Texpr.Builder
 open Gencommon
 open Gencommon
 
 
 (* ******************************************* *)
 (* ******************************************* *)
@@ -79,7 +80,7 @@ struct
 		let cl = mk_class en.e_module en.e_path pos in
 		let cl = mk_class en.e_module en.e_path pos in
 		Hashtbl.add t.ec_tbl en.e_path cl;
 		Hashtbl.add t.ec_tbl en.e_path cl;
 
 
-		(match Codegen.build_metadata gen.gcon (TEnumDecl en) with
+		(match Texpr.build_metadata gen.gcon.basic (TEnumDecl en) with
 			| Some expr ->
 			| Some expr ->
 				let cf = mk_class_field "__meta__" expr.etype false expr.epos (Var { v_read = AccNormal; v_write = AccNormal }) [] in
 				let cf = mk_class_field "__meta__" expr.etype false expr.epos (Var { v_read = AccNormal; v_write = AccNormal }) [] in
 				cf.cf_expr <- Some expr;
 				cf.cf_expr <- Some expr;
@@ -143,7 +144,7 @@ struct
 						eexpr = TFunction({
 						eexpr = TFunction({
 							tf_args = tf_args;
 							tf_args = tf_args;
 							tf_type = ret;
 							tf_type = ret;
-							tf_expr = mk_block ( mk_return { eexpr = TNew(cl,List.map snd dup_types, [ExprBuilder.make_int gen.gcon old_i pos; arr_decl] ); etype = TInst(cl, List.map snd dup_types); epos = pos } );
+							tf_expr = mk_block ( mk_return { eexpr = TNew(cl,List.map snd dup_types, [make_int gen.gcon.basic old_i pos; arr_decl] ); etype = TInst(cl, List.map snd dup_types); epos = pos } );
 						});
 						});
 						etype = ef_type;
 						etype = ef_type;
 						epos = pos
 						epos = pos
@@ -157,9 +158,9 @@ struct
 					in
 					in
 					let cf = mk_class_field name actual_t true pos (Var { v_read = AccNormal; v_write = AccNever }) [] in
 					let cf = mk_class_field name actual_t true pos (Var { v_read = AccNormal; v_write = AccNever }) [] in
 					let args = if has_params then
 					let args = if has_params then
-						[ExprBuilder.make_int gen.gcon old_i pos; null (gen.gclasses.nativearray t_dynamic) pos]
+						[make_int gen.gcon.basic old_i pos; null (gen.gclasses.nativearray t_dynamic) pos]
 					else
 					else
-						[ExprBuilder.make_int gen.gcon old_i pos]
+						[make_int gen.gcon.basic old_i pos]
 					in
 					in
 					cf.cf_meta <- [Meta.ReadOnly,[],pos];
 					cf.cf_meta <- [Meta.ReadOnly,[],pos];
 					cf.cf_expr <- Some {
 					cf.cf_expr <- Some {
@@ -287,7 +288,7 @@ struct
 					f
 					f
 				in
 				in
 				let cond_array = { (mk_field_access gen f "params" f.epos) with etype = gen.gclasses.nativearray t_dynamic } in
 				let cond_array = { (mk_field_access gen f "params" f.epos) with etype = gen.gclasses.nativearray t_dynamic } in
-				Codegen.index gen.gcon cond_array i e.etype e.epos
+				index gen.gcon.basic cond_array i e.etype e.epos
 			| _ ->
 			| _ ->
 				Type.map_expr run e
 				Type.map_expr run e
 		in
 		in

+ 14 - 14
src/generators/gencommon/enumToClass2.ml → src/codegen/gencommon/enumToClass2.ml

@@ -19,7 +19,7 @@
 open Common
 open Common
 open Ast
 open Ast
 open Codegen
 open Codegen
-open Codegen.ExprBuilder
+open Texpr.Builder
 open Type
 open Type
 open Gencommon
 open Gencommon
 
 
@@ -37,7 +37,7 @@ let add_meta com en cl_enum =
 		let cf_meta = mk_field "__meta__" expr.etype expr.epos expr.epos in
 		let cf_meta = mk_field "__meta__" expr.etype expr.epos expr.epos in
 		cf_meta.cf_expr <- Some expr;
 		cf_meta.cf_expr <- Some expr;
 		add_static cl_enum cf_meta;
 		add_static cl_enum cf_meta;
-	) (Codegen.build_metadata com (TEnumDecl en));
+	) (Texpr.build_metadata com.basic (TEnumDecl en));
 
 
 type enclasses = {
 type enclasses = {
 	base : tclass;
 	base : tclass;
@@ -68,7 +68,7 @@ module EnumToClass2Modf = struct
 
 
 		(* add constructs field (for reflection) *)
 		(* add constructs field (for reflection) *)
 		if has_feature gen.gcon "Type.getEnumConstructs" then begin
 		if has_feature gen.gcon "Type.getEnumConstructs" then begin
-			let e_constructs = mk_array_decl basic.tstring (List.map (fun s -> make_string gen.gcon s pos) en.e_names) pos in
+			let e_constructs = mk_array_decl basic.tstring (List.map (fun s -> make_string gen.gcon.basic s pos) en.e_names) pos in
 			let cf_constructs = mk_field "__hx_constructs" e_constructs.etype pos pos in
 			let cf_constructs = mk_field "__hx_constructs" e_constructs.etype pos pos in
 			cf_constructs.cf_kind <- Var { v_read = AccNormal; v_write = AccNever };
 			cf_constructs.cf_kind <- Var { v_read = AccNormal; v_write = AccNever };
 			cf_constructs.cf_meta <- (Meta.ReadOnly,[],pos) :: (Meta.Protected,[],pos) :: cf_constructs.cf_meta;
 			cf_constructs.cf_meta <- (Meta.ReadOnly,[],pos) :: (Meta.Protected,[],pos) :: cf_constructs.cf_meta;
@@ -105,7 +105,7 @@ module EnumToClass2Modf = struct
 			gen.gadd_to_module (TClassDecl cl_ctor) max_dep;
 			gen.gadd_to_module (TClassDecl cl_ctor) max_dep;
 
 
 			let esuper = mk (TConst TSuper) cl_enum_t pos in
 			let esuper = mk (TConst TSuper) cl_enum_t pos in
-			let etag = make_string gen.gcon name pos in
+			let etag = make_string gen.gcon.basic name pos in
 			let efields = ref [] in
 			let efields = ref [] in
 			(match follow ef.ef_type with
 			(match follow ef.ef_type with
 				| TFun(_, _) ->
 				| TFun(_, _) ->
@@ -146,7 +146,7 @@ module EnumToClass2Modf = struct
 						ctor_args := (ctor_arg_v, None) :: !ctor_args;
 						ctor_args := (ctor_arg_v, None) :: !ctor_args;
 
 
 						(* generate assignment for the constructor *)
 						(* generate assignment for the constructor *)
-						let assign = Codegen.binop OpAssign efield (mk_local ctor_arg_v pos) t pos in
+						let assign = binop OpAssign efield (mk_local ctor_arg_v pos) t pos in
 						ctor_block := assign :: !ctor_block;
 						ctor_block := assign :: !ctor_block;
 
 
 						(* generate an enumEq check for the Equals method (TODO: extract this) *)
 						(* generate an enumEq check for the Equals method (TODO: extract this) *)
@@ -154,13 +154,13 @@ module EnumToClass2Modf = struct
 						let e_enumeq_check = mk (TCall (enumeq, [efield; eotherfield])) basic.tbool pos in
 						let e_enumeq_check = mk (TCall (enumeq, [efield; eotherfield])) basic.tbool pos in
 						let e_param_check =
 						let e_param_check =
 							mk (TIf (mk (TUnop (Not, Prefix, e_enumeq_check)) basic.tbool pos,
 							mk (TIf (mk (TUnop (Not, Prefix, e_enumeq_check)) basic.tbool pos,
-							         mk_return (make_bool gen.gcon false pos),
+							         mk_return (make_bool gen.gcon.basic false pos),
 							         None)
 							         None)
 							) basic.tvoid pos in
 							) basic.tvoid pos in
 						param_equal_checks := e_param_check :: !param_equal_checks;
 						param_equal_checks := e_param_check :: !param_equal_checks;
 					) (List.rev params);
 					) (List.rev params);
 
 
-					ctor_block := (mk (TCall(esuper,[make_int gen.gcon index pos])) basic.tvoid pos) :: !ctor_block;
+					ctor_block := (mk (TCall(esuper,[make_int gen.gcon.basic index pos])) basic.tvoid pos) :: !ctor_block;
 
 
 					let cf_ctor_t = TFun (params, basic.tvoid) in
 					let cf_ctor_t = TFun (params, basic.tvoid) in
 					let cf_ctor = mk_class_field "new" cf_ctor_t true pos (Method MethNormal) [] in
 					let cf_ctor = mk_class_field "new" cf_ctor_t true pos (Method MethNormal) [] in
@@ -214,18 +214,18 @@ module EnumToClass2Modf = struct
 						let equals_exprs = ref (List.rev [
 						let equals_exprs = ref (List.rev [
 							mk (TIf (
 							mk (TIf (
 								mk (TCall(refeq,[ethis;eother_local])) basic.tbool pos,
 								mk (TCall(refeq,[ethis;eother_local])) basic.tbool pos,
-								mk_return (make_bool gen.gcon true pos),
+								mk_return (make_bool gen.gcon.basic true pos),
 								None
 								None
 							)) basic.tvoid pos;
 							)) basic.tvoid pos;
 							mk (TVar(other_en_v, Some ecast)) basic.tvoid pos;
 							mk (TVar(other_en_v, Some ecast)) basic.tvoid pos;
 							mk (TIf(
 							mk (TIf(
 								mk (TBinop(OpEq,other_en_local,make_null cl_ctor_t pos)) basic.tbool pos,
 								mk (TBinop(OpEq,other_en_local,make_null cl_ctor_t pos)) basic.tbool pos,
-								mk_return (make_bool gen.gcon false pos),
+								mk_return (make_bool gen.gcon.basic false pos),
 								None
 								None
 							)) basic.tvoid pos;
 							)) basic.tvoid pos;
 						]) in
 						]) in
 						equals_exprs := (List.rev !param_equal_checks) @ !equals_exprs;
 						equals_exprs := (List.rev !param_equal_checks) @ !equals_exprs;
-						equals_exprs := mk_return (make_bool gen.gcon true pos) :: !equals_exprs;
+						equals_exprs := mk_return (make_bool gen.gcon.basic true pos) :: !equals_exprs;
 
 
 						let cf_Equals_t = TFun([("other",false,t_dynamic)],basic.tbool) in
 						let cf_Equals_t = TFun([("other",false,t_dynamic)],basic.tbool) in
 						let cf_Equals = mk_class_field "Equals" cf_Equals_t true pos (Method MethNormal) [] in
 						let cf_Equals = mk_class_field "Equals" cf_Equals_t true pos (Method MethNormal) [] in
@@ -250,7 +250,7 @@ module EnumToClass2Modf = struct
 								tf_args = [];
 								tf_args = [];
 								tf_type = basic.tint;
 								tf_type = basic.tint;
 								tf_expr = mk_block (mk_return (
 								tf_expr = mk_block (mk_return (
-									mk (TCall(eparamsGetHashCode, [make_int gen.gcon index pos;etoString_args])) basic.tint pos
+									mk (TCall(eparamsGetHashCode, [make_int gen.gcon.basic index pos;etoString_args])) basic.tint pos
 								));
 								));
 							};
 							};
 							etype = cf_GetHashCode_t;
 							etype = cf_GetHashCode_t;
@@ -266,7 +266,7 @@ module EnumToClass2Modf = struct
 						eexpr = TFunction {
 						eexpr = TFunction {
 							tf_args = [];
 							tf_args = [];
 							tf_type = basic.tvoid;
 							tf_type = basic.tvoid;
-							tf_expr = mk (TBlock [mk (TCall(esuper,[make_int gen.gcon index pos])) basic.tvoid pos]) basic.tvoid pos;
+							tf_expr = mk (TBlock [mk (TCall(esuper,[make_int gen.gcon.basic index pos])) basic.tvoid pos]) basic.tvoid pos;
 						};
 						};
 						etype = cf_ctor_t;
 						etype = cf_ctor_t;
 						epos = pos;
 						epos = pos;
@@ -349,7 +349,7 @@ module EnumToClass2Exprf = struct
 			let mk_converted_enum_index_access f =
 			let mk_converted_enum_index_access f =
 				let cl = (get_converted_enum_classes f.etype).base in
 				let cl = (get_converted_enum_classes f.etype).base in
 				let e_enum = { f with etype = TInst (cl, []) } in
 				let e_enum = { f with etype = TInst (cl, []) } in
-				Codegen.field e_enum "_hx_index" com.basic.tint e.epos
+				field e_enum "_hx_index" com.basic.tint e.epos
 			in
 			in
 			match e.eexpr with
 			match e.eexpr with
 			| TEnumIndex f ->
 			| TEnumIndex f ->
@@ -378,7 +378,7 @@ module EnumToClass2Exprf = struct
 				(match ef.ef_type with
 				(match ef.ef_type with
 				| TFun (params, _) ->
 				| TFun (params, _) ->
 					let fname, _, _ = List.nth params i in
 					let fname, _, _ = List.nth params i in
-					Codegen.field ecast fname e.etype e.epos
+					field ecast fname e.etype e.epos
 				| _ -> assert false)
 				| _ -> assert false)
 			| _ ->
 			| _ ->
 				Type.map_expr run e
 				Type.map_expr run e

+ 1 - 1
src/generators/gencommon/expressionUnwrap.ml → src/codegen/gencommon/expressionUnwrap.ml

@@ -494,7 +494,7 @@ let try_call_unwrap_statement com handle_cast problematic_expression_unwrap (add
 				| _ when ExtType.is_void e.etype ->
 				| _ when ExtType.is_void e.etype ->
 					{ e with eexpr = TBlock([e; { e with eexpr = TReturn None }]) }
 					{ e with eexpr = TBlock([e; { e with eexpr = TReturn None }]) }
 				| _ ->
 				| _ ->
-					Codegen.mk_return e
+					Texpr.Builder.mk_return e
 		) e )
 		) e )
 	in
 	in
 
 

+ 0 - 0
src/generators/gencommon/filterClosures.ml → src/codegen/gencommon/filterClosures.ml


+ 2 - 2
src/generators/gencommon/fixOverrides.ml → src/codegen/gencommon/fixOverrides.ml

@@ -138,7 +138,7 @@ let run ~explicit_fn_name ~get_vmtype gen =
 									eexpr = TFunction({
 									eexpr = TFunction({
 										tf_args = List.map (fun v -> v,None) vars;
 										tf_args = List.map (fun v -> v,None) vars;
 										tf_type = r2;
 										tf_type = r2;
-										tf_expr = if is_void then call else (mk_return (mk_cast r2 call));
+										tf_expr = if is_void then call else (Texpr.Builder.mk_return (mk_cast r2 call));
 									});
 									});
 									etype = real_ftype;
 									etype = real_ftype;
 									epos = p;
 									epos = p;
@@ -208,7 +208,7 @@ let run ~explicit_fn_name ~get_vmtype gen =
 								let old_args, old_ret = get_fun f.cf_type in
 								let old_args, old_ret = get_fun f.cf_type in
 								let args, ret = get_fun t in
 								let args, ret = get_fun t in
 								let tf_args = List.rev new_args in
 								let tf_args = List.rev new_args in
-								let f3_mk_return = if ExtType.is_void ret then (fun e -> e) else (fun e -> mk_return (mk_cast ret e)) in
+								let f3_mk_return = if ExtType.is_void ret then (fun e -> e) else (fun e -> Texpr.Builder.mk_return (mk_cast ret e)) in
 								f3.cf_expr <- Some {
 								f3.cf_expr <- Some {
 									eexpr = TFunction({
 									eexpr = TFunction({
 										tf_args = tf_args;
 										tf_args = tf_args;

+ 13 - 13
src/generators/gencommon.ml → src/codegen/gencommon/gencommon.ml

@@ -108,7 +108,7 @@ let follow_once t =
 		| Some t -> t
 		| Some t -> t
 		| _ -> t_dynamic) (* avoid infinite loop / should be the same in this context *)
 		| _ -> t_dynamic) (* avoid infinite loop / should be the same in this context *)
 	| TLazy f ->
 	| TLazy f ->
-		!f()
+		lazy_type f
 	| TType (t,tl) ->
 	| TType (t,tl) ->
 		apply_params t.t_params tl t.t_type
 		apply_params t.t_params tl t.t_type
 	| TAbstract({a_path = [],"Null"},[t]) ->
 	| TAbstract({a_path = [],"Null"},[t]) ->
@@ -120,7 +120,7 @@ let t_empty = TAnon({ a_fields = PMap.empty; a_status = ref Closed })
 
 
 let alloc_var n t = Type.alloc_var n t null_pos
 let alloc_var n t = Type.alloc_var n t null_pos
 
 
-let mk_local = ExprBuilder.make_local
+let mk_local = Texpr.Builder.make_local
 
 
 (* the undefined is a special var that works like null, but can have special meaning *)
 (* the undefined is a special var that works like null, but can have special meaning *)
 let undefined =
 let undefined =
@@ -136,7 +136,7 @@ let debug_expr = s_expr debug_type
 
 
 let debug_mode = ref false
 let debug_mode = ref false
 let trace s = if !debug_mode then print_endline s else ()
 let trace s = if !debug_mode then print_endline s else ()
-let timer name = if !debug_mode then Common.timer name else fun () -> ()
+let timer name = if !debug_mode then Timer.timer name else fun () -> ()
 
 
 let is_string t =
 let is_string t =
 	match follow t with
 	match follow t with
@@ -164,7 +164,7 @@ let anon_class t =
 			| Statics cl -> TClassDecl cl
 			| Statics cl -> TClassDecl cl
 			| AbstractStatics a -> TAbstractDecl a
 			| AbstractStatics a -> TAbstractDecl a
 			| _ -> assert false)
 			| _ -> assert false)
-	| TLazy f -> t_to_md (!f())
+	| TLazy f -> t_to_md (lazy_type f)
 	| TMono r -> (match !r with | Some t -> t_to_md t | None -> assert false)
 	| TMono r -> (match !r with | Some t -> t_to_md t | None -> assert false)
 	| _ -> assert false
 	| _ -> assert false
 
 
@@ -186,7 +186,7 @@ let mk_castfast t e = { e with eexpr = TCast(e, Some (TClassDecl null_class)); e
 
 
 let mk_static_field_access_infer cl field pos params =
 let mk_static_field_access_infer cl field pos params =
 	try
 	try
-		let e_type = ExprBuilder.make_static_this cl pos in
+		let e_type = Texpr.Builder.make_static_this cl pos in
 		let cf = PMap.find field cl.cl_statics in
 		let cf = PMap.find field cl.cl_statics in
 		let t = if params = [] then cf.cf_type else apply_params cf.cf_params params cf.cf_type in
 		let t = if params = [] then cf.cf_type else apply_params cf.cf_params params cf.cf_type in
 		mk (TField(e_type, FStatic(cl, cf))) t pos
 		mk (TField(e_type, FStatic(cl, cf))) t pos
@@ -302,7 +302,7 @@ class ['tp, 'ret] rule_dispatcher name =
 				if key < priority then begin
 				if key < priority then begin
 					let q = Hashtbl.find tbl key in
 					let q = Hashtbl.find tbl key in
 					Stack.iter (fun (n, rule) ->
 					Stack.iter (fun (n, rule) ->
-						let t = if !debug_mode then Common.timer [("rule dispatcher rule: " ^ n)] else fun () -> () in
+						let t = if !debug_mode then Timer.timer [("rule dispatcher rule: " ^ n)] else fun () -> () in
 						let r = rule(tp) in
 						let r = rule(tp) in
 						t();
 						t();
 						if is_some r then begin ret := r; raise Exit end
 						if is_some r then begin ret := r; raise Exit end
@@ -362,7 +362,7 @@ class ['tp] rule_map_dispatcher name = object(self)
 				let q = Hashtbl.find tbl key in
 				let q = Hashtbl.find tbl key in
 				Stack.iter (fun (n, rule) ->
 				Stack.iter (fun (n, rule) ->
 					trace ("running rule " ^ n);
 					trace ("running rule " ^ n);
-					let t = if !debug_mode then Common.timer [("rule map dispatcher rule: " ^ n)] else fun () -> () in
+					let t = if !debug_mode then Timer.timer [("rule map dispatcher rule: " ^ n)] else fun () -> () in
 					cur := rule !cur;
 					cur := rule !cur;
 					t();
 					t();
 				) q
 				) q
@@ -655,7 +655,7 @@ let init_ctx gen =
 			| Some t -> follow_f t
 			| Some t -> follow_f t
 			| _ -> Some t)
 			| _ -> Some t)
 		| TLazy f ->
 		| TLazy f ->
-			follow_f (!f())
+			follow_f (lazy_type f)
 		| TType (t,tl) ->
 		| TType (t,tl) ->
 			follow_f (apply_params t.t_params tl t.t_type)
 			follow_f (apply_params t.t_params tl t.t_type)
 		| TAbstract({a_path = [],"Null"},[t]) ->
 		| TAbstract({a_path = [],"Null"},[t]) ->
@@ -719,7 +719,7 @@ let run_filters gen =
 	let has_errors = ref false in
 	let has_errors = ref false in
 	gen.gcon.error <- (fun msg pos -> has_errors := true; last_error msg pos);
 	gen.gcon.error <- (fun msg pos -> has_errors := true; last_error msg pos);
 	(* first of all, we have to make sure that the filters won't trigger a major Gc collection *)
 	(* first of all, we have to make sure that the filters won't trigger a major Gc collection *)
-	let t = Common.timer ["gencommon_filters"] in
+	let t = Timer.timer ["gencommon_filters"] in
 	(if Common.defined gen.gcon Define.GencommonDebug then debug_mode := true else debug_mode := false);
 	(if Common.defined gen.gcon Define.GencommonDebug then debug_mode := true else debug_mode := false);
 	let run_filters (filter : texpr rule_map_dispatcher) =
 	let run_filters (filter : texpr rule_map_dispatcher) =
 		let rec loop acc mds =
 		let rec loop acc mds =
@@ -815,7 +815,7 @@ let write_file gen w source_dir path extension out_files =
 	let t = timer ["write";"file"] in
 	let t = timer ["write";"file"] in
 	let s_path = source_dir	^ "/" ^ (snd path) ^ "." ^ (extension) in
 	let s_path = source_dir	^ "/" ^ (snd path) ^ "." ^ (extension) in
 	(* create the folders if they don't exist *)
 	(* create the folders if they don't exist *)
-	mkdir_from_path s_path;
+	Path.mkdir_from_path s_path;
 
 
 	let contents = SourceWriter.contents w in
 	let contents = SourceWriter.contents w in
 	let should_write = if not (Common.defined gen.gcon Define.ReplaceFiles) && Sys.file_exists s_path then begin
 	let should_write = if not (Common.defined gen.gcon Define.ReplaceFiles) && Sys.file_exists s_path then begin
@@ -870,7 +870,7 @@ let dump_descriptor gen name path_s module_s =
 	PMap.iter (fun name _ ->
 	PMap.iter (fun name _ ->
 		SourceWriter.write w name;
 		SourceWriter.write w name;
 		SourceWriter.newline w
 		SourceWriter.newline w
-	) gen.gcon.defines;
+	) gen.gcon.defines.Define.values;
 	SourceWriter.write w "end defines";
 	SourceWriter.write w "end defines";
 	SourceWriter.newline w;
 	SourceWriter.newline w;
 	(* dump all defines with their values; keeping the old defines for compatibility *)
 	(* dump all defines with their values; keeping the old defines for compatibility *)
@@ -881,7 +881,7 @@ let dump_descriptor gen name path_s module_s =
 		SourceWriter.write w "=";
 		SourceWriter.write w "=";
 		SourceWriter.write w v;
 		SourceWriter.write w v;
 		SourceWriter.newline w
 		SourceWriter.newline w
-	) gen.gcon.defines;
+	) gen.gcon.defines.Define.values;
 	SourceWriter.write w "end defines_data";
 	SourceWriter.write w "end defines_data";
 	SourceWriter.newline w;
 	SourceWriter.newline w;
 	(* dump all generated types *)
 	(* dump all generated types *)
@@ -1074,7 +1074,7 @@ let rec replace_mono t =
 	| TAnon _
 	| TAnon _
 	| TDynamic _ -> ()
 	| TDynamic _ -> ()
 	| TLazy f ->
 	| TLazy f ->
-		replace_mono (!f())
+		replace_mono (lazy_type f)
 
 
 (* helper *)
 (* helper *)
 let mk_class_field name t public pos kind params =
 let mk_class_field name t public pos kind params =

+ 1 - 1
src/generators/gencommon/hardNullableSynf.ml → src/codegen/gencommon/hardNullableSynf.ml

@@ -53,7 +53,7 @@ let rec is_null_t gen t = match gen.greal_type t with
 
 
 		Some (take_off_null of_t)
 		Some (take_off_null of_t)
 	| TMono r -> (match !r with | Some t -> is_null_t gen t | None -> None)
 	| TMono r -> (match !r with | Some t -> is_null_t gen t | None -> None)
-	| TLazy f -> is_null_t gen (!f())
+	| TLazy f -> is_null_t gen (lazy_type f)
 	| TType (t, tl) ->
 	| TType (t, tl) ->
 		is_null_t gen (apply_params t.t_params tl t.t_type)
 		is_null_t gen (apply_params t.t_params tl t.t_type)
 	| _ -> None
 	| _ -> None

+ 3 - 2
src/generators/gencommon/initFunction.ml → src/codegen/gencommon/initFunction.ml

@@ -19,6 +19,7 @@
 open Common
 open Common
 open Type
 open Type
 open Codegen
 open Codegen
+open Texpr.Builder
 open Gencommon
 open Gencommon
 
 
 (*
 (*
@@ -88,14 +89,14 @@ let handle_class com cl =
 				| Some e ->
 				| Some e ->
 					(match cf.cf_params with
 					(match cf.cf_params with
 					| [] ->
 					| [] ->
-						let var = mk (TField (ExprBuilder.make_static_this cl cf.cf_pos, FStatic(cl,cf))) cf.cf_type cf.cf_pos in
+						let var = mk (TField (make_static_this cl cf.cf_pos, FStatic(cl,cf))) cf.cf_type cf.cf_pos in
 						let ret = binop Ast.OpAssign var e cf.cf_type cf.cf_pos in
 						let ret = binop Ast.OpAssign var e cf.cf_type cf.cf_pos in
 						cf.cf_expr <- None;
 						cf.cf_expr <- None;
 						ret :: acc
 						ret :: acc
 					| _ ->
 					| _ ->
 						let params = List.map (fun _ -> t_dynamic) cf.cf_params in
 						let params = List.map (fun _ -> t_dynamic) cf.cf_params in
 						let fn = apply_params cf.cf_params params in
 						let fn = apply_params cf.cf_params params in
-						let var = mk (TField (ExprBuilder.make_static_this cl cf.cf_pos, FStatic(cl,cf))) (fn cf.cf_type) cf.cf_pos in
+						let var = mk (TField (make_static_this cl cf.cf_pos, FStatic(cl,cf))) (fn cf.cf_type) cf.cf_pos in
 						let rec change_expr e =
 						let rec change_expr e =
 							Type.map_expr_type change_expr fn (fun v -> v.v_type <- fn v.v_type; v) e
 							Type.map_expr_type change_expr fn (fun v -> v.v_type <- fn v.v_type; v) e
 						in
 						in

+ 0 - 0
src/generators/gencommon/intDivisionSynf.ml → src/codegen/gencommon/intDivisionSynf.ml


+ 0 - 0
src/generators/gencommon/interfaceProps.ml → src/codegen/gencommon/interfaceProps.ml


+ 0 - 0
src/generators/gencommon/interfaceVarsDeleteModf.ml → src/codegen/gencommon/interfaceVarsDeleteModf.ml


+ 1 - 1
src/generators/gencommon/normalize.ml → src/codegen/gencommon/normalize.ml

@@ -63,7 +63,7 @@ let rec filter_param t =
 	| TDynamic _ ->
 	| TDynamic _ ->
 		t
 		t
 	| TLazy f ->
 	| TLazy f ->
-		filter_param (!f())
+		filter_param (lazy_type f)
 
 
 let init_expr_filter allowed_metas =
 let init_expr_filter allowed_metas =
 	let rec run e =
 	let rec run e =

+ 0 - 0
src/generators/gencommon/objectDeclMap.ml → src/codegen/gencommon/objectDeclMap.ml


+ 2 - 2
src/generators/gencommon/overloadingConstructor.ml → src/codegen/gencommon/overloadingConstructor.ml

@@ -106,7 +106,7 @@ let replace_super_call com c tl with_params me p follow_type =
 	{
 	{
 		eexpr = TCall(
 		eexpr = TCall(
 			{
 			{
-				eexpr = TField(ExprBuilder.make_static_this sup p, FStatic(sup,cf));
+				eexpr = TField(Texpr.Builder.make_static_this sup p, FStatic(sup,cf));
 				etype = apply_params cf.cf_params stl cf.cf_type;
 				etype = apply_params cf.cf_params stl cf.cf_type;
 				epos = p
 				epos = p
 			},
 			},
@@ -205,7 +205,7 @@ let create_static_ctor com ~empty_ctor_expr cl ctor follow_type =
 				eexpr = TCall(
 				eexpr = TCall(
 					{
 					{
 						eexpr = TField(
 						eexpr = TField(
-							ExprBuilder.make_static_this cl p,
+							Texpr.Builder.make_static_this cl p,
 							FStatic(cl, static_ctor));
 							FStatic(cl, static_ctor));
 						etype = apply_params static_ctor.cf_params (List.map snd cl.cl_params) static_ctor.cf_type;
 						etype = apply_params static_ctor.cf_params (List.map snd cl.cl_params) static_ctor.cf_type;
 						epos = p
 						epos = p

+ 6 - 5
src/generators/gencommon/realTypeParams.ml → src/codegen/gencommon/realTypeParams.ml

@@ -21,6 +21,7 @@ open Common
 open Ast
 open Ast
 open Type
 open Type
 open Codegen
 open Codegen
+open Texpr.Builder
 open Gencommon
 open Gencommon
 
 
 (* ******************************************* *)
 (* ******************************************* *)
@@ -405,7 +406,7 @@ struct
 		Will also look for previous cast() definitions and override them, to reflect the current type and fields
 		Will also look for previous cast() definitions and override them, to reflect the current type and fields
 
 
 		FIXME: this function still doesn't support generics that extend generics, and are cast as one of its subclasses. This needs to be taken care, by
 		FIXME: this function still doesn't support generics that extend generics, and are cast as one of its subclasses. This needs to be taken care, by
-		looking at previous superclasses and whenever a generic class is found, its cast argument must be overriden. the toughest part is to know how to type
+		looking at previous superclasses and whenever a generic class is found, its cast argument must be overridden. the toughest part is to know how to type
 		the current type correctly.
 		the current type correctly.
 	*)
 	*)
 	let create_cast_cfield gen cl name =
 	let create_cast_cfield gen cl name =
@@ -468,12 +469,12 @@ struct
 						t_cf
 						t_cf
 						pos
 						pos
 				in
 				in
-				[ExprBuilder.make_string gen.gcon cf.cf_name pos], expr
+				[make_string gen.gcon.basic cf.cf_name pos], expr
 			) fields
 			) fields
 		in
 		in
 
 
 		let mk_typehandle =
 		let mk_typehandle =
-			(fun cl -> mk (TCall (mk (TIdent "__typeof__") t_dynamic pos, [ExprBuilder.make_static_this cl pos])) t_dynamic pos)
+			(fun cl -> mk (TCall (mk (TIdent "__typeof__") t_dynamic pos, [make_static_this cl pos])) t_dynamic pos)
 		in
 		in
 		let mk_eq cl1 cl2 =
 		let mk_eq cl1 cl2 =
 			binop OpEq (mk_typehandle cl1) (mk_typehandle cl2) basic.tbool pos
 			binop OpEq (mk_typehandle cl1) (mk_typehandle cl2) basic.tbool pos
@@ -503,7 +504,7 @@ struct
 				(* var fields = Reflect.fields(this); *)
 				(* var fields = Reflect.fields(this); *)
 				mk (TVar (fields_var, Some (gen.gtools.r_fields true this))) basic.tvoid pos;
 				mk (TVar (fields_var, Some (gen.gtools.r_fields true this))) basic.tvoid pos;
 				(* var i = 0; *)
 				(* var i = 0; *)
-				mk (TVar (i_var, Some (ExprBuilder.make_int gen.gcon 0 pos))) basic.tvoid pos;
+				mk (TVar (i_var, Some (make_int gen.gcon.basic 0 pos))) basic.tvoid pos;
 				(* while (i < fields.length) *)
 				(* while (i < fields.length) *)
 				mk (TWhile (
 				mk (TWhile (
 					binop OpLt local_i (mk_field_access gen local_fields "length" pos) basic.tbool pos,
 					binop OpLt local_i (mk_field_access gen local_fields "length" pos) basic.tbool pos,
@@ -711,7 +712,7 @@ let default_implementation gen (dyn_tparam_cast:texpr->t->texpr) ifaces =
 							false)
 							false)
 						| _ -> false
 						| _ -> false
 					in
 					in
-					let unifies = unifies && not (PMap.mem "cs_safe_casts" gen.gcon.defines) in
+					let unifies = unifies && not (PMap.mem "cs_safe_casts" gen.gcon.defines.Define.values) in
 					(match follow t with
 					(match follow t with
 						| TInst(cl, p1 :: pl) when is_hxgeneric (TClassDecl cl) && not unifies && not (Meta.has Meta.Enum cl.cl_meta) ->
 						| TInst(cl, p1 :: pl) when is_hxgeneric (TClassDecl cl) && not unifies && not (Meta.has Meta.Enum cl.cl_meta) ->
 							let iface = Hashtbl.find ifaces cl.cl_path in
 							let iface = Hashtbl.find ifaces cl.cl_path in

+ 18 - 17
src/generators/gencommon/reflectionCFs.ml → src/codegen/gencommon/reflectionCFs.ml

@@ -21,6 +21,7 @@ open Common
 open Ast
 open Ast
 open Type
 open Type
 open Codegen
 open Codegen
+open Texpr.Builder
 open Gencommon
 open Gencommon
 open ClosuresToClass
 open ClosuresToClass
 
 
@@ -238,7 +239,7 @@ let switch_case ctx pos field_name =
 			let i = hash_field_i32 ctx pos field_name in
 			let i = hash_field_i32 ctx pos field_name in
 			mk (TConst (TInt i)) ctx.rcf_gen.gcon.basic.tint pos
 			mk (TConst (TInt i)) ctx.rcf_gen.gcon.basic.tint pos
 		| false ->
 		| false ->
-			ExprBuilder.make_string ctx.rcf_gen.gcon field_name pos
+			make_string ctx.rcf_gen.gcon.basic field_name pos
 
 
 let call_super ctx fn_args ret_t cf cl this_t pos =
 let call_super ctx fn_args ret_t cf cl this_t pos =
 	{
 	{
@@ -264,7 +265,7 @@ let enumerate_dynamic_fields ctx cl when_found base_arr =
 		let convert_str e = if ctx.rcf_optimize then ctx.rcf_lookup_function e else e in
 		let convert_str e = if ctx.rcf_optimize then ctx.rcf_lookup_function e else e in
 		let tmpinc = { eexpr = TUnop(Ast.Increment, Ast.Postfix, mk_local vtmp pos); etype = basic.tint; epos = pos } in
 		let tmpinc = { eexpr = TUnop(Ast.Increment, Ast.Postfix, mk_local vtmp pos); etype = basic.tint; epos = pos } in
 		[
 		[
-			{ eexpr = TBinop(OpAssign, mk_local vtmp pos, ExprBuilder.make_int ctx.rcf_gen.gcon 0 pos); etype = basic.tint; epos = pos };
+			{ eexpr = TBinop(OpAssign, mk_local vtmp pos, make_int ctx.rcf_gen.gcon.basic 0 pos); etype = basic.tint; epos = pos };
 			{
 			{
 				eexpr = TWhile (
 				eexpr = TWhile (
 					{ eexpr = TBinop(Ast.OpLt, mk_local vtmp pos, len); etype = basic.tbool; epos = pos },
 					{ eexpr = TBinop(Ast.OpLt, mk_local vtmp pos, len); etype = basic.tbool; epos = pos },
@@ -378,12 +379,12 @@ let abstract_dyn_lookup_implementation ctx this field_local hash_local may_value
 				let vconflict = alloc_var "conflict" conflict_ctx.t in
 				let vconflict = alloc_var "conflict" conflict_ctx.t in
 				let local_conflict = mk_local vconflict pos in
 				let local_conflict = mk_local vconflict pos in
 				[mk (TIf (
 				[mk (TIf (
-					mk (TBinop (OpLt, hash_local, ExprBuilder.make_int gen.gcon 0 pos)) basic.tbool pos,
+					mk (TBinop (OpLt, hash_local, make_int gen.gcon.basic 0 pos)) basic.tbool pos,
 					mk (TBlock [
 					mk (TBlock [
 						mk (TVar (vconflict, Some (conflict_ctx.get_conflict ehead hash_local field_local))) basic.tvoid pos;
 						mk (TVar (vconflict, Some (conflict_ctx.get_conflict ehead hash_local field_local))) basic.tvoid pos;
 						mk (TIf (
 						mk (TIf (
 							mk (TBinop (OpNotEq, local_conflict, mk (TConst TNull) local_conflict.etype pos)) basic.tbool pos,
 							mk (TBinop (OpNotEq, local_conflict, mk (TConst TNull) local_conflict.etype pos)) basic.tbool pos,
-							mk_return (Codegen.field local_conflict "value" t_dynamic pos),
+							mk_return (field local_conflict "value" t_dynamic pos),
 							None
 							None
 						)) basic.tvoid pos;
 						)) basic.tvoid pos;
 					]) basic.tvoid pos,
 					]) basic.tvoid pos,
@@ -453,7 +454,7 @@ let abstract_dyn_lookup_implementation ctx this field_local hash_local may_value
 					let conflict_ctx = Option.get ctx.rcf_hash_conflict_ctx in
 					let conflict_ctx = Option.get ctx.rcf_hash_conflict_ctx in
 					let ehead = mk_this (mk_internal_name "hx" "conflicts") conflict_ctx.t in
 					let ehead = mk_this (mk_internal_name "hx" "conflicts") conflict_ctx.t in
 					[mk (TIf (
 					[mk (TIf (
-						mk (TBinop (OpLt, hash_local, ExprBuilder.make_int gen.gcon 0 pos)) basic.tbool pos,
+						mk (TBinop (OpLt, hash_local, make_int gen.gcon.basic 0 pos)) basic.tbool pos,
 						conflict_ctx.set ehead hash_local field_local value_local,
 						conflict_ctx.set ehead hash_local field_local value_local,
 						Some (mk (TBlock block) basic.tvoid pos)
 						Some (mk (TBlock block) basic.tvoid pos)
 					)) basic.tvoid pos]
 					)) basic.tvoid pos]
@@ -538,7 +539,7 @@ let get_delete_field ctx cl is_dynamic =
 			let conflict_ctx = Option.get ctx.rcf_hash_conflict_ctx in
 			let conflict_ctx = Option.get ctx.rcf_hash_conflict_ctx in
 			let ehead = mk_this (mk_internal_name "hx" "conflicts") conflict_ctx.t in
 			let ehead = mk_this (mk_internal_name "hx" "conflicts") conflict_ctx.t in
 			(mk (TIf (
 			(mk (TIf (
-				binop OpLt local_switch_var (ExprBuilder.make_int gen.gcon 0 pos) basic.tbool pos,
+				binop OpLt local_switch_var (make_int gen.gcon.basic 0 pos) basic.tbool pos,
 				mk_return (conflict_ctx.delete ehead local_switch_var local_name),
 				mk_return (conflict_ctx.delete ehead local_switch_var local_name),
 				None
 				None
 			)) basic.tvoid pos) :: common
 			)) basic.tvoid pos) :: common
@@ -693,14 +694,14 @@ let implement_dynamic_object_ctor ctx cl =
 		if ctx.rcf_optimize then begin
 		if ctx.rcf_optimize then begin
 			mk (TConst (TInt (hash_field_i32 ctx pos s))) basic.tint pos
 			mk (TConst (TInt (hash_field_i32 ctx pos s))) basic.tint pos
 		end else begin
 		end else begin
-			ExprBuilder.make_string gen.gcon s pos
+			make_string gen.gcon.basic s pos
 		end
 		end
 	in
 	in
 
 
 	let do_objdecl e objdecl =
 	let do_objdecl e objdecl =
 		let exprs_before = ref [] in
 		let exprs_before = ref [] in
 		let rec change_exprs decl acc = match decl with
 		let rec change_exprs decl acc = match decl with
-			| (name,expr) :: tl ->
+			| ((name,_,_),expr) :: tl ->
 				if is_side_effects_free expr then
 				if is_side_effects_free expr then
 					change_exprs tl ((name,expr) :: acc)
 					change_exprs tl ((name,expr) :: acc)
 				else begin
 				else begin
@@ -837,7 +838,7 @@ let implement_final_lookup ctx cl =
 
 
 	let mk_throw str pos =
 	let mk_throw str pos =
 		let e = ctx.rcf_mk_exception str pos in
 		let e = ctx.rcf_mk_exception str pos in
-		ExprBuilder.make_throw e pos
+		make_throw e pos
 	in
 	in
 
 
 	(*
 	(*
@@ -1219,7 +1220,7 @@ let implement_getFields ctx cl =
 				| Var _
 				| Var _
 				| Method MethDynamic when not (List.memq cf cl.cl_overrides) ->
 				| Method MethDynamic when not (List.memq cf cl.cl_overrides) ->
 					has_value := true;
 					has_value := true;
-					mk_push (ExprBuilder.make_string gen.gcon cf.cf_name pos)
+					mk_push (make_string gen.gcon.basic cf.cf_name pos)
 				| _ -> null basic.tvoid pos
 				| _ -> null basic.tvoid pos
 		)
 		)
 	in
 	in
@@ -1338,7 +1339,7 @@ let implement_invokeField ctx slow_invoke cl =
 			(cases,
 			(cases,
 				mk_return (
 				mk_return (
 					mk_this_call cf (List.map (fun (name,_,t) ->
 					mk_this_call cf (List.map (fun (name,_,t) ->
-						let ret = { eexpr = TArray(dyn_arg_local, ExprBuilder.make_int ctx.rcf_gen.gcon !i pos); etype = t_dynamic; epos = pos } in
+						let ret = { eexpr = TArray(dyn_arg_local, make_int ctx.rcf_gen.gcon.basic !i pos); etype = t_dynamic; epos = pos } in
 						incr i;
 						incr i;
 						ret
 						ret
 					) (fst (get_fun (cf.cf_type))))
 					) (fst (get_fun (cf.cf_type))))
@@ -1367,9 +1368,9 @@ let implement_invokeField ctx slow_invoke cl =
 				let tf_args, _ = field_type_args ctx pos in
 				let tf_args, _ = field_type_args ctx pos in
 				let tf_args, args = fun_args tf_args, field_args_exprs in
 				let tf_args, args = fun_args tf_args, field_args_exprs in
 
 
-				let tf_args, args = tf_args @ ["throwErrors",false, basic.tbool],       args @ [ExprBuilder.make_bool gen.gcon true pos] in
-				let tf_args, args = tf_args @ ["isCheck", false, basic.tbool],          args @ [ExprBuilder.make_bool gen.gcon false pos] in
-				let tf_args, args = tf_args @ ["handleProperties", false, basic.tbool], args @ [ExprBuilder.make_bool gen.gcon false pos] in
+				let tf_args, args = tf_args @ ["throwErrors",false, basic.tbool],       args @ [make_bool gen.gcon.basic true pos] in
+				let tf_args, args = tf_args @ ["isCheck", false, basic.tbool],          args @ [make_bool gen.gcon.basic false pos] in
+				let tf_args, args = tf_args @ ["handleProperties", false, basic.tbool], args @ [make_bool gen.gcon.basic false pos] in
 
 
 				mk (TCall ({ (mk_field_access gen this fun_name pos) with etype = TFun(tf_args, t_dynamic) }, args)) t_dynamic pos
 				mk (TCall ({ (mk_field_access gen this fun_name pos) with etype = TFun(tf_args, t_dynamic) }, args)) t_dynamic pos
 			end in
 			end in
@@ -1549,7 +1550,7 @@ let implement_closure_cl ctx cl =
 			tf_args = tf_args;
 			tf_args = tf_args;
 			tf_type = basic.tvoid;
 			tf_type = basic.tvoid;
 			tf_expr = { eexpr = TBlock({
 			tf_expr = { eexpr = TBlock({
-				eexpr = TCall({ eexpr = TConst(TSuper); etype = TInst(cl,[]); epos = pos }, [ExprBuilder.make_int ctx.rcf_gen.gcon (-1) pos; ExprBuilder.make_int ctx.rcf_gen.gcon (-1) pos]);
+				eexpr = TCall({ eexpr = TConst(TSuper); etype = TInst(cl,[]); epos = pos }, [make_int ctx.rcf_gen.gcon.basic (-1) pos; make_int ctx.rcf_gen.gcon.basic (-1) pos]);
 				etype = basic.tvoid;
 				etype = basic.tvoid;
 				epos = pos
 				epos = pos
 			} :: ctor_body); etype = basic.tvoid; epos = pos }
 			} :: ctor_body); etype = basic.tvoid; epos = pos }
@@ -1561,7 +1562,7 @@ let implement_closure_cl ctx cl =
 	cl.cl_constructor <- Some ctor_cf;
 	cl.cl_constructor <- Some ctor_cf;
 
 
 	let closure_fun eclosure e field is_static =
 	let closure_fun eclosure e field is_static =
-		let f = ExprBuilder.make_string gen.gcon field eclosure.epos in
+		let f = make_string gen.gcon.basic field eclosure.epos in
 		let args = if ctx.rcf_optimize then [ f; { eexpr = TConst(TInt (hash_field_i32 ctx eclosure.epos field)); etype = basic.tint; epos = eclosure.epos } ] else [ f ] in
 		let args = if ctx.rcf_optimize then [ f; { eexpr = TConst(TInt (hash_field_i32 ctx eclosure.epos field)); etype = basic.tint; epos = eclosure.epos } ] else [ f ] in
 		let args = args @ [ mk_cast (TInst(ctx.rcf_object_iface, [])) e ] in
 		let args = args @ [ mk_cast (TInst(ctx.rcf_object_iface, [])) e ] in
 
 
@@ -1576,7 +1577,7 @@ let get_closure_func ctx closure_cl =
 		mk_cast eclosure.etype { eclosure with
 		mk_cast eclosure.etype { eclosure with
 			eexpr = TNew(closure_cl, [], [
 			eexpr = TNew(closure_cl, [], [
 				e;
 				e;
-				ExprBuilder.make_string gen.gcon field eclosure.epos
+				make_string gen.gcon.basic field eclosure.epos
 			] @ (
 			] @ (
 				if ctx.rcf_optimize then [ { eexpr = TConst(TInt (hash_field_i32 ctx eclosure.epos field)); etype = basic.tint; epos = eclosure.epos } ] else []
 				if ctx.rcf_optimize then [ { eexpr = TConst(TInt (hash_field_i32 ctx eclosure.epos field)); etype = basic.tint; epos = eclosure.epos } ] else []
 			));
 			));

+ 0 - 0
src/generators/gencommon/renameTypeParameters.ml → src/codegen/gencommon/renameTypeParameters.ml


+ 0 - 0
src/generators/gencommon/setHXGen.ml → src/codegen/gencommon/setHXGen.ml


+ 1 - 1
src/generators/gencommon/switchToIf.ml → src/codegen/gencommon/switchToIf.ml

@@ -137,7 +137,7 @@ let configure gen (should_convert:texpr->bool) =
 						let fields = Hashtbl.create (List.length real_enum.e_names) in
 						let fields = Hashtbl.create (List.length real_enum.e_names) in
 						PMap.iter (fun _ ef -> Hashtbl.add fields ef.ef_index ef) real_enum.e_constrs;
 						PMap.iter (fun _ ef -> Hashtbl.add fields ef.ef_index ef) real_enum.e_constrs;
 
 
-						let enum_expr = ExprBuilder.make_typeexpr (TEnumDecl real_enum) e.epos in
+						let enum_expr = Texpr.Builder.make_typeexpr (TEnumDecl real_enum) e.epos in
 						let cases = List.map (fun (patterns, body) ->
 						let cases = List.map (fun (patterns, body) ->
 							let patterns = List.map (fun e ->
 							let patterns = List.map (fun e ->
 								match e.eexpr with
 								match e.eexpr with

+ 0 - 0
src/generators/gencommon/tArrayTransform.ml → src/codegen/gencommon/tArrayTransform.ml


+ 0 - 0
src/generators/gencommon/unnecessaryCastsRemoval.ml → src/codegen/gencommon/unnecessaryCastsRemoval.ml


+ 1 - 1
src/generators/gencommon/unreachableCodeEliminationSynf.ml → src/codegen/gencommon/unreachableCodeEliminationSynf.ml

@@ -129,7 +129,7 @@ let init com java_mode =
 			| TFunction tf ->
 			| TFunction tf ->
 				let changed, kind = process_expr tf.tf_expr in
 				let changed, kind = process_expr tf.tf_expr in
 				let changed = if not (ExtType.is_void tf.tf_type) && kind <> BreaksFunction then
 				let changed = if not (ExtType.is_void tf.tf_type) && kind <> BreaksFunction then
-					Type.concat changed (Codegen.mk_return (null tf.tf_type expr.epos))
+					Type.concat changed (Texpr.Builder.mk_return (null tf.tf_type expr.epos))
 				else
 				else
 					changed
 					changed
 				in
 				in

+ 10 - 8
src/generators/genxml.ml → src/codegen/genxml.ml

@@ -123,7 +123,7 @@ let rec gen_type ?(values=None) t =
 		node "f" (("a",names) :: values) (List.map gen_type (args @ [r]))
 		node "f" (("a",names) :: values) (List.map gen_type (args @ [r]))
 	| TAnon a -> node "a" [] (pmap (fun f -> gen_field [] { f with cf_public = false }) a.a_fields)
 	| TAnon a -> node "a" [] (pmap (fun f -> gen_field [] { f with cf_public = false }) a.a_fields)
 	| TDynamic t2 -> node "d" [] (if t == t2 then [] else [gen_type t2])
 	| TDynamic t2 -> node "d" [] (if t == t2 then [] else [gen_type t2])
-	| TLazy f -> gen_type (!f())
+	| TLazy f -> gen_type (lazy_type f)
 
 
 and gen_type_decl n t pl =
 and gen_type_decl n t pl =
 	let i = t_infos t in
 	let i = t_infos t in
@@ -132,7 +132,7 @@ and gen_type_decl n t pl =
 and gen_field att f =
 and gen_field att f =
 	let add_get_set acc name att =
 	let add_get_set acc name att =
 		match acc with
 		match acc with
-		| AccNormal | AccResolve | AccRequire _ -> att
+		| AccNormal | AccResolve | AccRequire _ | AccCtor -> att
 		| AccNo | AccNever -> (name, "null") :: att
 		| AccNo | AccNever -> (name, "null") :: att
 		| AccCall -> (name,"accessor") :: att
 		| AccCall -> (name,"accessor") :: att
 		| AccInline -> (name,"inline") :: att
 		| AccInline -> (name,"inline") :: att
@@ -171,7 +171,9 @@ and gen_field att f =
 		with Not_found ->
 		with Not_found ->
 			cf.cf_name
 			cf.cf_name
 	in
 	in
-	node (field_name f) (if f.cf_public then ("public","1") :: att else att) (gen_type ~values:(Some values) f.cf_type :: gen_meta f.cf_meta @ gen_doc_opt f.cf_doc @ overloads)
+	let att = if f.cf_public then ("public","1") :: att else att in
+	let att = if (Meta.has Meta.Final) f.cf_meta then ("final","1") :: att else att in
+	node (field_name f) att (gen_type ~values:(Some values) f.cf_type :: gen_meta f.cf_meta @ gen_doc_opt f.cf_doc @ overloads)
 
 
 let gen_constr e =
 let gen_constr e =
 	let doc = gen_doc_opt e.ef_doc in
 	let doc = gen_doc_opt e.ef_doc in
@@ -286,10 +288,10 @@ let rec write_xml ch tabs x =
 		IO.printf ch "<![CDATA[%s]]>" s
 		IO.printf ch "<![CDATA[%s]]>" s
 
 
 let generate com file =
 let generate com file =
-	let t = Common.timer ["generate";"xml"] in
+	let t = Timer.timer ["generate";"xml"] in
 	let x = node "haxe" [] (List.map (gen_type_decl com true) (List.filter (fun t -> not (Meta.has Meta.NoDoc (t_infos t).mt_meta)) com.types)) in
 	let x = node "haxe" [] (List.map (gen_type_decl com true) (List.filter (fun t -> not (Meta.has Meta.NoDoc (t_infos t).mt_meta)) com.types)) in
 	t();
 	t();
-	let t = Common.timer ["write";"xml"] in
+	let t = Timer.timer ["write";"xml"] in
 	let ch = IO.output_channel (open_out_bin file) in
 	let ch = IO.output_channel (open_out_bin file) in
 	IO.printf ch "<!-- This file can be parsed by haxe.rtti.XmlParser -->\n";
 	IO.printf ch "<!-- This file can be parsed by haxe.rtti.XmlParser -->\n";
 	write_xml ch "" x;
 	write_xml ch "" x;
@@ -356,7 +358,7 @@ let generate_type com t =
 			| None -> t
 			| None -> t
 			| Some t -> notnull t)
 			| Some t -> notnull t)
 		| TLazy f ->
 		| TLazy f ->
-			notnull ((!f)())
+			notnull (lazy_type f)
 		| TAbstract ({ a_path = [],"Null" },[t]) ->
 		| TAbstract ({ a_path = [],"Null" },[t]) ->
 			t
 			t
 		| _ ->
 		| _ ->
@@ -385,7 +387,7 @@ let generate_type com t =
 			let fields = PMap.fold (fun f acc -> (f.cf_name ^ " : " ^ stype f.cf_type) :: acc) a.a_fields [] in
 			let fields = PMap.fold (fun f acc -> (f.cf_name ^ " : " ^ stype f.cf_type) :: acc) a.a_fields [] in
 			"{" ^ String.concat ", " fields ^ "}"
 			"{" ^ String.concat ", " fields ^ "}"
 		| TLazy f ->
 		| TLazy f ->
-			stype ((!f)())
+			stype (lazy_type f)
 		| TDynamic t2 ->
 		| TDynamic t2 ->
 			if t == t2 then "Dynamic" else "Dynamic<" ^ stype t2 ^ ">"
 			if t == t2 then "Dynamic" else "Dynamic<" ^ stype t2 ^ ">"
 		| TFun ([],ret) ->
 		| TFun ([],ret) ->
@@ -399,7 +401,7 @@ let generate_type com t =
 			| None -> stype t
 			| None -> stype t
 			| Some t -> ftype t)
 			| Some t -> ftype t)
 		| TLazy f ->
 		| TLazy f ->
-			ftype ((!f)())
+			ftype (lazy_type f)
 		| TFun _ ->
 		| TFun _ ->
 			"(" ^ stype t ^ ")"
 			"(" ^ stype t ^ ")"
 		| _ ->
 		| _ ->

+ 6 - 6
src/typing/java.ml → src/codegen/java.ml

@@ -356,7 +356,7 @@ let convert_java_enum ctx p pe =
 							String.concat "_" parts,
 							String.concat "_" parts,
 							(Meta.Native, [EConst (String (cff_name) ), cff_pos], cff_pos) :: !cff_meta
 							(Meta.Native, [EConst (String (cff_name) ), cff_pos], cff_pos) :: !cff_meta
 		in
 		in
-		if PMap.mem "java_loader_debug" ctx.jcom.defines then
+		if PMap.mem "java_loader_debug" ctx.jcom.defines.Define.values then
 			Printf.printf "\t%s%sfield %s : %s\n" (if List.mem AStatic !cff_access then "static " else "") (if List.mem AOverride !cff_access then "override " else "") cff_name (s_sig field.jf_signature);
 			Printf.printf "\t%s%sfield %s : %s\n" (if List.mem AStatic !cff_access then "static " else "") (if List.mem AOverride !cff_access then "override " else "") cff_name (s_sig field.jf_signature);
 
 
 		{
 		{
@@ -398,7 +398,7 @@ let convert_java_enum ctx p pe =
 				[convert_java_enum ctx p jc]
 				[convert_java_enum ctx p jc]
 		| false ->
 		| false ->
 			let flags = ref [HExtern] in
 			let flags = ref [HExtern] in
-			if PMap.mem "java_loader_debug" ctx.jcom.defines then begin
+			if PMap.mem "java_loader_debug" ctx.jcom.defines.Define.values then begin
 				let sup = jc.csuper :: jc.cinterfaces in
 				let sup = jc.csuper :: jc.cinterfaces in
 				print_endline ("converting " ^ (if List.mem JAbstract jc.cflags then "abstract " else "") ^ JData.path_s jc.cpath ^ " : " ^ (String.concat ", " (List.map s_sig sup)));
 				print_endline ("converting " ^ (if List.mem JAbstract jc.cflags then "abstract " else "") ^ JData.path_s jc.cpath ^ " : " ^ (String.concat ", " (List.map s_sig sup)));
 			end;
 			end;
@@ -728,14 +728,14 @@ let fix_overrides_jclass com cls =
 			let super_methods = cls.cmethods @ super_methods in
 			let super_methods = cls.cmethods @ super_methods in
 			let super_fields = cls.cfields @ super_fields in
 			let super_fields = cls.cfields @ super_fields in
 			let cmethods = if force_check then begin
 			let cmethods = if force_check then begin
-				let overriden = ref [] in
+				let overridden = ref [] in
 				let cmethods = List.map (fun jm ->
 				let cmethods = List.map (fun jm ->
 					(* TODO rewrite/standardize empty spaces *)
 					(* TODO rewrite/standardize empty spaces *)
 					if not (is_override jm) && not (List.mem JStatic jm.jf_flags) && List.exists (fun msup ->
 					if not (is_override jm) && not (List.mem JStatic jm.jf_flags) && List.exists (fun msup ->
 						let ret = msup.jf_name = jm.jf_name && not(List.mem JStatic msup.jf_flags) && compatible_methods msup jm in
 						let ret = msup.jf_name = jm.jf_name && not(List.mem JStatic msup.jf_flags) && compatible_methods msup jm in
 						if ret then begin
 						if ret then begin
 							let f = mk_override msup in
 							let f = mk_override msup in
-							overriden := { f with jf_flags = jm.jf_flags } :: !overriden
+							overridden := { f with jf_flags = jm.jf_flags } :: !overridden
 						end;
 						end;
 						ret
 						ret
 					) cls.cmethods then
 					) cls.cmethods then
@@ -743,7 +743,7 @@ let fix_overrides_jclass com cls =
 					else
 					else
 						jm
 						jm
 				) cmethods in
 				) cmethods in
-				!overriden @ cmethods
+				!overridden @ cmethods
 			end else
 			end else
 				cmethods
 				cmethods
 			in
 			in
@@ -1144,7 +1144,7 @@ let add_java_lib com file std =
 
 
 let before_generate con =
 let before_generate con =
 	let java_ver = try
 	let java_ver = try
-			int_of_string (PMap.find "java_ver" con.defines)
+			int_of_string (PMap.find "java_ver" con.defines.Define.values)
 		with | Not_found ->
 		with | Not_found ->
 			Common.define_value con Define.JavaVer "7";
 			Common.define_value con Define.JavaVer "7";
 			7
 			7

+ 2 - 2
src/typing/overloads.ml → src/codegen/overloads.ml

@@ -14,7 +14,7 @@ let same_overload_args ?(get_vmtype) t1 t2 f1 f2 =
 			| Some t -> follow_skip_null t
 			| Some t -> follow_skip_null t
 			| _ -> t)
 			| _ -> t)
 		| TLazy f ->
 		| TLazy f ->
-			follow_skip_null (!f())
+			follow_skip_null (lazy_type f)
 		| TAbstract ({ a_path = [],"Null" } as a, [p]) ->
 		| TAbstract ({ a_path = [],"Null" } as a, [p]) ->
 			TAbstract(a,[follow p])
 			TAbstract(a,[follow p])
 		| TType (t,tl) ->
 		| TType (t,tl) ->
@@ -87,7 +87,7 @@ struct
 			| None -> t_dynamic)
 			| None -> t_dynamic)
 		| TAnon _ -> t_dynamic
 		| TAnon _ -> t_dynamic
 		| TDynamic _ -> t
 		| TDynamic _ -> t
-		| TLazy f -> simplify_t (!f())
+		| TLazy f -> simplify_t (lazy_type f)
 		| TFun _ -> t
 		| TFun _ -> t
 
 
 	(* rate type parameters *)
 	(* rate type parameters *)

+ 3 - 3
src/typing/swfLoader.ml → src/codegen/swfLoader.ml

@@ -235,7 +235,7 @@ let build_class com c file =
 							| HVInt i | HVUInt i ->
 							| HVInt i | HVUInt i ->
 								Some (Int (Int32.to_string i))
 								Some (Int (Int32.to_string i))
 							| HVFloat f ->
 							| HVFloat f ->
-								Some (Float (float_repres f))
+								Some (Float (Numeric.float_repres f))
 							) in
 							) in
 							match v with
 							match v with
 							| None -> None
 							| None -> None
@@ -358,7 +358,7 @@ let build_class com c file =
 	(path.tpackage, [(EClass class_data,pos)])
 	(path.tpackage, [(EClass class_data,pos)])
 
 
 let extract_data (_,tags) =
 let extract_data (_,tags) =
-	let t = Common.timer ["read";"swf"] in
+	let t = Timer.timer ["read";"swf"] in
 	let h = Hashtbl.create 0 in
 	let h = Hashtbl.create 0 in
 	let rec loop_field f =
 	let rec loop_field f =
 		match f.hlf_kind with
 		match f.hlf_kind with
@@ -450,7 +450,7 @@ let remove_debug_infos as3 =
 	As3hlparse.flatten (List.map loop_static hl)
 	As3hlparse.flatten (List.map loop_static hl)
 
 
 let parse_swf com file =
 let parse_swf com file =
-	let t = Common.timer ["read";"swf"] in
+	let t = Timer.timer ["read";"swf"] in
 	let is_swc = file_extension file = "swc" || file_extension file = "ane" in
 	let is_swc = file_extension file = "swc" || file_extension file = "ane" in
 	let file = (try Common.find_file com file with Not_found -> failwith ((if is_swc then "SWC" else "SWF") ^ " Library not found : " ^ file)) in
 	let file = (try Common.find_file com file with Not_found -> failwith ((if is_swc then "SWC" else "SWF") ^ " Library not found : " ^ file)) in
 	let ch = if is_swc then begin
 	let ch = if is_swc then begin

+ 4 - 3
src/display/displayOutput.ml → src/compiler/displayOutput.ml

@@ -1,5 +1,6 @@
 open Globals
 open Globals
 open Common
 open Common
+open Timer
 open Common.DisplayMode
 open Common.DisplayMode
 open Type
 open Type
 open Display
 open Display
@@ -16,12 +17,12 @@ let htmlescape s =
 
 
 let get_timer_fields start_time =
 let get_timer_fields start_time =
 	let tot = ref 0. in
 	let tot = ref 0. in
-	Hashtbl.iter (fun _ t -> tot := !tot +. t.total) Common.htimers;
+	Hashtbl.iter (fun _ t -> tot := !tot +. t.total) Timer.htimers;
 	let fields = [("@TOTAL", Printf.sprintf "%.3fs" (get_time() -. start_time))] in
 	let fields = [("@TOTAL", Printf.sprintf "%.3fs" (get_time() -. start_time))] in
 	if !tot > 0. then
 	if !tot > 0. then
 		Hashtbl.fold (fun _ t acc ->
 		Hashtbl.fold (fun _ t acc ->
 			((String.concat "." t.id),(Printf.sprintf "%.3fs (%.0f%%)" t.total (t.total *. 100. /. !tot))) :: acc
 			((String.concat "." t.id),(Printf.sprintf "%.3fs (%.0f%%)" t.total (t.total *. 100. /. !tot))) :: acc
-		) Common.htimers fields
+		) Timer.htimers fields
 	else
 	else
 		fields
 		fields
 
 
@@ -786,7 +787,7 @@ let process_global_display_mode com tctx = match com.display.dms_kind with
 		let symbols = match CompilationServer.get() with
 		let symbols = match CompilationServer.get() with
 			| None -> symbols
 			| None -> symbols
 			| Some cs ->
 			| Some cs ->
-				let l = CompilationServer.get_context_files cs ((get_signature com) :: (match com.get_macros() with None -> [] | Some com -> [get_signature com])) in
+				let l = CompilationServer.get_context_files cs ((Define.get_signature com.defines) :: (match com.get_macros() with None -> [] | Some com -> [Define.get_signature com.defines])) in
 				List.fold_left (fun acc (file,data) ->
 				List.fold_left (fun acc (file,data) ->
 					print_endline (Printf.sprintf "%s %b" file (is_display_file file));
 					print_endline (Printf.sprintf "%s %b" file (is_display_file file));
 					if (filter <> None || is_display_file file) then
 					if (filter <> None || is_display_file file) then

+ 40 - 67
src/compiler/main.ml

@@ -54,18 +54,8 @@ exception Abort
 let executable_path() =
 let executable_path() =
 	Extc.executable_path()
 	Extc.executable_path()
 
 
-let format msg p =
-	if p = null_pos then
-		msg
-	else begin
-		let error_printer file line = sprintf "%s:%d:" file line in
-		let epos = Lexer.get_error_pos error_printer p in
-		let msg = String.concat ("\n" ^ epos ^ " : ") (ExtString.String.nsplit msg "\n") in
-		sprintf "%s : %s" epos msg
-	end
-
-let message ctx msg p =
-	ctx.messages <- format msg p :: ctx.messages
+let message ctx msg =
+	ctx.messages <- msg :: ctx.messages
 
 
 let deprecated = []
 let deprecated = []
 
 
@@ -83,12 +73,12 @@ let limit_string s offset =
 
 
 let error ctx msg p =
 let error ctx msg p =
 	let msg = try List.assoc msg deprecated with Not_found -> msg in
 	let msg = try List.assoc msg deprecated with Not_found -> msg in
-	message ctx msg p;
+	message ctx (CMError(msg,p));
 	ctx.has_error <- true
 	ctx.has_error <- true
 
 
 let reserved_flags = [
 let reserved_flags = [
 	"cross";"js";"lua";"neko";"flash";"php";"cpp";"cs";"java";"python";
 	"cross";"js";"lua";"neko";"flash";"php";"cpp";"cs";"java";"python";
-	"as3";"swc";"macro";"sys"
+	"as3";"swc";"macro";"sys";"static"
 	]
 	]
 
 
 let delete_file f = try Sys.remove f with _ -> ()
 let delete_file f = try Sys.remove f with _ -> ()
@@ -109,7 +99,7 @@ let expand_env ?(h=None) path  =
 
 
 let add_libs com libs =
 let add_libs com libs =
 	let call_haxelib() =
 	let call_haxelib() =
-		let t = Common.timer ["haxelib"] in
+		let t = Timer.timer ["haxelib"] in
 		let cmd = "haxelib path " ^ String.concat " " libs in
 		let cmd = "haxelib path " ^ String.concat " " libs in
 		let pin, pout, perr = Unix.open_process_full cmd (Unix.environment()) in
 		let pin, pout, perr = Unix.open_process_full cmd (Unix.environment()) in
 		let lines = Std.input_list pin in
 		let lines = Std.input_list pin in
@@ -158,7 +148,7 @@ let run_command ctx cmd =
 	let h = Hashtbl.create 0 in
 	let h = Hashtbl.create 0 in
 	Hashtbl.add h "__file__" ctx.com.file;
 	Hashtbl.add h "__file__" ctx.com.file;
 	Hashtbl.add h "__platform__" (platform_name ctx.com.platform);
 	Hashtbl.add h "__platform__" (platform_name ctx.com.platform);
-	let t = Common.timer ["command"] in
+	let t = Timer.timer ["command"] in
 	let cmd = expand_env ~h:(Some h) cmd in
 	let cmd = expand_env ~h:(Some h) cmd in
 	let len = String.length cmd in
 	let len = String.length cmd in
 	if len > 3 && String.sub cmd 0 3 = "cd " then begin
 	if len > 3 && String.sub cmd 0 3 = "cd " then begin
@@ -180,7 +170,7 @@ let run_command ctx cmd =
 	let result = (match Unix.close_process_full (pout,pin,perr) with Unix.WEXITED c | Unix.WSIGNALED c | Unix.WSTOPPED c -> c) in
 	let result = (match Unix.close_process_full (pout,pin,perr) with Unix.WEXITED c | Unix.WSIGNALED c | Unix.WSTOPPED c -> c) in
 	let serr = binary_string (Buffer.contents berr) in
 	let serr = binary_string (Buffer.contents berr) in
 	let sout = binary_string (Buffer.contents bout) in
 	let sout = binary_string (Buffer.contents bout) in
-	if serr <> "" then ctx.messages <- (if serr.[String.length serr - 1] = '\n' then String.sub serr 0 (String.length serr - 1) else serr) :: ctx.messages;
+	if serr <> "" then ctx.messages <- CMError((if serr.[String.length serr - 1] = '\n' then String.sub serr 0 (String.length serr - 1) else serr),null_pos) :: ctx.messages;
 	if sout <> "" then ctx.com.print (sout ^ "\n");
 	if sout <> "" then ctx.com.print (sout ^ "\n");
 	t();
 	t();
 	result
 	result
@@ -218,7 +208,7 @@ module Initialize = struct
 				add_std "neko";
 				add_std "neko";
 				"n"
 				"n"
 			| 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.Define.values) then
 					Common.define_value com Define.JqueryVer "11204";
 					Common.define_value com Define.JqueryVer "11204";
 
 
 				let es_version =
 				let es_version =
@@ -242,14 +232,7 @@ module Initialize = struct
 				add_std "lua";
 				add_std "lua";
 				"lua"
 				"lua"
 			| Php ->
 			| Php ->
-				if Common.is_php7 com then
-					begin
-						com.package_rules <- PMap.add "php" (Directory "php7") com.package_rules;
-						com.package_rules <- PMap.add "php7" Forbidden com.package_rules;
-						add_std "php7"
-					end
-				else
-					add_std "php";
+				add_std "php";
 				"php"
 				"php"
 			| Cpp ->
 			| Cpp ->
 				Common.define_value com Define.HxcppApiLevel "332";
 				Common.define_value com Define.HxcppApiLevel "332";
@@ -276,6 +259,8 @@ module Initialize = struct
 				add_std "java"; "java"
 				add_std "java"; "java"
 			| Python ->
 			| Python ->
 				add_std "python";
 				add_std "python";
+				if not (Common.defined com Define.PythonVersion) then
+					Common.define_value com Define.PythonVersion "3.3";
 				"python"
 				"python"
 			| Hl ->
 			| Hl ->
 				add_std "hl";
 				add_std "hl";
@@ -296,16 +281,16 @@ let generate tctx ext xml_out interp swf_header =
 		Codegen.Dump.dump_dependencies com;
 		Codegen.Dump.dump_dependencies com;
 		if not tctx.Typecore.in_macro then match tctx.Typecore.g.Typecore.macros with
 		if not tctx.Typecore.in_macro then match tctx.Typecore.g.Typecore.macros with
 			| None -> ()
 			| None -> ()
-			| Some(_,ctx) -> print_endline "generate"; Codegen.Dump.dump_dependencies ~target_override:(Some "macro") ctx.Typecore.com
+			| Some(_,ctx) -> Codegen.Dump.dump_dependencies ~target_override:(Some "macro") ctx.Typecore.com
 	end;
 	end;
 	begin match com.platform with
 	begin match com.platform with
 		| Neko | Hl | Eval when interp -> ()
 		| Neko | Hl | Eval when interp -> ()
 		| Cpp when Common.defined com Define.Cppia -> ()
 		| Cpp when Common.defined com Define.Cppia -> ()
-		| Cpp | Cs | Java | Php -> Common.mkdir_from_path (com.file ^ "/.")
-		| _ -> Common.mkdir_from_path com.file
+		| Cpp | Cs | Java | Php -> Path.mkdir_from_path (com.file ^ "/.")
+		| _ -> Path.mkdir_from_path com.file
 	end;
 	end;
 	if interp then
 	if interp then
-		Std.finally (Common.timer ["interp"]) MacroContext.interpret tctx
+		Std.finally (Timer.timer ["interp"]) MacroContext.interpret tctx
 	else if com.platform = Cross then
 	else if com.platform = Cross then
 		()
 		()
 	else begin
 	else begin
@@ -321,10 +306,7 @@ let generate tctx ext xml_out interp swf_header =
 		| Lua ->
 		| Lua ->
 			Genlua.generate,"lua"
 			Genlua.generate,"lua"
 		| Php ->
 		| Php ->
-			if Common.is_php7 com then
-				Genphp7.generate,"php"
-			else
-				Genphp.generate,"php"
+			Genphp7.generate,"php"
 		| Cpp ->
 		| Cpp ->
 			Gencpp.generate,"cpp"
 			Gencpp.generate,"cpp"
 		| Cs ->
 		| Cs ->
@@ -341,7 +323,7 @@ let generate tctx ext xml_out interp swf_header =
 			assert false
 			assert false
 		in
 		in
 		Common.log com ("Generating " ^ name ^ ": " ^ com.file);
 		Common.log com ("Generating " ^ name ^ ": " ^ com.file);
-		let t = Common.timer ["generate";name] in
+		let t = Timer.timer ["generate";name] in
 		generate com;
 		generate com;
 		t()
 		t()
 	end
 	end
@@ -453,7 +435,7 @@ try
 	Common.define_value com Define.HaxeVer (Printf.sprintf "%.3f" (float_of_int Globals.version /. 1000.));
 	Common.define_value com Define.HaxeVer (Printf.sprintf "%.3f" (float_of_int Globals.version /. 1000.));
 	Common.raw_define com "haxe3";
 	Common.raw_define com "haxe3";
 	Common.define_value com Define.Dce "std";
 	Common.define_value com Define.Dce "std";
-	com.warning <- (fun msg p -> message ctx ("Warning : " ^ msg) p);
+	com.warning <- (fun msg p -> message ctx (CMWarning(msg,p)));
 	com.error <- error ctx;
 	com.error <- error ctx;
 	if CompilationServer.runs() then com.run_command <- run_command ctx;
 	if CompilationServer.runs() then com.run_command <- run_command ctx;
 	Parser.display_error := (fun e p -> com.error (Parser.error_msg e) p);
 	Parser.display_error := (fun e p -> com.error (Parser.error_msg e) p);
@@ -654,19 +636,6 @@ try
 			com.foptimize <- false;
 			com.foptimize <- false;
 			Common.define com Define.NoOpt;
 			Common.define com Define.NoOpt;
 		), ": disable code optimizations");
 		), ": disable code optimizations");
-		("--php-front",Arg.String (fun f ->
-			if com.php_front <> None then raise (Arg.Bad "Multiple --php-front");
-			com.php_front <- Some f;
-		),"<filename> : select the name for the php front file");
-		("--php-lib",Arg.String (fun f ->
-			if com.php_lib <> None then raise (Arg.Bad "Multiple --php-lib");
-			com.php_lib <- Some f;
-		),"<filename> : select the name for the php lib folder");
-		("--php-prefix", Arg.String (fun f ->
-			if com.php_prefix <> None then raise (Arg.Bad "Multiple --php-prefix");
-			com.php_prefix <- Some f;
-			Common.define com Define.PhpPrefix;
-		),"<name> : prefix all classes with given name");
 		("--remap", Arg.String (fun s ->
 		("--remap", Arg.String (fun s ->
 			let pack, target = (try ExtString.String.split s ":" with _ -> raise (Arg.Bad "Invalid remap format, expected source:target")) in
 			let pack, target = (try ExtString.String.split s ":" with _ -> raise (Arg.Bad "Invalid remap format, expected source:target")) in
 			com.package_rules <- PMap.add pack (Remap target) com.package_rules;
 			com.package_rules <- PMap.add pack (Remap target) com.package_rules;
@@ -690,7 +659,7 @@ try
 					init_wait_socket com.verbose host port
 					init_wait_socket com.verbose host port
 			in
 			in
 			wait_loop process_params com.verbose accept
 			wait_loop process_params com.verbose accept
-		),"<[host:]port> : wait on the given port for commands to run)");
+		),"[[host:]port]|stdio] : wait on the given port (or use standard i/o) for commands to run)");
 		("--connect",Arg.String (fun _ ->
 		("--connect",Arg.String (fun _ ->
 			assert false
 			assert false
 		),"<[host:]port> : connect on the given port and run commands there)");
 		),"<[host:]port> : connect on the given port and run commands there)");
@@ -698,7 +667,7 @@ try
 			assert false
 			assert false
 		),"<dir> : set current working directory");
 		),"<dir> : set current working directory");
 		("-version",Arg.Unit (fun() ->
 		("-version",Arg.Unit (fun() ->
-			message ctx s_version null_pos;
+			message ctx (CMInfo(s_version,null_pos));
 			did_something := true;
 			did_something := true;
 		),": print version and exit");
 		),": print version and exit");
 		("--help-defines", Arg.Unit (fun() ->
 		("--help-defines", Arg.Unit (fun() ->
@@ -745,11 +714,15 @@ try
 	process ctx.com.args;
 	process ctx.com.args;
 	process_libs();
 	process_libs();
 	if com.display.dms_display then begin
 	if com.display.dms_display then begin
-		com.warning <- if com.display.dms_error_policy = EPCollect then (fun s p -> add_diagnostics_message com s p DisplayTypes.DiagnosticsSeverity.Warning) else message ctx;
+		com.warning <-
+			if com.display.dms_error_policy = EPCollect then
+				(fun s p -> add_diagnostics_message com s p DisplayTypes.DiagnosticsSeverity.Warning)
+			else
+				(fun msg p -> message ctx (CMWarning(msg,p)));
 		com.error <- error ctx;
 		com.error <- error ctx;
 	end;
 	end;
 	Lexer.old_format := Common.defined com Define.OldErrorFormat;
 	Lexer.old_format := Common.defined com Define.OldErrorFormat;
-	if !Lexer.old_format && !Parser.resume_display <> null_pos then begin
+	if !Lexer.old_format && Parser.do_resume () then begin
 		let p = !Parser.resume_display in
 		let p = !Parser.resume_display in
 		(* convert byte position to utf8 position *)
 		(* convert byte position to utf8 position *)
 		try
 		try
@@ -779,8 +752,8 @@ try
 	end else begin
 	end else begin
 		ctx.setup();
 		ctx.setup();
 		Common.log com ("Classpath : " ^ (String.concat ";" com.class_path));
 		Common.log com ("Classpath : " ^ (String.concat ";" com.class_path));
-		Common.log com ("Defines : " ^ (String.concat ";" (PMap.foldi (fun k v acc -> (match v with "1" -> k | _ -> k ^ "=" ^ v) :: acc) com.defines [])));
-		let t = Common.timer ["typing"] in
+		Common.log com ("Defines : " ^ (String.concat ";" (PMap.foldi (fun k v acc -> (match v with "1" -> k | _ -> k ^ "=" ^ v) :: acc) com.defines.Define.values [])));
+		let t = Timer.timer ["typing"] in
 		Typecore.type_expr_ref := (fun ctx e with_type -> Typer.type_expr ctx e with_type);
 		Typecore.type_expr_ref := (fun ctx e with_type -> Typer.type_expr ctx e with_type);
 		let tctx = Typer.create com in
 		let tctx = Typer.create com in
 		List.iter (MacroContext.call_init_macro tctx) (List.rev !config_macros);
 		List.iter (MacroContext.call_init_macro tctx) (List.rev !config_macros);
@@ -792,7 +765,7 @@ try
 			if ctx.has_next || ctx.has_error then raise Abort;
 			if ctx.has_next || ctx.has_error then raise Abort;
 			failwith "No completion point was found";
 			failwith "No completion point was found";
 		end;
 		end;
-		let t = Common.timer ["filters"] in
+		let t = Timer.timer ["filters"] in
 		let main, types, modules = Typer.generate tctx in
 		let main, types, modules = Typer.generate tctx in
 		com.main <- main;
 		com.main <- main;
 		com.types <- types;
 		com.types <- types;
@@ -809,7 +782,7 @@ try
 			Genxml.generate_hx com
 			Genxml.generate_hx com
 		| Some file ->
 		| Some file ->
 			Common.log com ("Generating xml : " ^ file);
 			Common.log com ("Generating xml : " ^ file);
-			Common.mkdir_from_path file;
+			Path.mkdir_from_path file;
 			Genxml.generate com file);
 			Genxml.generate com file);
 		if not !no_output then generate tctx ext !xml_out !interp !swf_header;
 		if not !no_output then generate tctx ext !xml_out !interp !swf_header;
 	end;
 	end;
@@ -842,9 +815,9 @@ with
 		end
 		end
 	| Error.Error (m,p) ->
 	| Error.Error (m,p) ->
 		error ctx (Error.error_msg m) p
 		error ctx (Error.error_msg m) p
-	| Interp.Error (msg,p :: l) | Hlmacro.Error (msg,p :: l) ->
-		message ctx msg p;
-		List.iter (message ctx "Called from") l;
+	| Hlmacro.Error (msg,p :: l) ->
+		message ctx (CMError(msg,p));
+		List.iter (fun p -> message ctx (CMError("Called from",p))) l;
 		error ctx "Aborted" null_pos;
 		error ctx "Aborted" null_pos;
 	| Typeload.Generic_Exception(m,p) ->
 	| Typeload.Generic_Exception(m,p) ->
 		error ctx m p
 		error ctx m p
@@ -853,7 +826,7 @@ with
 	| Failure msg when not (is_debug_run()) ->
 	| Failure msg when not (is_debug_run()) ->
 		error ctx ("Error: " ^ msg) null_pos
 		error ctx ("Error: " ^ msg) null_pos
 	| Arg.Help msg ->
 	| Arg.Help msg ->
-		message ctx msg null_pos
+		message ctx (CMInfo(msg,null_pos))
 	| Display.DisplayPackage pack ->
 	| Display.DisplayPackage pack ->
 		raise (DisplayOutput.Completion (String.concat "." pack))
 		raise (DisplayOutput.Completion (String.concat "." pack))
 	| Display.DisplayFields fields ->
 	| Display.DisplayFields fields ->
@@ -862,7 +835,7 @@ with
 		) fields in
 		) fields in
 		let fields =
 		let fields =
 			if !measure_times then begin
 			if !measure_times then begin
-				close_times();
+				Timer.close_times();
 				(List.map (fun (name,value) -> ("@TIME " ^ name, Display.FKTimer value, "")) (DisplayOutput.get_timer_fields !start_time)) @ fields
 				(List.map (fun (name,value) -> ("@TIME " ^ name, Display.FKTimer value, "")) (DisplayOutput.get_timer_fields !start_time)) @ fields
 			end else
 			end else
 				fields
 				fields
@@ -881,7 +854,7 @@ with
 	| Display.DisplayToplevel il ->
 	| Display.DisplayToplevel il ->
 		let il =
 		let il =
 			if !measure_times then begin
 			if !measure_times then begin
-				close_times();
+				Timer.close_times();
 				(List.map (fun (name,value) -> IdentifierType.ITTimer ("@TIME " ^ name ^ ": " ^ value)) (DisplayOutput.get_timer_fields !start_time)) @ il
 				(List.map (fun (name,value) -> IdentifierType.ITTimer ("@TIME " ^ name ^ ": " ^ value)) (DisplayOutput.get_timer_fields !start_time)) @ il
 			end else
 			end else
 				il
 				il
@@ -901,15 +874,15 @@ with
 		Option.may (fun fields -> raise (DisplayOutput.Completion (DisplayOutput.print_fields fields))) fields
 		Option.may (fun fields -> raise (DisplayOutput.Completion (DisplayOutput.print_fields fields))) fields
 	| Display.ModuleSymbols s | Display.Diagnostics s | Display.Statistics s | Display.Metadata s ->
 	| Display.ModuleSymbols s | Display.Diagnostics s | Display.Statistics s | Display.Metadata s ->
 		raise (DisplayOutput.Completion s)
 		raise (DisplayOutput.Completion s)
-	| Interp.Sys_exit i | Hlinterp.Sys_exit i ->
+	| EvalExceptions.Sys_exit i | Hlinterp.Sys_exit i ->
 		ctx.flush();
 		ctx.flush();
-		if !measure_times then report_times prerr_endline;
+		if !measure_times then Timer.report_times prerr_endline;
 		exit i
 		exit i
 	| e when (try Sys.getenv "OCAMLRUNPARAM" <> "b" || CompilationServer.runs() with _ -> true) && not (is_debug_run()) ->
 	| e when (try Sys.getenv "OCAMLRUNPARAM" <> "b" || CompilationServer.runs() with _ -> true) && not (is_debug_run()) ->
 		error ctx (Printexc.to_string e) null_pos
 		error ctx (Printexc.to_string e) null_pos
 
 
 ;;
 ;;
-let other = Common.timer ["other"] in
+let other = Timer.timer ["other"] in
 Sys.catch_break true;
 Sys.catch_break true;
 MacroContext.setup();
 MacroContext.setup();
 let args = List.tl (Array.to_list Sys.argv) in
 let args = List.tl (Array.to_list Sys.argv) in
@@ -927,4 +900,4 @@ with DisplayOutput.Completion c ->
 	exit 1
 	exit 1
 );
 );
 other();
 other();
-if !measure_times then report_times prerr_endline
+if !measure_times then Timer.report_times prerr_endline

+ 29 - 113
src/compiler/server.ml

@@ -3,6 +3,7 @@ open Globals
 open Ast
 open Ast
 open Common
 open Common
 open Common.DisplayMode
 open Common.DisplayMode
+open Timer
 open Type
 open Type
 open DisplayOutput
 open DisplayOutput
 open Json
 open Json
@@ -11,7 +12,7 @@ exception Dirty of module_def
 
 
 let measure_times = ref false
 let measure_times = ref false
 let prompt = ref false
 let prompt = ref false
-let start_time = ref (get_time())
+let start_time = ref (Timer.get_time())
 
 
 let is_debug_run() =
 let is_debug_run() =
 	try Sys.getenv "HAXEDEBUG" = "1" with _ -> false
 	try Sys.getenv "HAXEDEBUG" = "1" with _ -> false
@@ -20,7 +21,7 @@ type context = {
 	com : Common.context;
 	com : Common.context;
 	mutable flush : unit -> unit;
 	mutable flush : unit -> unit;
 	mutable setup : unit -> unit;
 	mutable setup : unit -> unit;
-	mutable messages : string list;
+	mutable messages : compiler_message list;
 	mutable has_next : bool;
 	mutable has_next : bool;
 	mutable has_error : bool;
 	mutable has_error : bool;
 }
 }
@@ -39,104 +40,13 @@ type server_message =
 let s_version =
 let s_version =
 	Printf.sprintf "%d.%d.%d%s" version_major version_minor version_revision (match Version.version_extra with None -> "" | Some v -> " " ^ v)
 	Printf.sprintf "%d.%d.%d%s" version_major version_minor version_revision (match Version.version_extra with None -> "" | Some v -> " " ^ v)
 
 
-type timer_node = {
-	name : string;
-	path : string;
-	parent : timer_node;
-	info : string;
-	mutable time : float;
-	mutable num_calls : int;
-	mutable children : timer_node list;
-}
-
-let report_times print =
-	let nodes = Hashtbl.create 0 in
-	let rec root = {
-		name = "";
-		path = "";
-		parent = root;
-		info = "";
-		time = 0.;
-		num_calls = 0;
-		children = [];
-	} in
-	Hashtbl.iter (fun _ timer ->
-		let rec loop parent sl = match sl with
-			| [] -> assert false
-			| s :: sl ->
-				let path = (match parent.path with "" -> "" | _ -> parent.path ^ ".") ^ s in
-				let node = try
-					let node = Hashtbl.find nodes path in
-					node.num_calls <- node.num_calls + timer.calls;
-					node.time <- node.time +. timer.total;
-					node
-				with Not_found ->
-					let name,info = try
-						let i = String.rindex s '.' in
-						String.sub s (i + 1) (String.length s - i - 1),String.sub s 0 i
-					with Not_found ->
-						s,""
-					in
-					let node = {
-						name = name;
-						path = path;
-						parent = parent;
-						info = info;
-						time = timer.total;
-						num_calls = timer.calls;
-						children = [];
-					} in
-					Hashtbl.add nodes path node;
-					node
-				in
-				begin match sl with
-					| [] -> ()
-					| _ ->
-						let child = loop node sl in
-						if not (List.memq child node.children) then
-							node.children <- child :: node.children;
-				end;
-				node
-		in
-		let node = loop root timer.id in
-		if not (List.memq node root.children) then
-			root.children <- node :: root.children
-	) Common.htimers;
-	let max_name = ref 0 in
-	let max_calls = ref 0 in
-	let rec loop depth node =
-		let l = (String.length node.name) + 2 * depth in
-		if l > !max_name then max_name := l;
-		List.iter (fun child ->
-			if depth = 0 then begin
-				node.num_calls <- node.num_calls + child.num_calls;
-				node.time <- node.time +. child.time;
-			end;
-			loop (depth + 1) child;
-		) node.children;
-		node.children <- List.sort (fun node1 node2 -> compare node2.time node1.time) node.children;
-		if node.num_calls > !max_calls then max_calls := node.num_calls;
-	in
-	loop 0 root;
-	let max_calls = String.length (string_of_int !max_calls) in
-	print (Printf.sprintf "%-*s | %7s |   %% |  p%% | %*s | info" !max_name "name" "time(s)" max_calls "#");
-	let sep = String.make (!max_name + max_calls + 27) '-' in
-	print sep;
-	let print_time name node =
-		if node.time > 0.0009 then
-			print (Printf.sprintf "%-*s | %7.3f | %3.0f | %3.0f | %*i | %s" !max_name name node.time (node.time *. 100. /. root.time) (node.time *. 100. /. node.parent.time) max_calls node.num_calls node.info)
-	in
-	let rec loop depth node =
-		let name = (String.make (depth * 2) ' ') ^ node.name in
-		print_time name node;
-		List.iter (loop (depth + 1)) node.children
-	in
-	List.iter (loop 0) root.children;
-	print sep;
-	print_time "total" root
-
 let default_flush ctx =
 let default_flush ctx =
-	List.iter prerr_endline (List.rev ctx.messages);
+	List.iter
+		(fun msg -> match msg with
+			| CMInfo _ -> print_endline (compiler_message_string msg)
+			| CMWarning _ | CMError _ -> prerr_endline (compiler_message_string msg)
+		)
+		(List.rev ctx.messages);
 	if ctx.has_error && !prompt then begin
 	if ctx.has_error && !prompt then begin
 		print_endline "Press enter to exit...";
 		print_endline "Press enter to exit...";
 		ignore(read_line());
 		ignore(read_line());
@@ -193,7 +103,7 @@ let rec wait_loop process_params verbose accept =
 	let test_server_messages = DynArray.create () in
 	let test_server_messages = DynArray.create () in
 	let cs = CompilationServer.create () in
 	let cs = CompilationServer.create () in
 	let sign_string com =
 	let sign_string com =
-		let sign = get_signature com in
+		let sign = Define.get_signature com.defines in
 		let	sign_id =
 		let	sign_id =
 			try
 			try
 				CompilationServer.get_sign cs sign;
 				CompilationServer.get_sign cs sign;
@@ -245,7 +155,7 @@ let rec wait_loop process_params verbose accept =
 		| true, Some stdin when Common.defined com2 Define.DisplayStdin ->
 		| true, Some stdin when Common.defined com2 Define.DisplayStdin ->
 			Typeload.parse_file_from_string com2 file p stdin
 			Typeload.parse_file_from_string com2 file p stdin
 		| _ ->
 		| _ ->
-			let sign = get_signature com2 in
+			let sign = Define.get_signature com2.defines in
 			let ftime = file_time ffile in
 			let ftime = file_time ffile in
 			let fkey = (ffile,sign) in
 			let fkey = (ffile,sign) in
 			try
 			try
@@ -289,9 +199,9 @@ let rec wait_loop process_params verbose accept =
 		(Unix.stat (Path.remove_trailing_slash dir)).Unix.st_mtime
 		(Unix.stat (Path.remove_trailing_slash dir)).Unix.st_mtime
 	in
 	in
 	let get_changed_directories (ctx : Typecore.typer) =
 	let get_changed_directories (ctx : Typecore.typer) =
-		let t = Common.timer ["server";"module cache";"changed dirs"] in
+		let t = Timer.timer ["server";"module cache";"changed dirs"] in
 		let com = ctx.Typecore.com in
 		let com = ctx.Typecore.com in
-		let sign = get_signature com in
+		let sign = Define.get_signature com.defines in
 		let dirs = try
 		let dirs = try
 			(* First, check if we already have determined changed directories for current compilation. *)
 			(* First, check if we already have determined changed directories for current compilation. *)
 			Hashtbl.find changed_directories sign
 			Hashtbl.find changed_directories sign
@@ -355,9 +265,9 @@ let rec wait_loop process_params verbose accept =
 	let compilation_mark = ref 0 in
 	let compilation_mark = ref 0 in
 	let mark_loop = ref 0 in
 	let mark_loop = ref 0 in
 	Typeload.type_module_hook := (fun (ctx:Typecore.typer) mpath p ->
 	Typeload.type_module_hook := (fun (ctx:Typecore.typer) mpath p ->
-		let t = Common.timer ["server";"module cache"] in
+		let t = Timer.timer ["server";"module cache"] in
 		let com2 = ctx.Typecore.com in
 		let com2 = ctx.Typecore.com in
-		let sign = get_signature com2 in
+		let sign = Define.get_signature com2.defines in
 		let content_changed m file =
 		let content_changed m file =
 			let ffile = Path.unique_full_path file in
 			let ffile = Path.unique_full_path file in
 			let fkey = (ffile,sign) in
 			let fkey = (ffile,sign) in
@@ -475,13 +385,13 @@ let rec wait_loop process_params verbose accept =
 					PMap.iter (Hashtbl.replace com2.resources) m.m_extra.m_binded_res;
 					PMap.iter (Hashtbl.replace com2.resources) m.m_extra.m_binded_res;
 					if ctx.Typecore.in_macro || com2.display.dms_full_typing then
 					if ctx.Typecore.in_macro || com2.display.dms_full_typing then
 						PMap.iter (fun _ m2 -> add_modules (tabs ^ "  ") m0 m2) m.m_extra.m_deps;
 						PMap.iter (fun _ m2 -> add_modules (tabs ^ "  ") m0 m2) m.m_extra.m_deps;
-					List.iter (MacroContext.call_init_macro ctx) m.m_extra.m_macro_calls
+					List.iter (MacroContext.call_init_macro ctx) m.m_extra.m_reuse_macro_calls
 				)
 				)
 			end
 			end
 		in
 		in
 		try
 		try
 			let m = CompilationServer.find_module cs (mpath,sign) in
 			let m = CompilationServer.find_module cs (mpath,sign) in
-			let tcheck = Common.timer ["server";"module cache";"check"] in
+			let tcheck = Timer.timer ["server";"module cache";"check"] in
 			begin match check m with
 			begin match check m with
 			| None -> ()
 			| None -> ()
 			| Some m' ->
 			| Some m' ->
@@ -490,7 +400,7 @@ let rec wait_loop process_params verbose accept =
 				raise Not_found;
 				raise Not_found;
 			end;
 			end;
 			tcheck();
 			tcheck();
-			let tadd = Common.timer ["server";"module cache";"add modules"] in
+			let tadd = Timer.timer ["server";"module cache";"add modules"] in
 			add_modules "" m m;
 			add_modules "" m m;
 			tadd();
 			tadd();
 			t();
 			t();
@@ -520,16 +430,22 @@ let rec wait_loop process_params verbose accept =
 			ctx.flush <- (fun() ->
 			ctx.flush <- (fun() ->
 				incr compilation_step;
 				incr compilation_step;
 				compilation_mark := !mark_loop;
 				compilation_mark := !mark_loop;
-				List.iter (fun s -> write (s ^ "\n"); if verbose then print_endline ("> " ^ s)) (List.rev ctx.messages);
+				List.iter
+					(fun msg ->
+						let s = compiler_message_string msg in
+						write (s ^ "\n");
+						if verbose then print_endline ("> " ^ s)
+					)
+					(List.rev ctx.messages);
 				if ctx.has_error then begin
 				if ctx.has_error then begin
 					measure_times := false;
 					measure_times := false;
 					write "\x02\n"
 					write "\x02\n"
 				end else cache_context ctx.com;
 				end else cache_context ctx.com;
 			);
 			);
 			ctx.setup <- (fun() ->
 			ctx.setup <- (fun() ->
-				let sign = get_signature ctx.com in
+				let sign = Define.get_signature ctx.com.defines in
 				if verbose then begin
 				if verbose then begin
-					let defines = PMap.foldi (fun k v acc -> (k ^ "=" ^ v) :: acc) ctx.com.defines [] in
+					let defines = PMap.foldi (fun k v acc -> (k ^ "=" ^ v) :: acc) ctx.com.defines.Define.values [] in
 					print_endline ("Defines " ^ (String.concat "," (List.sort compare defines)));
 					print_endline ("Defines " ^ (String.concat "," (List.sort compare defines)));
 					print_endline ("Using signature " ^ Digest.to_hex sign);
 					print_endline ("Using signature " ^ Digest.to_hex sign);
 					print_endline ("Display position: " ^ (Printer.s_pos !Parser.resume_display));
 					print_endline ("Display position: " ^ (Printer.s_pos !Parser.resume_display));
@@ -580,8 +496,8 @@ let rec wait_loop process_params verbose accept =
 				stats.s_classes_built := 0;
 				stats.s_classes_built := 0;
 				stats.s_methods_typed := 0;
 				stats.s_methods_typed := 0;
 				stats.s_macros_called := 0;
 				stats.s_macros_called := 0;
-				Hashtbl.clear Common.htimers;
-				let _ = Common.timer ["other"] in
+				Hashtbl.clear Timer.htimers;
+				let _ = Timer.timer ["other"] in
 				incr compilation_step;
 				incr compilation_step;
 				compilation_mark := !mark_loop;
 				compilation_mark := !mark_loop;
 				start_time := get_time();
 				start_time := get_time();

+ 67 - 426
src/context/common.ml

@@ -20,6 +20,7 @@
 open Ast
 open Ast
 open Type
 open Type
 open Globals
 open Globals
+open Define
 
 
 type package_rule =
 type package_rule =
 	| Forbidden
 	| Forbidden
@@ -28,16 +29,6 @@ type package_rule =
 
 
 type pos = Globals.pos
 type pos = Globals.pos
 
 
-type basic_types = {
-	mutable tvoid : t;
-	mutable tint : t;
-	mutable tfloat : t;
-	mutable tbool : t;
-	mutable tnull : t -> t;
-	mutable tstring : t;
-	mutable tarray : t -> t;
-}
-
 let const_type basic const default =
 let const_type basic const default =
 	match const with
 	match const with
 	| TString _ -> basic.tstring
 	| TString _ -> basic.tstring
@@ -53,6 +44,25 @@ type stats = {
 	s_macros_called : int ref;
 	s_macros_called : int ref;
 }
 }
 
 
+type compiler_message =
+	| CMInfo of string * pos
+	| CMWarning of string * pos
+	| CMError of string * pos
+
+let compiler_message_string msg =
+	let (str,p) = match msg with
+		| CMInfo(str,p) | CMError(str,p) -> (str,p)
+		| CMWarning(str,p) -> ("Warning : " ^ str, p)
+	in
+	if p = null_pos then
+		str
+	else begin
+		let error_printer file line = Printf.sprintf "%s:%d:" file line in
+		let epos = Lexer.get_error_pos error_printer p in
+		let str = String.concat ("\n" ^ epos ^ " : ") (ExtString.String.nsplit str "\n") in
+		Printf.sprintf "%s : %s" epos str
+	end
+
 (**
 (**
 	The capture policy tells which handling we make of captured locals
 	The capture policy tells which handling we make of captured locals
 	(the locals which are referenced in local functions)
 	(the locals which are referenced in local functions)
@@ -264,13 +274,12 @@ type context = {
 	mutable std_path : string list;
 	mutable std_path : string list;
 	mutable class_path : string list;
 	mutable class_path : string list;
 	mutable main_class : Type.path option;
 	mutable main_class : Type.path option;
-	mutable defines : (string,string) PMap.t;
 	mutable package_rules : (string,package_rule) PMap.t;
 	mutable package_rules : (string,package_rule) PMap.t;
 	mutable error : string -> pos -> unit;
 	mutable error : string -> pos -> unit;
 	mutable warning : string -> pos -> unit;
 	mutable warning : string -> pos -> unit;
 	mutable load_extern_type : (path -> pos -> (string * Ast.package) option) list; (* allow finding types which are not in sources *)
 	mutable load_extern_type : (path -> pos -> (string * Ast.package) option) list; (* allow finding types which are not in sources *)
 	callbacks : compiler_callback;
 	callbacks : compiler_callback;
-	mutable defines_signature : string option;
+	defines : Define.define;
 	mutable print : string -> unit;
 	mutable print : string -> unit;
 	mutable get_macros : unit -> context option;
 	mutable get_macros : unit -> context option;
 	mutable run_command : string -> int;
 	mutable run_command : string -> int;
@@ -288,9 +297,6 @@ type context = {
 	mutable resources : (string,string) Hashtbl.t;
 	mutable resources : (string,string) Hashtbl.t;
 	mutable neko_libs : string list;
 	mutable neko_libs : string list;
 	mutable include_files : (string * string) list;
 	mutable include_files : (string * string) list;
-	mutable php_front : string option;
-	mutable php_lib : string option;
-	mutable php_prefix : string option;
 	mutable swf_libs : (string * (unit -> Swf.swf) * (unit -> ((string list * string),As3hl.hl_class) Hashtbl.t)) list;
 	mutable swf_libs : (string * (unit -> Swf.swf) * (unit -> ((string list * string),As3hl.hl_class) Hashtbl.t)) list;
 	mutable java_libs : (string * bool * (unit -> unit) * (unit -> (path list)) * (path -> ((JData.jclass * string * string) option))) list; (* (path,std,close,all_files,lookup) *)
 	mutable java_libs : (string * bool * (unit -> unit) * (unit -> (path list)) * (path -> ((JData.jclass * string * string) option))) list; (* (path,std,close,all_files,lookup) *)
 	mutable net_libs : (string * bool * (unit -> path list) * (path -> IlData.ilclass option)) list; (* (path,std,all_files,lookup) *)
 	mutable net_libs : (string * bool * (unit -> path list) * (path -> IlData.ilclass option)) list; (* (path,std,all_files,lookup) *)
@@ -307,25 +313,6 @@ exception Abort of string * pos
 
 
 let display_default = ref DisplayMode.DMNone
 let display_default = ref DisplayMode.DMNone
 
 
-let get_signature com =
-	match com.defines_signature with
-	| Some s -> s
-	| None ->
-		let defines = PMap.foldi (fun k v acc ->
-			(* don't make much difference between these special compilation flags *)
-			match String.concat "_" (ExtString.String.nsplit k "-") with
-			(* If we add something here that might be used in conditional compilation it should be added to
-			   Parser.parse_macro_ident as well (issue #5682). *)
-			| "display" | "use_rtti_doc" | "macro_times" | "display_details" | "no_copt" | "display_stdin" -> acc
-			| _ -> (k ^ "=" ^ v) :: acc
-		) com.defines [] in
-		let str = String.concat "@" (List.sort compare defines) in
-		let s = Digest.string str in
-		com.defines_signature <- Some s;
-		s
-
-let is_php7 com = com.platform = Php && PMap.exists "php7" com.defines
-
 module CompilationServer = struct
 module CompilationServer = struct
 	type cache = {
 	type cache = {
 		c_haxelib : (string list, string list) Hashtbl.t;
 		c_haxelib : (string list, string list) Hashtbl.t;
@@ -448,237 +435,35 @@ module CompilationServer = struct
 		Hashtbl.remove cs.cache.c_directories key
 		Hashtbl.remove cs.cache.c_directories key
 end
 end
 
 
-module Define = struct
-
-	type strict_defined =
-		| AbsolutePath
-		| AdvancedTelemetry
-		| AnnotateSource
-		(* | Analyzer *)
-		| As3
-		| CheckXmlProxy
-		| CoreApi
-		| CoreApiSerialize
-		| Cppia
-		| NoCppiaAst
-		| Dce
-		| DceDebug
-		| Debug
-		| Display
-		| DisplayStdin
-		| DllExport
-		| DllImport
-		| DocGen
-		| Dump
-		| DumpDependencies
-		| DumpIgnoreVarIds
-		| DynamicInterfaceClosures
-		| EraseGenerics
-		| EvalDebugger
-		| EvalStack
-		| EvalTimes
-		| FastCast
-		| Fdb
-		| FileExtension
-		| FlashStrict
-		| FlashUseStage
-		| ForceLibCheck
-		| ForceNativeProperty
-		| FormatWarning
-		| GencommonDebug
-		| HaxeBoot
-		| HaxeVer
-		| HxcppApiLevel
-		| HxcppGcGenerational
-		| HxcppDebugger
-		| IncludePrefix
-		| Interp
-		| JavaVer
-		| JqueryVer
-		| JsClassic
-		| JsEs
-		| JsUnflatten
-		| JsSourceMap
-		| JsEnumsAsObjects
-		| SourceMap
-		| KeepOldOutput
-		| LoopUnrollMaxCost
-		| LuaVer
-		| LuaJit
-		| Macro
-		| MacroDebug
-		| MacroTimes
-		| NekoSource
-		| NekoV1
-		| NetworkSandbox
-		| NetVer
-		| NetTarget
-		| NoCompilation
-		| NoCOpt
-		| NoDeprecationWarnings
-		| NoFlashOverride
-		| NoDebug
-		| NoInline
-		| NoOpt
-		| NoRoot
-		| NoSwfCompress
-		| NoTraces
-		| Objc
-		| OldConstructorInline
-		| OldErrorFormat
-		| PhpPrefix
-		| RealPosition
-		| ReplaceFiles
-		| Scriptable
-		| ShallowExpose
-		| SourceHeader
-		| SourceMapContent
-		| Swc
-		| SwfCompressLevel
-		| SwfDebugPassword
-		| SwfDirectBlit
-		| SwfGpu
-		| SwfMetadata
-		| SwfPreloaderFrame
-		| SwfProtected
-		| SwfScriptTimeout
-		| SwfUseDoAbc
-		| Sys
-		| Unsafe
-		| UseNekoc
-		| UseRttiDoc
-		| Vcproj
-		| NoMacroCache
-		| Last (* must be last *)
-
-	type define_parameter =
-		| HasParam of string
-		| Platform of platform
-		| Platforms of platform list
-
-	let infos = function
-		| AbsolutePath -> "absolute_path",("Print absolute file path in trace output",[])
-		| AdvancedTelemetry -> "advanced-telemetry",("Allow the SWF to be measured with Monocle tool",[Platform Flash])
-		| AnnotateSource -> "annotate_source",("Add additional comments to generated source code",[Platform Cpp])
-		(* | Analyzer -> "analyzer",("Use static analyzer for optimization (experimental)") *)
-		| As3 -> "as3",("Defined when outputing flash9 as3 source code",[])
-		| CheckXmlProxy -> "check_xml_proxy",("Check the used fields of the xml proxy",[])
-		| CoreApi -> "core_api",("Defined in the core api context",[])
-		| CoreApiSerialize -> "core_api_serialize",("Mark some generated core api classes with the Serializable attribute on C#",[Platform Cs])
-		| Cppia -> "cppia",("Generate cpp instruction assembly",[])
-		| NoCppiaAst -> "nocppiaast",("Use legacy cppia generation",[])
-		| Dce -> "dce",("<mode:std|full|no> Set the dead code elimination mode (default std)",[])
-		| DceDebug -> "dce_debug",("Show DCE log",[])
-		| Debug -> "debug",("Activated when compiling with -debug",[])
-		| Display -> "display",("Activated during completion",[])
-		| DisplayStdin -> "display_stdin",("Read the contents of a file specified in --display from standard input",[])
-		| DllExport -> "dll_export",("GenCPP experimental linking",[Platform Cpp])
-		| DllImport -> "dll_import",("Handle Haxe-generated .NET dll imports",[Platform Cs])
-		| DocGen -> "doc_gen",("Do not perform any removal/change in order to correctly generate documentation",[])
-		| Dump -> "dump",("<mode:pretty|record|legacy> Dump typed AST in dump subdirectory using specified mode or non-prettified default",[])
-		| DumpDependencies -> "dump_dependencies",("Dump the classes dependencies in a dump subdirectory",[])
-		| DumpIgnoreVarIds -> "dump_ignore_var_ids",("Remove variable IDs from non-pretty dumps (helps with diff)",[])
-		| DynamicInterfaceClosures -> "dynamic_interface_closures",("Use slow path for interface closures to save space",[Platform Cpp])
-		| EraseGenerics -> "erase_generics",("Erase generic classes on C#",[Platform Cs])
-		| EvalDebugger -> "eval_debugger",("Support debugger in macro/interp mode. Allows host:port value to open a socket. Implies eval_stack.",[])
-		| EvalStack -> "eval_stack",("Record stack information in macro/interp mode",[])
-		| EvalTimes -> "eval_times",("Record per-method execution times in macro/interp mode. Implies eval_stack.",[])
-		| FastCast -> "fast_cast",("Enables an experimental casts cleanup on C# and Java",[Platforms [Cs;Java]])
-		| Fdb -> "fdb",("Enable full flash debug infos for FDB interactive debugging",[Platform Flash])
-		| FileExtension -> "file_extension",("Output filename extension for cpp source code",[Platform Cpp])
-		| FlashStrict -> "flash_strict",("More strict typing for flash target",[Platform Flash])
-		| FlashUseStage -> "flash_use_stage",("Keep the SWF library initial stage",[Platform Flash])
-		(* force_lib_check is only here as a debug facility - compiler checking allows errors to be found more easily *)
-		| ForceLibCheck -> "force_lib_check",("Force the compiler to check -net-lib and -java-lib added classes (internal)",[Platforms [Cs;Java]])
-		| ForceNativeProperty -> "force_native_property",("Tag all properties with :nativeProperty metadata for 3.1 compatibility",[Platform Cpp])
-		| FormatWarning -> "format_warning",("Print a warning for each formated string, for 2.x compatibility",[])
-		| GencommonDebug -> "gencommon_debug",("GenCommon internal",[Platforms [Cs;Java]])
-		| HaxeBoot -> "haxe_boot",("Given the name 'haxe' to the flash boot class instead of a generated name",[Platform Flash])
-		| HaxeVer -> "haxe_ver",("The current Haxe version value",[])
-		| HxcppApiLevel -> "hxcpp_api_level",("Provided to allow compatibility between hxcpp versions",[Platform Cpp])
-		| HxcppGcGenerational -> "HXCPP_GC_GENERATIONAL",("Experimental Garbage Collector",[Platform Cpp])
-		| HxcppDebugger -> "HXCPP_DEBUGGER",("Include additional information for HXCPP_DEBUGGER",[Platform Cpp])
-		| IncludePrefix -> "include_prefix",("prepend path to generated include files",[Platform Cpp])
-		| Interp -> "interp",("The code is compiled to be run with --interp",[])
-		| JavaVer -> "java_ver",("<version:5-7> Sets the Java version to be targeted",[Platform Java])
-		| 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",[Platform Js])
-		| JsClassic -> "js_classic",("Don't use a function wrapper and strict mode in JS output",[Platform Js])
-		| JsEs -> "js_es",("Generate JS compilant with given ES standard version (default 5)",[Platform Js; HasParam "version number"])
-		| JsEnumsAsObjects -> "js_enums_as_objects",("Generate enum representation as object instead of as array",[Platform Js])
-		| JsUnflatten -> "js_unflatten",("Generate nested objects for packages and types",[Platform Js])
-		| JsSourceMap -> "js_source_map",("Generate JavaScript source map even in non-debug mode",[Platform Js])
-		| SourceMap -> "source_map",("Generate source map for compiled files (Currently supported for php7 only)",[Platform Php])
-		| KeepOldOutput -> "keep_old_output",("Keep old source files in the output directory (for C#/Java)",[Platforms [Cs;Java]])
-		| LoopUnrollMaxCost -> "loop_unroll_max_cost",("Maximum cost (number of expressions * iterations) before loop unrolling is canceled (default 250)",[])
-		| LuaJit -> "lua_jit",("Enable the jit compiler for lua (version 5.2 only)",[Platform Lua])
-		| LuaVer -> "lua_ver",("The lua version to target",[Platform Lua])
-		| Macro -> "macro",("Defined when code is compiled in the macro context",[])
-		| MacroDebug -> "macro_debug",("Show warnings for potential macro problems (e.g. macro-in-macro calls)",[])
-		| MacroTimes -> "macro_times",("Display per-macro timing when used with --times",[])
-		| NetVer -> "net_ver",("<version:20-45> Sets the .NET version to be targeted",[Platform Cs])
-		| NetTarget -> "net_target",("<name> Sets the .NET target. Defaults to \"net\". xbox, micro (Micro Framework), compact (Compact Framework) are some valid values",[Platform Cs])
-		| NekoSource -> "neko_source",("Output neko source instead of bytecode",[Platform Neko])
-		| NekoV1 -> "neko_v1",("Keep Neko 1.x compatibility",[Platform Neko])
-		| NetworkSandbox -> "network-sandbox",("Use local network sandbox instead of local file access one",[Platform Flash])
-		| NoCompilation -> "no-compilation",("Disable final compilation",[Platforms [Cs;Java;Cpp;Hl]])
-		| NoCOpt -> "no_copt",("Disable completion optimization (for debug purposes)",[])
-		| NoDebug -> "no_debug",("Remove all debug macros from cpp output",[])
-		| NoDeprecationWarnings -> "no-deprecation-warnings",("Do not warn if fields annotated with @:deprecated are used",[])
-		| NoFlashOverride -> "no-flash-override",("Change overrides on some basic classes into HX suffixed methods, flash only",[Platform Flash])
-		| NoOpt -> "no_opt",("Disable optimizations",[])
-		| NoInline -> "no_inline",("Disable inlining",[])
-		| NoRoot -> "no_root",("Generate top-level types into haxe.root namespace",[Platform Cs])
-		| NoMacroCache -> "no_macro_cache",("Disable macro context caching",[])
-		| NoSwfCompress -> "no_swf_compress",("Disable SWF output compression",[Platform Flash])
-		| NoTraces -> "no_traces",("Disable all trace calls",[])
-		| Objc -> "objc",("Sets the hxcpp output to objective-c++ classes. Must be defined for interop",[Platform Cpp])
-		| OldConstructorInline -> "old-constructor-inline",("Use old constructor inlining logic (from haxe 3.4.2) instead of the reworked version.",[])
-		| OldErrorFormat -> "old-error-format",("Use Haxe 3.x zero-based column error messages instead of new one-based format.",[])
-		| PhpPrefix -> "php_prefix",("Compiled with --php-prefix",[Platform Php])
-		| RealPosition -> "real_position",("Disables Haxe source mapping when targetting C#, removes position comments in Java and Php7 output",[Platforms [Cs;Java;Php]])
-		| ReplaceFiles -> "replace_files",("GenCommon internal",[Platforms [Java;Cs]])
-		| Scriptable -> "scriptable",("GenCPP internal",[Platform Cpp])
-		| ShallowExpose -> "shallow-expose",("Expose types to surrounding scope of Haxe generated closure without writing to window object",[Platform Js])
-		| SourceHeader -> "source-header",("Print value as comment on top of generated files, use '' value to disable",[])
-		| SourceMapContent -> "source-map-content",("Include the hx sources as part of the JS source map",[Platform Js])
-		| Swc -> "swc",("Output a SWC instead of a SWF",[Platform Flash])
-		| SwfCompressLevel -> "swf_compress_level",("<level:1-9> Set the amount of compression for the SWF output",[Platform Flash])
-		| SwfDebugPassword -> "swf_debug_password",("Set a password for debugging",[Platform Flash])
-		| SwfDirectBlit -> "swf_direct_blit",("Use hardware acceleration to blit graphics",[Platform Flash])
-		| SwfGpu -> "swf_gpu",("Use GPU compositing features when drawing graphics",[Platform Flash])
-		| SwfMetadata -> "swf_metadata",("<file> Include contents of <file> as metadata in the swf",[Platform Flash])
-		| SwfPreloaderFrame -> "swf_preloader_frame",("Insert empty first frame in swf",[Platform Flash])
-		| SwfProtected -> "swf_protected",("Compile Haxe private as protected in the SWF instead of public",[Platform Flash])
-		| SwfScriptTimeout -> "swf_script_timeout",("Maximum ActionScript processing time before script stuck dialog box displays (in seconds)",[Platform Flash])
-		| SwfUseDoAbc -> "swf_use_doabc",("Use DoAbc swf-tag instead of DoAbcDefine",[Platform Flash])
-		| Sys -> "sys",("Defined for all system platforms",[])
-		| Unsafe -> "unsafe",("Allow unsafe code when targeting C#",[Platform Cs])
-		| UseNekoc -> "use_nekoc",("Use nekoc compiler instead of internal one",[Platform Neko])
-		| UseRttiDoc -> "use_rtti_doc",("Allows access to documentation during compilation",[])
-		| Vcproj -> "vcproj",("GenCPP internal",[Platform Cpp])
-		| Last -> assert false
-
-	let get_documentation_list() =
-		let m = ref 0 in
-		let rec loop i =
-			let d = Obj.magic i in
-			if d <> Last then begin
-				let t, (doc,flags) = infos d in
-				let pfs = ref [] in
-				List.iter (function
-				| HasParam s -> () (* TODO *)
-				| Platform p -> pfs := p :: !pfs;
-				| Platforms pl -> pfs := pl @ !pfs;
-				) flags;
-				let pfs = platform_list_help (List.rev !pfs) in
-				if String.length t > !m then m := String.length t;
-				((String.concat "-" (ExtString.String.nsplit t "_")),doc ^ pfs) :: (loop (i + 1))
-			end else
-				[]
-		in
-		let all = List.sort (fun (s1,_) (s2,_) -> String.compare s1 s2) (loop 0) in
-		all,!m
-end
+(* Defines *)
+
+module Define = Define
+
+let defined com s =
+	Define.defined com.defines s
+
+let raw_defined com v =
+	Define.raw_defined com.defines v
+
+let defined_value com v =
+	Define.defined_value com.defines v
+
+let defined_value_safe ?default com v =
+	match default with
+		| Some s -> Define.defined_value_safe ~default:s com.defines v
+		| None -> Define.defined_value_safe com.defines v
+
+let define com v =
+	Define.define com.defines v
+
+let raw_define com v =
+	Define.raw_define com.defines v
+
+let define_value com k v =
+	Define.define_value com.defines k v
+
+let raw_defined_value com k =
+	Define.raw_defined_value com.defines k
 
 
 let short_platform_name = function
 let short_platform_name = function
 	| Cross -> "x"
 	| Cross -> "x"
@@ -715,7 +500,7 @@ let default_config =
 	}
 	}
 
 
 let get_config com =
 let get_config com =
-	let defined f = PMap.mem (fst (Define.infos f)) com.defines in
+	let defined f = PMap.mem (fst (Define.infos f)) com.defines.values in
 	match com.platform with
 	match com.platform with
 	| Cross ->
 	| Cross ->
 		default_config
 		default_config
@@ -756,17 +541,10 @@ let get_config com =
 			pf_reserved_type_paths = [([],"Object");([],"Error")];
 			pf_reserved_type_paths = [([],"Object");([],"Error")];
 		}
 		}
 	| Php ->
 	| Php ->
-		if is_php7 com then
-			{
-				default_config with
-				pf_static = false;
-			}
-		else
-			{
-				default_config with
-				pf_static = false;
-				pf_pad_nulls = true;
-			}
+		{
+			default_config with
+			pf_static = false;
+		}
 	| Cpp ->
 	| Cpp ->
 		{
 		{
 			default_config with
 			default_config with
@@ -853,7 +631,6 @@ let create version s_version args =
 		std_path = [];
 		std_path = [];
 		class_path = [];
 		class_path = [];
 		main_class = None;
 		main_class = None;
-		defines = defines;
 		package_rules = PMap.empty;
 		package_rules = PMap.empty;
 		file = "";
 		file = "";
 		types = [];
 		types = [];
@@ -862,8 +639,6 @@ let create version s_version args =
 		main = None;
 		main = None;
 		flash_version = 10.;
 		flash_version = 10.;
 		resources = Hashtbl.create 0;
 		resources = Hashtbl.create 0;
-		php_front = None;
-		php_lib = None;
 		swf_libs = [];
 		swf_libs = [];
 		java_libs = [];
 		java_libs = [];
 		net_libs = [];
 		net_libs = [];
@@ -872,10 +647,12 @@ let create version s_version args =
 		c_args = [];
 		c_args = [];
 		neko_libs = [];
 		neko_libs = [];
 		include_files = [];
 		include_files = [];
-		php_prefix = None;
 		js_gen = None;
 		js_gen = None;
 		load_extern_type = [];
 		load_extern_type = [];
-		defines_signature = None;
+		defines = {
+			defines_signature = None;
+			values = defines;
+		};
 		get_macros = (fun() -> None);
 		get_macros = (fun() -> None);
 		warning = (fun _ _ -> assert false);
 		warning = (fun _ _ -> assert false);
 		error = (fun _ _ -> assert false);
 		error = (fun _ _ -> assert false);
@@ -911,6 +688,10 @@ let clone com =
 			unresolved_identifiers = [];
 			unresolved_identifiers = [];
 			interface_field_implementations = [];
 			interface_field_implementations = [];
 		};
 		};
+		defines = {
+			values = com.defines.values;
+			defines_signature = com.defines.defines_signature;
+		}
 	}
 	}
 
 
 let file_time file = Extc.filetime file
 let file_time file = Extc.filetime file
@@ -947,42 +728,13 @@ let flash_version_tag = function
 	| v when v >= 12.0 && float_of_int (int_of_float v) = v -> int_of_float v + 11
 	| v when v >= 12.0 && float_of_int (int_of_float v) = v -> int_of_float v + 11
 	| v -> failwith ("Invalid SWF version " ^ string_of_float v)
 	| v -> failwith ("Invalid SWF version " ^ string_of_float v)
 
 
-let raw_defined ctx v =
-	PMap.mem v ctx.defines
-
-let defined ctx v =
-	raw_defined ctx (fst (Define.infos v))
-
-let raw_defined_value ctx k =
-	PMap.find k ctx.defines
-
-let defined_value ctx v =
-	raw_defined_value ctx (fst (Define.infos v))
-
-let defined_value_safe ctx v =
-	try defined_value ctx v
-	with Not_found -> ""
-
-let raw_define ctx v =
-	let k,v = try ExtString.String.split v "=" with _ -> v,"1" in
-	ctx.defines <- PMap.add k v ctx.defines;
-	let k = String.concat "_" (ExtString.String.nsplit k "-") in
-	ctx.defines <- PMap.add k v ctx.defines;
-	ctx.defines_signature <- None
-
-let define_value ctx k v =
-	raw_define ctx (fst (Define.infos k) ^ "=" ^ v)
-
-let define ctx v =
-	raw_define ctx (fst (Define.infos v))
-
 let init_platform com pf =
 let init_platform com pf =
 	com.platform <- pf;
 	com.platform <- pf;
 	let name = platform_name pf in
 	let name = platform_name pf in
 	let forbid acc p = if p = name || PMap.mem p acc then acc else PMap.add p Forbidden acc in
 	let forbid acc p = if p = name || PMap.mem p acc then acc else PMap.add p Forbidden acc in
 	com.package_rules <- List.fold_left forbid com.package_rules (List.map platform_name platforms);
 	com.package_rules <- List.fold_left forbid com.package_rules (List.map platform_name platforms);
 	com.config <- get_config com;
 	com.config <- get_config com;
-(*	if com.config.pf_static then define com "static"; *)
+	if com.config.pf_static then define com Define.Static;
 	if com.config.pf_sys then define com Define.Sys else com.package_rules <- PMap.add "sys" Forbidden com.package_rules;
 	if com.config.pf_sys then define com Define.Sys else com.package_rules <- PMap.add "sys" Forbidden com.package_rules;
 	raw_define com name
 	raw_define com name
 
 
@@ -1078,121 +830,10 @@ let find_file ctx f =
 		| None -> raise Not_found
 		| None -> raise Not_found
 		| Some f -> f)
 		| Some f -> f)
 
 
-let rec mkdir_recursive base dir_list =
-	match dir_list with
-	| [] -> ()
-	| dir :: remaining ->
-		let path = match base with
-				   | "" ->  dir
-				   | "/" -> "/" ^ dir
-				   | _ -> base ^ "/" ^ dir
-		in
-		let path_len = String.length path in
-		let path =
-			if path_len > 0 && (path.[path_len - 1] = '/' || path.[path_len - 1] == '\\') then
-				String.sub path 0 (path_len - 1)
-			else
-				path
-		in
-		if not ( (path = "") || ( (path_len = 2) && ((String.sub path 1 1) = ":") ) ) then
-			if not (Sys.file_exists path) then
-				Unix.mkdir path 0o755;
-		mkdir_recursive (if (path = "") then "/" else path) remaining
-
-let mkdir_from_path path =
-	let parts = Str.split_delim (Str.regexp "[\\/]+") path in
-	match parts with
-		| [] -> (* path was "" *) ()
-		| _ ->
-			let dir_list = List.rev (List.tl (List.rev parts)) in
-			mkdir_recursive "" dir_list
 
 
 let mem_size v =
 let mem_size v =
 	Objsize.size_with_headers (Objsize.objsize v [] [])
 	Objsize.size_with_headers (Objsize.objsize v [] [])
 
 
-(* ------------------------- TIMERS ----------------------------- *)
-
-type timer_infos = {
-	id : string list;
-	mutable start : float list;
-	mutable total : float;
-	mutable calls : int;
-}
-
-let get_time = Extc.time
-let htimers = Hashtbl.create 0
-
-let new_timer id =
-	let key = String.concat "." id in
-	try
-		let t = Hashtbl.find htimers key in
-		t.start <- get_time() :: t.start;
-		t.calls <- t.calls + 1;
-		t
-	with Not_found ->
-		let t = { id = id; start = [get_time()]; total = 0.; calls = 1; } in
-		Hashtbl.add htimers key t;
-		t
-
-let curtime = ref []
-
-let close t =
-	let start = (match t.start with
-		| [] -> assert false
-		| s :: l -> t.start <- l; s
-	) in
-	let now = get_time() in
-	let dt = now -. start in
-	t.total <- t.total +. dt;
-	let rec loop() =
-		match !curtime with
-		| [] -> failwith ("Timer " ^ (String.concat "." t.id) ^ " closed while not active")
-		| tt :: l -> curtime := l; if t != tt then loop()
-	in
-	loop();
-	(* because of rounding errors while adding small times, we need to make sure that we don't have start > now *)
-	List.iter (fun ct -> ct.start <- List.map (fun t -> let s = t +. dt in if s > now then now else s) ct.start) !curtime
-
-let timer id =
-	let t = new_timer id in
-	curtime := t :: !curtime;
-	(function() -> close t)
-
-let rec close_times() =
-	match !curtime with
-	| [] -> ()
-	| t :: _ -> close t; close_times()
-
-;;
-
-(*  Taken from OCaml source typing/oprint.ml
-
-	This is a better version of string_of_float which prints without loss of precision
-	so that float_of_string (float_repres x) = x for all floats x
-*)
-let valid_float_lexeme s =
-	let l = String.length s in
-	let rec loop i =
-		if i >= l then s ^ "." else
-		match s.[i] with
-		| '0' .. '9' | '-' -> loop (i+1)
-		| _ -> s
-	in loop 0
-
-let float_repres f =
-	match classify_float f with
-	| FP_nan -> "nan"
-	| FP_infinite ->
-		if f < 0.0 then "neg_infinity" else "infinity"
-	| _ ->
-		let float_val =
-			let s1 = Printf.sprintf "%.12g" f in
-			if f = float_of_string s1 then s1 else
-			let s2 = Printf.sprintf "%.15g" f in
-			if f = float_of_string s2 then s2 else
-			Printf.sprintf "%.18g" f
-		in valid_float_lexeme float_val
-
 let hash f =
 let hash f =
 	let h = ref 0 in
 	let h = ref 0 in
 	for i = 0 to String.length f - 1 do
 	for i = 0 to String.length f - 1 do
@@ -1213,6 +854,6 @@ let dump_context com = s_record_fields "" [
 	"platform",platform_name com.platform;
 	"platform",platform_name com.platform;
 	"std_path",s_list ", " (fun s -> s) com.std_path;
 	"std_path",s_list ", " (fun s -> s) com.std_path;
 	"class_path",s_list ", " (fun s -> s) com.class_path;
 	"class_path",s_list ", " (fun s -> s) com.class_path;
-	"defines",s_pmap (fun s -> s) (fun s -> s) com.defines;
-	"defines_signature",s_opt (fun s -> Digest.to_hex s) com.defines_signature;
-]
+	"defines",s_pmap (fun s -> s) (fun s -> s) com.defines.values;
+	"defines_signature",s_opt (fun s -> Digest.to_hex s) com.defines.defines_signature;
+]

+ 0 - 182
src/display/display.ml → src/context/display.ml

@@ -751,185 +751,3 @@ module Statistics = struct
 		if false then deal_with_imports ctx.com.shared.shared_display_information.import_positions;
 		if false then deal_with_imports ctx.com.shared.shared_display_information.import_positions;
 		symbols,relations
 		symbols,relations
 end
 end
-
-let explore_class_paths ctx class_paths recusive f_pack f_module f_type =
-	let rec loop dir pack =
-		try
-			let entries = Sys.readdir dir in
-			Array.iter (fun file ->
-				match file with
-					| "." | ".." ->
-						()
-					| _ when Sys.is_directory (dir ^ file) && file.[0] >= 'a' && file.[0] <= 'z' ->
-						f_pack file;
-						if recusive then loop (dir ^ file ^ "/") (file :: pack)
-					| _ ->
-						let l = String.length file in
-						if l > 3 && String.sub file (l - 3) 3 = ".hx" then begin
-							try
-								let name = String.sub file 0 (l - 3) in
-								let path = (List.rev pack,name) in
-								let md = ctx.g.do_load_module ctx path null_pos in
-								f_module md;
-								List.iter (fun mt -> f_type mt) md.m_types
-							with _ ->
-								()
-						end
-			) entries;
-		with Sys_error _ ->
-			()
-	in
-	List.iter (fun dir -> loop dir []) class_paths
-
-module ToplevelCollector = struct
-	open IdentifierType
-
-	let run ctx only_types =
-		let acc = DynArray.create () in
-		let add x = DynArray.add acc x in
-
-		if not only_types then begin
-			(* locals *)
-			PMap.iter (fun _ v ->
-				if not (is_gen_local v) then
-					add (ITLocal v)
-			) ctx.locals;
-
-			(* member vars *)
-			if ctx.curfun <> FunStatic then begin
-				let rec loop c =
-					List.iter (fun cf ->
-						if not (Meta.has Meta.NoCompletion cf.cf_meta) then add (ITMember(ctx.curclass,cf))
-					) c.cl_ordered_fields;
-					match c.cl_super with
-						| None ->
-							()
-						| Some (csup,tl) ->
-							loop csup; (* TODO: type parameters *)
-				in
-				loop ctx.curclass;
-				(* TODO: local using? *)
-			end;
-
-			(* statics *)
-			List.iter (fun cf ->
-				if not (Meta.has Meta.NoCompletion cf.cf_meta) then add (ITStatic(ctx.curclass,cf))
-			) ctx.curclass.cl_ordered_statics;
-
-			(* enum constructors *)
-			let rec enum_ctors t =
-				match t with
-				| TAbstractDecl ({a_impl = Some c} as a) when Meta.has Meta.Enum a.a_meta ->
-					List.iter (fun cf ->
-						if (Meta.has Meta.Enum cf.cf_meta) && not (Meta.has Meta.NoCompletion cf.cf_meta) then add (ITEnumAbstract(a,cf));
-					) c.cl_ordered_statics
-				| TClassDecl _ | TAbstractDecl _ ->
-					()
-				| TTypeDecl t ->
-					begin match follow t.t_type with
-						| TEnum (e,_) -> enum_ctors (TEnumDecl e)
-						| _ -> ()
-					end
-				| TEnumDecl e ->
-					PMap.iter (fun _ ef ->
-						add (ITEnum(e,ef))
-					) e.e_constrs;
-			in
-			List.iter enum_ctors ctx.m.curmod.m_types;
-			List.iter enum_ctors (List.map fst ctx.m.module_types);
-
-			(* imported globals *)
-			PMap.iter (fun _ (mt,s,_) ->
-				try
-					let t = match resolve_typedef mt with
-						| TClassDecl c -> (PMap.find s c.cl_statics).cf_type
-						| TEnumDecl en -> (PMap.find s en.e_constrs).ef_type
-						| TAbstractDecl {a_impl = Some c} -> (PMap.find s c.cl_statics).cf_type
-						| _ -> raise Not_found
-					in
-					add (ITGlobal(mt,s,t))
-				with Not_found ->
-					()
-			) ctx.m.module_globals;
-
-			(* literals *)
-			add (ITLiteral "null");
-			add (ITLiteral "true");
-			add (ITLiteral "false");
-		end;
-
-		let module_types = ref [] in
-
-		let add_type mt =
-			match mt with
-			| TClassDecl {cl_kind = KAbstractImpl _} -> ()
-			| _ ->
-				let path = (t_infos mt).mt_path in
-				if not (List.exists (fun mt2 -> (t_infos mt2).mt_path = path) !module_types) then begin
-					(match mt with
-					| TClassDecl c | TAbstractDecl { a_impl = Some c } when Meta.has Meta.CoreApi c.cl_meta ->
-						!merge_core_doc_ref ctx c
-					| _ -> ());
-					module_types := mt :: !module_types
-				end
-		in
-
-		(* module types *)
-		List.iter add_type ctx.m.curmod.m_types;
-
-		(* module imports *)
-		List.iter add_type (List.map fst ctx.m.module_types);
-
-		(* module using *)
-		List.iter (fun (c,_) ->
-			add_type (TClassDecl c)
-		) ctx.m.module_using;
-
-		(* TODO: wildcard packages. How? *)
-
-		(* packages and toplevel types *)
-		let class_paths = ctx.com.class_path in
-		let class_paths = List.filter (fun s -> s <> "") class_paths in
-
-		let packages = ref [] in
-		let add_package pack =
-			try
-				begin match PMap.find pack ctx.com.package_rules with
-					| Forbidden ->
-						()
-					| _ ->
-						raise Not_found
-				end
-			with Not_found ->
-				if not (List.mem pack !packages) then packages := pack :: !packages
-		in
-
-		let maybe_add_type mt = if not (t_infos mt).mt_private then add_type mt in
-
-		explore_class_paths ctx class_paths false add_package (fun _ -> ()) maybe_add_type;
-
-		List.iter (fun pack ->
-			add (ITPackage pack)
-		) !packages;
-
-		List.iter (fun mt ->
-			add (ITType mt)
-		) !module_types;
-
-		(* type params *)
-		List.iter (fun (_,t) ->
-			add (ITType (module_type_of_type t))
-		) ctx.type_params;
-
-		DynArray.to_list acc
-
-	let handle_unresolved_identifier ctx i p only_types =
-		let l = run ctx only_types in
-		let cl = List.map (fun it ->
-			let s = IdentifierType.get_name it in
-			(s,it),StringError.levenshtein i s
-		) l in
-		let cl = List.sort (fun (_,c1) (_,c2) -> compare c1 c2) cl in
-		let cl = StringError.filter_similar (fun (s,_) r -> r > 0 && r <= (min (String.length s) (String.length i)) / 3) cl in
-		ctx.com.display_information.unresolved_identifiers <- (i,p,cl) :: ctx.com.display_information.unresolved_identifiers
-end

+ 182 - 0
src/context/displayToplevel.ml

@@ -0,0 +1,182 @@
+open Common
+open Type
+open Typecore
+open Common.IdentifierType
+
+let explore_class_paths ctx class_paths recusive f_pack f_module f_type =
+	let rec loop dir pack =
+		try
+			let entries = Sys.readdir dir in
+			Array.iter (fun file ->
+				match file with
+					| "." | ".." ->
+						()
+					| _ when Sys.is_directory (dir ^ file) && file.[0] >= 'a' && file.[0] <= 'z' ->
+						f_pack file;
+						if recusive then loop (dir ^ file ^ "/") (file :: pack)
+					| _ ->
+						let l = String.length file in
+						if l > 3 && String.sub file (l - 3) 3 = ".hx" then begin
+							try
+								let name = String.sub file 0 (l - 3) in
+								let path = (List.rev pack,name) in
+								let md = ctx.g.do_load_module ctx path Globals.null_pos in
+								f_module md;
+								List.iter (fun mt -> f_type mt) md.m_types
+							with _ ->
+								()
+						end
+			) entries;
+		with Sys_error _ ->
+			()
+	in
+	List.iter (fun dir -> loop dir []) class_paths
+
+let collect ctx only_types =
+	let acc = DynArray.create () in
+	let add x = DynArray.add acc x in
+
+	if not only_types then begin
+		(* locals *)
+		PMap.iter (fun _ v ->
+			if not (is_gen_local v) then
+				add (ITLocal v)
+		) ctx.locals;
+
+		(* member vars *)
+		if ctx.curfun <> FunStatic then begin
+			let rec loop c =
+				List.iter (fun cf ->
+					if not (Meta.has Meta.NoCompletion cf.cf_meta) then add (ITMember(ctx.curclass,cf))
+				) c.cl_ordered_fields;
+				match c.cl_super with
+					| None ->
+						()
+					| Some (csup,tl) ->
+						loop csup; (* TODO: type parameters *)
+			in
+			loop ctx.curclass;
+			(* TODO: local using? *)
+		end;
+
+		(* statics *)
+		List.iter (fun cf ->
+			if not (Meta.has Meta.NoCompletion cf.cf_meta) then add (ITStatic(ctx.curclass,cf))
+		) ctx.curclass.cl_ordered_statics;
+
+		(* enum constructors *)
+		let rec enum_ctors t =
+			match t with
+			| TAbstractDecl ({a_impl = Some c} as a) when Meta.has Meta.Enum a.a_meta ->
+				List.iter (fun cf ->
+					if (Meta.has Meta.Enum cf.cf_meta) && not (Meta.has Meta.NoCompletion cf.cf_meta) then add (ITEnumAbstract(a,cf));
+				) c.cl_ordered_statics
+			| TClassDecl _ | TAbstractDecl _ ->
+				()
+			| TTypeDecl t ->
+				begin match follow t.t_type with
+					| TEnum (e,_) -> enum_ctors (TEnumDecl e)
+					| _ -> ()
+				end
+			| TEnumDecl e ->
+				PMap.iter (fun _ ef ->
+					add (ITEnum(e,ef))
+				) e.e_constrs;
+		in
+		List.iter enum_ctors ctx.m.curmod.m_types;
+		List.iter enum_ctors (List.map fst ctx.m.module_types);
+
+		(* imported globals *)
+		PMap.iter (fun _ (mt,s,_) ->
+			try
+				let t = match resolve_typedef mt with
+					| TClassDecl c -> (PMap.find s c.cl_statics).cf_type
+					| TEnumDecl en -> (PMap.find s en.e_constrs).ef_type
+					| TAbstractDecl {a_impl = Some c} -> (PMap.find s c.cl_statics).cf_type
+					| _ -> raise Not_found
+				in
+				add (ITGlobal(mt,s,t))
+			with Not_found ->
+				()
+		) ctx.m.module_globals;
+
+		(* literals *)
+		add (ITLiteral "null");
+		add (ITLiteral "true");
+		add (ITLiteral "false");
+	end;
+
+	let module_types = ref [] in
+
+	let add_type mt =
+		match mt with
+		| TClassDecl {cl_kind = KAbstractImpl _} -> ()
+		| _ ->
+			let path = (t_infos mt).mt_path in
+			if not (List.exists (fun mt2 -> (t_infos mt2).mt_path = path) !module_types) then begin
+				(match mt with
+				| TClassDecl c | TAbstractDecl { a_impl = Some c } when Meta.has Meta.CoreApi c.cl_meta ->
+					!merge_core_doc_ref ctx c
+				| _ -> ());
+				module_types := mt :: !module_types
+			end
+	in
+
+	(* module types *)
+	List.iter add_type ctx.m.curmod.m_types;
+
+	(* module imports *)
+	List.iter add_type (List.map fst ctx.m.module_types);
+
+	(* module using *)
+	List.iter (fun (c,_) ->
+		add_type (TClassDecl c)
+	) ctx.m.module_using;
+
+	(* TODO: wildcard packages. How? *)
+
+	(* packages and toplevel types *)
+	let class_paths = ctx.com.class_path in
+	let class_paths = List.filter (fun s -> s <> "") class_paths in
+
+	let packages = ref [] in
+	let add_package pack =
+		try
+			begin match PMap.find pack ctx.com.package_rules with
+				| Forbidden ->
+					()
+				| _ ->
+					raise Not_found
+			end
+		with Not_found ->
+			if not (List.mem pack !packages) then packages := pack :: !packages
+	in
+
+	let maybe_add_type mt = if not (t_infos mt).mt_private then add_type mt in
+
+	explore_class_paths ctx class_paths false add_package (fun _ -> ()) maybe_add_type;
+
+	List.iter (fun pack ->
+		add (ITPackage pack)
+	) !packages;
+
+	List.iter (fun mt ->
+		add (ITType mt)
+	) !module_types;
+
+	(* type params *)
+	List.iter (fun (_,t) ->
+		add (ITType (module_type_of_type t))
+	) ctx.type_params;
+
+	DynArray.to_list acc
+
+let handle_unresolved_identifier ctx i p only_types =
+	let l = collect ctx only_types in
+	let cl = List.map (fun it ->
+		let s = IdentifierType.get_name it in
+		(s,it),StringError.levenshtein i s
+	) l in
+	let cl = List.sort (fun (_,c1) (_,c2) -> compare c1 c2) cl in
+	let cl = StringError.filter_similar (fun (s,_) r -> r > 0 && r <= (min (String.length s) (String.length i)) / 3) cl in
+	ctx.com.display_information.unresolved_identifiers <- (i,p,cl) :: ctx.com.display_information.unresolved_identifiers

+ 0 - 0
src/display/displayTypes.ml → src/context/displayTypes.ml


+ 0 - 0
src/compiler/sourcemaps.ml → src/context/sourcemaps.ml


+ 27 - 12
src/typing/typecore.ml → src/context/typecore.ml

@@ -207,6 +207,14 @@ let save_locals ctx =
 
 
 let add_local ctx n t p =
 let add_local ctx n t p =
 	let v = alloc_var n t p in
 	let v = alloc_var n t p in
+	if Define.raw_defined ctx.com.defines "warn-var-shadowing" then begin
+		try
+			let v' = PMap.find n ctx.locals in
+			ctx.com.warning "This variable shadows a previously declared variable" p;
+			ctx.com.warning "Previous variable was here" v'.v_pos
+		with Not_found ->
+			()
+	end;
 	ctx.locals <- PMap.add n v ctx.locals;
 	ctx.locals <- PMap.add n v ctx.locals;
 	v
 	v
 
 
@@ -268,14 +276,18 @@ let make_pass ctx f = f
 let init_class_done ctx =
 let init_class_done ctx =
 	ctx.pass <- PTypeField
 	ctx.pass <- PTypeField
 
 
-let exc_protect ctx f (where:string) =
-	let rec r = ref (fun() ->
+let exc_protect ?(force=true) ctx f (where:string) =
+	let r = ref (lazy_available t_dynamic) in
+	r := lazy_wait (fun() ->
 		try
 		try
-			f r
+			let t = f r in
+			r := lazy_available t;
+			t
 		with
 		with
 			| Error (m,p) ->
 			| Error (m,p) ->
 				raise (Fatal_error ((error_msg m),p))
 				raise (Fatal_error ((error_msg m),p))
-	) in
+	);
+	if force then delay ctx PForce (fun () -> ignore(lazy_type r));
 	r
 	r
 
 
 let fake_modules = Hashtbl.create 0
 let fake_modules = Hashtbl.create 0
@@ -286,7 +298,7 @@ let create_fake_module ctx file =
 			m_id = alloc_mid();
 			m_id = alloc_mid();
 			m_path = (["$DEP"],file);
 			m_path = (["$DEP"],file);
 			m_types = [];
 			m_types = [];
-			m_extra = module_extra file (Common.get_signature ctx.com) (file_time file) MFake [];
+			m_extra = module_extra file (Define.get_signature ctx.com.defines) (file_time file) MFake [];
 		} in
 		} in
 		Hashtbl.add fake_modules file mdep;
 		Hashtbl.add fake_modules file mdep;
 		mdep
 		mdep
@@ -476,7 +488,7 @@ module AbstractCast = struct
 						if not (has_mono t) then t
 						if not (has_mono t) then t
 						else t_dynamic
 						else t_dynamic
 				) a.a_params pl in
 				) a.a_params pl in
-				if com.platform = Globals.Js && a.a_path = ([],"Map") then begin match tl with
+				if com.platform = Globals.Js && a.a_path = (["haxe";"ds"],"Map") then begin match tl with
 					| t1 :: _ ->
 					| t1 :: _ ->
 						let rec loop stack t =
 						let rec loop stack t =
 							if List.exists (fun t2 -> fast_eq t t2) stack then
 							if List.exists (fun t2 -> fast_eq t t2) stack then
@@ -721,15 +733,18 @@ let rec flush_pass ctx p where =
 let make_where ctx where =
 let make_where ctx where =
 	where ^ " (" ^ ctx_pos ctx ^ ")"
 	where ^ " (" ^ ctx_pos ctx ^ ")"
 
 
-let exc_protect ctx f (where:string) =
-	let f = make_pass ~inf:(make_where ctx where) ctx f in
-	let rec r = ref (fun() ->
+let exc_protect ?(force=true) ctx f (where:string) =
+	let r = ref (lazy_available t_dynamic) in
+	r := lazy_wait (make_pass ~inf:(make_where ctx where) ctx (fun() ->
 		try
 		try
-			f r
+			let t = f r in
+			r := lazy_available t;
+			t
 		with
 		with
 			| Error (m,p) ->
 			| Error (m,p) ->
-				raise (Fatal_error (error_msg m,p))
-	) in
+				raise (Fatal_error ((error_msg m),p))
+	));
+	if force then delay ctx PForce (fun () -> ignore(lazy_type r));
 	r
 	r
 
 
 */*)
 */*)

+ 1 - 1
src/typing/abstract.ml → src/core/abstract.ml

@@ -29,7 +29,7 @@ let rec get_underlying_type a pl =
 				| Some t -> loop t
 				| Some t -> loop t
 				| _ -> t)
 				| _ -> t)
 			| TLazy f ->
 			| TLazy f ->
-				loop (!f())
+				loop (lazy_type f)
 			| TAbstract({a_path=([],"Null")} as a,[t1]) ->
 			| TAbstract({a_path=([],"Null")} as a,[t1]) ->
 				TAbstract(a,[loop t1])
 				TAbstract(a,[loop t1])
 			| TType (t,tl) ->
 			| TType (t,tl) ->

+ 32 - 6
src/syntax/ast.ml → src/core/ast.ml

@@ -62,6 +62,7 @@ type keyword =
 	| False
 	| False
 	| Abstract
 	| Abstract
 	| Macro
 	| Macro
+	| Final
 
 
 type binop =
 type binop =
 	| OpAdd
 	| OpAdd
@@ -136,6 +137,10 @@ type while_flag =
 	| NormalWhile
 	| NormalWhile
 	| DoWhile
 	| DoWhile
 
 
+type quote_status =
+	| NoQuotes
+	| DoubleQuotes
+
 type type_path = {
 type type_path = {
 	tpackage : string list;
 	tpackage : string list;
 	tname : string;
 	tname : string;
@@ -156,6 +161,7 @@ and complex_type =
 	| CTParent of type_hint
 	| CTParent of type_hint
 	| CTExtend of placed_type_path list * class_field list
 	| CTExtend of placed_type_path list * class_field list
 	| CTOptional of type_hint
 	| CTOptional of type_hint
+	| CTNamed of placed_name * type_hint
 
 
 and type_hint = complex_type * pos
 and type_hint = complex_type * pos
 
 
@@ -174,7 +180,7 @@ and expr_def =
 	| EBinop of binop * expr * expr
 	| EBinop of binop * expr * expr
 	| EField of expr * string
 	| EField of expr * string
 	| EParenthesis of expr
 	| EParenthesis of expr
-	| EObjectDecl of (placed_name * expr) list
+	| EObjectDecl of ((string * pos * quote_status) * expr) list
 	| EArrayDecl of expr list
 	| EArrayDecl of expr list
 	| ECall of expr * expr list
 	| ECall of expr * expr list
 	| ENew of placed_type_path * expr list
 	| ENew of placed_type_path * expr list
@@ -221,6 +227,7 @@ and access =
 	| ADynamic
 	| ADynamic
 	| AInline
 	| AInline
 	| AMacro
 	| AMacro
+	| AFinal
 
 
 and class_field_kind =
 and class_field_kind =
 	| FVar of type_hint option * expr option
 	| FVar of type_hint option * expr option
@@ -362,6 +369,7 @@ let s_access = function
 	| ADynamic -> "dynamic"
 	| ADynamic -> "dynamic"
 	| AInline -> "inline"
 	| AInline -> "inline"
 	| AMacro -> "macro"
 	| AMacro -> "macro"
+	| AFinal -> "final"
 
 
 let s_keyword = function
 let s_keyword = function
 	| Function -> "function"
 	| Function -> "function"
@@ -406,6 +414,7 @@ let s_keyword = function
 	| False -> "false"
 	| False -> "false"
 	| Abstract -> "abstract"
 	| Abstract -> "abstract"
 	| Macro -> "macro"
 	| Macro -> "macro"
+	| Final -> "final"
 
 
 let rec s_binop = function
 let rec s_binop = function
 	| OpAdd -> "+"
 	| OpAdd -> "+"
@@ -551,7 +560,9 @@ let map_expr loop (e,p) =
 			let tl = List.map tpath tl in
 			let tl = List.map tpath tl in
 			let fl = List.map cfield fl in
 			let fl = List.map cfield fl in
 			CTExtend (tl,fl)
 			CTExtend (tl,fl)
-		| CTOptional t -> CTOptional (type_hint t)),p
+		| CTOptional t -> CTOptional (type_hint t)
+		| CTNamed (n,t) -> CTNamed (n,type_hint t)
+		),p
 	and tparamdecl t =
 	and tparamdecl t =
 		let constraints = List.map type_hint t.tp_constraints in
 		let constraints = List.map type_hint t.tp_constraints in
 		let params = List.map tparamdecl t.tp_params in
 		let params = List.map tparamdecl t.tp_params in
@@ -585,7 +596,7 @@ let map_expr loop (e,p) =
 		EBinop (op,e1,e2)
 		EBinop (op,e1,e2)
 	| EField (e,f) -> EField (loop e, f)
 	| EField (e,f) -> EField (loop e, f)
 	| EParenthesis e -> EParenthesis (loop e)
 	| EParenthesis e -> EParenthesis (loop e)
-	| EObjectDecl fl -> EObjectDecl (List.map (fun ((f,p),e) -> (f,p),loop e) fl)
+	| EObjectDecl fl -> EObjectDecl (List.map (fun (k,e) -> k,loop e) fl)
 	| EArrayDecl el -> EArrayDecl (List.map loop el)
 	| EArrayDecl el -> EArrayDecl (List.map loop el)
 	| ECall (e,el) ->
 	| ECall (e,el) ->
 		let e = loop e in
 		let e = loop e in
@@ -683,6 +694,10 @@ let iter_expr loop (e,p) =
 		opt f.f_expr
 		opt f.f_expr
 	| EVars vl -> List.iter (fun (_,_,eo) -> opt eo) vl
 	| EVars vl -> List.iter (fun (_,_,eo) -> opt eo) vl
 
 
+let s_object_key_name name =  function
+	| DoubleQuotes -> "\"" ^ s_escape name ^ "\""
+	| NoQuotes -> name
+
 let s_expr e =
 let s_expr e =
 	let rec s_expr_inner tabs (e,_) =
 	let rec s_expr_inner tabs (e,_) =
 		match e with
 		match e with
@@ -691,7 +706,7 @@ let s_expr e =
 		| EBinop (op,e1,e2) -> s_expr_inner tabs e1 ^ " " ^ s_binop op ^ " " ^ s_expr_inner tabs e2
 		| EBinop (op,e1,e2) -> s_expr_inner tabs e1 ^ " " ^ s_binop op ^ " " ^ s_expr_inner tabs e2
 		| EField (e,f) -> s_expr_inner tabs e ^ "." ^ f
 		| EField (e,f) -> s_expr_inner tabs e ^ "." ^ f
 		| EParenthesis e -> "(" ^ (s_expr_inner tabs e) ^ ")"
 		| EParenthesis e -> "(" ^ (s_expr_inner tabs e) ^ ")"
-		| EObjectDecl fl -> "{ " ^ (String.concat ", " (List.map (fun ((n,_),e) -> n ^ " : " ^ (s_expr_inner tabs e)) fl)) ^ " }"
+		| EObjectDecl fl -> "{ " ^ (String.concat ", " (List.map (fun ((n,_,qs),e) -> (s_object_key_name n qs) ^ " : " ^ (s_expr_inner tabs e)) fl)) ^ " }"
 		| EArrayDecl el -> "[" ^ s_expr_list tabs el ", " ^ "]"
 		| EArrayDecl el -> "[" ^ s_expr_list tabs el ", " ^ "]"
 		| ECall (e,el) -> s_expr_inner tabs e ^ "(" ^ s_expr_list tabs el ", " ^ ")"
 		| ECall (e,el) -> s_expr_inner tabs e ^ "(" ^ s_expr_list tabs el ", " ^ ")"
 		| ENew (t,el) -> "new " ^ s_complex_type_path tabs t ^ "(" ^ s_expr_list tabs el ", " ^ ")"
 		| ENew (t,el) -> "new " ^ s_complex_type_path tabs t ^ "(" ^ s_expr_list tabs el ", " ^ ")"
@@ -745,6 +760,7 @@ let s_expr e =
 		| CTAnonymous fl -> "{ " ^ String.concat "; " (List.map (s_class_field tabs) fl) ^ "}";
 		| CTAnonymous fl -> "{ " ^ String.concat "; " (List.map (s_class_field tabs) fl) ^ "}";
 		| CTParent(t,_) -> "(" ^ s_complex_type tabs t ^ ")"
 		| CTParent(t,_) -> "(" ^ s_complex_type tabs t ^ ")"
 		| CTOptional(t,_) -> "?" ^ s_complex_type tabs t
 		| CTOptional(t,_) -> "?" ^ s_complex_type tabs t
+		| CTNamed((n,_),(t,_)) -> n ^ ":" ^ s_complex_type tabs t
 		| CTExtend (tl, fl) -> "{> " ^ String.concat " >, " (List.map (s_complex_type_path tabs) tl) ^ ", " ^ String.concat ", " (List.map (s_class_field tabs) fl) ^ " }"
 		| CTExtend (tl, fl) -> "{> " ^ String.concat " >, " (List.map (s_complex_type_path tabs) tl) ^ ", " ^ String.concat ", " (List.map (s_class_field tabs) fl) ^ " }"
 	and s_class_field tabs f =
 	and s_class_field tabs f =
 		match f.cff_doc with
 		match f.cff_doc with
@@ -798,7 +814,7 @@ let s_expr e =
 let get_value_meta meta =
 let get_value_meta meta =
 	try
 	try
 		begin match Meta.get Meta.Value meta with
 		begin match Meta.get Meta.Value meta with
-			| (_,[EObjectDecl values,_],_) -> List.fold_left (fun acc ((s,_),e) -> PMap.add s e acc) PMap.empty values
+			| (_,[EObjectDecl values,_],_) -> List.fold_left (fun acc ((s,_,_),e) -> PMap.add s e acc) PMap.empty values
 			| _ -> raise Not_found
 			| _ -> raise Not_found
 		end
 		end
 	with Not_found ->
 	with Not_found ->
@@ -858,8 +874,18 @@ module Expr = struct
 
 
 	let field_assoc name fl =
 	let field_assoc name fl =
 		let rec loop fl = match fl with
 		let rec loop fl = match fl with
-			| ((name',_),e) :: fl -> if name' = name then e else loop fl
+			| ((name',_,_),e) :: fl -> if name' = name then e else loop fl
 			| [] -> raise Not_found
 			| [] -> raise Not_found
 		in
 		in
 		loop fl
 		loop fl
+
+	let field_mem_assoc name fl =
+		let rec loop fl = match fl with
+			| ((name',_,_),e) :: fl -> if name' = name then raise Exit else loop fl
+			| [] -> false
+		in
+		try
+			loop fl
+		with Exit ->
+			true
 end
 end

+ 291 - 0
src/core/define.ml

@@ -0,0 +1,291 @@
+open Globals
+
+type define = {
+	mutable values : (string,string) PMap.t;
+	mutable defines_signature : string option;
+}
+
+type strict_defined =
+	| AbsolutePath
+	| AdvancedTelemetry
+	| AnnotateSource
+	(* | Analyzer *)
+	| As3
+	| CheckXmlProxy
+	| CoreApi
+	| CoreApiSerialize
+	| Cppia
+	| NoCppiaAst
+	| Dce
+	| DceDebug
+	| Debug
+	| Display
+	| DisplayStdin
+	| DllExport
+	| DllImport
+	| DocGen
+	| Dump
+	| DumpDependencies
+	| DumpIgnoreVarIds
+	| DynamicInterfaceClosures
+	| EraseGenerics
+	| EvalDebugger
+	| EvalStack
+	| EvalTimes
+	| FastCast
+	| Fdb
+	| FileExtension
+	| FlashStrict
+	| FlashUseStage
+	| ForceLibCheck
+	| ForceNativeProperty
+	| FormatWarning
+	| GencommonDebug
+	| Haxe3Compat
+	| HaxeBoot
+	| HaxeVer
+	| HxcppApiLevel
+	| HxcppGcGenerational
+	| HxcppDebugger
+	| IncludePrefix
+	| Interp
+	| JavaVer
+	| JqueryVer
+	| JsClassic
+	| JsEs
+	| JsUnflatten
+	| JsSourceMap
+	| JsEnumsAsObjects
+	| SourceMap
+	| KeepOldOutput
+	| LoopUnrollMaxCost
+	| LuaVer
+	| LuaJit
+	| Macro
+	| MacroDebug
+	| MacroTimes
+	| NekoSource
+	| NekoV1
+	| NetworkSandbox
+	| NetVer
+	| NetTarget
+	| NoCompilation
+	| NoCOpt
+	| NoDeprecationWarnings
+	| NoFlashOverride
+	| NoDebug
+	| NoInline
+	| NoOpt
+	| NoRoot
+	| NoSwfCompress
+	| NoTraces
+	| Objc
+	| OldConstructorInline
+	| OldErrorFormat
+	| PhpLib
+	| PhpFront
+	| PhpPrefix
+	| PythonVersion
+	| RealPosition
+	| ReplaceFiles
+	| Scriptable
+	| ShallowExpose
+	| SourceHeader
+	| SourceMapContent
+	| Static
+	| Swc
+	| SwfCompressLevel
+	| SwfDebugPassword
+	| SwfDirectBlit
+	| SwfGpu
+	| SwfMetadata
+	| SwfPreloaderFrame
+	| SwfProtected
+	| SwfScriptTimeout
+	| SwfUseDoAbc
+	| Sys
+	| Unsafe
+	| UseNekoc
+	| UseRttiDoc
+	| Vcproj
+	| NoMacroCache
+	| Last (* must be last *)
+
+type define_parameter =
+	| HasParam of string
+	| Platform of platform
+	| Platforms of platform list
+
+let infos = function
+	| AbsolutePath -> "absolute_path",("Print absolute file path in trace output",[])
+	| AdvancedTelemetry -> "advanced-telemetry",("Allow the SWF to be measured with Monocle tool",[Platform Flash])
+	| AnnotateSource -> "annotate_source",("Add additional comments to generated source code",[Platform Cpp])
+	(* | Analyzer -> "analyzer",("Use static analyzer for optimization (experimental)") *)
+	| As3 -> "as3",("Defined when outputting flash9 as3 source code",[])
+	| CheckXmlProxy -> "check_xml_proxy",("Check the used fields of the xml proxy",[])
+	| CoreApi -> "core_api",("Defined in the core api context",[])
+	| CoreApiSerialize -> "core_api_serialize",("Mark some generated core api classes with the Serializable attribute on C#",[Platform Cs])
+	| Cppia -> "cppia",("Generate cpp instruction assembly",[])
+	| NoCppiaAst -> "nocppiaast",("Use legacy cppia generation",[])
+	| Dce -> "dce",("<mode:std|full|no> Set the dead code elimination mode (default std)",[])
+	| DceDebug -> "dce_debug",("Show DCE log",[])
+	| Debug -> "debug",("Activated when compiling with -debug",[])
+	| Display -> "display",("Activated during completion",[])
+	| DisplayStdin -> "display_stdin",("Read the contents of a file specified in --display from standard input",[])
+	| DllExport -> "dll_export",("GenCPP experimental linking",[Platform Cpp])
+	| DllImport -> "dll_import",("Handle Haxe-generated .NET dll imports",[Platform Cs])
+	| DocGen -> "doc_gen",("Do not perform any removal/change in order to correctly generate documentation",[])
+	| Dump -> "dump",("<mode:pretty|record|legacy> Dump typed AST in dump subdirectory using specified mode or non-prettified default",[])
+	| DumpDependencies -> "dump_dependencies",("Dump the classes dependencies in a dump subdirectory",[])
+	| DumpIgnoreVarIds -> "dump_ignore_var_ids",("Remove variable IDs from non-pretty dumps (helps with diff)",[])
+	| DynamicInterfaceClosures -> "dynamic_interface_closures",("Use slow path for interface closures to save space",[Platform Cpp])
+	| EraseGenerics -> "erase_generics",("Erase generic classes on C#",[Platform Cs])
+	| EvalDebugger -> "eval_debugger",("Support debugger in macro/interp mode. Allows host:port value to open a socket. Implies eval_stack.",[])
+	| EvalStack -> "eval_stack",("Record stack information in macro/interp mode",[])
+	| EvalTimes -> "eval_times",("Record per-method execution times in macro/interp mode. Implies eval_stack.",[])
+	| FastCast -> "fast_cast",("Enables an experimental casts cleanup on C# and Java",[Platforms [Cs;Java]])
+	| Fdb -> "fdb",("Enable full flash debug infos for FDB interactive debugging",[Platform Flash])
+	| FileExtension -> "file_extension",("Output filename extension for cpp source code",[Platform Cpp])
+	| FlashStrict -> "flash_strict",("More strict typing for flash target",[Platform Flash])
+	| FlashUseStage -> "flash_use_stage",("Keep the SWF library initial stage",[Platform Flash])
+	(* force_lib_check is only here as a debug facility - compiler checking allows errors to be found more easily *)
+	| ForceLibCheck -> "force_lib_check",("Force the compiler to check -net-lib and -java-lib added classes (internal)",[Platforms [Cs;Java]])
+	| ForceNativeProperty -> "force_native_property",("Tag all properties with :nativeProperty metadata for 3.1 compatibility",[Platform Cpp])
+	| FormatWarning -> "format_warning",("Print a warning for each formatted string, for 2.x compatibility",[])
+	| GencommonDebug -> "gencommon_debug",("GenCommon internal",[Platforms [Cs;Java]])
+	| Haxe3Compat -> "haxe3compat", ("Gives warnings about transition from Haxe 3.x to Haxe 4.0",[])
+	| HaxeBoot -> "haxe_boot",("Given the name 'haxe' to the flash boot class instead of a generated name",[Platform Flash])
+	| HaxeVer -> "haxe_ver",("The current Haxe version value",[])
+	| HxcppApiLevel -> "hxcpp_api_level",("Provided to allow compatibility between hxcpp versions",[Platform Cpp])
+	| HxcppGcGenerational -> "HXCPP_GC_GENERATIONAL",("Experimental Garbage Collector",[Platform Cpp])
+	| HxcppDebugger -> "HXCPP_DEBUGGER",("Include additional information for HXCPP_DEBUGGER",[Platform Cpp])
+	| IncludePrefix -> "include_prefix",("prepend path to generated include files",[Platform Cpp])
+	| Interp -> "interp",("The code is compiled to be run with --interp",[])
+	| JavaVer -> "java_ver",("<version:5-7> Sets the Java version to be targeted",[Platform Java])
+	| JqueryVer -> "jquery_ver",("The jQuery version supported by js.jquery.*. The version is encoded as an integer. e.g. 1.11.3 is encoded as 11103",[Platform Js])
+	| JsClassic -> "js_classic",("Don't use a function wrapper and strict mode in JS output",[Platform Js])
+	| JsEs -> "js_es",("Generate JS compliant with given ES standard version (default 5)",[Platform Js; HasParam "version number"])
+	| JsEnumsAsObjects -> "js_enums_as_objects",("Generate enum representation as object instead of as array",[Platform Js])
+	| JsUnflatten -> "js_unflatten",("Generate nested objects for packages and types",[Platform Js])
+	| JsSourceMap -> "js_source_map",("Generate JavaScript source map even in non-debug mode",[Platform Js])
+	| SourceMap -> "source_map",("Generate source map for compiled files (Currently supported for php only)",[Platform Php])
+	| KeepOldOutput -> "keep_old_output",("Keep old source files in the output directory (for C#/Java)",[Platforms [Cs;Java]])
+	| LoopUnrollMaxCost -> "loop_unroll_max_cost",("Maximum cost (number of expressions * iterations) before loop unrolling is canceled (default 250)",[])
+	| LuaJit -> "lua_jit",("Enable the jit compiler for lua (version 5.2 only)",[Platform Lua])
+	| LuaVer -> "lua_ver",("The lua version to target",[Platform Lua])
+	| Macro -> "macro",("Defined when code is compiled in the macro context",[])
+	| MacroDebug -> "macro_debug",("Show warnings for potential macro problems (e.g. macro-in-macro calls)",[])
+	| MacroTimes -> "macro_times",("Display per-macro timing when used with --times",[])
+	| NetVer -> "net_ver",("<version:20-45> Sets the .NET version to be targeted",[Platform Cs])
+	| NetTarget -> "net_target",("<name> Sets the .NET target. Defaults to \"net\". xbox, micro (Micro Framework), compact (Compact Framework) are some valid values",[Platform Cs])
+	| NekoSource -> "neko_source",("Output neko source instead of bytecode",[Platform Neko])
+	| NekoV1 -> "neko_v1",("Keep Neko 1.x compatibility",[Platform Neko])
+	| NetworkSandbox -> "network-sandbox",("Use local network sandbox instead of local file access one",[Platform Flash])
+	| NoCompilation -> "no-compilation",("Disable final compilation",[Platforms [Cs;Java;Cpp;Hl]])
+	| NoCOpt -> "no_copt",("Disable completion optimization (for debug purposes)",[])
+	| NoDebug -> "no_debug",("Remove all debug macros from cpp output",[])
+	| NoDeprecationWarnings -> "no-deprecation-warnings",("Do not warn if fields annotated with @:deprecated are used",[])
+	| NoFlashOverride -> "no-flash-override",("Change overrides on some basic classes into HX suffixed methods, flash only",[Platform Flash])
+	| NoOpt -> "no_opt",("Disable optimizations",[])
+	| NoInline -> "no_inline",("Disable inlining",[])
+	| NoRoot -> "no_root",("Generate top-level types into haxe.root namespace",[Platform Cs])
+	| NoMacroCache -> "no_macro_cache",("Disable macro context caching",[])
+	| NoSwfCompress -> "no_swf_compress",("Disable SWF output compression",[Platform Flash])
+	| NoTraces -> "no_traces",("Disable all trace calls",[])
+	| Objc -> "objc",("Sets the hxcpp output to objective-c++ classes. Must be defined for interop",[Platform Cpp])
+	| OldConstructorInline -> "old-constructor-inline",("Use old constructor inlining logic (from haxe 3.4.2) instead of the reworked version.",[])
+	| OldErrorFormat -> "old-error-format",("Use Haxe 3.x zero-based column error messages instead of new one-based format.",[])
+	| PhpPrefix -> "php_prefix",("Root namespace for generated php classes. E.g. if compiled with`-D php-prefix=some.sub`, then all classes will be generated in `\\some\\sub` namespace.",[Platform Php])
+	| PhpLib -> "php_lib",("Select the name for the php lib folder.",[Platform Php])
+	| PhpFront -> "php_front",("Select the name for the php front file (by default: `index.php`).", [Platform Php])
+	| PythonVersion -> "python_version",("The python version to target (default 3.3)",[Platform Python])
+	| RealPosition -> "real_position",("Disables Haxe source mapping when targetting C#, removes position comments in Java and Php output",[Platforms [Cs;Java;Php]])
+	| ReplaceFiles -> "replace_files",("GenCommon internal",[Platforms [Java;Cs]])
+	| Scriptable -> "scriptable",("GenCPP internal",[Platform Cpp])
+	| ShallowExpose -> "shallow-expose",("Expose types to surrounding scope of Haxe generated closure without writing to window object",[Platform Js])
+	| SourceHeader -> "source-header",("Print value as comment on top of generated files, use '' value to disable",[])
+	| SourceMapContent -> "source-map-content",("Include the hx sources as part of the JS source map",[Platform Js])
+	| Static -> "static",("Defined if the current target is static",[])
+	| Swc -> "swc",("Output a SWC instead of a SWF",[Platform Flash])
+	| SwfCompressLevel -> "swf_compress_level",("<level:1-9> Set the amount of compression for the SWF output",[Platform Flash])
+	| SwfDebugPassword -> "swf_debug_password",("Set a password for debugging",[Platform Flash])
+	| SwfDirectBlit -> "swf_direct_blit",("Use hardware acceleration to blit graphics",[Platform Flash])
+	| SwfGpu -> "swf_gpu",("Use GPU compositing features when drawing graphics",[Platform Flash])
+	| SwfMetadata -> "swf_metadata",("<file> Include contents of <file> as metadata in the swf",[Platform Flash])
+	| SwfPreloaderFrame -> "swf_preloader_frame",("Insert empty first frame in swf",[Platform Flash])
+	| SwfProtected -> "swf_protected",("Compile Haxe private as protected in the SWF instead of public",[Platform Flash])
+	| SwfScriptTimeout -> "swf_script_timeout",("Maximum ActionScript processing time before script stuck dialog box displays (in seconds)",[Platform Flash])
+	| SwfUseDoAbc -> "swf_use_doabc",("Use DoAbc swf-tag instead of DoAbcDefine",[Platform Flash])
+	| Sys -> "sys",("Defined for all system platforms",[])
+	| Unsafe -> "unsafe",("Allow unsafe code when targeting C#",[Platform Cs])
+	| UseNekoc -> "use_nekoc",("Use nekoc compiler instead of internal one",[Platform Neko])
+	| UseRttiDoc -> "use_rtti_doc",("Allows access to documentation during compilation",[])
+	| Vcproj -> "vcproj",("GenCPP internal",[Platform Cpp])
+	| Last -> assert false
+
+let get_documentation_list() =
+	let m = ref 0 in
+	let rec loop i =
+		let d = Obj.magic i in
+		if d <> Last then begin
+			let t, (doc,flags) = infos d in
+			let pfs = ref [] in
+			List.iter (function
+			| HasParam s -> () (* TODO *)
+			| Platform p -> pfs := p :: !pfs;
+			| Platforms pl -> pfs := pl @ !pfs;
+			) flags;
+			let pfs = platform_list_help (List.rev !pfs) in
+			if String.length t > !m then m := String.length t;
+			((String.concat "-" (ExtString.String.nsplit t "_")),doc ^ pfs) :: (loop (i + 1))
+		end else
+			[]
+	in
+	let all = List.sort (fun (s1,_) (s2,_) -> String.compare s1 s2) (loop 0) in
+	all,!m
+
+let raw_defined ctx v =
+	PMap.mem v ctx.values
+
+let defined ctx v =
+	raw_defined ctx (fst (infos v))
+
+let raw_defined_value ctx k =
+	PMap.find k ctx.values
+
+let defined_value ctx v =
+	raw_defined_value ctx (fst (infos v))
+
+let defined_value_safe ?default ctx v =
+	try defined_value ctx v
+	with Not_found -> match default with Some s -> s | None -> ""
+
+let raw_define ctx v =
+	let k,v = try ExtString.String.split v "=" with _ -> v,"1" in
+	ctx.values <- PMap.add k v ctx.values;
+	let k = String.concat "_" (ExtString.String.nsplit k "-") in
+	ctx.values <- PMap.add k v ctx.values;
+	ctx.defines_signature <- None
+
+let define_value ctx k v =
+	raw_define ctx (fst (infos k) ^ "=" ^ v)
+
+let define ctx v =
+	raw_define ctx (fst (infos v))
+
+let get_signature def =
+	match def.defines_signature with
+	| Some s -> s
+	| None ->
+		let defines = PMap.foldi (fun k v acc ->
+			(* don't make much difference between these special compilation flags *)
+			match String.concat "_" (ExtString.String.nsplit k "-") with
+			(* If we add something here that might be used in conditional compilation it should be added to
+			   Parser.parse_macro_ident as well (issue #5682). *)
+			| "display" | "use_rtti_doc" | "macro_times" | "display_details" | "no_copt" | "display_stdin" -> acc
+			| _ -> (k ^ "=" ^ v) :: acc
+		) def.values [] in
+		let str = String.concat "@" (List.sort compare defines) in
+		let s = Digest.string str in
+		def.defines_signature <- Some s;
+		s

+ 0 - 0
src/typing/error.ml → src/core/error.ml


+ 0 - 0
src/compiler/globals.ml → src/core/globals.ml


+ 0 - 0
src/compiler/json.ml → src/core/json.ml


+ 9 - 13
src/context/meta.ml → src/core/meta.ml

@@ -89,7 +89,7 @@ type strict_meta =
 	| LibType
 	| LibType
 	| LoopLabel
 	| LoopLabel
 	| LuaRequire
 	| LuaRequire
-	| LuaDotMethod 
+	| LuaDotMethod
 	| Meta
 	| Meta
 	| Macro
 	| Macro
 	| MaybeUsed
 	| MaybeUsed
@@ -119,7 +119,6 @@ type strict_meta =
 	| Op
 	| Op
 	| Optional
 	| Optional
 	| Overload
 	| Overload
-	| PhpConstants
 	| PhpGlobal
 	| PhpGlobal
 	| PhpClassConst
 	| PhpClassConst
 	| PhpMagic
 	| PhpMagic
@@ -131,7 +130,6 @@ type strict_meta =
 	| Public
 	| Public
 	| PublicFields
 	| PublicFields
 	| Pure
 	| Pure
-	| QuotedField
 	| ReadOnly
 	| ReadOnly
 	| RealPath
 	| RealPath
 	| Remove
 	| Remove
@@ -317,15 +315,13 @@ let get_info = function
 	| Op -> ":op",("Declares an abstract field as being an operator overload",[HasParam "The operation";UsedOn TAbstractField])
 	| Op -> ":op",("Declares an abstract field as being an operator overload",[HasParam "The operation";UsedOn TAbstractField])
 	| Optional -> ":optional",("Marks the field of a structure as optional",[UsedOn TClassField])
 	| Optional -> ":optional",("Marks the field of a structure as optional",[UsedOn TClassField])
 	| Overload -> ":overload",("Allows the field to be called with different argument types",[HasParam "Function specification (no expression)";UsedOn TClassField])
 	| Overload -> ":overload",("Allows the field to be called with different argument types",[HasParam "Function specification (no expression)";UsedOn TClassField])
-	| PhpConstants -> ":phpConstants",("Marks the static fields of a class as PHP constants, without $",[Platform Php;UsedOn TClass])
-	| PhpGlobal -> ":phpGlobal",("(php7) Puts the static fields of a class in the global PHP namespace",[Platform Php;UsedOn TClass])
-	| PhpClassConst -> ":phpClassConst",("(php7)  Generate static var of an extern class as a PHP class constant",[Platform Php;UsedOn TClass])
-	| PhpMagic -> ":phpMagic",("(php7) Treat annotated field as special PHP magic field",[Platform Php;UsedOn TClassField])
-	| PhpNoConstructor -> ":phpNoConstructor",("(php7) Special meta for extern classes which does not have native constructor in PHP, but need a constructor in Haxe extern",[Platform Php;UsedOn TClass])
+	| PhpGlobal -> ":phpGlobal",("Indicates that static fields of an extern class actually are located in the global PHP namespace",[Platform Php;UsedOn TClass])
+	| PhpClassConst -> ":phpClassConst",("Indicates that a static var of an extern class is a PHP class constant",[Platform Php;UsedOn TClassField])
+	| PhpMagic -> ":phpMagic",("Treat annotated field as special PHP magic field. This meta makes compiler avoid renaming such fields on generating PHP code.",[Platform Php;UsedOn TClassField])
+	| PhpNoConstructor -> ":phpNoConstructor",("Special meta for extern classes which do not have native constructor in PHP, but need a constructor in Haxe extern",[Platform Php;UsedOn TClass])
 	| Pos -> ":pos",("Sets the position of a reified expression",[HasParam "Position";UsedOn TExpr])
 	| Pos -> ":pos",("Sets the position of a reified expression",[HasParam "Position";UsedOn TExpr])
 	| Public -> ":public",("Marks a class field as being public",[UsedOn TClassField;UsedInternally])
 	| Public -> ":public",("Marks a class field as being public",[UsedOn TClassField;UsedInternally])
 	| PublicFields -> ":publicFields",("Forces all class fields of inheriting classes to be public",[UsedOn TClass])
 	| PublicFields -> ":publicFields",("Forces all class fields of inheriting classes to be public",[UsedOn TClass])
-	| QuotedField -> ":quotedField",("Used internally to mark structure fields which are quoted in syntax",[UsedInternally])
 	| PrivateAccess -> ":privateAccess",("Allow private access to anything for the annotated expression",[UsedOn TExpr])
 	| PrivateAccess -> ":privateAccess",("Allow private access to anything for the annotated expression",[UsedOn TExpr])
 	| Protected -> ":protected",("Marks a class field as being protected",[UsedOn TClassField;Platforms [Cs;Java;Flash]])
 	| Protected -> ":protected",("Marks a class field as being protected",[UsedOn TClassField;Platforms [Cs;Java;Flash]])
 	| Property -> ":property",("Marks a property field to be compiled as a native C# property",[UsedOn TClassField;Platform Cs])
 	| Property -> ":property",("Marks a property field to be compiled as a native C# property",[UsedOn TClassField;Platform Cs])
@@ -336,11 +332,11 @@ let get_info = function
 	| Require -> ":require",("Allows access to a field only if the specified compiler flag is set",[HasParam "Compiler flag to check";UsedOn TClassField])
 	| Require -> ":require",("Allows access to a field only if the specified compiler flag is set",[HasParam "Compiler flag to check";UsedOn TClassField])
 	| RequiresAssign -> ":requiresAssign",("Used internally to mark certain abstract operator overloads",[UsedInternally])
 	| RequiresAssign -> ":requiresAssign",("Used internally to mark certain abstract operator overloads",[UsedInternally])
 	| Resolve -> ":resolve",("Abstract fields marked with this metadata can be used to resolve unknown fields",[UsedOn TClassField])
 	| Resolve -> ":resolve",("Abstract fields marked with this metadata can be used to resolve unknown fields",[UsedOn TClassField])
-	| Rtti -> ":rtti",("Adds runtime type informations",[UsedOn TClass])
+	| Rtti -> ":rtti",("Adds runtime type information",[UsedOn TClass])
 	| Runtime -> ":runtime",("?",[])
 	| Runtime -> ":runtime",("?",[])
 	| RuntimeValue -> ":runtimeValue",("Marks an abstract as being a runtime value",[UsedOn TAbstract])
 	| RuntimeValue -> ":runtimeValue",("Marks an abstract as being a runtime value",[UsedOn TAbstract])
 	| Scalar -> ":scalar",("Used by hxcpp to mark a custom coreType abstract",[UsedOn TAbstract; Platform Cpp])
 	| Scalar -> ":scalar",("Used by hxcpp to mark a custom coreType abstract",[UsedOn TAbstract; Platform Cpp])
-	| SelfCall -> ":selfCall",("Translates method calls into calling object directly",[UsedOn TClassField; Platform Js])
+	| SelfCall -> ":selfCall",("Translates method calls into calling object directly",[UsedOn TClassField; Platforms [Js;Lua]])
 	| Setter -> ":setter",("Generates a native setter function on the given field",[HasParam "Class field name";UsedOn TClassField;Platform Flash])
 	| Setter -> ":setter",("Generates a native setter function on the given field",[HasParam "Class field name";UsedOn TClassField;Platform Flash])
 	| StackOnly -> ":stackOnly",("Instances of this type can only appear on the stack",[Platform Cpp])
 	| StackOnly -> ":stackOnly",("Instances of this type can only appear on the stack",[Platform Cpp])
 	| StoredTypedExpr -> ":storedTypedExpr",("Used internally to reference a typed expression returned from a macro",[UsedInternally])
 	| StoredTypedExpr -> ":storedTypedExpr",("Used internally to reference a typed expression returned from a macro",[UsedInternally])
@@ -351,9 +347,9 @@ let get_info = function
 	| Strict -> ":strict",("Used to declare a native C# attribute or a native Java metadata. Is type checked",[Platforms [Java;Cs]])
 	| Strict -> ":strict",("Used to declare a native C# attribute or a native Java metadata. Is type checked",[Platforms [Java;Cs]])
 	| Struct -> ":struct",("Marks a class definition as a struct",[Platform Cs; UsedOn TClass])
 	| Struct -> ":struct",("Marks a class definition as a struct",[Platform Cs; UsedOn TClass])
 	| StructAccess -> ":structAccess",("Marks an extern class as using struct access('.') not pointer('->')",[Platform Cpp; UsedOn TClass])
 	| StructAccess -> ":structAccess",("Marks an extern class as using struct access('.') not pointer('->')",[Platform Cpp; UsedOn TClass])
-	| StructInit -> ":structInit",("Allows to initialize the class with a structure that matches constructor parameters",[UsedOn TClass])
+	| StructInit -> ":structInit",("Allows one to initialize the class with a structure that matches constructor parameters",[UsedOn TClass])
 	| SuppressWarnings -> ":suppressWarnings",("Adds a SuppressWarnings annotation for the generated Java class",[Platform Java; UsedOn TClass])
 	| SuppressWarnings -> ":suppressWarnings",("Adds a SuppressWarnings annotation for the generated Java class",[Platform Java; UsedOn TClass])
-	| TemplatedCall -> ":templatedCall",("Indicates that the first parameter of static call should be treated as a template arguement",[Platform Cpp; UsedOn TClassField])
+	| TemplatedCall -> ":templatedCall",("Indicates that the first parameter of static call should be treated as a template argument",[Platform Cpp; UsedOn TClassField])
 	| Throws -> ":throws",("Adds a 'throws' declaration to the generated function",[HasParam "Type as String"; Platform Java; UsedOn TClassField])
 	| Throws -> ":throws",("Adds a 'throws' declaration to the generated function",[HasParam "Type as String"; Platform Java; UsedOn TClassField])
 	| This -> ":this",("Internally used to pass a 'this' expression to macros",[UsedInternally; UsedOn TExpr])
 	| This -> ":this",("Internally used to pass a 'this' expression to macros",[UsedInternally; UsedOn TExpr])
 	| To -> ":to",("Specifies that the field of the abstract is a cast operation to the type identified in the function",[UsedOn TAbstractField])
 	| To -> ":to",("Specifies that the field of the abstract is a cast operation to the type identified in the function",[UsedOn TAbstractField])

+ 74 - 0
src/core/numeric.ml

@@ -0,0 +1,74 @@
+(*
+	The Haxe Compiler
+	Copyright (C) 2005-2017  Haxe Foundation
+
+	This program is free software; you can redistribute it and/or
+	modify it under the terms of the GNU General Public License
+	as published by the Free Software Foundation; either version 2
+	of the License, or (at your option) any later version.
+
+	This program is distributed in the hope that it will be useful,
+	but WITHOUT ANY WARRANTY; without even the implied warranty of
+	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+	GNU General Public License for more details.
+
+	You should have received a copy of the GNU General Public License
+	along with this program; if not, write to the Free Software
+	Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *)
+
+(*  Taken from OCaml source typing/oprint.ml
+
+	This is a better version of string_of_float which prints without loss of precision
+	so that float_of_string (float_repres x) = x for all floats x
+*)
+let valid_float_lexeme s =
+	let l = String.length s in
+	let rec loop i =
+		if i >= l then s ^ "." else
+		match s.[i] with
+		| '0' .. '9' | '-' -> loop (i+1)
+		| _ -> s
+	in loop 0
+
+let float_repres f =
+	match classify_float f with
+	| FP_nan -> "nan"
+	| FP_infinite ->
+		if f < 0.0 then "neg_infinity" else "infinity"
+	| _ ->
+		let float_val =
+			let s1 = Printf.sprintf "%.12g" f in
+			if f = float_of_string s1 then s1 else
+			let s2 = Printf.sprintf "%.15g" f in
+			if f = float_of_string s2 then s2 else
+			Printf.sprintf "%.18g" f
+		in valid_float_lexeme float_val
+
+let parse_float s =
+	let rec loop sp i =
+		if i = String.length s then (if sp = 0 then s else String.sub s sp (i - sp)) else
+		match String.unsafe_get s i with
+		| ' ' when sp = i -> loop (sp + 1) (i + 1)
+		| '0'..'9' | '-' | '+' | 'e' | 'E' | '.' -> loop sp (i + 1)
+		| _ -> String.sub s sp (i - sp)
+	in
+	float_of_string (loop 0 0)
+
+let parse_int s =
+	let rec loop_hex i =
+		if i = String.length s then s else
+		match String.unsafe_get s i with
+		| '0'..'9' | 'a'..'f' | 'A'..'F' -> loop_hex (i + 1)
+		| _ -> String.sub s 0 i
+	in
+	let rec loop sp i =
+		if i = String.length s then (if sp = 0 then s else String.sub s sp (i - sp)) else
+		match String.unsafe_get s i with
+		| '0'..'9' -> loop sp (i + 1)
+		| ' ' when sp = i -> loop (sp + 1) (i + 1)
+		| '-' when i = 0 -> loop sp (i + 1)
+		| ('x' | 'X') when i = 1 && String.get s 0 = '0' -> loop_hex (i + 1)
+		| _ -> String.sub s sp (i - sp)
+	in
+	Int32.of_string (loop 0 0)

+ 47 - 1
src/compiler/path.ml → src/core/path.ml

@@ -153,4 +153,50 @@ let find_directories target recursive paths =
 		with Sys_error _ ->
 		with Sys_error _ ->
 			acc
 			acc
 	in
 	in
-	List.fold_left (fun acc dir -> loop acc dir) [] paths
+	List.fold_left (fun acc dir -> loop acc dir) [] paths
+
+let make_valid_filename s =
+	let r = Str.regexp "[^A-Za-z0-9_\\-\\.,]" in
+	Str.global_substitute r (fun s -> "_") s
+
+let rec create_file bin ext acc = function
+	| [] -> assert false
+	| d :: [] ->
+		let d = make_valid_filename d in
+		let maxlen = 200 - String.length ext in
+		let d = if String.length d > maxlen then String.sub d 0 maxlen else d in
+		let ch = (if bin then open_out_bin else open_out) (String.concat "/" (List.rev (d :: acc)) ^ ext) in
+		ch
+	| d :: l ->
+		let dir = String.concat "/" (List.rev (d :: acc)) in
+		if not (Sys.file_exists (remove_trailing_slash dir)) then Unix.mkdir dir 0o755;
+		create_file bin ext (d :: acc) l
+
+let rec mkdir_recursive base dir_list =
+	match dir_list with
+	| [] -> ()
+	| dir :: remaining ->
+		let path = match base with
+				   | "" ->  dir
+				   | "/" -> "/" ^ dir
+				   | _ -> base ^ "/" ^ dir
+		in
+		let path_len = String.length path in
+		let path =
+			if path_len > 0 && (path.[path_len - 1] = '/' || path.[path_len - 1] == '\\') then
+				String.sub path 0 (path_len - 1)
+			else
+				path
+		in
+		if not ( (path = "") || ( (path_len = 2) && ((String.sub path 1 1) = ":") ) ) then
+			if not (Sys.file_exists path) then
+				Unix.mkdir path 0o755;
+		mkdir_recursive (if (path = "") then "/" else path) remaining
+
+let mkdir_from_path path =
+	let parts = Str.split_delim (Str.regexp "[\\/]+") path in
+	match parts with
+		| [] -> (* path was "" *) ()
+		| _ ->
+			let dir_list = List.rev (List.tl (List.rev parts)) in
+			mkdir_recursive "" dir_list

+ 388 - 0
src/core/texpr.ml

@@ -0,0 +1,388 @@
+open Globals
+open Ast
+open Type
+open Error
+
+let equal_fa fa1 fa2 = match fa1,fa2 with
+	| FStatic(c1,cf1),FStatic(c2,cf2) -> c1 == c2 && cf1 == cf2
+	| FInstance(c1,tl1,cf1),FInstance(c2,tl2,cf2) -> c1 == c2 && safe_for_all2 type_iseq tl1 tl2 && cf1 == cf2
+	(* TODO: This is technically not correct but unfortunately the compiler makes a distinct tclass_field for each anon field access. *)
+	| FAnon cf1,FAnon cf2 -> cf1.cf_name = cf2.cf_name
+	| FDynamic s1,FDynamic s2 -> s1 = s2
+	| FClosure(None,cf1),FClosure(None,cf2) -> cf1 == cf2
+	| FClosure(Some(c1,tl1),cf1),FClosure(Some(c2,tl2),cf2) -> c1 == c2 && safe_for_all2 type_iseq tl1 tl2 && cf1 == cf2
+	| FEnum(en1,ef1),FEnum(en2,ef2) -> en1 == en2 && ef1 == ef2
+	| _ -> false
+
+let rec equal e1 e2 = match e1.eexpr,e2.eexpr with
+	| TConst ct1,TConst ct2 -> ct1 = ct2
+	| TLocal v1,TLocal v2 -> v1 == v2
+	| TArray(eb1,ei1),TArray(eb2,ei2) -> equal eb1 eb2 && equal ei1 ei2
+	| TBinop(op1,lhs1,rhs1),TBinop(op2,lhs2,rhs2) -> op1 = op2 && equal lhs1 lhs2 && equal rhs1 rhs2
+	| TField(e1,fa1),TField(e2,fa2) -> equal e1 e2 && equal_fa fa1 fa2
+	| TTypeExpr mt1,TTypeExpr mt2 -> mt1 == mt2
+	| TParenthesis e1,TParenthesis e2 -> equal e1 e2
+	| TObjectDecl fl1,TObjectDecl fl2 -> safe_for_all2 (fun (s1,e1) (s2,e2) -> s1 = s2 && equal e1 e2) fl1 fl2
+	| (TArrayDecl el1,TArrayDecl el2) | (TBlock el1,TBlock el2) -> safe_for_all2 equal el1 el2
+	| TCall(e1,el1),TCall(e2,el2) -> equal e1 e2 && safe_for_all2 equal el1 el2
+	| TNew(c1,tl1,el1),TNew(c2,tl2,el2) -> c1 == c2 && safe_for_all2 type_iseq tl1 tl2 && safe_for_all2 equal el1 el2
+	| TUnop(op1,flag1,e1),TUnop(op2,flag2,e2) -> op1 = op2 && flag1 = flag2 && equal e1 e2
+	| TFunction tf1,TFunction tf2 -> tf1 == tf2
+	| TVar(v1,None),TVar(v2,None) -> v1 == v2
+	| TVar(v1,Some e1),TVar(v2,Some e2) -> v1 == v2 && equal e1 e2
+	| TFor(v1,ec1,eb1),TFor(v2,ec2,eb2) -> v1 == v2 && equal ec1 ec2 && equal eb1 eb2
+	| TIf(e1,ethen1,None),TIf(e2,ethen2,None) -> equal e1 e2 && equal ethen1 ethen2
+	| TIf(e1,ethen1,Some eelse1),TIf(e2,ethen2,Some eelse2) -> equal e1 e2 && equal ethen1 ethen2 && equal eelse1 eelse2
+	| TWhile(e1,eb1,flag1),TWhile(e2,eb2,flag2) -> equal e1 e2 && equal eb2 eb2 && flag1 = flag2
+	| TSwitch(e1,cases1,eo1),TSwitch(e2,cases2,eo2) ->
+		equal e1 e2 &&
+		safe_for_all2 (fun (el1,e1) (el2,e2) -> safe_for_all2 equal el1 el2 && equal e1 e2) cases1 cases2 &&
+		(match eo1,eo2 with None,None -> true | Some e1,Some e2 -> equal e1 e2 | _ -> false)
+	| TTry(e1,catches1),TTry(e2,catches2) -> equal e1 e2 && safe_for_all2 (fun (v1,e1) (v2,e2) -> v1 == v2 && equal e1 e2) catches1 catches2
+	| TReturn None,TReturn None -> true
+	| TReturn(Some e1),TReturn(Some e2) -> equal e1 e2
+	| TThrow e1,TThrow e2 -> equal e1 e2
+	| TCast(e1,None),TCast(e2,None) -> equal e1 e2
+	| TCast(e1,Some mt1),TCast(e2,Some mt2) -> equal e1 e2 && mt1 == mt2
+	| TMeta((m1,el1,_),e1),TMeta((m2,el2,_),e2) -> m1 = m2 && safe_for_all2 (fun e1 e2 -> (* TODO: cheating? *) (Ast.s_expr e1) = (Ast.s_expr e2)) el1 el2 && equal e1 e2
+	| (TBreak,TBreak) | (TContinue,TContinue) -> true
+	| TEnumParameter(e1,ef1,i1),TEnumParameter(e2,ef2,i2) -> equal e1 e2 && ef1 == ef2 && i1 = i2
+	| _ -> false
+
+let duplicate_tvars e =
+	let vars = Hashtbl.create 0 in
+	let copy_var v =
+		let v2 = alloc_var v.v_name v.v_type v.v_pos in
+		v2.v_meta <- v.v_meta;
+		v2.v_extra <- v.v_extra;
+		Hashtbl.add vars v.v_id v2;
+		v2;
+	in
+	let rec build_expr e =
+		match e.eexpr with
+		| TVar (v,eo) ->
+			let v2 = copy_var v in
+			{e with eexpr = TVar(v2, Option.map build_expr eo)}
+		| TFor (v,e1,e2) ->
+			let v2 = copy_var v in
+			{e with eexpr = TFor(v2, build_expr e1, build_expr e2)}
+		| TTry (e1,cl) ->
+			let cl = List.map (fun (v,e) ->
+				let v2 = copy_var v in
+				v2, build_expr e
+			) cl in
+			{e with eexpr = TTry(build_expr e1, cl)}
+		| TFunction f ->
+			let args = List.map (fun (v,c) -> copy_var v, c) f.tf_args in
+			let f = {
+				tf_args = args;
+				tf_type = f.tf_type;
+				tf_expr = build_expr f.tf_expr;
+			} in
+			{e with eexpr = TFunction f}
+		| TLocal v ->
+			(try
+				let v2 = Hashtbl.find vars v.v_id in
+				{e with eexpr = TLocal v2}
+			with _ ->
+				e)
+		| _ ->
+			map_expr build_expr e
+	in
+	build_expr e
+
+let rec skip e = match e.eexpr with
+	| TParenthesis e1 | TMeta(_,e1) | TBlock [e1] | TCast(e1,None) -> skip e1
+	| _ -> e
+
+let foldmap_list f acc el =
+	let rec loop acc el acc2 = (match el with
+		| [] -> acc,(List.rev acc2)
+		| e1 :: el ->
+			let acc,e1 = f acc e1 in
+			loop acc el (e1 :: acc2))
+	in loop acc el []
+
+let foldmap_opt f acc eo = match eo with
+	| Some(e) -> let acc,e = f acc e in acc,Some(e)
+	| None    -> acc,eo
+
+let foldmap_pairs f acc pairs =
+	let acc,pairs = List.fold_left
+		(fun (acc,el) (v,e) -> let acc,e = f acc e in (acc,(v,e) :: el))
+		(acc,[])
+		pairs
+	in acc,(List.rev pairs)
+
+let foldmap f acc e =
+	begin match e.eexpr with
+	| TConst _
+	| TLocal _
+	| TBreak
+	| TContinue
+	| TTypeExpr _
+	| TIdent _ ->
+		acc,e
+	| TArray (e1,e2) ->
+		let acc,e1 = f acc e1 in
+		let acc,e2 = f acc e2 in
+		acc,{ e with eexpr = TArray (e1, e2) }
+	| TBinop (op,e1,e2) ->
+		let acc,e1 = f acc e1 in
+		let acc,e2 = f acc e2 in
+		acc,{ e with eexpr = TBinop (op,e1,e2) }
+	| TFor (v,e1,e2) ->
+		let acc,e1 = f acc e1 in
+		let acc,e2 = f acc e2 in
+		acc,{ e with eexpr = TFor (v,e1,e2) }
+	| TWhile (e1,e2,flag) ->
+		let acc,e1 = f acc e1 in
+		let acc,e2 = f acc e2 in
+		acc,{ e with eexpr = TWhile (e1,e2,flag) }
+	| TThrow e1 ->
+		let acc,e1 = f acc e1 in
+		acc,{ e with eexpr = TThrow (e1) }
+	| TEnumParameter (e1,ef,i) ->
+		let acc,e1 = f acc e1 in
+		acc,{ e with eexpr = TEnumParameter(e1,ef,i) }
+	| TEnumIndex e1 ->
+		let acc,e1 = f acc e1 in
+		acc,{ e with eexpr = TEnumIndex e1 }
+	| TField (e1,v) ->
+		let acc,e1 = f acc e1 in
+		acc,{ e with eexpr = TField (e1,v) }
+	| TParenthesis e1 ->
+		let acc,e1 = f acc e1 in
+		acc,{ e with eexpr = TParenthesis (e1) }
+	| TUnop (op,pre,e1) ->
+		let acc,e1 = f acc e1 in
+		acc,{ e with eexpr = TUnop (op,pre,e1) }
+	| TArrayDecl el ->
+		let acc,el = foldmap_list f acc el in
+		acc,{ e with eexpr = TArrayDecl el }
+	| TNew (t,pl,el) ->
+		let acc,el = foldmap_list f acc el in
+		acc,{ e with eexpr = TNew (t,pl,el) }
+	| TBlock el ->
+		let acc,el = foldmap_list f acc el in
+		acc,{ e with eexpr = TBlock (el) }
+	| TObjectDecl el ->
+		let acc,el = foldmap_pairs f acc el in
+		acc,{ e with eexpr = TObjectDecl el }
+	| TCall (e1,el) ->
+		let acc,e1 = f acc e1 in
+		let acc,el = foldmap_list f acc el in
+		acc,{ e with eexpr = TCall (e1,el) }
+	| TVar (v,eo) ->
+		let acc,eo = foldmap_opt f acc eo in
+		acc,{ e with eexpr = TVar (v, eo) }
+	| TFunction fu ->
+		let acc,e1 = f acc fu.tf_expr in
+		acc,{ e with eexpr = TFunction { fu with tf_expr = e1 } }
+	| TIf (ec,e1,eo) ->
+		let acc,ec = f acc ec in
+		let acc,e1 = f acc e1 in
+		let acc,eo = foldmap_opt f acc eo in
+		acc,{ e with eexpr = TIf (ec,e1,eo)}
+	| TSwitch (e1,cases,def) ->
+		let acc,e1 = f acc e1 in
+		let acc,cases = List.fold_left (fun (acc,cases) (el,e2) ->
+			let acc,el = foldmap_list f acc el in
+			let acc,e2 = f acc e2 in
+			acc,((el,e2) :: cases)
+		) (acc,[]) cases in
+		let acc,def = foldmap_opt f acc def in
+		acc,{ e with eexpr = TSwitch (e1, cases, def) }
+	| TTry (e1,catches) ->
+		let acc,e1 = f acc e1 in
+		let acc,catches = foldmap_pairs f acc catches in
+		acc,{ e with eexpr = TTry (e1, catches) }
+	| TReturn eo ->
+		let acc,eo = foldmap_opt f acc eo in
+		acc,{ e with eexpr = TReturn eo }
+	| TCast (e1,t) ->
+		let acc,e1 = f acc e1 in
+		acc,{ e with eexpr = TCast (e1,t) }
+	| TMeta (m,e1) ->
+		let acc,e1 = f acc e1 in
+		acc,{ e with eexpr = TMeta(m,e1)}
+	end
+
+(* Collection of functions that return expressions *)
+module Builder = struct
+	let make_static_this c p =
+		let ta = TAnon { a_fields = c.cl_statics; a_status = ref (Statics c) } in
+		mk (TTypeExpr (TClassDecl c)) ta p
+
+	let make_typeexpr mt pos =
+		let t =
+			match mt with
+			| TClassDecl c -> TAnon { a_fields = c.cl_statics; a_status = ref (Statics c) }
+			| TEnumDecl e -> TAnon { a_fields = PMap.empty; a_status = ref (EnumStatics e) }
+			| TAbstractDecl a -> TAnon { a_fields = PMap.empty; a_status = ref (AbstractStatics a) }
+			| _ -> assert false
+		in
+		mk (TTypeExpr mt) t pos
+
+	let make_static_field c cf p =
+		let e_this = make_static_this c p in
+		mk (TField(e_this,FStatic(c,cf))) cf.cf_type p
+
+	let make_throw e p =
+		mk (TThrow e) t_dynamic p
+
+	let make_int basic i p =
+		mk (TConst (TInt (Int32.of_int i))) basic.tint p
+
+	let make_float basic f p =
+		mk (TConst (TFloat f)) basic.tfloat p
+
+	let make_bool basic b p =
+		mk (TConst(TBool b)) basic.tbool p
+
+	let make_string basic s p =
+		mk (TConst (TString s)) basic.tstring p
+
+	let make_null t p =
+		mk (TConst TNull) t p
+
+	let make_local v p =
+		mk (TLocal v) v.v_type p
+
+	let make_const_texpr basic ct p = match ct with
+		| TString s -> mk (TConst (TString s)) basic.tstring p
+		| TInt i -> mk (TConst (TInt i)) basic.tint p
+		| TFloat f -> mk (TConst (TFloat f)) basic.tfloat p
+		| TBool b -> mk (TConst (TBool b)) basic.tbool p
+		| TNull -> mk (TConst TNull) (basic.tnull (mk_mono())) p
+		| _ -> error "Unsupported constant" p
+
+	let field e name t p =
+		mk (TField (e,try quick_field e.etype name with Not_found -> assert false)) t p
+
+	let fcall e name el ret p =
+		let ft = tfun (List.map (fun e -> e.etype) el) ret in
+		mk (TCall (field e name ft p,el)) ret p
+
+	let mk_parent e =
+		mk (TParenthesis e) e.etype e.epos
+
+	let mk_return e =
+		mk (TReturn (Some e)) t_dynamic e.epos
+
+	let binop op a b t p =
+		mk (TBinop (op,a,b)) t p
+
+	let index basic e index t p =
+		mk (TArray (e,mk (TConst (TInt (Int32.of_int index))) basic.tint p)) t p
+end
+
+let set_default basic a c p =
+	let t = a.v_type in
+	let ve = mk (TLocal a) t p in
+	let cond =  TBinop (OpEq,ve,mk (TConst TNull) t p) in
+	mk (TIf (Builder.mk_parent (mk cond basic.tbool p), mk (TBinop (OpAssign,ve,mk (TConst c) t p)) t p,None)) basic.tvoid p
+
+(*
+	Tells if the constructor might be called without any issue whatever its parameters
+*)
+let rec constructor_side_effects e =
+	match e.eexpr with
+	| TBinop (op,_,_) when op <> OpAssign ->
+		true
+	| TField (_,FEnum _) ->
+		false
+	| TUnop _ | TArray _ | TField _ | TEnumParameter _ | TEnumIndex _ | TCall _ | TNew _ | TFor _ | TWhile _ | TSwitch _ | TReturn _ | TThrow _ ->
+		true
+	| TBinop _ | TTry _ | TIf _ | TBlock _ | TVar _
+	| TFunction _ | TArrayDecl _ | TObjectDecl _
+	| TParenthesis _ | TTypeExpr _ | TLocal _ | TMeta _
+	| TConst _ | TContinue | TBreak | TCast _ | TIdent _ ->
+		try
+			Type.iter (fun e -> if constructor_side_effects e then raise Exit) e;
+			false;
+		with Exit ->
+			true
+
+let type_constant basic c p =
+	match c with
+	| Int s ->
+		if String.length s > 10 && String.sub s 0 2 = "0x" then error "Invalid hexadecimal integer" p;
+		(try mk (TConst (TInt (Int32.of_string s))) basic.tint p
+		with _ -> mk (TConst (TFloat s)) basic.tfloat p)
+	| Float f -> mk (TConst (TFloat f)) basic.tfloat p
+	| String s -> mk (TConst (TString s)) basic.tstring p
+	| Ident "true" -> mk (TConst (TBool true)) basic.tbool p
+	| Ident "false" -> mk (TConst (TBool false)) basic.tbool p
+	| Ident "null" -> mk (TConst TNull) (basic.tnull (mk_mono())) p
+	| Ident t -> error ("Invalid constant :  " ^ t) p
+	| Regexp _ -> error "Invalid constant" p
+
+let rec type_constant_value basic (e,p) =
+	match e with
+	| EConst c ->
+		type_constant basic c p
+	| EParenthesis e ->
+		type_constant_value basic e
+	| EObjectDecl el ->
+		mk (TObjectDecl (List.map (fun (k,e) -> k,type_constant_value basic e) el)) (TAnon { a_fields = PMap.empty; a_status = ref Closed }) p
+	| EArrayDecl el ->
+		mk (TArrayDecl (List.map (type_constant_value basic) el)) (basic.tarray t_dynamic) p
+	| _ ->
+		error "Constant value expected" p
+
+let for_remap basic v e1 e2 p =
+	let v' = alloc_var v.v_name e1.etype e1.epos 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 [] basic.tbool) e1.epos in
+	let ehasnext = mk (TCall(ehasnext,[])) 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)) basic.tvoid p in
+	let ebody = Type.concat eassign e2 in
+	mk (TBlock [
+		mk (TVar (v',Some e1)) basic.tvoid e1.epos;
+		mk (TWhile((mk (TParenthesis ehasnext) ehasnext.etype ehasnext.epos),ebody,NormalWhile)) basic.tvoid e1.epos;
+	]) basic.tvoid p
+
+(* -------------------------------------------------------------------------- *)
+(* BUILD META DATA OBJECT *)
+
+let build_metadata api t =
+	let p, meta, fields, statics = (match t with
+		| TClassDecl c ->
+			let fields = List.map (fun f -> f.cf_name,f.cf_meta) (c.cl_ordered_fields @ (match c.cl_constructor with None -> [] | Some f -> [{ f with cf_name = "_" }])) in
+			let statics =  List.map (fun f -> f.cf_name,f.cf_meta) c.cl_ordered_statics in
+			(c.cl_pos, ["",c.cl_meta],fields,statics)
+		| TEnumDecl e ->
+			(e.e_pos, ["",e.e_meta],List.map (fun n -> n, (PMap.find n e.e_constrs).ef_meta) e.e_names, [])
+		| TTypeDecl t ->
+			(t.t_pos, ["",t.t_meta],(match follow t.t_type with TAnon a -> PMap.fold (fun f acc -> (f.cf_name,f.cf_meta) :: acc) a.a_fields [] | _ -> []),[])
+		| TAbstractDecl a ->
+			(a.a_pos, ["",a.a_meta],[],[])
+	) in
+	let filter l =
+		let l = List.map (fun (n,ml) -> n, ExtList.List.filter_map (fun (m,el,p) -> match m with Meta.Custom s when String.length s > 0 && s.[0] <> ':' -> Some (s,el,p) | _ -> None) ml) l in
+		List.filter (fun (_,ml) -> ml <> []) l
+	in
+	let meta, fields, statics = filter meta, filter fields, filter statics in
+	let make_meta_field ml =
+		let h = Hashtbl.create 0 in
+		mk (TObjectDecl (List.map (fun (f,el,p) ->
+			if Hashtbl.mem h f then error ("Duplicate metadata '" ^ f ^ "'") p;
+			Hashtbl.add h f ();
+			(f,null_pos,NoQuotes), mk (match el with [] -> TConst TNull | _ -> TArrayDecl (List.map (type_constant_value api) el)) (api.tarray t_dynamic) p
+		) ml)) t_dynamic p
+	in
+	let make_meta l =
+		mk (TObjectDecl (List.map (fun (f,ml) -> (f,null_pos,NoQuotes),make_meta_field ml) l)) t_dynamic p
+	in
+	if meta = [] && fields = [] && statics = [] then
+		None
+	else
+		let meta_obj = [] in
+		let meta_obj = (if fields = [] then meta_obj else (("fields",null_pos,NoQuotes),make_meta fields) :: meta_obj) in
+		let meta_obj = (if statics = [] then meta_obj else (("statics",null_pos,NoQuotes),make_meta statics) :: meta_obj) in
+		let meta_obj = (try (("obj",null_pos,NoQuotes), make_meta_field (List.assoc "" meta)) :: meta_obj with Not_found -> meta_obj) in
+		Some (mk (TObjectDecl meta_obj) t_dynamic p)

+ 167 - 0
src/core/timer.ml

@@ -0,0 +1,167 @@
+(*
+	The Haxe Compiler
+	Copyright (C) 2005-2017  Haxe Foundation
+
+	This program is free software; you can redistribute it and/or
+	modify it under the terms of the GNU General Public License
+	as published by the Free Software Foundation; either version 2
+	of the License, or (at your option) any later version.
+
+	This program is distributed in the hope that it will be useful,
+	but WITHOUT ANY WARRANTY; without even the implied warranty of
+	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+	GNU General Public License for more details.
+
+	You should have received a copy of the GNU General Public License
+	along with this program; if not, write to the Free Software
+	Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *)
+
+type timer_infos = {
+	id : string list;
+	mutable start : float list;
+	mutable total : float;
+	mutable calls : int;
+}
+
+let get_time = Extc.time
+let htimers = Hashtbl.create 0
+
+let new_timer id =
+	let key = String.concat "." id in
+	try
+		let t = Hashtbl.find htimers key in
+		t.start <- get_time() :: t.start;
+		t.calls <- t.calls + 1;
+		t
+	with Not_found ->
+		let t = { id = id; start = [get_time()]; total = 0.; calls = 1; } in
+		Hashtbl.add htimers key t;
+		t
+
+let curtime = ref []
+
+let close t =
+	let start = (match t.start with
+		| [] -> assert false
+		| s :: l -> t.start <- l; s
+	) in
+	let now = get_time() in
+	let dt = now -. start in
+	t.total <- t.total +. dt;
+	let rec loop() =
+		match !curtime with
+		| [] -> failwith ("Timer " ^ (String.concat "." t.id) ^ " closed while not active")
+		| tt :: l -> curtime := l; if t != tt then loop()
+	in
+	loop();
+	(* because of rounding errors while adding small times, we need to make sure that we don't have start > now *)
+	List.iter (fun ct -> ct.start <- List.map (fun t -> let s = t +. dt in if s > now then now else s) ct.start) !curtime
+
+let timer id =
+	let t = new_timer id in
+	curtime := t :: !curtime;
+	(function() -> close t)
+
+let rec close_times() =
+	match !curtime with
+	| [] -> ()
+	| t :: _ -> close t; close_times()
+
+(* Printing *)
+
+type timer_node = {
+	name : string;
+	path : string;
+	parent : timer_node;
+	info : string;
+	mutable time : float;
+	mutable num_calls : int;
+	mutable children : timer_node list;
+}
+
+let report_times print =
+	let nodes = Hashtbl.create 0 in
+	let rec root = {
+		name = "";
+		path = "";
+		parent = root;
+		info = "";
+		time = 0.;
+		num_calls = 0;
+		children = [];
+	} in
+	Hashtbl.iter (fun _ timer ->
+		let rec loop parent sl = match sl with
+			| [] -> assert false
+			| s :: sl ->
+				let path = (match parent.path with "" -> "" | _ -> parent.path ^ ".") ^ s in
+				let node = try
+					let node = Hashtbl.find nodes path in
+					node.num_calls <- node.num_calls + timer.calls;
+					node.time <- node.time +. timer.total;
+					node
+				with Not_found ->
+					let name,info = try
+						let i = String.rindex s '.' in
+						String.sub s (i + 1) (String.length s - i - 1),String.sub s 0 i
+					with Not_found ->
+						s,""
+					in
+					let node = {
+						name = name;
+						path = path;
+						parent = parent;
+						info = info;
+						time = timer.total;
+						num_calls = timer.calls;
+						children = [];
+					} in
+					Hashtbl.add nodes path node;
+					node
+				in
+				begin match sl with
+					| [] -> ()
+					| _ ->
+						let child = loop node sl in
+						if not (List.memq child node.children) then
+							node.children <- child :: node.children;
+				end;
+				node
+		in
+		let node = loop root timer.id in
+		if not (List.memq node root.children) then
+			root.children <- node :: root.children
+	) htimers;
+	let max_name = ref 0 in
+	let max_calls = ref 0 in
+	let rec loop depth node =
+		let l = (String.length node.name) + 2 * depth in
+		List.iter (fun child ->
+			if depth = 0 then begin
+				node.num_calls <- node.num_calls + child.num_calls;
+				node.time <- node.time +. child.time;
+			end;
+			loop (depth + 1) child;
+		) node.children;
+		node.children <- List.sort (fun node1 node2 -> compare node2.time node1.time) node.children;
+		if node.num_calls > !max_calls then max_calls := node.num_calls;
+		if node.time > 0.0009 && l > !max_name then max_name := l;
+	in
+	loop 0 root;
+	let max_calls = String.length (string_of_int !max_calls) in
+	print (Printf.sprintf "%-*s | %7s |   %% |  p%% | %*s | info" !max_name "name" "time(s)" max_calls "#");
+	let sep = String.make (!max_name + max_calls + 27) '-' in
+	print sep;
+	let print_time name node =
+		if node.time > 0.0009 then
+			print (Printf.sprintf "%-*s | %7.3f | %3.0f | %3.0f | %*i | %s" !max_name name node.time (node.time *. 100. /. root.time) (node.time *. 100. /. node.parent.time) max_calls node.num_calls node.info)
+	in
+	let rec loop depth node =
+		let name = (String.make (depth * 2) ' ') ^ node.name in
+		print_time name node;
+		List.iter (loop (depth + 1)) node.children
+	in
+	List.iter (loop 0) root.children;
+	print sep;
+	print_time "total" root

+ 120 - 246
src/typing/type.ml → src/core/type.ml

@@ -33,11 +33,12 @@ and var_kind = {
 
 
 and var_access =
 and var_access =
 	| AccNormal
 	| AccNormal
-	| AccNo				(* can't be accessed outside of the class itself and its subclasses *)
-	| AccNever			(* can't be accessed, even in subclasses *)
-	| AccResolve		(* call resolve("field") when accessed *)
-	| AccCall			(* perform a method call when accessed *)
-	| AccInline			(* similar to Normal but inline when accessed *)
+	| AccNo             (* can't be accessed outside of the class itself and its subclasses *)
+	| AccNever          (* can't be accessed, even in subclasses *)
+	| AccCtor           (* can only be accessed from the constructor *)
+	| AccResolve        (* call resolve("field") when accessed *)
+	| AccCall           (* perform a method call when accessed *)
+	| AccInline         (* similar to Normal but inline when accessed *)
 	| AccRequire of string * string option (* set when @:require(cond) fails *)
 	| AccRequire of string * string option (* set when @:require(cond) fails *)
 
 
 and method_kind =
 and method_kind =
@@ -52,6 +53,7 @@ type module_check_policy =
 	| NoCheckDependencies
 	| NoCheckDependencies
 	| NoCheckShadowing
 	| NoCheckShadowing
 
 
+
 type t =
 type t =
 	| TMono of t option ref
 	| TMono of t option ref
 	| TEnum of tenum * tparams
 	| TEnum of tenum * tparams
@@ -60,9 +62,14 @@ type t =
 	| TFun of tsignature
 	| TFun of tsignature
 	| TAnon of tanon
 	| TAnon of tanon
 	| TDynamic of t
 	| TDynamic of t
-	| TLazy of (unit -> t) ref
+	| TLazy of tlazy ref
 	| TAbstract of tabstract * tparams
 	| TAbstract of tabstract * tparams
 
 
+and tlazy =
+	| LAvailable of t
+	| LProcessing of (unit -> t)
+	| LWait of (unit -> t)
+
 and tsignature = (string * bool * t) list * t
 and tsignature = (string * bool * t) list * t
 
 
 and tparams = t list
 and tparams = t list
@@ -118,7 +125,7 @@ and texpr_expr =
 	| TField of texpr * tfield_access
 	| TField of texpr * tfield_access
 	| TTypeExpr of module_type
 	| TTypeExpr of module_type
 	| TParenthesis of texpr
 	| TParenthesis of texpr
-	| TObjectDecl of (string * texpr) list
+	| TObjectDecl of ((string * pos * quote_status) * texpr) list
 	| TArrayDecl of texpr list
 	| TArrayDecl of texpr list
 	| TCall of texpr * texpr list
 	| TCall of texpr * texpr list
 	| TNew of tclass * tparams * texpr list
 	| TNew of tclass * tparams * texpr list
@@ -229,12 +236,12 @@ and tclass = {
 
 
 and tenum_field = {
 and tenum_field = {
 	ef_name : string;
 	ef_name : string;
-	ef_type : t;
+	mutable ef_type : t;
 	ef_pos : pos;
 	ef_pos : pos;
 	ef_name_pos : pos;
 	ef_name_pos : pos;
 	ef_doc : Ast.documentation;
 	ef_doc : Ast.documentation;
 	ef_index : int;
 	ef_index : int;
-	ef_params : type_params;
+	mutable ef_params : type_params;
 	mutable ef_meta : metadata;
 	mutable ef_meta : metadata;
 }
 }
 
 
@@ -314,7 +321,7 @@ and module_def_extra = {
 	mutable m_processed : int;
 	mutable m_processed : int;
 	mutable m_kind : module_kind;
 	mutable m_kind : module_kind;
 	mutable m_binded_res : (string, string) PMap.t;
 	mutable m_binded_res : (string, string) PMap.t;
-	mutable m_macro_calls : string list;
+	mutable m_reuse_macro_calls : string list;
 	mutable m_if_feature : (string *(tclass * tclass_field * bool)) list;
 	mutable m_if_feature : (string *(tclass * tclass_field * bool)) list;
 	mutable m_features : (string,bool) Hashtbl.t;
 	mutable m_features : (string,bool) Hashtbl.t;
 }
 }
@@ -331,6 +338,16 @@ and build_state =
 	| Building of tclass list
 	| Building of tclass list
 	| BuildMacro of (unit -> unit) list ref
 	| BuildMacro of (unit -> unit) list ref
 
 
+type basic_types = {
+	mutable tvoid : t;
+	mutable tint : t;
+	mutable tfloat : t;
+	mutable tbool : t;
+	mutable tnull : t -> t;
+	mutable tstring : t;
+	mutable tarray : t -> t;
+}
+
 (* ======= General utility ======= *)
 (* ======= General utility ======= *)
 
 
 let alloc_var =
 let alloc_var =
@@ -409,7 +426,7 @@ let module_extra file sign time kind policy =
 		m_deps = PMap.empty;
 		m_deps = PMap.empty;
 		m_kind = kind;
 		m_kind = kind;
 		m_binded_res = PMap.empty;
 		m_binded_res = PMap.empty;
-		m_macro_calls = [];
+		m_reuse_macro_calls = [];
 		m_if_feature = [];
 		m_if_feature = [];
 		m_features = Hashtbl.create 0;
 		m_features = Hashtbl.create 0;
 		m_check_policy = policy;
 		m_check_policy = policy;
@@ -490,6 +507,15 @@ let rec is_parent csup c =
 let add_descendant c descendant =
 let add_descendant c descendant =
 	c.cl_descendants <- descendant :: c.cl_descendants
 	c.cl_descendants <- descendant :: c.cl_descendants
 
 
+let lazy_type f =
+	match !f with
+	| LAvailable t -> t
+	| LProcessing f | LWait f -> f()
+
+let lazy_available t = LAvailable t
+let lazy_processing f = LProcessing f
+let lazy_wait f = LWait f
+
 let map loop t =
 let map loop t =
 	match t with
 	match t with
 	| TMono r ->
 	| TMono r ->
@@ -521,7 +547,7 @@ let map loop t =
 				}
 				}
 		end
 		end
 	| TLazy f ->
 	| TLazy f ->
-		let ft = !f() in
+		let ft = lazy_type f in
 		let ft2 = loop ft in
 		let ft2 = loop ft in
 		if ft == ft2 then t else ft2
 		if ft == ft2 then t else ft2
 	| TDynamic t2 ->
 	| TDynamic t2 ->
@@ -551,7 +577,7 @@ let apply_params cparams params t =
 	let rec loop l1 l2 =
 	let rec loop l1 l2 =
 		match l1, l2 with
 		match l1, l2 with
 		| [] , [] -> []
 		| [] , [] -> []
-		| (x,TLazy f) :: l1, _ -> loop ((x,(!f)()) :: l1) l2
+		| (x,TLazy f) :: l1, _ -> loop ((x,lazy_type f) :: l1) l2
 		| (_,t1) :: l1 , t2 :: l2 -> (t1,t2) :: loop l1 l2
 		| (_,t1) :: l1 , t2 :: l2 -> (t1,t2) :: loop l1 l2
 		| _ -> assert false
 		| _ -> assert false
 	in
 	in
@@ -607,7 +633,7 @@ let apply_params cparams params t =
 					}
 					}
 			end
 			end
 		| TLazy f ->
 		| TLazy f ->
-			let ft = !f() in
+			let ft = lazy_type f in
 			let ft2 = loop ft in
 			let ft2 = loop ft in
 			if ft == ft2 then
 			if ft == ft2 then
 				t
 				t
@@ -631,7 +657,7 @@ let rec follow t =
 		| Some t -> follow t
 		| Some t -> follow t
 		| _ -> t)
 		| _ -> t)
 	| TLazy f ->
 	| TLazy f ->
-		follow (!f())
+		follow (lazy_type f)
 	| TType (t,tl) ->
 	| TType (t,tl) ->
 		follow (apply_params t.t_params tl t.t_type)
 		follow (apply_params t.t_params tl t.t_type)
 	| TAbstract({a_path = [],"Null"},[t]) ->
 	| TAbstract({a_path = [],"Null"},[t]) ->
@@ -644,7 +670,7 @@ let rec is_nullable = function
 	| TAbstract ({ a_path = ([],"Null") },[_]) ->
 	| TAbstract ({ a_path = ([],"Null") },[_]) ->
 		true
 		true
 	| TLazy f ->
 	| TLazy f ->
-		is_nullable (!f())
+		is_nullable (lazy_type f)
 	| TType (t,tl) ->
 	| TType (t,tl) ->
 		is_nullable (apply_params t.t_params tl t.t_type)
 		is_nullable (apply_params t.t_params tl t.t_type)
 	| TFun _ ->
 	| TFun _ ->
@@ -671,7 +697,7 @@ let rec is_null ?(no_lazy=false) = function
 	| TAbstract ({ a_path = ([],"Null") },[t]) ->
 	| TAbstract ({ a_path = ([],"Null") },[t]) ->
 		not (is_nullable (follow t))
 		not (is_nullable (follow t))
 	| TLazy f ->
 	| TLazy f ->
-		if no_lazy then raise Exit else is_null (!f())
+		if no_lazy then raise Exit else is_null (lazy_type f)
 	| TType (t,tl) ->
 	| TType (t,tl) ->
 		is_null (apply_params t.t_params tl t.t_type)
 		is_null (apply_params t.t_params tl t.t_type)
 	| _ ->
 	| _ ->
@@ -684,7 +710,7 @@ let rec is_explicit_null = function
 	| TAbstract ({ a_path = ([],"Null") },[t]) ->
 	| TAbstract ({ a_path = ([],"Null") },[t]) ->
 		true
 		true
 	| TLazy f ->
 	| TLazy f ->
-		is_null (!f())
+		is_null (lazy_type f)
 	| TType (t,tl) ->
 	| TType (t,tl) ->
 		is_null (apply_params t.t_params tl t.t_type)
 		is_null (apply_params t.t_params tl t.t_type)
 	| _ ->
 	| _ ->
@@ -701,8 +727,8 @@ let rec has_mono t = match t with
 		has_mono r || List.exists (fun (_,_,t) -> has_mono t) args
 		has_mono r || List.exists (fun (_,_,t) -> has_mono t) args
 	| TAnon a ->
 	| TAnon a ->
 		PMap.fold (fun cf b -> has_mono cf.cf_type || b) a.a_fields false
 		PMap.fold (fun cf b -> has_mono cf.cf_type || b) a.a_fields false
-	| TLazy r ->
-		has_mono (!r())
+	| TLazy f ->
+		has_mono (lazy_type f)
 
 
 let concat e1 e2 =
 let concat e1 e2 =
 	let e = (match e1.eexpr, e2.eexpr with
 	let e = (match e1.eexpr, e2.eexpr with
@@ -726,7 +752,7 @@ let rec module_type_of_type = function
 	| TEnum(en,_) -> TEnumDecl en
 	| TEnum(en,_) -> TEnumDecl en
 	| TType(t,_) -> TTypeDecl t
 	| TType(t,_) -> TTypeDecl t
 	| TAbstract(a,_) -> TAbstractDecl a
 	| TAbstract(a,_) -> TAbstractDecl a
-	| TLazy f -> module_type_of_type (!f())
+	| TLazy f -> module_type_of_type (lazy_type f)
 	| TMono r ->
 	| TMono r ->
 		(match !r with
 		(match !r with
 		| Some t -> module_type_of_type t
 		| Some t -> module_type_of_type t
@@ -925,12 +951,19 @@ let rec s_type ctx t =
 			(if b then "?" else "") ^ (if s = "" then "" else s ^ " : ") ^ s_fun ctx t true
 			(if b then "?" else "") ^ (if s = "" then "" else s ^ " : ") ^ s_fun ctx t true
 		) l) ^ " -> " ^ s_fun ctx t false
 		) l) ^ " -> " ^ s_fun ctx t false
 	| TAnon a ->
 	| TAnon a ->
-		let fl = PMap.fold (fun f acc -> ((if Meta.has Meta.Optional f.cf_meta then " ?" else " ") ^ f.cf_name ^ " : " ^ s_type ctx f.cf_type) :: acc) a.a_fields [] in
-		"{" ^ (if not (is_closed a) then "+" else "") ^  String.concat "," fl ^ " }"
+		begin
+			match !(a.a_status) with
+			| Statics c -> Printf.sprintf "{ Statics %s }" (s_type_path c.cl_path)
+			| EnumStatics e -> Printf.sprintf "{ EnumStatics %s }" (s_type_path e.e_path)
+			| AbstractStatics a -> Printf.sprintf "{ AbstractStatics %s }" (s_type_path a.a_path)
+			| _ ->
+				let fl = PMap.fold (fun f acc -> ((if Meta.has Meta.Optional f.cf_meta then " ?" else " ") ^ f.cf_name ^ " : " ^ s_type ctx f.cf_type) :: acc) a.a_fields [] in
+				"{" ^ (if not (is_closed a) then "+" else "") ^  String.concat "," fl ^ " }"
+		end
 	| TDynamic t2 ->
 	| TDynamic t2 ->
 		"Dynamic" ^ s_type_params ctx (if t == t2 then [] else [t2])
 		"Dynamic" ^ s_type_params ctx (if t == t2 then [] else [t2])
 	| TLazy f ->
 	| TLazy f ->
-		s_type ctx (!f())
+		s_type ctx (lazy_type f)
 
 
 and s_fun ctx t void =
 and s_fun ctx t void =
 	match t with
 	match t with
@@ -943,7 +976,7 @@ and s_fun ctx t void =
 		| None -> s_type ctx t
 		| None -> s_type ctx t
 		| Some t -> s_fun ctx t void)
 		| Some t -> s_fun ctx t void)
 	| TLazy f ->
 	| TLazy f ->
-		s_fun ctx (!f()) void
+		s_fun ctx (lazy_type f) void
 	| _ ->
 	| _ ->
 		s_type ctx t
 		s_type ctx t
 
 
@@ -959,6 +992,7 @@ let s_access is_read = function
 	| AccCall -> if is_read then "get" else "set"
 	| AccCall -> if is_read then "get" else "set"
 	| AccInline	-> "inline"
 	| AccInline	-> "inline"
 	| AccRequire (n,_) -> "require " ^ n
 	| AccRequire (n,_) -> "require " ^ n
+	| AccCtor -> "ctor"
 
 
 let s_kind = function
 let s_kind = function
 	| Var { v_read = AccNormal; v_write = AccNormal } -> "var"
 	| Var { v_read = AccNormal; v_write = AccNormal } -> "var"
@@ -1044,7 +1078,7 @@ let rec s_expr s_type e =
 	| TParenthesis e ->
 	| TParenthesis e ->
 		sprintf "Parenthesis %s" (loop e)
 		sprintf "Parenthesis %s" (loop e)
 	| TObjectDecl fl ->
 	| TObjectDecl fl ->
-		sprintf "ObjectDecl {%s}" (slist (fun (f,e) -> sprintf "%s : %s" f (loop e)) fl)
+		sprintf "ObjectDecl {%s}" (slist (fun ((f,_,qs),e) -> sprintf "%s : %s" (s_object_key_name f qs) (loop e)) fl)
 	| TArrayDecl el ->
 	| TArrayDecl el ->
 		sprintf "ArrayDecl [%s]" (slist loop el)
 		sprintf "ArrayDecl [%s]" (slist loop el)
 	| TCall (e,el) ->
 	| TCall (e,el) ->
@@ -1109,7 +1143,7 @@ let rec s_expr_pretty print_var_ids tabs top_level s_type e =
 	| TField (e1,s) -> sprintf "%s.%s" (loop e1) (field_name s)
 	| TField (e1,s) -> sprintf "%s.%s" (loop e1) (field_name s)
 	| TTypeExpr mt -> (s_type_path (t_path mt))
 	| TTypeExpr mt -> (s_type_path (t_path mt))
 	| TParenthesis e1 -> sprintf "(%s)" (loop e1)
 	| TParenthesis e1 -> sprintf "(%s)" (loop e1)
-	| TObjectDecl fl -> sprintf "{%s}" (clist (fun (f,e) -> sprintf "%s : %s" f (loop e)) fl)
+	| TObjectDecl fl -> sprintf "{%s}" (clist (fun ((f,_,qs),e) -> sprintf "%s : %s" (s_object_key_name f qs) (loop e)) fl)
 	| TArrayDecl el -> sprintf "[%s]" (clist loop el)
 	| TArrayDecl el -> sprintf "[%s]" (clist loop el)
 	| TCall (e1,el) -> sprintf "%s(%s)" (loop e1) (clist loop el)
 	| TCall (e1,el) -> sprintf "%s(%s)" (loop e1) (clist loop el)
 	| TNew (c,pl,el) ->
 	| TNew (c,pl,el) ->
@@ -1204,7 +1238,7 @@ let rec s_expr_ast print_var_ids tabs s_type e =
 		tag "Field" [loop e1; sfa]
 		tag "Field" [loop e1; sfa]
 	| TTypeExpr mt -> module_type mt
 	| TTypeExpr mt -> module_type mt
 	| TParenthesis e1 -> tag "Parenthesis" [loop e1]
 	| TParenthesis e1 -> tag "Parenthesis" [loop e1]
-	| TObjectDecl fl -> tag "ObjectDecl" (List.map (fun (s,e) -> sprintf "%s: %s" s (loop e)) fl)
+	| TObjectDecl fl -> tag "ObjectDecl" (List.map (fun ((s,_,qs),e) -> sprintf "%s: %s" (s_object_key_name s qs) (loop e)) fl)
 	| TArrayDecl el -> tag "ArrayDecl" (List.map loop el)
 	| TArrayDecl el -> tag "ArrayDecl" (List.map loop el)
 	| TCall (e1,el) -> tag "Call" (loop e1 :: (List.map loop el))
 	| TCall (e1,el) -> tag "Call" (loop e1 :: (List.map loop el))
 	| TNew (c,tl,el) -> tag "New" ((s_type (TInst(c,tl))) :: (List.map loop el))
 	| TNew (c,tl,el) -> tag "New" ((s_type (TInst(c,tl))) :: (List.map loop el))
@@ -1452,7 +1486,7 @@ module Printer = struct
 			"m_processed",string_of_int me.m_processed;
 			"m_processed",string_of_int me.m_processed;
 			"m_kind",s_module_kind me.m_kind;
 			"m_kind",s_module_kind me.m_kind;
 			"m_binded_res",""; (* TODO *)
 			"m_binded_res",""; (* TODO *)
-			"m_macro_calls",String.concat ", " me.m_macro_calls;
+			"m_reuse_macro_calls",String.concat ", " me.m_reuse_macro_calls;
 			"m_if_feature",""; (* TODO *)
 			"m_if_feature",""; (* TODO *)
 			"m_features",""; (* TODO *)
 			"m_features",""; (* TODO *)
 		]
 		]
@@ -1510,7 +1544,7 @@ let rec link e a b =
 			else
 			else
 				loop t2
 				loop t2
 		| TLazy f ->
 		| TLazy f ->
-			loop (!f())
+			loop (lazy_type f)
 		| TAnon a ->
 		| TAnon a ->
 			try
 			try
 				PMap.iter (fun _ f -> if loop f.cf_type then raise Exit) a.a_fields;
 				PMap.iter (fun _ f -> if loop f.cf_type then raise Exit) a.a_fields;
@@ -1612,7 +1646,7 @@ let unify_access a1 a2 =
 	| _ -> false
 	| _ -> false
 
 
 let direct_access = function
 let direct_access = function
-	| AccNo | AccNever | AccNormal | AccInline | AccRequire _ -> true
+	| AccNo | AccNever | AccNormal | AccInline | AccRequire _ | AccCtor -> true
 	| AccResolve | AccCall -> false
 	| AccResolve | AccCall -> false
 
 
 let unify_kind k1 k2 =
 let unify_kind k1 k2 =
@@ -1687,8 +1721,8 @@ let rec type_eq param a b =
 	if a == b then
 	if a == b then
 		()
 		()
 	else match a , b with
 	else match a , b with
-	| TLazy f , _ -> type_eq param (!f()) b
-	| _ , TLazy f -> type_eq param a (!f())
+	| TLazy f , _ -> type_eq param (lazy_type f) b
+	| _ , TLazy f -> type_eq param a (lazy_type f)
 	| TMono t , _ ->
 	| TMono t , _ ->
 		(match !t with
 		(match !t with
 		| None -> if param = EqCoreType || not (link t a b) then error [cannot_unify a b]
 		| None -> if param = EqCoreType || not (link t a b) then error [cannot_unify a b]
@@ -1798,8 +1832,8 @@ let rec unify a b =
 	if a == b then
 	if a == b then
 		()
 		()
 	else match a, b with
 	else match a, b with
-	| TLazy f , _ -> unify (!f()) b
-	| _ , TLazy f -> unify a (!f())
+	| TLazy f , _ -> unify (lazy_type f) b
+	| _ , TLazy f -> unify a (lazy_type f)
 	| TMono t , _ ->
 	| TMono t , _ ->
 		(match !t with
 		(match !t with
 		| None -> if not (link t a b) then error [cannot_unify a b]
 		| None -> if not (link t a b) then error [cannot_unify a b]
@@ -2493,7 +2527,7 @@ module TExprToExpr = struct
 		| (TDynamic t2) as t ->
 		| (TDynamic t2) as t ->
 			tpath ([],"Dynamic") ([],"Dynamic") (if t == t_dynamic then [] else [convert_type' t2])
 			tpath ([],"Dynamic") ([],"Dynamic") (if t == t_dynamic then [] else [convert_type' t2])
 		| TLazy f ->
 		| TLazy f ->
-			convert_type ((!f)())
+			convert_type (lazy_type f)
 
 
 	and convert_type' t =
 	and convert_type' t =
 		convert_type t,null_pos
 		convert_type t,null_pos
@@ -2528,7 +2562,7 @@ module TExprToExpr = struct
 		| TField (e,f) -> EField (convert_expr e, field_name f)
 		| TField (e,f) -> EField (convert_expr e, field_name f)
 		| TTypeExpr t -> fst (mk_path (full_type_path t) e.epos)
 		| TTypeExpr t -> fst (mk_path (full_type_path t) e.epos)
 		| TParenthesis e -> EParenthesis (convert_expr e)
 		| TParenthesis e -> EParenthesis (convert_expr e)
-		| TObjectDecl fl -> EObjectDecl (List.map (fun (f,e) -> (f,null_pos), convert_expr e) fl)
+		| TObjectDecl fl -> EObjectDecl (List.map (fun (k,e) -> k, convert_expr e) fl)
 		| TArrayDecl el -> EArrayDecl (List.map convert_expr el)
 		| TArrayDecl el -> EArrayDecl (List.map convert_expr el)
 		| TCall (e,el) -> ECall (convert_expr e,List.map convert_expr el)
 		| TCall (e,el) -> ECall (convert_expr e,List.map convert_expr el)
 		| TNew (c,pl,el) -> ENew ((match (try convert_type (TInst (c,pl)) with Exit -> convert_type (TInst (c,[]))) with CTPath p -> p,null_pos | _ -> assert false),List.map convert_expr el)
 		| TNew (c,pl,el) -> ENew ((match (try convert_type (TInst (c,pl)) with Exit -> convert_type (TInst (c,[]))) with CTPath p -> p,null_pos | _ -> assert false),List.map convert_expr el)
@@ -2581,213 +2615,6 @@ module TExprToExpr = struct
 
 
 end
 end
 
 
-module Texpr = struct
-	let equal_fa fa1 fa2 = match fa1,fa2 with
-		| FStatic(c1,cf1),FStatic(c2,cf2) -> c1 == c2 && cf1 == cf2
-		| FInstance(c1,tl1,cf1),FInstance(c2,tl2,cf2) -> c1 == c2 && safe_for_all2 type_iseq tl1 tl2 && cf1 == cf2
-		(* TODO: This is technically not correct but unfortunately the compiler makes a distinct tclass_field for each anon field access. *)
-		| FAnon cf1,FAnon cf2 -> cf1.cf_name = cf2.cf_name
-		| FDynamic s1,FDynamic s2 -> s1 = s2
-		| FClosure(None,cf1),FClosure(None,cf2) -> cf1 == cf2
-		| FClosure(Some(c1,tl1),cf1),FClosure(Some(c2,tl2),cf2) -> c1 == c2 && safe_for_all2 type_iseq tl1 tl2 && cf1 == cf2
-		| FEnum(en1,ef1),FEnum(en2,ef2) -> en1 == en2 && ef1 == ef2
-		| _ -> false
-
-	let rec equal e1 e2 = match e1.eexpr,e2.eexpr with
-		| TConst ct1,TConst ct2 -> ct1 = ct2
-		| TLocal v1,TLocal v2 -> v1 == v2
-		| TArray(eb1,ei1),TArray(eb2,ei2) -> equal eb1 eb2 && equal ei1 ei2
-		| TBinop(op1,lhs1,rhs1),TBinop(op2,lhs2,rhs2) -> op1 = op2 && equal lhs1 lhs2 && equal rhs1 rhs2
-		| TField(e1,fa1),TField(e2,fa2) -> equal e1 e2 && equal_fa fa1 fa2
-		| TTypeExpr mt1,TTypeExpr mt2 -> mt1 == mt2
-		| TParenthesis e1,TParenthesis e2 -> equal e1 e2
-		| TObjectDecl fl1,TObjectDecl fl2 -> safe_for_all2 (fun (s1,e1) (s2,e2) -> s1 = s2 && equal e1 e2) fl1 fl2
-		| (TArrayDecl el1,TArrayDecl el2) | (TBlock el1,TBlock el2) -> safe_for_all2 equal el1 el2
-		| TCall(e1,el1),TCall(e2,el2) -> equal e1 e2 && safe_for_all2 equal el1 el2
-		| TNew(c1,tl1,el1),TNew(c2,tl2,el2) -> c1 == c2 && safe_for_all2 type_iseq tl1 tl2 && safe_for_all2 equal el1 el2
-		| TUnop(op1,flag1,e1),TUnop(op2,flag2,e2) -> op1 = op2 && flag1 = flag2 && equal e1 e2
-		| TFunction tf1,TFunction tf2 -> tf1 == tf2
-		| TVar(v1,None),TVar(v2,None) -> v1 == v2
-		| TVar(v1,Some e1),TVar(v2,Some e2) -> v1 == v2 && equal e1 e2
-		| TFor(v1,ec1,eb1),TFor(v2,ec2,eb2) -> v1 == v2 && equal ec1 ec2 && equal eb1 eb2
-		| TIf(e1,ethen1,None),TIf(e2,ethen2,None) -> equal e1 e2 && equal ethen1 ethen2
-		| TIf(e1,ethen1,Some eelse1),TIf(e2,ethen2,Some eelse2) -> equal e1 e2 && equal ethen1 ethen2 && equal eelse1 eelse2
-		| TWhile(e1,eb1,flag1),TWhile(e2,eb2,flag2) -> equal e1 e2 && equal eb2 eb2 && flag1 = flag2
-		| TSwitch(e1,cases1,eo1),TSwitch(e2,cases2,eo2) ->
-			equal e1 e2 &&
-			safe_for_all2 (fun (el1,e1) (el2,e2) -> safe_for_all2 equal el1 el2 && equal e1 e2) cases1 cases2 &&
-			(match eo1,eo2 with None,None -> true | Some e1,Some e2 -> equal e1 e2 | _ -> false)
-		| TTry(e1,catches1),TTry(e2,catches2) -> equal e1 e2 && safe_for_all2 (fun (v1,e1) (v2,e2) -> v1 == v2 && equal e1 e2) catches1 catches2
-		| TReturn None,TReturn None -> true
-		| TReturn(Some e1),TReturn(Some e2) -> equal e1 e2
-		| TThrow e1,TThrow e2 -> equal e1 e2
-		| TCast(e1,None),TCast(e2,None) -> equal e1 e2
-		| TCast(e1,Some mt1),TCast(e2,Some mt2) -> equal e1 e2 && mt1 == mt2
-		| TMeta((m1,el1,_),e1),TMeta((m2,el2,_),e2) -> m1 = m2 && safe_for_all2 (fun e1 e2 -> (* TODO: cheating? *) (Ast.s_expr e1) = (Ast.s_expr e2)) el1 el2 && equal e1 e2
-		| (TBreak,TBreak) | (TContinue,TContinue) -> true
-		| TEnumParameter(e1,ef1,i1),TEnumParameter(e2,ef2,i2) -> equal e1 e2 && ef1 == ef2 && i1 = i2
-		| _ -> false
-
-	let duplicate_tvars e =
-		let vars = Hashtbl.create 0 in
-		let copy_var v =
-			let v2 = alloc_var v.v_name v.v_type v.v_pos in
-			v2.v_meta <- v.v_meta;
-			v2.v_extra <- v.v_extra;
-			Hashtbl.add vars v.v_id v2;
-			v2;
-		in
-		let rec build_expr e =
-			match e.eexpr with
-			| TVar (v,eo) ->
-				let v2 = copy_var v in
-				{e with eexpr = TVar(v2, Option.map build_expr eo)}
-			| TFor (v,e1,e2) ->
-				let v2 = copy_var v in
-				{e with eexpr = TFor(v2, build_expr e1, build_expr e2)}
-			| TTry (e1,cl) ->
-				let cl = List.map (fun (v,e) ->
-					let v2 = copy_var v in
-					v2, build_expr e
-				) cl in
-				{e with eexpr = TTry(build_expr e1, cl)}
-			| TFunction f ->
-				let args = List.map (fun (v,c) -> copy_var v, c) f.tf_args in
-				let f = {
-					tf_args = args;
-					tf_type = f.tf_type;
-					tf_expr = build_expr f.tf_expr;
-				} in
-				{e with eexpr = TFunction f}
-			| TLocal v ->
-				(try
-					let v2 = Hashtbl.find vars v.v_id in
-					{e with eexpr = TLocal v2}
-				with _ ->
-					e)
-			| _ ->
-				map_expr build_expr e
-		in
-		build_expr e
-
-	let rec skip e = match e.eexpr with
-		| TParenthesis e1 | TMeta(_,e1) | TBlock [e1] | TCast(e1,None) -> skip e1
-		| _ -> e
-
-	let foldmap_list f acc el =
-		let rec loop acc el acc2 = (match el with
-			| [] -> acc,(List.rev acc2)
-			| e1 :: el ->
-				let acc,e1 = f acc e1 in
-				loop acc el (e1 :: acc2))
-		in loop acc el []
-
-	let foldmap_opt f acc eo = match eo with
-		| Some(e) -> let acc,e = f acc e in acc,Some(e)
-		| None    -> acc,eo
-
-	let foldmap_pairs f acc pairs =
-		let acc,pairs = List.fold_left
-			(fun (acc,el) (v,e) -> let acc,e = f acc e in (acc,(v,e) :: el))
-			(acc,[])
-			pairs
-		in acc,(List.rev pairs)
-
-	let foldmap f acc e =
-		begin match e.eexpr with
-		| TConst _
-		| TLocal _
-		| TBreak
-		| TContinue
-		| TTypeExpr _
-		| TIdent _ ->
-			acc,e
-		| TArray (e1,e2) ->
-			let acc,e1 = f acc e1 in
-			let acc,e2 = f acc e2 in
-			acc,{ e with eexpr = TArray (e1, e2) }
-		| TBinop (op,e1,e2) ->
-			let acc,e1 = f acc e1 in
-			let acc,e2 = f acc e2 in
-			acc,{ e with eexpr = TBinop (op,e1,e2) }
-		| TFor (v,e1,e2) ->
-			let acc,e1 = f acc e1 in
-			let acc,e2 = f acc e2 in
-			acc,{ e with eexpr = TFor (v,e1,e2) }
-		| TWhile (e1,e2,flag) ->
-			let acc,e1 = f acc e1 in
-			let acc,e2 = f acc e2 in
-			acc,{ e with eexpr = TWhile (e1,e2,flag) }
-		| TThrow e1 ->
-			let acc,e1 = f acc e1 in
-			acc,{ e with eexpr = TThrow (e1) }
-		| TEnumParameter (e1,ef,i) ->
-			let acc,e1 = f acc e1 in
-			acc,{ e with eexpr = TEnumParameter(e1,ef,i) }
-		| TEnumIndex e1 ->
-			let acc,e1 = f acc e1 in
-			acc,{ e with eexpr = TEnumIndex e1 }
-		| TField (e1,v) ->
-			let acc,e1 = f acc e1 in
-			acc,{ e with eexpr = TField (e1,v) }
-		| TParenthesis e1 ->
-			let acc,e1 = f acc e1 in
-			acc,{ e with eexpr = TParenthesis (e1) }
-		| TUnop (op,pre,e1) ->
-			let acc,e1 = f acc e1 in
-			acc,{ e with eexpr = TUnop (op,pre,e1) }
-		| TArrayDecl el ->
-			let acc,el = foldmap_list f acc el in
-			acc,{ e with eexpr = TArrayDecl el }
-		| TNew (t,pl,el) ->
-			let acc,el = foldmap_list f acc el in
-			acc,{ e with eexpr = TNew (t,pl,el) }
-		| TBlock el ->
-			let acc,el = foldmap_list f acc el in
-			acc,{ e with eexpr = TBlock (el) }
-		| TObjectDecl el ->
-			let acc,el = foldmap_pairs f acc el in
-			acc,{ e with eexpr = TObjectDecl el }
-		| TCall (e1,el) ->
-			let acc,e1 = f acc e1 in
-			let acc,el = foldmap_list f acc el in
-			acc,{ e with eexpr = TCall (e1,el) }
-		| TVar (v,eo) ->
-			let acc,eo = foldmap_opt f acc eo in
-			acc,{ e with eexpr = TVar (v, eo) }
-		| TFunction fu ->
-			let acc,e1 = f acc fu.tf_expr in
-			acc,{ e with eexpr = TFunction { fu with tf_expr = e1 } }
-		| TIf (ec,e1,eo) ->
-			let acc,ec = f acc ec in
-			let acc,e1 = f acc e1 in
-			let acc,eo = foldmap_opt f acc eo in
-			acc,{ e with eexpr = TIf (ec,e1,eo)}
-		| TSwitch (e1,cases,def) ->
-			let acc,e1 = f acc e1 in
-			let acc,cases = List.fold_left (fun (acc,cases) (el,e2) ->
-				let acc,el = foldmap_list f acc el in
-				let acc,e2 = f acc e2 in
-				acc,((el,e2) :: cases)
-			) (acc,[]) cases in
-			let acc,def = foldmap_opt f acc def in
-			acc,{ e with eexpr = TSwitch (e1, cases, def) }
-		| TTry (e1,catches) ->
-			let acc,e1 = f acc e1 in
-			let acc,catches = foldmap_pairs f acc catches in
-			acc,{ e with eexpr = TTry (e1, catches) }
-		| TReturn eo ->
-			let acc,eo = foldmap_opt f acc eo in
-			acc,{ e with eexpr = TReturn eo }
-		| TCast (e1,t) ->
-			let acc,e1 = f acc e1 in
-			acc,{ e with eexpr = TCast (e1,t) }
-		| TMeta (m,e1) ->
-			let acc,e1 = f acc e1 in
-			acc,{ e with eexpr = TMeta(m,e1)}
-		end
-end
-
 module ExtType = struct
 module ExtType = struct
 	let is_void = function
 	let is_void = function
 		| TAbstract({a_path=[],"Void"},_) -> true
 		| TAbstract({a_path=[],"Void"},_) -> true
@@ -2831,11 +2658,16 @@ module StringError = struct
 		in
 		in
 		loop cl
 		loop cl
 
 
-	let string_error_raise s sl msg =
-		if sl = [] then msg else
+	let get_similar s sl =
+		if sl = [] then [] else
 		let cl = List.map (fun s2 -> s2,levenshtein s s2) sl in
 		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 cl = List.sort (fun (_,c1) (_,c2) -> compare c1 c2) cl in
 		let cl = filter_similar (fun s2 i -> i <= (min (String.length s) (String.length s2)) / 3) cl in
 		let cl = filter_similar (fun s2 i -> i <= (min (String.length s) (String.length s2)) / 3) cl in
+		cl
+
+	let string_error_raise s sl msg =
+		if sl = [] then msg else
+		let cl = get_similar s sl in
 		match cl with
 		match cl with
 			| [] -> raise Not_found
 			| [] -> raise Not_found
 			| [s] -> Printf.sprintf "%s (Suggestion: %s)" msg s
 			| [s] -> Printf.sprintf "%s (Suggestion: %s)" msg s
@@ -2845,3 +2677,45 @@ module StringError = struct
 		try string_error_raise s sl msg
 		try string_error_raise s sl msg
 		with Not_found -> msg
 		with Not_found -> msg
 end
 end
+
+let class_module_type c = {
+	t_path = [],"Class<" ^ (s_type_path c.cl_path) ^ ">" ;
+	t_module = c.cl_module;
+	t_doc = None;
+	t_pos = c.cl_pos;
+	t_name_pos = null_pos;
+	t_type = TAnon {
+		a_fields = c.cl_statics;
+		a_status = ref (Statics c);
+	};
+	t_private = true;
+	t_params = [];
+	t_meta = no_meta;
+}
+
+let enum_module_type m path p  = {
+	t_path = [], "Enum<" ^ (s_type_path path) ^ ">";
+	t_module = m;
+	t_doc = None;
+	t_pos = p;
+	t_name_pos = null_pos;
+	t_type = mk_mono();
+	t_private = true;
+	t_params = [];
+	t_meta = [];
+}
+
+let abstract_module_type a tl = {
+	t_path = [],Printf.sprintf "Abstract<%s%s>" (s_type_path a.a_path) (s_type_params (ref []) tl);
+	t_module = a.a_module;
+	t_doc = None;
+	t_pos = a.a_pos;
+	t_name_pos = null_pos;
+	t_type = TAnon {
+		a_fields = PMap.empty;
+		a_status = ref (AbstractStatics a);
+	};
+	t_private = true;
+	t_params = [];
+	t_meta = no_meta;
+}

+ 1 - 1
src/filters/capturedVars.ml

@@ -168,7 +168,7 @@ let captured_vars com e =
 				in
 				in
 				let e = loop e in
 				let e = loop e in
 				mk (TCall (
 				mk (TCall (
-					Codegen.mk_parent (mk (TFunction {
+					Texpr.Builder.mk_parent (mk (TFunction {
 						tf_args = List.map (fun (_,v) -> v, None) new_vars;
 						tf_args = List.map (fun (_,v) -> v, None) new_vars;
 						tf_type = e.etype;
 						tf_type = e.etype;
 						tf_expr = mk_block (mk (TReturn (Some e)) e.etype e.epos);
 						tf_expr = mk_block (mk (TReturn (Some e)) e.etype e.epos);

+ 2 - 2
src/filters/defaultArguments.ml

@@ -19,7 +19,7 @@
 open Common
 open Common
 open Type
 open Type
 open Codegen
 open Codegen
-open Codegen.ExprBuilder
+open Texpr.Builder
 
 
 (*
 (*
 	This Module Filter will go through all defined functions in all modules and change them
 	This Module Filter will go through all defined functions in all modules and change them
@@ -48,7 +48,7 @@ let add_opt com block pos (var,opt) =
 	| None | Some TNull ->
 	| None | Some TNull ->
 		(var,opt)
 		(var,opt)
 	| Some (TString str) ->
 	| Some (TString str) ->
-		block := Codegen.set_default com var (TString str) pos :: !block;
+		block := Texpr.set_default com.basic var (TString str) pos :: !block;
 		(var, opt)
 		(var, opt)
 	| Some const ->
 	| Some const ->
 		let basic = com.basic in
 		let basic = com.basic in

+ 6 - 118
src/optimization/filters.ml → src/filters/filters.ml

@@ -23,6 +23,7 @@ open Type
 open Typecore
 open Typecore
 open Error
 open Error
 open Globals
 open Globals
+open FiltersCommon
 
 
 (** retrieve string from @:native metadata or raise Not_found *)
 (** retrieve string from @:native metadata or raise Not_found *)
 let get_native_name meta =
 let get_native_name meta =
@@ -81,33 +82,6 @@ let rec add_final_return e =
 			{ e with eexpr = TFunction f }
 			{ e with eexpr = TFunction f }
 		| _ -> e
 		| _ -> e
 
 
-let rec wrap_js_exceptions com e =
-	let rec is_error t =
-		match follow t with
-		| TInst ({cl_path = (["js"],"Error")},_) -> true
-		| TInst ({cl_super = Some (csup,tl)}, _) -> is_error (TInst (csup,tl))
-		| _ -> false
-	in
-	let rec loop e =
-		match e.eexpr with
-		| TThrow eerr when not (is_error eerr.etype) ->
-			let terr = List.find (fun mt -> match mt with TClassDecl {cl_path = ["js";"_Boot"],"HaxeError"} -> true | _ -> false) com.types in
-			let cerr = match terr with TClassDecl c -> c | _ -> assert false in
-			(match eerr.etype with
-			| TDynamic _ ->
-				let eterr = Codegen.ExprBuilder.make_static_this cerr e.epos in
-				let ewrap = Codegen.fcall eterr "wrap" [eerr] t_dynamic e.epos in
-				{ e with eexpr = TThrow ewrap }
-			| _ ->
-				let ewrap = { eerr with eexpr = TNew (cerr,[],[eerr]); etype = TInst (cerr,[]) } in
-				{ e with eexpr = TThrow ewrap }
-			)
-		| _ ->
-			Type.map_expr loop e
-	in
-
-	loop e
-
 (* -------------------------------------------------------------------------- *)
 (* -------------------------------------------------------------------------- *)
 (* CHECK LOCAL VARS INIT *)
 (* CHECK LOCAL VARS INIT *)
 
 
@@ -441,25 +415,6 @@ let save_class_state ctx t = match t with
 
 
 (* PASS 2 begin *)
 (* PASS 2 begin *)
 
 
-let rec is_removable_class c =
-	match c.cl_kind with
-	| KGeneric ->
-		(Meta.has Meta.Remove c.cl_meta ||
-		(match c.cl_super with
-			| Some (c,_) -> is_removable_class c
-			| _ -> false) ||
-		List.exists (fun (_,t) -> match follow t with
-			| TInst(c,_) ->
-				has_ctor_constraint c || Meta.has Meta.Const c.cl_meta
-			| _ ->
-				false
-		) c.cl_params)
-	| KTypeParameter _ ->
-		(* this shouldn't happen, have to investigate (see #4092) *)
-		true
-	| _ ->
-		false
-
 let remove_generic_base ctx t = match t with
 let remove_generic_base ctx t = match t with
 	| TClassDecl c when is_removable_class c ->
 	| TClassDecl c when is_removable_class c ->
 		c.cl_extern <- true
 		c.cl_extern <- true
@@ -485,43 +440,6 @@ let remove_extern_fields ctx t = match t with
 	| _ ->
 	| _ ->
 		()
 		()
 
 
-
-module VarLazifier = struct
-	let apply com e =
-		let rec loop var_inits e = match e.eexpr with
-			| TVar(v,Some e1) when (Meta.has (Meta.Custom ":extractorVariable") v.v_meta) ->
-				let var_inits,e1 = loop var_inits e1 in
-				let var_inits = PMap.add v.v_id e1 var_inits in
-				var_inits,{e with eexpr = TVar(v,None)}
-			| TLocal v ->
-				begin try
-					let e_init = PMap.find v.v_id var_inits in
-					let e = {e with eexpr = TBinop(OpAssign,e,e_init)} in
-					let e = {e with eexpr = TParenthesis e} in
-					let var_inits = PMap.remove v.v_id var_inits in
-					var_inits,e
-				with Not_found ->
-					var_inits,e
-				end
-			| TIf(e1,e2,eo) ->
-				let var_inits,e1 = loop var_inits e1 in
-				let _,e2 = loop var_inits e2 in
-				let eo = match eo with None -> None | Some e -> Some (snd (loop var_inits e)) in
-				var_inits,{e with eexpr = TIf(e1,e2,eo)}
-			| TSwitch(e1,cases,edef) ->
-				let var_inits,e1 = loop var_inits e1 in
-				let cases = List.map (fun (el,e) ->
-					let _,e = loop var_inits e in
-					el,e
-				) cases in
-				let edef = match edef with None -> None | Some e -> Some (snd (loop var_inits e)) in
-				var_inits,{e with eexpr = TSwitch(e1,cases,edef)}
-			| _ ->
-				Texpr.foldmap loop var_inits e
-		in
-		snd (loop PMap.empty e)
-end
-
 (* PASS 2 end *)
 (* PASS 2 end *)
 
 
 (* PASS 3 begin *)
 (* PASS 3 begin *)
@@ -687,7 +605,7 @@ let add_field_inits reserved ctx t =
 (* Adds the __meta__ field if required *)
 (* Adds the __meta__ field if required *)
 let add_meta_field ctx t = match t with
 let add_meta_field ctx t = match t with
 	| TClassDecl c ->
 	| TClassDecl c ->
-		(match Codegen.build_metadata ctx.com t with
+		(match Texpr.build_metadata ctx.com.basic t with
 		| None -> ()
 		| None -> ()
 		| Some e ->
 		| Some e ->
 			add_feature ctx.com "has_metadata";
 			add_feature ctx.com "has_metadata";
@@ -695,7 +613,6 @@ let add_meta_field ctx t = match t with
 			cf.cf_expr <- Some e;
 			cf.cf_expr <- Some e;
 			let can_deal_with_interface_metadata () = match ctx.com.platform with
 			let can_deal_with_interface_metadata () = match ctx.com.platform with
 				| Flash when Common.defined ctx.com Define.As3 -> false
 				| Flash when Common.defined ctx.com Define.As3 -> false
-				| Php when not (Common.is_php7 ctx.com) -> false
 				| Cs | Java -> false
 				| Cs | Java -> false
 				| _ -> true
 				| _ -> true
 			in
 			in
@@ -814,37 +731,6 @@ let check_reserved_type_paths ctx t =
 
 
 (* PASS 3 end *)
 (* PASS 3 end *)
 
 
-let run_expression_filters ctx filters t =
-	let run e =
-		List.fold_left (fun e f -> f e) e filters
-	in
-	match t with
-	| TClassDecl c when is_removable_class c -> ()
-	| TClassDecl c ->
-		ctx.curclass <- c;
-		let rec process_field f =
-			ctx.curfield <- f;
-			(match f.cf_expr with
-			| Some e when not (is_removable_field ctx f) ->
-				AbstractCast.cast_stack := f :: !AbstractCast.cast_stack;
-				f.cf_expr <- Some (run e);
-				AbstractCast.cast_stack := List.tl !AbstractCast.cast_stack;
-			| _ -> ());
-			List.iter process_field f.cf_overloads
-		in
-		List.iter process_field c.cl_ordered_fields;
-		List.iter process_field c.cl_ordered_statics;
-		(match c.cl_constructor with
-		| None -> ()
-		| Some f -> process_field f);
-		(match c.cl_init with
-		| None -> ()
-		| Some e ->
-			c.cl_init <- Some (run e));
-	| TEnumDecl _ -> ()
-	| TTypeDecl _ -> ()
-	| TAbstractDecl _ -> ()
-
 let pp_counter = ref 1
 let pp_counter = ref 1
 
 
 let is_cached t =
 let is_cached t =
@@ -872,7 +758,7 @@ let iter_expressions fl mt =
 		()
 		()
 
 
 let filter_timer detailed s =
 let filter_timer detailed s =
-	timer (if detailed then "filters" :: s else ["filters"])
+	Timer.timer (if detailed then "filters" :: s else ["filters"])
 
 
 let run com tctx main =
 let run com tctx main =
 	let detail_times = Common.raw_defined com "filter-times" in
 	let detail_times = Common.raw_defined com "filter-times" in
@@ -907,6 +793,8 @@ let run com tctx main =
 			filters @ [
 			filters @ [
 				TryCatchWrapper.configure_java com
 				TryCatchWrapper.configure_java com
 			]
 			]
+		| Js ->
+			filters @ [JsExceptions.init tctx];
 		| _ -> filters
 		| _ -> filters
 	in
 	in
 	let t = filter_timer detail_times ["expr 1"] in
 	let t = filter_timer detail_times ["expr 1"] in
@@ -935,7 +823,6 @@ let run com tctx main =
 	let filters = [
 	let filters = [
 		Optimizer.sanitize com;
 		Optimizer.sanitize com;
 		if com.config.pf_add_final_return then add_final_return else (fun e -> e);
 		if com.config.pf_add_final_return then add_final_return else (fun e -> e);
-		if com.platform = Js then wrap_js_exceptions com else (fun e -> e);
 		rename_local_vars tctx reserved;
 		rename_local_vars tctx reserved;
 		mark_switch_break_loops;
 		mark_switch_break_loops;
 	] in
 	] in
@@ -987,6 +874,7 @@ let run com tctx main =
 	] in
 	] in
 	let type_filters = match com.platform with
 	let type_filters = match com.platform with
 		| Cs -> type_filters @ [ fun _ t -> InterfaceProps.run t ]
 		| Cs -> type_filters @ [ fun _ t -> InterfaceProps.run t ]
+		| Js -> JsExceptions.inject_callstack com type_filters
 		| _ -> type_filters
 		| _ -> type_filters
 	in
 	in
 	let t = filter_timer detail_times ["type 3"] in
 	let t = filter_timer detail_times ["type 3"] in

+ 70 - 0
src/filters/filtersCommon.ml

@@ -0,0 +1,70 @@
+(*
+	The Haxe Compiler
+	Copyright (C) 2005-2017  Haxe Foundation
+
+	This program is free software; you can redistribute it and/or
+	modify it under the terms of the GNU General Public License
+	as published by the Free Software Foundation; either version 2
+	of the License, or (at your option) any later version.
+
+	This program is distributed in the hope that it will be useful,
+	but WITHOUT ANY WARRANTY; without even the implied warranty of
+	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+	GNU General Public License for more details.
+
+	You should have received a copy of the GNU General Public License
+	along with this program; if not, write to the Free Software
+	Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+*)
+open Type
+open Typecore
+
+let rec is_removable_class c =
+	match c.cl_kind with
+	| KGeneric ->
+		(Meta.has Meta.Remove c.cl_meta ||
+		(match c.cl_super with
+			| Some (c,_) -> is_removable_class c
+			| _ -> false) ||
+		List.exists (fun (_,t) -> match follow t with
+			| TInst(c,_) ->
+				has_ctor_constraint c || Meta.has Meta.Const c.cl_meta
+			| _ ->
+				false
+		) c.cl_params)
+	| KTypeParameter _ ->
+		(* this shouldn't happen, have to investigate (see #4092) *)
+		true
+	| _ ->
+		false
+
+let run_expression_filters ctx filters t =
+	let run e =
+		List.fold_left (fun e f -> f e) e filters
+	in
+	match t with
+	| TClassDecl c when is_removable_class c -> ()
+	| TClassDecl c ->
+		ctx.curclass <- c;
+		let rec process_field f =
+			ctx.curfield <- f;
+			(match f.cf_expr with
+			| Some e when not (is_removable_field ctx f) ->
+				AbstractCast.cast_stack := f :: !AbstractCast.cast_stack;
+				f.cf_expr <- Some (run e);
+				AbstractCast.cast_stack := List.tl !AbstractCast.cast_stack;
+			| _ -> ());
+			List.iter process_field f.cf_overloads
+		in
+		List.iter process_field c.cl_ordered_fields;
+		List.iter process_field c.cl_ordered_statics;
+		(match c.cl_constructor with
+		| None -> ()
+		| Some f -> process_field f);
+		(match c.cl_init with
+		| None -> ()
+		| Some e ->
+			c.cl_init <- Some (run e));
+	| TEnumDecl _ -> ()
+	| TTypeDecl _ -> ()
+	| TAbstractDecl _ -> ()

+ 209 - 0
src/filters/jsExceptions.ml

@@ -0,0 +1,209 @@
+(*
+	The Haxe Compiler
+	Copyright (C) 2005-2017  Haxe Foundation
+
+	This program is free software; you can redistribute it and/or
+	modify it under the terms of the GNU General Public License
+	as published by the Free Software Foundation; either version 2
+	of the License, or (at your option) any later version.
+
+	This program is distributed in the hope that it will be useful,
+	but WITHOUT ANY WARRANTY; without even the implied warranty of
+	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+	GNU General Public License for more details.
+
+	You should have received a copy of the GNU General Public License
+	along with this program; if not, write to the Free Software
+	Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *)
+
+(*
+	This filter handles everything related to exceptions for the JavaScript target:
+
+	- wrapping non-js.Error types in HaxeError on throwing
+	- unwrapping HaxeError on catch
+	- transforming series of catches into a single catch with Std.is checks (optimized)
+	- re-throwing caught exception with js.Lib.rethrow
+	- storing caught exception in haxe.CallStack.lastException (if haxe.CallStack is used)
+
+	Basically it translates this:
+
+	 try throw "fail"
+	 catch (e:String) { trace(e); js.Lib.rethrow(); }
+	 catch (e:Bool) {}
+
+	into something like this (JS):
+
+	 try {
+		 throw new HaxeError("fail");
+	 } catch (e) {
+		 haxe.CallStack.lastException = e;
+		 var e1 = (e instanceof HaxeError) e.val : e;
+		 if (typeof e1 == "string") {
+			 trace(e1);
+			 throw e;
+		 } else if (typeof e1 == "boolean") {
+		 } else {
+			 throw e;
+		 }
+	 }
+*)
+
+open Common
+open Type
+open Typecore
+open Texpr.Builder
+
+let follow = Abstract.follow_with_abstracts
+
+let rec is_js_error c =
+	match c with
+	| { cl_path = ["js"],"Error" } -> true
+	| { cl_super = Some (csup,_) } -> is_js_error csup
+	| _ -> false
+
+let find_cl com path =
+	ExtList.List.find_map (function
+		| TClassDecl c when c.cl_path = path -> Some c
+		| _ -> None
+	) com.types
+
+let init ctx =
+	let cJsError = find_cl ctx.com (["js"],"Error") in
+	let cHaxeError = find_cl ctx.com (["js";"_Boot"],"HaxeError") in
+	let cStd = find_cl ctx.com ([],"Std") in
+	let cBoot = find_cl ctx.com (["js"],"Boot") in
+	let cSyntax = find_cl ctx.com (["js"],"Syntax") in
+
+	let dynamic_wrap e =
+		let eHaxeError = make_static_this cHaxeError e.epos in
+		fcall eHaxeError "wrap" [e] (TInst (cJsError, [])) e.epos
+	in
+
+	let static_wrap e =
+		{ e with eexpr = TNew (cHaxeError,[],[e]); etype = TInst (cHaxeError,[]) }
+	in
+
+	let rec loop vrethrow e =
+		match e.eexpr with
+		| TThrow eexc ->
+			let eexc = loop vrethrow eexc in
+			let eexc =
+				match follow eexc.etype with
+				| TDynamic _ | TMono _ ->
+					(match eexc.eexpr with
+					| TConst (TInt _ | TFloat _ | TString _ | TBool _ | TNull) -> static_wrap eexc
+					| _ -> dynamic_wrap eexc)
+				| TInst (c,_) when (is_js_error c) ->
+					eexc
+				| _ ->
+					static_wrap eexc
+			in
+			{ e with eexpr = TThrow eexc }
+
+		| TCall ({ eexpr = TField (_, FStatic ({ cl_path = ["js"],"Lib" }, { cf_name = "getOriginalException" })) }, _) ->
+			(match vrethrow with
+			| Some erethrowvar -> erethrowvar
+			| None -> abort "js.Lib.getOriginalException can only be called inside a catch block" e.epos)
+
+		| TCall ({ eexpr = TField (_, FStatic ({ cl_path = ["js"],"Lib" }, { cf_name = "rethrow" })) }, _) ->
+			(match vrethrow with
+			| Some erethrowvar -> { e with eexpr = TThrow erethrowvar }
+			| None -> abort "js.Lib.rethrow can only be called inside a catch block" e.epos)
+
+		| TTry (etry, catches) ->
+			let etry = loop vrethrow etry in
+
+			let catchall_name = match catches with [(v,_)] -> v.v_name | _ -> "e" in
+			let vcatchall = alloc_var catchall_name t_dynamic e.epos in
+			let ecatchall = make_local vcatchall e.epos in
+			let erethrow = mk (TThrow ecatchall) t_dynamic e.epos in
+
+			let eSyntax = make_static_this cSyntax e.epos in
+			let eHaxeError = make_static_this cHaxeError e.epos in
+			let eInstanceof = fcall eSyntax "instanceof" [ecatchall;eHaxeError] ctx.com.basic.tbool e.epos in
+			let eVal = field { ecatchall with etype = TInst (cHaxeError,[]) } "val" t_dynamic e.epos in
+			let eunwrap = mk (TIf (eInstanceof, eVal, Some (ecatchall))) t_dynamic e.epos in
+
+			let vunwrapped = alloc_var catchall_name t_dynamic e.epos in
+			vunwrapped.v_meta <- (Meta.CompilerGenerated,[],Globals.null_pos) :: vunwrapped.v_meta;
+			let eunwrapped = make_local vunwrapped e.epos in
+
+			let ecatch = List.fold_left (fun acc (v,ecatch) ->
+				let ecatch = loop (Some ecatchall) ecatch in
+
+				(* it's not really compiler-generated, but it kind of is, since it was used as catch identifier and we add a TVar for it *)
+				v.v_meta <- (Meta.CompilerGenerated,[],Globals.null_pos) :: v.v_meta;
+
+				match follow v.v_type with
+				| TDynamic _ ->
+					{ ecatch with
+						eexpr = TBlock [
+							mk (TVar (v, Some eunwrapped)) ctx.com.basic.tvoid ecatch.epos;
+							ecatch;
+						]
+					}
+				| t ->
+					let etype = make_typeexpr (module_type_of_type t) e.epos in
+					let args = [eunwrapped;etype] in
+					let echeck =
+						match Optimizer.api_inline ctx cStd "is" args e.epos with
+						| Some e -> e
+						| None ->
+							let eBoot = make_static_this cBoot e.epos in
+							fcall eBoot "__instanceof" [eunwrapped;etype] ctx.com.basic.tbool e.epos
+					in
+					let ecatch = { ecatch with
+						eexpr = TBlock [
+							mk (TVar (v, Some eunwrapped)) ctx.com.basic.tvoid ecatch.epos;
+							ecatch;
+						]
+					} in
+					mk (TIf (echeck, ecatch, Some acc)) e.etype e.epos
+			) erethrow (List.rev catches) in
+
+			let ecatch = { ecatch with
+				eexpr = TBlock [
+					mk (TVar (vunwrapped, Some eunwrap)) ctx.com.basic.tvoid e.epos;
+					ecatch;
+				]
+			} in
+			{ e with eexpr = TTry (etry, [(vcatchall,ecatch)]) }
+		| _ ->
+			Type.map_expr (loop vrethrow) e
+	in
+	loop None
+
+let inject_callstack com type_filters =
+	let cCallStack =
+		if Common.has_dce com then
+			if Common.has_feature com "haxe.CallStack.lastException" then
+				Some (find_cl com (["haxe"],"CallStack"))
+			else
+				None
+		else
+			try Some (find_cl com (["haxe"],"CallStack")) with Not_found -> None
+	in
+	match cCallStack with
+	| Some cCallStack ->
+		let rec loop e =
+			match e.eexpr with
+			| TTry (etry,[(v,ecatch)]) ->
+				let etry = loop etry in
+				let ecatch = loop ecatch in
+
+				let eCallStack = make_static_this cCallStack ecatch.epos in
+				let elastException = field eCallStack "lastException" t_dynamic ecatch.epos in
+				let elocal = make_local v ecatch.epos in
+				let eStoreException = mk (TBinop (Ast.OpAssign, elastException, elocal)) ecatch.etype ecatch.epos in
+				let ecatch = Type.concat eStoreException ecatch in
+				{ e with eexpr = TTry (etry,[(v,ecatch)]) }
+			| TTry _ ->
+				(* this should be handled by the filter above *)
+				assert false
+			| _ ->
+				Type.map_expr loop e
+		in
+		type_filters @ [ fun ctx t -> FiltersCommon.run_expression_filters ctx [loop] t ]
+	| None ->
+		type_filters

+ 4 - 4
src/filters/tryCatchWrapper.ml

@@ -21,7 +21,7 @@ open Common
 open Ast
 open Ast
 open Type
 open Type
 open Codegen
 open Codegen
-open Codegen.ExprBuilder
+open Texpr.Builder
 
 
 (* ******************************************* *)
 (* ******************************************* *)
 (* Try / Catch + throw native types handling *)
 (* Try / Catch + throw native types handling *)
@@ -138,11 +138,11 @@ let configure_cs com =
 			let e_wrap = fcall e_hxexception "wrap" [expr] base_exception_t expr.epos in
 			let e_wrap = fcall e_hxexception "wrap" [expr] base_exception_t expr.epos in
 			make_throw e_wrap expr.epos
 			make_throw e_wrap expr.epos
 	in
 	in
-	let unwrap_expr local_to_unwrap = Codegen.field (mk_cast local_to_unwrap hx_exception_t local_to_unwrap.epos) "obj" t_dynamic local_to_unwrap.epos in
+	let unwrap_expr local_to_unwrap = field (mk_cast local_to_unwrap hx_exception_t local_to_unwrap.epos) "obj" t_dynamic local_to_unwrap.epos in
 	let rethrow_expr rethrow = make_throw e_rethrow rethrow.epos in
 	let rethrow_expr rethrow = make_throw e_rethrow rethrow.epos in
 	let catch_map v e =
 	let catch_map v e =
 		let e_exc = make_static_this exc_cl e.epos in
 		let e_exc = make_static_this exc_cl e.epos in
-		let e_field = Codegen.field e_exc "exception" base_exception_t e.epos in
+		let e_field = field e_exc "exception" base_exception_t e.epos in
 		let e_setstack = binop OpAssign e_field (make_local v e.epos) v.v_type e.epos in
 		let e_setstack = binop OpAssign e_field (make_local v e.epos) v.v_type e.epos in
 		Type.concat e_setstack e
 		Type.concat e_setstack e
 	in
 	in
@@ -171,7 +171,7 @@ let configure_java com =
 		let e_wrap = fcall e_hxexception "wrap" [expr] base_exception_t expr.epos in
 		let e_wrap = fcall e_hxexception "wrap" [expr] base_exception_t expr.epos in
 		make_throw e_wrap expr.epos
 		make_throw e_wrap expr.epos
 	in
 	in
-	let unwrap_expr local_to_unwrap = Codegen.field (mk_cast local_to_unwrap hx_exception_t local_to_unwrap.epos) "obj" t_dynamic local_to_unwrap.epos in
+	let unwrap_expr local_to_unwrap = field (mk_cast local_to_unwrap hx_exception_t local_to_unwrap.epos) "obj" t_dynamic local_to_unwrap.epos in
 	let rethrow_expr exc = { exc with eexpr = TThrow exc } in
 	let rethrow_expr exc = { exc with eexpr = TThrow exc } in
 	let catch_map v e =
 	let catch_map v e =
 		let exc = make_static_this exc_cl e.epos in
 		let exc = make_static_this exc_cl e.epos in

+ 36 - 0
src/filters/varLazifier.ml

@@ -0,0 +1,36 @@
+open Ast
+open Type
+
+let apply com e =
+	let rec loop var_inits e = match e.eexpr with
+		| TVar(v,Some e1) when (Meta.has (Meta.Custom ":extractorVariable") v.v_meta) ->
+			let var_inits,e1 = loop var_inits e1 in
+			let var_inits = PMap.add v.v_id e1 var_inits in
+			var_inits,{e with eexpr = TVar(v,None)}
+		| TLocal v ->
+			begin try
+				let e_init = PMap.find v.v_id var_inits in
+				let e = {e with eexpr = TBinop(OpAssign,e,e_init)} in
+				let e = {e with eexpr = TParenthesis e} in
+				let var_inits = PMap.remove v.v_id var_inits in
+				var_inits,e
+			with Not_found ->
+				var_inits,e
+			end
+		| TIf(e1,e2,eo) ->
+			let var_inits,e1 = loop var_inits e1 in
+			let _,e2 = loop var_inits e2 in
+			let eo = match eo with None -> None | Some e -> Some (snd (loop var_inits e)) in
+			var_inits,{e with eexpr = TIf(e1,e2,eo)}
+		| TSwitch(e1,cases,edef) ->
+			let var_inits,e1 = loop var_inits e1 in
+			let cases = List.map (fun (el,e) ->
+				let _,e = loop var_inits e in
+				el,e
+			) cases in
+			let edef = match edef with None -> None | Some e -> Some (snd (loop var_inits e)) in
+			var_inits,{e with eexpr = TSwitch(e1,cases,edef)}
+		| _ ->
+			Texpr.foldmap loop var_inits e
+	in
+	snd (loop PMap.empty e)

+ 4 - 4
src/generators/genas3.ml

@@ -300,7 +300,7 @@ let rec type_str ctx t p =
 		| [], "UInt" -> "uint"
 		| [], "UInt" -> "uint"
 		| _ -> type_str ctx (apply_params t.t_params args t.t_type) p)
 		| _ -> type_str ctx (apply_params t.t_params args t.t_type) p)
 	| TLazy f ->
 	| TLazy f ->
-		type_str ctx ((!f)()) p
+		type_str ctx (lazy_type f) p
 
 
 let rec iter_switch_break in_switch e =
 let rec iter_switch_break in_switch e =
 	match e.eexpr with
 	match e.eexpr with
@@ -676,7 +676,7 @@ and gen_expr ctx e =
 		let bend = open_block ctx in
 		let bend = open_block ctx in
 		let cb = (if not ctx.constructor_block then
 		let cb = (if not ctx.constructor_block then
 			(fun () -> ())
 			(fun () -> ())
-		else if not (Codegen.constructor_side_effects e) then begin
+		else if not (Texpr.constructor_side_effects e) then begin
 			ctx.constructor_block <- false;
 			ctx.constructor_block <- false;
 			(fun () -> ())
 			(fun () -> ())
 		end else begin
 		end else begin
@@ -754,7 +754,7 @@ and gen_expr ctx e =
 		handle_break();
 		handle_break();
 	| TObjectDecl fields ->
 	| TObjectDecl fields ->
 		spr ctx "{ ";
 		spr ctx "{ ";
-		concat ctx ", " (fun (f,e) -> print ctx "%s : " (anon_field f); gen_value ctx e) fields;
+		concat ctx ", " (fun ((f,_,_),e) -> print ctx "%s : " (anon_field f); gen_value ctx e) fields;
 		spr ctx "}"
 		spr ctx "}"
 	| TFor (v,it,e) ->
 	| TFor (v,it,e) ->
 		let handle_break = handle_break ctx e in
 		let handle_break = handle_break ctx e in
@@ -1204,7 +1204,7 @@ let generate_enum ctx e =
 			print ctx "public static var %s : %s = new %s(\"%s\",%d)" c.ef_name ename ename c.ef_name c.ef_index;
 			print ctx "public static var %s : %s = new %s(\"%s\",%d)" c.ef_name ename ename c.ef_name c.ef_index;
 	) e.e_constrs;
 	) e.e_constrs;
 	newline ctx;
 	newline ctx;
-	(match Codegen.build_metadata ctx.inf.com (TEnumDecl e) with
+	(match Texpr.build_metadata ctx.inf.com.basic (TEnumDecl e) with
 	| None -> ()
 	| None -> ()
 	| Some e ->
 	| Some e ->
 		print ctx "public static var __meta__ : * = ";
 		print ctx "public static var __meta__ : * = ";

+ 31 - 27
src/generators/gencpp.ml

@@ -176,7 +176,7 @@ let cached_source_writer common_ctx filename =
    new source_writer common_ctx (add_header) (add_buf) (close)
    new source_writer common_ctx (add_header) (add_buf) (close)
 ;;
 ;;
 
 
-let make_class_directories = Common.mkdir_recursive;;
+let make_class_directories = Path.mkdir_recursive;;
 
 
 let make_base_directory dir =
 let make_base_directory dir =
    make_class_directories "" ( ( Str.split_delim (Str.regexp "[\\/]+") dir ) );;
    make_class_directories "" ( ( Str.split_delim (Str.regexp "[\\/]+") dir ) );;
@@ -634,7 +634,7 @@ let rec is_objc_type t =
    | TType(td,_) -> (Meta.has Meta.Objc td.t_meta)
    | TType(td,_) -> (Meta.has Meta.Objc td.t_meta)
    | TAbstract (a,_) -> (Meta.has Meta.Objc a.a_meta)
    | TAbstract (a,_) -> (Meta.has Meta.Objc a.a_meta)
    | TMono r -> (match !r with | Some t -> is_objc_type t | _ -> false)
    | TMono r -> (match !r with | Some t -> is_objc_type t | _ -> false)
-   | TLazy f -> is_objc_type (!f())
+   | TLazy f -> is_objc_type (lazy_type f)
    | _ -> false
    | _ -> false
 ;;
 ;;
 
 
@@ -806,7 +806,7 @@ and type_string_suff suffix haxe_type remap =
       | _ -> "Dynamic"  ^ suffix )
       | _ -> "Dynamic"  ^ suffix )
       *)
       *)
    | TDynamic haxe_type -> "Dynamic" ^ suffix
    | TDynamic haxe_type -> "Dynamic" ^ suffix
-   | TLazy func -> type_string_suff suffix ((!func)()) remap
+   | TLazy func -> type_string_suff suffix (lazy_type func) remap
    | TAbstract (abs,pl) when abs.a_impl <> None ->
    | TAbstract (abs,pl) when abs.a_impl <> None ->
       type_string_suff suffix (Abstract.get_underlying_type abs pl) remap
       type_string_suff suffix (Abstract.get_underlying_type abs pl) remap
    | TAbstract (abs,pl) ->
    | TAbstract (abs,pl) ->
@@ -1796,7 +1796,7 @@ let rec cpp_type_of ctx haxe_type =
    | TFun _ -> TCppObject
    | TFun _ -> TCppObject
    | TAnon _ -> TCppObject
    | TAnon _ -> TCppObject
    | TDynamic _ -> TCppDynamic
    | TDynamic _ -> TCppDynamic
-   | TLazy func -> cpp_type_of ctx ((!func)())
+   | TLazy func -> cpp_type_of ctx (lazy_type func)
    )
    )
    and  cpp_type_from_path ctx path params default =
    and  cpp_type_from_path ctx path params default =
       match path,params with
       match path,params with
@@ -2895,7 +2895,7 @@ let retype_expression ctx request_type function_args function_type expression_tr
             | OpDiv -> TCppScalar("Float")
             | OpDiv -> TCppScalar("Float")
             | OpBoolAnd | OpBoolOr -> TCppScalar("bool")
             | OpBoolAnd | OpBoolOr -> TCppScalar("bool")
             | OpAnd | OpOr | OpXor | OpShl | OpShr | OpUShr -> TCppScalar("int")
             | OpAnd | OpOr | OpXor | OpShl | OpShr | OpUShr -> TCppScalar("int")
-            | OpAssign -> cpp_type_of left.etype
+            | OpAssign -> (retype TCppUnchanged left).cpptype
             | _ -> TCppUnchanged
             | _ -> TCppUnchanged
             in
             in
             let e1 = retype binOpType left in
             let e1 = retype binOpType left in
@@ -3006,14 +3006,14 @@ let retype_expression ctx request_type function_args function_type expression_tr
             CppBlock(cppExprs, List.rev !local_closures, !gc_stack ), TCppVoid
             CppBlock(cppExprs, List.rev !local_closures, !gc_stack ), TCppVoid
 
 
          | TObjectDecl (
          | TObjectDecl (
-            ("fileName" , { eexpr = (TConst (TString file)) }) ::
-               ("lineNumber" , { eexpr = (TConst (TInt line)) }) ::
-                  ("className" , { eexpr = (TConst (TString class_name)) }) ::
-                     ("methodName", { eexpr = (TConst (TString meth)) }) :: [] ) ->
+            (("fileName",_,_) , { eexpr = (TConst (TString file)) }) ::
+               (("lineNumber",_,_) , { eexpr = (TConst (TInt line)) }) ::
+                  (("className",_,_) , { eexpr = (TConst (TString class_name)) }) ::
+                     (("methodName",_,_), { eexpr = (TConst (TString meth)) }) :: [] ) ->
               CppPosition(file,line,class_name,meth), TCppDynamic
               CppPosition(file,line,class_name,meth), TCppDynamic
 
 
          | TObjectDecl el ->
          | TObjectDecl el ->
-            let retypedEls = List.map ( fun(v,e) -> v, retype TCppDynamic e) el in
+            let retypedEls = List.map ( fun((v,_,_),e) -> v, retype TCppDynamic e) el in
             (match return_type with
             (match return_type with
             | TCppVoid -> CppObjectDecl(retypedEls,false), TCppVoid
             | TCppVoid -> CppObjectDecl(retypedEls,false), TCppVoid
             | _ -> CppObjectDecl(retypedEls,false), TCppDynamic
             | _ -> CppObjectDecl(retypedEls,false), TCppDynamic
@@ -4736,7 +4736,7 @@ let find_referenced_types_flags ctx obj field_name super_deps constructor_deps h
          | _ -> () );
          | _ -> () );
          ) enum_def.e_constrs;
          ) enum_def.e_constrs;
       if (not header_only) then begin
       if (not header_only) then begin
-         let meta = Codegen.build_metadata ctx.ctx_common (TEnumDecl enum_def) in
+         let meta = Texpr.build_metadata ctx.ctx_common.basic (TEnumDecl enum_def) in
          match meta with Some expr -> visit_params expr | _ -> ();
          match meta with Some expr -> visit_params expr | _ -> ();
       end;
       end;
    in
    in
@@ -5318,7 +5318,8 @@ let access_str a = match a with
    | AccResolve -> "AccResolve"
    | AccResolve -> "AccResolve"
    | AccCall -> "AccCall"
    | AccCall -> "AccCall"
    | AccInline -> "AccInline"
    | AccInline -> "AccInline"
-   | AccRequire(_,_) -> "AccRequire" ;;
+   | AccRequire(_,_) -> "AccRequire"
+   | AccCtor -> "AccCtor";;
 
 
 
 
 let script_type t optional = if optional then begin
 let script_type t optional = if optional then begin
@@ -6050,7 +6051,7 @@ let generate_class_files baseCtx super_deps constructor_deps class_def inScripta
          )
          )
       in
       in
 
 
-      output_cpp "#if HXCPP_SCRIPTABLE\n";
+      output_cpp "#ifdef HXCPP_SCRIPTABLE\n";
 
 
       let stored_fields = List.filter is_data_member implemented_instance_fields in
       let stored_fields = List.filter is_data_member implemented_instance_fields in
       if ( (List.length stored_fields) > 0) then begin
       if ( (List.length stored_fields) > 0) then begin
@@ -7532,16 +7533,16 @@ class script_writer ctx filename asciiOut =
               this#checkCast return_type value false false;
               this#checkCast return_type value false false;
          )
          )
    | TObjectDecl (
    | TObjectDecl (
-      ("fileName" , { eexpr = (TConst (TString file)) }) ::
-         ("lineNumber" , { eexpr = (TConst (TInt line)) }) ::
-            ("className" , { eexpr = (TConst (TString class_name)) }) ::
-               ("methodName", { eexpr = (TConst (TString meth)) }) :: [] ) ->
+      (("fileName",_,_) , { eexpr = (TConst (TString file)) }) ::
+         (("lineNumber",_,_) , { eexpr = (TConst (TInt line)) }) ::
+            (("className",_,_) , { eexpr = (TConst (TString class_name)) }) ::
+               (("methodName",_,_), { eexpr = (TConst (TString meth)) }) :: [] ) ->
             this#write ( (this#op IaPosInfo) ^ (this#stringText file) ^ (Printf.sprintf "%ld" line) ^ " " ^
             this#write ( (this#op IaPosInfo) ^ (this#stringText file) ^ (Printf.sprintf "%ld" line) ^ " " ^
                         (this#stringText class_name) ^ " " ^  (this#stringText meth))
                         (this#stringText class_name) ^ " " ^  (this#stringText meth))
 
 
    | TObjectDecl values ->this#write ( (this#op IaObjDef) ^ (string_of_int (List.length values)));
    | TObjectDecl values ->this#write ( (this#op IaObjDef) ^ (string_of_int (List.length values)));
          this#write " ";
          this#write " ";
-         List.iter (fun (name,_) -> this#write (this#stringText name)  ) values;
+         List.iter (fun ((name,_,_),_) -> this#write (this#stringText name)  ) values;
          this#write "\n";
          this#write "\n";
          List.iter (fun (_,e) -> this#gen_expression e ) values;
          List.iter (fun (_,e) -> this#gen_expression e ) values;
    | TTypeExpr type_expr ->
    | TTypeExpr type_expr ->
@@ -7992,7 +7993,7 @@ let generate_script_class common_ctx script class_def =
          script#writeOpLine IaInline;
          script#writeOpLine IaInline;
       | Var v,_ ->
       | Var v,_ ->
          let mode_code mode = match mode with
          let mode_code mode = match mode with
-         | AccNormal -> IaAccessNormal
+         | AccNormal | AccCtor -> IaAccessNormal
          | AccNo -> IaAccessNot
          | AccNo -> IaAccessNot
          | AccNever -> IaAccessNot
          | AccNever -> IaAccessNot
          | AccResolve -> IaAccessResolve
          | AccResolve -> IaAccessResolve
@@ -8075,7 +8076,7 @@ let generate_cppia ctx =
          if (is_internal) then
          if (is_internal) then
             (if (debug>=4) then print_endline (" internal enum " ^ (join_class_path enum_def.e_path ".") ))
             (if (debug>=4) then print_endline (" internal enum " ^ (join_class_path enum_def.e_path ".") ))
          else begin
          else begin
-            let meta = Codegen.build_metadata common_ctx object_def in
+            let meta = Texpr.build_metadata common_ctx.basic object_def in
             if (enum_def.e_extern) then
             if (enum_def.e_extern) then
                (if (debug>=4) then print_endline ("external enum " ^  (join_class_path enum_def.e_path ".") ));
                (if (debug>=4) then print_endline ("external enum " ^  (join_class_path enum_def.e_path ".") ));
             generate_script_enum common_ctx script enum_def meta
             generate_script_enum common_ctx script enum_def meta
@@ -8170,7 +8171,7 @@ let generate_source ctx =
          if (is_internal) then
          if (is_internal) then
             (if (debug>1) then print_endline (" internal enum " ^ name ))
             (if (debug>1) then print_endline (" internal enum " ^ name ))
          else begin
          else begin
-            let meta = Codegen.build_metadata common_ctx object_def in
+            let meta = Texpr.build_metadata common_ctx.basic object_def in
             if (enum_def.e_extern) then
             if (enum_def.e_extern) then
                (if (debug>1) then print_endline ("external enum " ^ name ));
                (if (debug>1) then print_endline ("external enum " ^ name ));
             boot_enums := enum_def.e_path :: !boot_enums;
             boot_enums := enum_def.e_path :: !boot_enums;
@@ -8188,7 +8189,9 @@ let generate_source ctx =
    (match common_ctx.main with
    (match common_ctx.main with
    | None -> generate_dummy_main common_ctx
    | None -> generate_dummy_main common_ctx
    | Some e ->
    | Some e ->
-      let main_field = { cf_name = "__main__"; cf_type = t_dynamic; cf_expr = Some e; cf_expr_unoptimized = None; cf_pos = e.epos; cf_name_pos = null_pos; cf_public = true; cf_meta = []; cf_overloads = []; cf_doc = None; cf_kind = Var { v_read = AccNormal; v_write = AccNormal; }; cf_params = [] } in
+      let main_field = { (mk_field "__main__" t_dynamic e.epos null_pos) with
+         cf_expr = Some e;
+	  } in
       let class_def = { null_class with cl_path = ([],"@Main"); cl_ordered_statics = [main_field] } in
       let class_def = { null_class with cl_path = ([],"@Main"); cl_ordered_statics = [main_field] } in
       main_deps := find_referenced_types ctx (TClassDecl class_def) super_deps constructor_deps false true false;
       main_deps := find_referenced_types ctx (TClassDecl class_def) super_deps constructor_deps false true false;
       generate_main ctx super_deps class_def
       generate_main ctx super_deps class_def
@@ -8254,10 +8257,10 @@ let generate_source ctx =
    let cmd_defines = ref "" in
    let cmd_defines = ref "" in
    PMap.iter ( fun name value -> match name with
    PMap.iter ( fun name value -> match name with
       | "true" | "sys" | "dce" | "cpp" | "debug" -> ()
       | "true" | "sys" | "dce" | "cpp" | "debug" -> ()
-      | _ -> cmd_defines := !cmd_defines ^ " -D" ^ name ^ "=\"" ^ (escape_command value) ^ "\"" ) common_ctx.defines;
-   write_build_options common_ctx (common_ctx.file ^ "/Options.txt") common_ctx.defines;
+      | _ -> cmd_defines := !cmd_defines ^ " -D" ^ name ^ "=\"" ^ (escape_command value) ^ "\"" ) common_ctx.defines.Define.values;
+   write_build_options common_ctx (common_ctx.file ^ "/Options.txt") common_ctx.defines.Define.values;
    if ( not (Common.defined common_ctx Define.NoCompilation) ) then begin
    if ( not (Common.defined common_ctx Define.NoCompilation) ) then begin
-      let t = Common.timer ["generate";"cpp";"native compilation"] in
+      let t = Timer.timer ["generate";"cpp";"native compilation"] in
       let old_dir = Sys.getcwd() in
       let old_dir = Sys.getcwd() in
       Sys.chdir common_ctx.file;
       Sys.chdir common_ctx.file;
       let cmd = ref "haxelib run hxcpp Build.xml haxe" in
       let cmd = ref "haxelib run hxcpp Build.xml haxe" in
@@ -8272,11 +8275,12 @@ let generate_source ctx =
    ;;
    ;;
 
 
 let generate common_ctx =
 let generate common_ctx =
+   let debug_level = if (Common.defined common_ctx Define.NoDebug) then 0 else 1 in
    if (Common.defined common_ctx Define.Cppia) then begin
    if (Common.defined common_ctx Define.Cppia) then begin
-      let ctx = new_context common_ctx 1 (ref PMap.empty) (Hashtbl.create 0)  in
+      let ctx = new_context common_ctx debug_level (ref PMap.empty) (Hashtbl.create 0)  in
       generate_cppia ctx
       generate_cppia ctx
    end else begin
    end else begin
-      let ctx = new_context common_ctx 1 (ref PMap.empty) (create_member_types common_ctx) in
+      let ctx = new_context common_ctx debug_level (ref PMap.empty) (create_member_types common_ctx) in
       generate_source ctx
       generate_source ctx
    end
    end
 ;;
 ;;

+ 16 - 13
src/generators/gencs.ml

@@ -25,6 +25,7 @@ open Type
 open Gencommon
 open Gencommon
 open Gencommon.SourceWriter
 open Gencommon.SourceWriter
 open Codegen
 open Codegen
+open Texpr.Builder
 open Printf
 open Printf
 open Option
 open Option
 open ExtString
 open ExtString
@@ -45,7 +46,7 @@ let rec is_cs_basic_type t =
 			true
 			true
 		| TAbstract(a,pl) when not (Meta.has Meta.CoreType a.a_meta) ->
 		| TAbstract(a,pl) when not (Meta.has Meta.CoreType a.a_meta) ->
 			is_cs_basic_type (Abstract.get_underlying_type a pl)
 			is_cs_basic_type (Abstract.get_underlying_type a pl)
-		| TEnum(e, _) when not (Meta.has Meta.Class e.e_meta) -> true
+		| TEnum(e, _) as t when not (is_hxgen_t t) -> true
 		| TInst(cl, _) when Meta.has Meta.Struct cl.cl_meta -> true
 		| TInst(cl, _) when Meta.has Meta.Struct cl.cl_meta -> true
 		| _ -> false
 		| _ -> false
 
 
@@ -101,7 +102,7 @@ let rec is_null t =
 			| Some t -> is_null t
 			| Some t -> is_null t
 			| _ -> false)
 			| _ -> false)
 		| TLazy f ->
 		| TLazy f ->
-			is_null (!f())
+			is_null (lazy_type f)
 		| _ -> false
 		| _ -> false
 
 
 let rec get_ptr e = match e.eexpr with
 let rec get_ptr e = match e.eexpr with
@@ -381,7 +382,7 @@ struct
 					{ e with eexpr = TField(run ef, FDynamic "ToUpperInvariant") }
 					{ e with eexpr = TField(run ef, FDynamic "ToUpperInvariant") }
 
 
 				| TCall( { eexpr = TField(_, FStatic({ cl_path = [], "String" }, { cf_name = "fromCharCode" })) }, [cc] ) ->
 				| TCall( { eexpr = TField(_, FStatic({ cl_path = [], "String" }, { cf_name = "fromCharCode" })) }, [cc] ) ->
-					{ e with eexpr = TNew(get_cl_from_t basic.tstring, [], [mk_cast tchar (run cc); ExprBuilder.make_int gen.gcon 1 cc.epos]) }
+					{ e with eexpr = TNew(get_cl_from_t basic.tstring, [], [mk_cast tchar (run cc); make_int gen.gcon.basic 1 cc.epos]) }
 				| TCall( { eexpr = TField(ef, FInstance({ cl_path = [], "String" }, _, { cf_name = ("charAt" as field) })) }, args )
 				| TCall( { eexpr = TField(ef, FInstance({ cl_path = [], "String" }, _, { cf_name = ("charAt" as field) })) }, args )
 				| TCall( { eexpr = TField(ef, FInstance({ cl_path = [], "String" }, _, { cf_name = ("charCodeAt" as field) })) }, args )
 				| TCall( { eexpr = TField(ef, FInstance({ cl_path = [], "String" }, _, { cf_name = ("charCodeAt" as field) })) }, args )
 				| TCall( { eexpr = TField(ef, FInstance({ cl_path = [], "String" }, _, { cf_name = ("indexOf" as field) })) }, args )
 				| TCall( { eexpr = TField(ef, FInstance({ cl_path = [], "String" }, _, { cf_name = ("indexOf" as field) })) }, args )
@@ -535,7 +536,7 @@ let add_cast_handler gen =
 				epos = e.epos
 				epos = e.epos
 			};
 			};
 			{
 			{
-				eexpr = TVar(i, Some( ExprBuilder.make_int gen.gcon (-1) e.epos ));
+				eexpr = TVar(i, Some( make_int gen.gcon.basic (-1) e.epos ));
 				etype = basic.tvoid;
 				etype = basic.tvoid;
 				epos = e.epos
 				epos = e.epos
 			};
 			};
@@ -1797,7 +1798,7 @@ let generate con =
 						| Some t -> run t
 						| Some t -> run t
 						| _ -> () (* avoid infinite loop / should be the same in this context *))
 						| _ -> () (* avoid infinite loop / should be the same in this context *))
 					| TLazy f ->
 					| TLazy f ->
-						run (!f())
+						run (lazy_type f)
 					| _ -> ()
 					| _ -> ()
 			in
 			in
 			run t;
 			run t;
@@ -2124,7 +2125,7 @@ let generate con =
 										| TBlock _ ->
 										| TBlock _ ->
 											let unchecked = needs_unchecked e in
 											let unchecked = needs_unchecked e in
 											if unchecked then (begin_block w; write w "unchecked ");
 											if unchecked then (begin_block w; write w "unchecked ");
-											let t = Common.timer ["expression to string"] in
+											let t = Timer.timer ["expression to string"] in
 											expr_s w e;
 											expr_s w e;
 											t();
 											t();
 											line_reset_directive w;
 											line_reset_directive w;
@@ -2151,7 +2152,7 @@ let generate con =
 													| None -> ()
 													| None -> ()
 													| Some sc ->
 													| Some sc ->
 														write w ": ";
 														write w ": ";
-														let t = Common.timer ["expression to string"] in
+														let t = Timer.timer ["expression to string"] in
 														expr_s w sc;
 														expr_s w sc;
 														write w " ";
 														write w " ";
 														t()
 														t()
@@ -2316,7 +2317,7 @@ let generate con =
 					in
 					in
 					if prop v.v_read && prop v.v_write && (v.v_read = AccCall || v.v_write = AccCall) then begin
 					if prop v.v_read && prop v.v_write && (v.v_read = AccCall || v.v_write = AccCall) then begin
 						let this = if static then
 						let this = if static then
-							ExprBuilder.make_static_this cl f.cf_pos
+							make_static_this cl f.cf_pos
 						else
 						else
 							{ eexpr = TConst TThis; etype = TInst(cl,List.map snd cl.cl_params); epos = f.cf_pos }
 							{ eexpr = TConst TThis; etype = TInst(cl,List.map snd cl.cl_params); epos = f.cf_pos }
 						in
 						in
@@ -2689,6 +2690,8 @@ let generate con =
 				match e.eexpr, real_type e.etype with
 				match e.eexpr, real_type e.etype with
 					| TConst TThis, _ when gen.gcurrent_path = (["haxe";"lang"], "Null") ->
 					| TConst TThis, _ when gen.gcurrent_path = (["haxe";"lang"], "Null") ->
 						e
 						e
+					| TConst (TInt _ | TFloat _ | TBool _), _ ->
+						e
 					| _, TInst({ cl_path = (["haxe";"lang"], "Null") }, [t]) ->
 					| _, TInst({ cl_path = (["haxe";"lang"], "Null") }, [t]) ->
 						let e = { e with eexpr = TParenthesis(e) } in
 						let e = { e with eexpr = TParenthesis(e) } in
 						{ (mk_field_access gen e "value" e.epos) with etype = t }
 						{ (mk_field_access gen e "value" e.epos) with etype = t }
@@ -2737,7 +2740,7 @@ let generate con =
 
 
 		let cl_arg_exc = get_cl (get_type gen (["System"],"ArgumentException")) in
 		let cl_arg_exc = get_cl (get_type gen (["System"],"ArgumentException")) in
 		let cl_arg_exc_t = TInst (cl_arg_exc, []) in
 		let cl_arg_exc_t = TInst (cl_arg_exc, []) in
-		let mk_arg_exception msg pos = mk (TNew (cl_arg_exc, [], [ExprBuilder.make_string gen.gcon msg pos])) cl_arg_exc_t pos in
+		let mk_arg_exception msg pos = mk (TNew (cl_arg_exc, [], [make_string gen.gcon.basic msg pos])) cl_arg_exc_t pos in
 		let closure_t = ClosuresToClass.DoubleAndDynamicClosureImpl.get_ctx gen (get_cl (get_type gen (["haxe";"lang"],"Function"))) 6 mk_arg_exception in
 		let closure_t = ClosuresToClass.DoubleAndDynamicClosureImpl.get_ctx gen (get_cl (get_type gen (["haxe";"lang"],"Function"))) 6 mk_arg_exception in
 		ClosuresToClass.configure gen closure_t;
 		ClosuresToClass.configure gen closure_t;
 
 
@@ -2840,7 +2843,7 @@ let generate con =
 
 
 		let cl_field_exc = get_cl (get_type gen (["System"],"MemberAccessException")) in
 		let cl_field_exc = get_cl (get_type gen (["System"],"MemberAccessException")) in
 		let cl_field_exc_t = TInst (cl_field_exc, []) in
 		let cl_field_exc_t = TInst (cl_field_exc, []) in
-		let mk_field_exception msg pos = mk (TNew (cl_field_exc, [], [ExprBuilder.make_string gen.gcon msg pos])) cl_field_exc_t pos in
+		let mk_field_exception msg pos = mk (TNew (cl_field_exc, [], [make_string gen.gcon.basic msg pos])) cl_field_exc_t pos in
 
 
 		let rcf_ctx =
 		let rcf_ctx =
 			ReflectionCFs.new_ctx
 			ReflectionCFs.new_ctx
@@ -3073,7 +3076,7 @@ let generate con =
 									{ eexpr = TCall(static, [e1; e2]); etype = gen.gcon.basic.tint; epos=e1.epos }
 									{ eexpr = TCall(static, [e1; e2]); etype = gen.gcon.basic.tint; epos=e1.epos }
 								end
 								end
 							in
 							in
-							let zero = ExprBuilder.make_int gen.gcon 0 e.epos in
+							let zero = make_int gen.gcon.basic 0 e.epos in
 							{ e with eexpr = TBinop(op, handler, zero) }
 							{ e with eexpr = TBinop(op, handler, zero) }
 		);
 		);
 
 
@@ -3120,7 +3123,7 @@ let generate con =
 			Hashtbl.iter (fun name v ->
 			Hashtbl.iter (fun name v ->
 				let name = Codegen.escape_res_name name true in
 				let name = Codegen.escape_res_name name true in
 				let full_path = src ^ "/" ^ name in
 				let full_path = src ^ "/" ^ name in
-				mkdir_from_path full_path;
+				Path.mkdir_from_path full_path;
 
 
 				let f = open_out_bin full_path in
 				let f = open_out_bin full_path in
 				output_string f v;
 				output_string f v;
@@ -3223,7 +3226,7 @@ let generate con =
 
 
 		RenameTypeParameters.run gen.gtypes_list;
 		RenameTypeParameters.run gen.gtypes_list;
 
 
-		mkdir_from_path gen.gcon.file;
+		Path.mkdir_from_path gen.gcon.file;
 
 
 		List.iter (fun md_def ->
 		List.iter (fun md_def ->
 			let source_dir = gen.gcon.file ^ "/src/" ^ (String.concat "/" (fst (path_of_md_def md_def))) in
 			let source_dir = gen.gcon.file ^ "/src/" ^ (String.concat "/" (fst (path_of_md_def md_def))) in

+ 55 - 66
src/generators/genhl.ml

@@ -46,7 +46,7 @@ type allocator = {
 	mutable a_hold : int list;
 	mutable a_hold : int list;
 }
 }
 
 
-type lassign = (string index * int * int)
+type lassign = (string index * int)
 
 
 type method_context = {
 type method_context = {
 	mid : int;
 	mid : int;
@@ -108,8 +108,6 @@ type context = {
 	core_enum : tclass;
 	core_enum : tclass;
 	ref_abstract : tabstract;
 	ref_abstract : tabstract;
 	cdebug_files : (string, string) lookup;
 	cdebug_files : (string, string) lookup;
-	cdebug_locals : (string, string ) lookup;
-	cdebug_assigns : (lassign array) DynArray.t;
 }
 }
 
 
 (* --- *)
 (* --- *)
@@ -246,7 +244,7 @@ let efield_name e f =
 let global_type ctx g =
 let global_type ctx g =
 	DynArray.get ctx.cglobals.arr g
 	DynArray.get ctx.cglobals.arr g
 
 
-let is_overriden ctx c f =
+let is_overridden ctx c f =
 	ctx.is_macro || Hashtbl.mem ctx.overrides (f.cf_name,c.cl_path)
 	ctx.is_macro || Hashtbl.mem ctx.overrides (f.cf_name,c.cl_path)
 
 
 let alloc_float ctx f =
 let alloc_float ctx f =
@@ -362,7 +360,7 @@ let rec to_type ?tref ctx t =
 		| ["haxe";"macro"], name -> Hashtbl.replace ctx.macro_typedefs name t; t
 		| ["haxe";"macro"], name -> Hashtbl.replace ctx.macro_typedefs name t; t
 		| _ -> t)
 		| _ -> t)
 	| TLazy f ->
 	| TLazy f ->
-		to_type ?tref ctx (!f())
+		to_type ?tref ctx (lazy_type f)
 	| TFun (args, ret) ->
 	| TFun (args, ret) ->
 		HFun (List.map (fun (_,o,t) ->
 		HFun (List.map (fun (_,o,t) ->
 			let pt = to_type ctx t in
 			let pt = to_type ctx t in
@@ -592,7 +590,7 @@ and class_type ?(tref=None) ctx c pl statics =
 					let vid = (try -(fst (get_index f.cf_name p))-1 with Not_found -> assert false) in
 					let vid = (try -(fst (get_index f.cf_name p))-1 with Not_found -> assert false) in
 					DynArray.set virtuals vid g;
 					DynArray.set virtuals vid g;
 					Some vid
 					Some vid
-				else if is_overriden ctx c f then begin
+				else if is_overridden ctx c f then begin
 					let vid = DynArray.length virtuals in
 					let vid = DynArray.length virtuals in
 					DynArray.add virtuals g;
 					DynArray.add virtuals g;
 					p.pindex <- PMap.add f.cf_name (-vid-1,HVoid) p.pindex;
 					p.pindex <- PMap.add f.cf_name (-vid-1,HVoid) p.pindex;
@@ -827,10 +825,13 @@ let op ctx o =
 		DynArray.add ctx.m.mdebug ctx.m.mcurpos;
 		DynArray.add ctx.m.mdebug ctx.m.mcurpos;
 		DynArray.add ctx.m.mops o
 		DynArray.add ctx.m.mops o
 
 
+let set_op ctx pos o =
+	DynArray.set ctx.m.mops pos o
+
 let jump ctx f =
 let jump ctx f =
 	let pos = current_pos ctx in
 	let pos = current_pos ctx in
 	op ctx (OJAlways (-1)); (* loop *)
 	op ctx (OJAlways (-1)); (* loop *)
-	(fun() -> DynArray.set ctx.m.mops pos (f (current_pos ctx - pos - 1)))
+	(fun() -> set_op ctx pos (f (current_pos ctx - pos - 1)))
 
 
 let jump_back ctx =
 let jump_back ctx =
 	let pos = current_pos ctx in
 	let pos = current_pos ctx in
@@ -928,14 +929,14 @@ let real_name v =
 	in
 	in
 	loop v.v_meta
 	loop v.v_meta
 
 
-let add_assign ctx v r =
+let add_assign ctx v =
 	let name = real_name v in
 	let name = real_name v in
-	ctx.m.massign <- (lookup ctx.cdebug_locals name (fun() -> name), DynArray.length ctx.m.mops, r) :: ctx.m.massign
+	ctx.m.massign <- (alloc_string ctx name, current_pos ctx - 1) :: ctx.m.massign
 
 
 let add_capture ctx r =
 let add_capture ctx r =
 	Array.iter (fun v ->
 	Array.iter (fun v ->
 		let name = real_name v in
 		let name = real_name v in
-		ctx.m.massign <- (lookup ctx.cdebug_locals name (fun() -> name), -1, r) :: ctx.m.massign
+		ctx.m.massign <- (alloc_string ctx name, -(r+2)) :: ctx.m.massign
 	) ctx.m.mcaptured.c_vars
 	) ctx.m.mcaptured.c_vars
 
 
 let before_return ctx =
 let before_return ctx =
@@ -1208,7 +1209,7 @@ and direct_method_call ctx c f ethis =
 		false
 		false
 	else if (match c.cl_kind with KTypeParameter _ ->  true | _ -> false) then
 	else if (match c.cl_kind with KTypeParameter _ ->  true | _ -> false) then
 		false
 		false
-	else if is_overriden ctx c f && ethis.eexpr <> TConst(TSuper) then
+	else if is_overridden ctx c f && ethis.eexpr <> TConst(TSuper) then
 		false
 		false
 	else
 	else
 		true
 		true
@@ -1333,10 +1334,20 @@ and jump_expr ctx e jcond =
 		jump_expr ctx e (not jcond)
 		jump_expr ctx e (not jcond)
 	| TBinop (OpEq,{ eexpr = TConst(TNull) },e) | TBinop (OpEq,e,{ eexpr = TConst(TNull) }) ->
 	| TBinop (OpEq,{ eexpr = TConst(TNull) },e) | TBinop (OpEq,e,{ eexpr = TConst(TNull) }) ->
 		let r = eval_expr ctx e in
 		let r = eval_expr ctx e in
-		jump ctx (fun i -> if jcond then OJNull (r,i) else OJNotNull (r,i))
+		if is_nullable(rtype ctx r) then
+			jump ctx (fun i -> if jcond then OJNull (r,i) else OJNotNull (r,i))
+		else if not jcond then
+			jump ctx (fun i -> OJAlways i)
+		else
+			(fun i -> ())
 	| TBinop (OpNotEq,{ eexpr = TConst(TNull) },e) | TBinop (OpNotEq,e,{ eexpr = TConst(TNull) }) ->
 	| TBinop (OpNotEq,{ eexpr = TConst(TNull) },e) | TBinop (OpNotEq,e,{ eexpr = TConst(TNull) }) ->
 		let r = eval_expr ctx e in
 		let r = eval_expr ctx e in
-		jump ctx (fun i -> if jcond then OJNotNull (r,i) else OJNull (r,i))
+		if is_nullable(rtype ctx r) then
+			jump ctx (fun i -> if jcond then OJNotNull (r,i) else OJNull (r,i))
+		else if jcond then
+			jump ctx (fun i -> OJAlways i)
+		else
+			(fun i -> ())
 	| TBinop (OpEq | OpNotEq | OpGt | OpGte | OpLt | OpLte as jop, e1, e2) ->
 	| TBinop (OpEq | OpNotEq | OpGt | OpGte | OpLt | OpLte as jop, e1, e2) ->
 		let t = common_type ctx e1 e2 (match jop with OpEq | OpNotEq -> true | _ -> false) e.epos in
 		let t = common_type ctx e1 e2 (match jop with OpEq | OpNotEq -> true | _ -> false) e.epos in
 		let r1 = eval_to ctx e1 t in
 		let r1 = eval_to ctx e1 t in
@@ -1454,7 +1465,7 @@ and eval_expr ctx e =
 			| None ->
 			| None ->
 				let r = alloc_var ctx v true in
 				let r = alloc_var ctx v true in
 				op ctx (OMov (r,ri));
 				op ctx (OMov (r,ri));
-				add_assign ctx v r;
+				add_assign ctx v;
 			| Some idx ->
 			| Some idx ->
 				op ctx (OSetEnumField (ctx.m.mcaptreg, idx, ri));
 				op ctx (OSetEnumField (ctx.m.mcaptreg, idx, ri));
 		);
 		);
@@ -2052,11 +2063,11 @@ and eval_expr ctx e =
 		unsafe_cast_to ctx r (to_type ctx e.etype) e.epos
 		unsafe_cast_to ctx r (to_type ctx e.etype) e.epos
 	| TObjectDecl fl ->
 	| TObjectDecl fl ->
 		(match to_type ctx e.etype with
 		(match to_type ctx e.etype with
-		| HVirtual vp as t when Array.length vp.vfields = List.length fl && not (List.exists (fun (s,e) -> s = "toString" && is_to_string e.etype) fl)  ->
+		| HVirtual vp as t when Array.length vp.vfields = List.length fl && not (List.exists (fun ((s,_,_),e) -> s = "toString" && is_to_string e.etype) fl)  ->
 			let r = alloc_tmp ctx t in
 			let r = alloc_tmp ctx t in
 			op ctx (ONew r);
 			op ctx (ONew r);
 			hold ctx r;
 			hold ctx r;
-			List.iter (fun (s,ev) ->
+			List.iter (fun ((s,_,_),ev) ->
 				let fidx = (try PMap.find s vp.vindex with Not_found -> assert false) in
 				let fidx = (try PMap.find s vp.vindex with Not_found -> assert false) in
 				let _, _, ft = vp.vfields.(fidx) in
 				let _, _, ft = vp.vfields.(fidx) in
 				let v = eval_to ctx ev ft in
 				let v = eval_to ctx ev ft in
@@ -2069,7 +2080,7 @@ and eval_expr ctx e =
 			op ctx (ONew r);
 			op ctx (ONew r);
 			hold ctx r;
 			hold ctx r;
 			let a = (match follow e.etype with TAnon a -> Some a | t -> if t == t_dynamic then None else assert false) in
 			let a = (match follow e.etype with TAnon a -> Some a | t -> if t == t_dynamic then None else assert false) in
-			List.iter (fun (s,ev) ->
+			List.iter (fun ((s,_,_),ev) ->
 				let ft = (try (match a with None -> raise Not_found | Some a -> PMap.find s a.a_fields).cf_type with Not_found -> ev.etype) in
 				let ft = (try (match a with None -> raise Not_found | Some a -> PMap.find s a.a_fields).cf_type with Not_found -> ev.etype) in
 				let v = eval_to ctx ev (to_type ctx ft) in
 				let v = eval_to ctx ev (to_type ctx ft) in
 				op ctx (ODynSet (r,alloc_string ctx s,v));
 				op ctx (ODynSet (r,alloc_string ctx s,v));
@@ -2235,7 +2246,7 @@ and eval_expr ctx e =
 			| ALocal (v,l) ->
 			| ALocal (v,l) ->
 				let r = value() in
 				let r = value() in
 				op ctx (OMov (l, r));
 				op ctx (OMov (l, r));
-				add_assign ctx v l;
+				add_assign ctx v;
 				r
 				r
 			| AArray (ra,(at,vt),ridx) ->
 			| AArray (ra,(at,vt),ridx) ->
 				hold ctx ra;
 				hold ctx ra;
@@ -2307,7 +2318,6 @@ and eval_expr ctx e =
 			| ALocal (v,l) ->
 			| ALocal (v,l) ->
 				let r = eval_to ctx { e with eexpr = TBinop (bop,e1,e2) } (to_type ctx e1.etype) in
 				let r = eval_to ctx { e with eexpr = TBinop (bop,e1,e2) } (to_type ctx e1.etype) in
 				op ctx (OMov (l, r));
 				op ctx (OMov (l, r));
-				add_assign ctx v l;
 				r
 				r
 			| acc ->
 			| acc ->
 				gen_assign_op ctx acc e1 (fun r ->
 				gen_assign_op ctx acc e1 (fun r ->
@@ -2369,13 +2379,11 @@ and eval_expr ctx e =
 		(match get_access ctx v, fix with
 		(match get_access ctx v, fix with
 		| ALocal (v,r), Prefix ->
 		| ALocal (v,r), Prefix ->
 			unop r;
 			unop r;
-			add_assign ctx v r;
 			r
 			r
 		| ALocal (v,r), Postfix ->
 		| ALocal (v,r), Postfix ->
 			let r2 = alloc_tmp ctx (rtype ctx r) in
 			let r2 = alloc_tmp ctx (rtype ctx r) in
 			op ctx (OMov (r2,r));
 			op ctx (OMov (r2,r));
 			unop r;
 			unop r;
-			add_assign ctx v r;
 			r2
 			r2
 		| acc, _ ->
 		| acc, _ ->
 			let ret = ref 0 in
 			let ret = ref 0 in
@@ -2534,7 +2542,7 @@ and eval_expr ctx e =
 	| TMeta (_,e) ->
 	| TMeta (_,e) ->
 		eval_expr ctx e
 		eval_expr ctx e
 	| TFor (v,it,loop) ->
 	| TFor (v,it,loop) ->
-		eval_expr ctx (Codegen.for_remap ctx.com v it loop e.epos)
+		eval_expr ctx (Texpr.for_remap ctx.com.basic v it loop e.epos)
 	| 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
@@ -2576,7 +2584,7 @@ and eval_expr ctx e =
 				if rt <> HVoid then op ctx (OMov (r,re));
 				if rt <> HVoid then op ctx (OMov (r,re));
 				jends := jump ctx (fun i -> OJAlways i) :: !jends
 				jends := jump ctx (fun i -> OJAlways i) :: !jends
 			) cases;
 			) cases;
-			DynArray.set ctx.m.mops (switch_pos - 1) (OSwitch (ridx,indexes,current_pos ctx - switch_pos));
+			set_op ctx (switch_pos - 1) (OSwitch (ridx,indexes,current_pos ctx - switch_pos));
 			List.iter (fun j -> j()) (!jends);
 			List.iter (fun j -> j()) (!jends);
 		with Exit ->
 		with Exit ->
 			let jends = ref [] in
 			let jends = ref [] in
@@ -2649,13 +2657,13 @@ and eval_expr ctx e =
 		before_break_continue ctx;
 		before_break_continue ctx;
 		let pos = current_pos ctx in
 		let pos = current_pos ctx in
 		op ctx (OJAlways (-1)); (* loop *)
 		op ctx (OJAlways (-1)); (* loop *)
-		ctx.m.mcontinues <- (fun target -> DynArray.set ctx.m.mops pos (OJAlways (target - (pos + 1)))) :: ctx.m.mcontinues;
+		ctx.m.mcontinues <- (fun target -> set_op ctx pos (OJAlways (target - (pos + 1)))) :: ctx.m.mcontinues;
 		alloc_tmp ctx HVoid
 		alloc_tmp ctx HVoid
 	| TBreak ->
 	| TBreak ->
 		before_break_continue ctx;
 		before_break_continue ctx;
 		let pos = current_pos ctx in
 		let pos = current_pos ctx in
 		op ctx (OJAlways (-1)); (* loop *)
 		op ctx (OJAlways (-1)); (* loop *)
-		ctx.m.mbreaks <- (fun target -> DynArray.set ctx.m.mops pos (OJAlways (target - (pos + 1)))) :: ctx.m.mbreaks;
+		ctx.m.mbreaks <- (fun target -> set_op ctx pos (OJAlways (target - (pos + 1)))) :: ctx.m.mbreaks;
 		alloc_tmp ctx HVoid
 		alloc_tmp ctx HVoid
 	| TTry (etry,catches) ->
 	| TTry (etry,catches) ->
 		let pos = current_pos ctx in
 		let pos = current_pos ctx in
@@ -2669,7 +2677,7 @@ and eval_expr ctx e =
 		ctx.m.mtrys <- ctx.m.mtrys - 1;
 		ctx.m.mtrys <- ctx.m.mtrys - 1;
 		op ctx (OEndTrap true);
 		op ctx (OEndTrap true);
 		let j = jump ctx (fun n -> OJAlways n) in
 		let j = jump ctx (fun n -> OJAlways n) in
-		DynArray.set ctx.m.mops pos (OTrap (rtrap, current_pos ctx - (pos + 1)));
+		set_op ctx pos (OTrap (rtrap, current_pos ctx - (pos + 1)));
 		let rec loop l =
 		let rec loop l =
 			match l with
 			match l with
 			| [] ->
 			| [] ->
@@ -2718,7 +2726,7 @@ and eval_expr ctx e =
 			op ctx (OSafeCast (r,re));
 			op ctx (OSafeCast (r,re));
 		r
 		r
 	| TIdent s ->
 	| TIdent s ->
-		assert false
+		abort ("Unbound identifier " ^ s) e.epos
 
 
 and gen_assign_op ctx acc e1 f =
 and gen_assign_op ctx acc e1 f =
 	let f r =
 	let f r =
@@ -2902,10 +2910,10 @@ and gen_method_wrapper ctx rt t p =
 			regs = DynArray.to_array ctx.m.mregs.arr;
 			regs = DynArray.to_array ctx.m.mregs.arr;
 			code = DynArray.to_array ctx.m.mops;
 			code = DynArray.to_array ctx.m.mops;
 			debug = make_debug ctx ctx.m.mdebug;
 			debug = make_debug ctx ctx.m.mdebug;
+			assigns = Array.of_list (List.rev ctx.m.massign);
 		} in
 		} in
 		ctx.m <- old;
 		ctx.m <- old;
 		DynArray.add ctx.cfunctions f;
 		DynArray.add ctx.cfunctions f;
-		DynArray.add ctx.cdebug_assigns [||];
 		fid
 		fid
 
 
 and make_fun ?gen_content ctx name fidx f cthis cparent =
 and make_fun ?gen_content ctx name fidx f cthis cparent =
@@ -2943,7 +2951,7 @@ and make_fun ?gen_content ctx name fidx f cthis cparent =
 	let args = List.map (fun (v,o) ->
 	let args = List.map (fun (v,o) ->
 		let t = to_type ctx v.v_type in
 		let t = to_type ctx v.v_type in
 		let r = alloc_var ctx (if o = None then v else { v with v_type = if not (is_nullable t) then TAbstract(ctx.ref_abstract,[v.v_type]) else v.v_type }) true in
 		let r = alloc_var ctx (if o = None then v else { v with v_type = if not (is_nullable t) then TAbstract(ctx.ref_abstract,[v.v_type]) else v.v_type }) true in
-		add_assign ctx v r;
+		add_assign ctx v; (* record var name *)
 		rtype ctx r
 		rtype ctx r
 	) f.tf_args in
 	) f.tf_args in
 
 
@@ -2988,11 +2996,11 @@ and make_fun ?gen_content ctx name fidx f cthis cparent =
 				| _ -> assert false)
 				| _ -> assert false)
 			| _ ->
 			| _ ->
 				assert false);
 				assert false);
-			if capt = None then add_assign ctx v t;
+			if capt = None then add_assign ctx v;
 			let jend = jump ctx (fun n -> OJAlways n) in
 			let jend = jump ctx (fun n -> OJAlways n) in
 			j();
 			j();
 			op ctx (OUnref (t,r));
 			op ctx (OUnref (t,r));
-			if capt = None then add_assign ctx v t;
+			if capt = None then add_assign ctx v;
 			jend();
 			jend();
 			Hashtbl.replace ctx.m.mvars v.v_id t;
 			Hashtbl.replace ctx.m.mvars v.v_id t;
 			free ctx r;
 			free ctx r;
@@ -3024,7 +3032,6 @@ and make_fun ?gen_content ctx name fidx f cthis cparent =
 			| TString s ->
 			| TString s ->
 				op ctx (OMov (r, make_string ctx s f.tf_expr.epos))
 				op ctx (OMov (r, make_string ctx s f.tf_expr.epos))
 			);
 			);
-			if capt = None then add_assign ctx v r;
 			j();
 			j();
 		);
 		);
 		(match capt with
 		(match capt with
@@ -3066,13 +3073,12 @@ and make_fun ?gen_content ctx name fidx f cthis cparent =
 		regs = DynArray.to_array ctx.m.mregs.arr;
 		regs = DynArray.to_array ctx.m.mregs.arr;
 		code = DynArray.to_array ctx.m.mops;
 		code = DynArray.to_array ctx.m.mops;
 		debug = make_debug ctx ctx.m.mdebug;
 		debug = make_debug ctx ctx.m.mdebug;
+		assigns = Array.of_list (List.rev ctx.m.massign);
 	} in
 	} in
-	let assigns = Array.of_list (List.rev ctx.m.massign) in
 	ctx.m <- old;
 	ctx.m <- old;
 	Hashtbl.add ctx.defined_funs fidx ();
 	Hashtbl.add ctx.defined_funs fidx ();
 	let f = if ctx.optimize then Hlopt.optimize ctx.dump_out f else f in
 	let f = if ctx.optimize then Hlopt.optimize ctx.dump_out f else f in
 	DynArray.add ctx.cfunctions f;
 	DynArray.add ctx.cfunctions f;
-	DynArray.add ctx.cdebug_assigns assigns;
 	capt
 	capt
 
 
 let generate_static ctx c f =
 let generate_static ctx c f =
@@ -3260,7 +3266,7 @@ let generate_static_init ctx types main =
 					op ctx (OSetGlobal (g, rt));
 					op ctx (OSetGlobal (g, rt));
 				end;
 				end;
 
 
-				(match Codegen.build_metadata ctx.com (TClassDecl c) with
+				(match Texpr.build_metadata ctx.com.basic (TClassDecl c) with
 				| None -> ()
 				| None -> ()
 				| Some e ->
 				| Some e ->
 					let r = eval_to ctx e HDyn in
 					let r = eval_to ctx e HDyn in
@@ -3306,7 +3312,7 @@ let generate_static_init ctx types main =
 						op ctx (OSetGlobal (g,r));
 						op ctx (OSetGlobal (g,r));
 				) e.e_names;
 				) e.e_names;
 
 
-				(match Codegen.build_metadata ctx.com (TEnumDecl e) with
+				(match Texpr.build_metadata ctx.com.basic (TEnumDecl e) with
 				| None -> ()
 				| None -> ()
 				| Some e -> op ctx (OSetField (r,index "__meta__",eval_to ctx e HDyn)));
 				| Some e -> op ctx (OSetField (r,index "__meta__",eval_to ctx e HDyn)));
 
 
@@ -3647,7 +3653,14 @@ let write_code ch code debug =
 		write_index (Array.length f.code);
 		write_index (Array.length f.code);
 		Array.iter write_type f.regs;
 		Array.iter write_type f.regs;
 		Array.iter write_op f.code;
 		Array.iter write_op f.code;
-		if debug then write_debug_infos f.debug;
+		if debug then begin
+			write_debug_infos f.debug;
+			write_index (Array.length f.assigns);
+			Array.iter (fun (i,p) ->
+				write_index i;
+				write_index (p + 1);
+			) f.assigns;
+		end;
 	) code.functions
 	) code.functions
 
 
 (* --------------------------------------------------------------------------------------------------------------------- *)
 (* --------------------------------------------------------------------------------------------------------------------- *)
@@ -3709,8 +3722,6 @@ let create_context com is_macro dump =
 		method_wrappers = PMap.empty;
 		method_wrappers = PMap.empty;
 		cdebug_files = new_lookup();
 		cdebug_files = new_lookup();
 		macro_typedefs = Hashtbl.create 0;
 		macro_typedefs = Hashtbl.create 0;
-		cdebug_locals = new_lookup();
-		cdebug_assigns = DynArray.create();
 	} in
 	} in
 	ignore(alloc_string ctx "");
 	ignore(alloc_string ctx "");
 	ignore(class_type ctx ctx.base_class [] false);
 	ignore(class_type ctx ctx.base_class [] false);
@@ -3757,7 +3768,7 @@ let add_types ctx types =
 let build_code ctx types main =
 let build_code ctx types main =
 	let ep = generate_static_init ctx types main in
 	let ep = generate_static_init ctx types main in
 	{
 	{
-		version = 2;
+		version = 3;
 		entrypoint = ep;
 		entrypoint = ep;
 		strings = DynArray.to_array ctx.cstrings.arr;
 		strings = DynArray.to_array ctx.cstrings.arr;
 		ints = DynArray.to_array ctx.cints.arr;
 		ints = DynArray.to_array ctx.cints.arr;
@@ -3800,7 +3811,7 @@ let generate com =
 		check ctx;
 		check ctx;
 		Hlinterp.check code false;
 		Hlinterp.check code false;
 	end;
 	end;
-	let t = Common.timer ["write";"hl"] in
+	let t = Timer.timer ["write";"hl"] in
 
 
 	let escape_command s =
 	let escape_command s =
 		let b = Buffer.create 0 in
 		let b = Buffer.create 0 in
@@ -3810,38 +3821,16 @@ let generate com =
 
 
 	if file_extension com.file = "c" then begin
 	if file_extension com.file = "c" then begin
 		Hl2c.write_c com com.file code;
 		Hl2c.write_c com com.file code;
-		let t = Common.timer ["nativecompile";"hl"] in
+		let t = Timer.timer ["nativecompile";"hl"] in
 		if not (Common.defined com Define.NoCompilation) && com.run_command ("haxelib run hashlink build " ^ escape_command com.file) <> 0 then failwith "Build failed";
 		if not (Common.defined com Define.NoCompilation) && com.run_command ("haxelib run hashlink build " ^ escape_command com.file) <> 0 then failwith "Build failed";
 		t();
 		t();
 	end else begin
 	end else begin
 		let ch = IO.output_string() in
 		let ch = IO.output_string() in
-		write_code ch code true;
+		write_code ch code (not (Common.raw_defined com "hl-no-debug"));
 		let str = IO.close_out ch in
 		let str = IO.close_out ch in
 		let ch = open_out_bin com.file in
 		let ch = open_out_bin com.file in
 		output_string ch str;
 		output_string ch str;
 		close_out ch;
 		close_out ch;
-(*
-		let ch = IO.output_string() in
-		let byte = IO.write_byte ch in
-		let write_index = write_index_gen byte in
-		write_index (DynArray.length ctx.cdebug_locals.arr);
-		DynArray.iter (fun s ->
-			write_index (String.length s);
-			IO.write_string ch s;
-		) ctx.cdebug_locals.arr;
-		write_index (DynArray.length ctx.cdebug_assigns);
-		DynArray.iter (fun a ->
-			write_index (Array.length a);
-			Array.iter (fun (i,p,r) ->
-				write_index i;
-				write_index p;
-				write_index r;
-			) a;
-		) ctx.cdebug_assigns;
-		let str = IO.close_out ch in
-		let dbg = open_out_bin (com.file ^ "d") in
-		output_string dbg str;
-		close_out dbg; *)
 	end;
 	end;
 	t();
 	t();
 	if Common.raw_defined com "run" then begin
 	if Common.raw_defined com "run" then begin
@@ -3849,7 +3838,7 @@ let generate com =
 	end;
 	end;
 	if Common.defined com Define.Interp then
 	if Common.defined com Define.Interp then
 		try
 		try
-			let t = Common.timer ["generate";"hl";"interp"] in
+			let t = Timer.timer ["generate";"hl";"interp"] in
 			let ctx = Hlinterp.create true in
 			let ctx = Hlinterp.create true in
 			Hlinterp.add_code ctx code;
 			Hlinterp.add_code ctx code;
 			t();
 			t();

+ 7 - 7
src/generators/genjava.ml

@@ -1868,7 +1868,7 @@ let generate con =
 					| Some t -> run t
 					| Some t -> run t
 					| _ -> () (* avoid infinite loop / should be the same in this context *))
 					| _ -> () (* avoid infinite loop / should be the same in this context *))
 				| TLazy f ->
 				| TLazy f ->
-					run (!f())
+					run (lazy_type f)
 				| _ -> ()
 				| _ -> ()
 		in
 		in
 		run t;
 		run t;
@@ -2288,7 +2288,7 @@ let generate con =
 
 
 	let cl_arg_exc = get_cl (get_type gen (["java";"lang"],"IllegalArgumentException")) in
 	let cl_arg_exc = get_cl (get_type gen (["java";"lang"],"IllegalArgumentException")) in
 	let cl_arg_exc_t = TInst (cl_arg_exc, []) in
 	let cl_arg_exc_t = TInst (cl_arg_exc, []) in
-	let mk_arg_exception msg pos = mk (TNew (cl_arg_exc, [], [ExprBuilder.make_string gen.gcon msg pos])) cl_arg_exc_t pos in
+	let mk_arg_exception msg pos = mk (TNew (cl_arg_exc, [], [Texpr.Builder.make_string gen.gcon.basic msg pos])) cl_arg_exc_t pos in
 	let closure_t = ClosuresToClass.DoubleAndDynamicClosureImpl.get_ctx gen (get_cl (get_type gen (["haxe";"lang"],"Function"))) 6 mk_arg_exception in
 	let closure_t = ClosuresToClass.DoubleAndDynamicClosureImpl.get_ctx gen (get_cl (get_type gen (["haxe";"lang"],"Function"))) 6 mk_arg_exception in
 	ClosuresToClass.configure gen closure_t;
 	ClosuresToClass.configure gen closure_t;
 
 
@@ -2379,7 +2379,7 @@ let generate con =
 
 
 	let cl_field_exc = get_cl (get_type gen (["java";"lang"],"RuntimeException")) in
 	let cl_field_exc = get_cl (get_type gen (["java";"lang"],"RuntimeException")) in
 	let cl_field_exc_t = TInst (cl_field_exc, []) in
 	let cl_field_exc_t = TInst (cl_field_exc, []) in
-	let mk_field_exception msg pos = mk (TNew (cl_field_exc, [], [ExprBuilder.make_string gen.gcon msg pos])) cl_field_exc_t pos in
+	let mk_field_exception msg pos = mk (TNew (cl_field_exc, [], [Texpr.Builder.make_string gen.gcon.basic msg pos])) cl_field_exc_t pos in
 
 
 	let rcf_ctx =
 	let rcf_ctx =
 		ReflectionCFs.new_ctx
 		ReflectionCFs.new_ctx
@@ -2557,7 +2557,7 @@ let generate con =
 									{ eexpr = TCall(static, [e1; e2]); etype = gen.gcon.basic.tint; epos=e1.epos }
 									{ eexpr = TCall(static, [e1; e2]); etype = gen.gcon.basic.tint; epos=e1.epos }
 								end
 								end
 							in
 							in
-							let zero = ExprBuilder.make_int gen.gcon 0 e.epos in
+							let zero = Texpr.Builder.make_int gen.gcon.basic 0 e.epos in
 							{ e with eexpr = TBinop(op, handler, zero) }
 							{ e with eexpr = TBinop(op, handler, zero) }
 			);
 			);
 
 
@@ -2600,7 +2600,7 @@ let generate con =
 	let str_cl = match gen.gcon.basic.tstring with | TInst(cl,_) -> cl | _ -> assert false in
 	let str_cl = match gen.gcon.basic.tstring with | TInst(cl,_) -> cl | _ -> assert false in
 	str_cl.cl_super <- Some (get_cl (get_type gen (["haxe";"lang"], "NativeString")), []);
 	str_cl.cl_super <- Some (get_cl (get_type gen (["haxe";"lang"], "NativeString")), []);
 
 
-	mkdir_from_path (gen.gcon.file ^ "/src");
+	Path.mkdir_from_path (gen.gcon.file ^ "/src");
 
 
 	let out_files = ref [] in
 	let out_files = ref [] in
 
 
@@ -2610,7 +2610,7 @@ let generate con =
 		res := { eexpr = TConst(TString name); etype = gen.gcon.basic.tstring; epos = null_pos } :: !res;
 		res := { eexpr = TConst(TString name); etype = gen.gcon.basic.tstring; epos = null_pos } :: !res;
 		let name = Codegen.escape_res_name name true in
 		let name = Codegen.escape_res_name name true in
 		let full_path = gen.gcon.file ^ "/src/" ^ name in
 		let full_path = gen.gcon.file ^ "/src/" ^ name in
-		mkdir_from_path full_path;
+		Path.mkdir_from_path full_path;
 
 
 		let f = open_out_bin full_path in
 		let f = open_out_bin full_path in
 		output_string f v;
 		output_string f v;
@@ -2629,7 +2629,7 @@ let generate con =
 	RenameTypeParameters.run gen.gtypes_list;
 	RenameTypeParameters.run gen.gtypes_list;
 
 
 	let parts = Str.split_delim (Str.regexp "[\\/]+") gen.gcon.file in
 	let parts = Str.split_delim (Str.regexp "[\\/]+") gen.gcon.file in
-	mkdir_recursive "" parts;
+	Path.mkdir_recursive "" parts;
 
 
 	let source_dir = gen.gcon.file ^ "/src" in
 	let source_dir = gen.gcon.file ^ "/src" in
 	List.iter (fun md ->
 	List.iter (fun md ->

+ 197 - 217
src/generators/genjs.ml

@@ -27,13 +27,17 @@ type sourcemap = {
 	sources_hash : (string, int) Hashtbl.t;
 	sources_hash : (string, int) Hashtbl.t;
 	mappings : Rbuffer.t;
 	mappings : Rbuffer.t;
 
 
-	mutable source_last_line : int;
-	mutable source_last_col : int;
-	mutable source_last_file : int;
+	mutable source_last_pos : sourcemap_pos;
 	mutable print_comma : bool;
 	mutable print_comma : bool;
 	mutable output_last_col : int;
 	mutable output_last_col : int;
 	mutable output_current_col : int;
 	mutable output_current_col : int;
-	mutable current_expr : texpr option;
+	mutable current_expr : sourcemap_pos option;
+}
+
+and sourcemap_pos = {
+	file : int;
+	line : int;
+	col : int;
 }
 }
 
 
 type ctx = {
 type ctx = {
@@ -45,7 +49,6 @@ type ctx = {
 	js_modern : bool;
 	js_modern : bool;
 	js_flatten : bool;
 	js_flatten : bool;
 	es_version : int;
 	es_version : int;
-	store_exception_stack : bool;
 	mutable current : tclass;
 	mutable current : tclass;
 	mutable statics : (tclass * string * texpr) list;
 	mutable statics : (tclass * string * texpr) list;
 	mutable inits : texpr list;
 	mutable inits : texpr list;
@@ -139,10 +142,55 @@ let add_feature ctx = Common.add_feature ctx.com
 
 
 let unsupported p = abort "This expression cannot be compiled to Javascript" p
 let unsupported p = abort "This expression cannot be compiled to Javascript" p
 
 
+let encode_mapping smap pos =
+	if smap.print_comma then
+		Rbuffer.add_char smap.mappings ','
+	else
+		smap.print_comma <- true;
+
+	let base64_vlq number =
+		let encode_digit digit =
+			let chars = [|
+				'A';'B';'C';'D';'E';'F';'G';'H';'I';'J';'K';'L';'M';'N';'O';'P';
+				'Q';'R';'S';'T';'U';'V';'W';'X';'Y';'Z';'a';'b';'c';'d';'e';'f';
+				'g';'h';'i';'j';'k';'l';'m';'n';'o';'p';'q';'r';'s';'t';'u';'v';
+				'w';'x';'y';'z';'0';'1';'2';'3';'4';'5';'6';'7';'8';'9';'+';'/'
+			|] in
+			Array.unsafe_get chars digit
+		in
+		let to_vlq number =
+			if number < 0 then
+				((-number) lsl 1) + 1
+			else
+				number lsl 1
+		in
+		let rec loop vlq =
+			let shift = 5 in
+			let base = 1 lsl shift in
+			let mask = base - 1 in
+			let continuation_bit = base in
+			let digit = vlq land mask in
+			let next = vlq asr shift in
+			Rbuffer.add_char smap.mappings (encode_digit (
+				if next > 0 then digit lor continuation_bit else digit));
+			if next > 0 then loop next else ()
+		in
+		loop (to_vlq number)
+	in
+
+	base64_vlq (smap.output_current_col - smap.output_last_col);
+	base64_vlq (pos.file - smap.source_last_pos.file);
+	base64_vlq (pos.line - smap.source_last_pos.line);
+	base64_vlq (pos.col - smap.source_last_pos.col);
+
+	smap.source_last_pos <- pos;
+	smap.output_last_col <- smap.output_current_col
+
+let noop () = ()
+
+let add_mapping smap pos =
+	if pos.pmin < 0 then noop else
 
 
-let add_mapping smap force e =
-	if e.epos.pmin < 0 then () else
-	let pos = e.epos in
 	let file = try
 	let file = try
 		Hashtbl.find smap.sources_hash pos.pfile
 		Hashtbl.find smap.sources_hash pos.pfile
 	with Not_found ->
 	with Not_found ->
@@ -151,55 +199,23 @@ let add_mapping smap force e =
 		DynArray.add smap.sources pos.pfile;
 		DynArray.add smap.sources pos.pfile;
 		length
 		length
 	in
 	in
-	let line, col = Lexer.find_pos pos in
-	let line = line - 1 in
-	if force || smap.source_last_file != file || smap.source_last_line != line || smap.source_last_col != col then begin
-		smap.current_expr <- Some e;
-		if smap.print_comma then
-			Rbuffer.add_char smap.mappings ','
-		else
-			smap.print_comma <- true;
-
-		let base64_vlq number =
-			let encode_digit digit =
-				let chars = [|
-					'A';'B';'C';'D';'E';'F';'G';'H';'I';'J';'K';'L';'M';'N';'O';'P';
-					'Q';'R';'S';'T';'U';'V';'W';'X';'Y';'Z';'a';'b';'c';'d';'e';'f';
-					'g';'h';'i';'j';'k';'l';'m';'n';'o';'p';'q';'r';'s';'t';'u';'v';
-					'w';'x';'y';'z';'0';'1';'2';'3';'4';'5';'6';'7';'8';'9';'+';'/'
-				|] in
-				Array.unsafe_get chars digit
-			in
-			let to_vlq number =
-				if number < 0 then
-					((-number) lsl 1) + 1
-				else
-					number lsl 1
-			in
-			let rec loop vlq =
-				let shift = 5 in
-				let base = 1 lsl shift in
-				let mask = base - 1 in
-				let continuation_bit = base in
-				let digit = vlq land mask in
-				let next = vlq asr shift in
-				Rbuffer.add_char smap.mappings (encode_digit (
-					if next > 0 then digit lor continuation_bit else digit));
-				if next > 0 then loop next else ()
-			in
-			loop (to_vlq number)
-		in
 
 
-		base64_vlq (smap.output_current_col - smap.output_last_col);
-		base64_vlq (file - smap.source_last_file);
-		base64_vlq (line - smap.source_last_line);
-		base64_vlq (col - smap.source_last_col);
+	let pos =
+		let line, col = Lexer.find_pos pos in
+		let line = line - 1 in
+		{ file = file; line = line; col = col }
+	in
+
+	if smap.source_last_pos <> pos then begin
+		let old_current_expr = smap.current_expr in
+		smap.current_expr <- Some pos;
+		encode_mapping smap pos;
+		(fun () -> smap.current_expr <- old_current_expr)
+	end else
+		noop
 
 
-		smap.source_last_file <- file;
-		smap.source_last_line <- line;
-		smap.source_last_col <- col;
-		smap.output_last_col <- smap.output_current_col
-	end
+let add_mapping ctx e =
+	Option.map_default (fun smap -> add_mapping smap e.epos) noop ctx.smap
 
 
 let handle_newlines ctx str =
 let handle_newlines ctx str =
 	Option.may (fun smap ->
 	Option.may (fun smap ->
@@ -210,7 +226,7 @@ let handle_newlines ctx str =
 				smap.output_last_col <- 0;
 				smap.output_last_col <- 0;
 				smap.output_current_col <- 0;
 				smap.output_current_col <- 0;
 				smap.print_comma <- false;
 				smap.print_comma <- false;
-				Option.may (fun e -> add_mapping smap true e) smap.current_expr;
+				Option.may (encode_mapping smap) smap.current_expr;
 				loop next
 				loop next
 			end with Not_found ->
 			end with Not_found ->
 				smap.output_current_col <- smap.output_current_col + (String.length str - from);
 				smap.output_current_col <- smap.output_current_col + (String.length str - from);
@@ -288,7 +304,7 @@ let fun_block ctx f p =
 	let e = List.fold_left (fun e (a,c) ->
 	let e = List.fold_left (fun e (a,c) ->
 		match c with
 		match c with
 		| None | Some TNull -> e
 		| None | Some TNull -> e
-		| Some c -> Type.concat (Codegen.set_default ctx.com a c p) e
+		| Some c -> Type.concat (Texpr.set_default ctx.com.basic a c p) e
 	) f.tf_expr f.tf_args in
 	) f.tf_expr f.tf_args in
 	e
 	e
 
 
@@ -336,6 +352,9 @@ let gen_constant ctx p = function
 	| TThis -> spr ctx (this ctx)
 	| TThis -> spr ctx (this ctx)
 	| TSuper -> assert false
 	| TSuper -> assert false
 
 
+let print_deprecation_message com msg p =
+	com.warning msg p
+
 let rec gen_call ctx e el in_value =
 let rec gen_call ctx e el in_value =
 	match e.eexpr , el with
 	match e.eexpr , el with
 	| TConst TSuper , params ->
 	| TConst TSuper , params ->
@@ -362,46 +381,26 @@ let rec gen_call ctx e el in_value =
 		spr ctx "(";
 		spr ctx "(";
 		concat ctx "," (gen_value ctx) el;
 		concat ctx "," (gen_value ctx) el;
 		spr ctx ")";
 		spr ctx ")";
-	| TIdent "__new__", { eexpr = TConst (TString cl) } :: params ->
-		print ctx "new %s(" cl;
-		concat ctx "," (gen_value ctx) params;
-		spr ctx ")";
-	| TIdent "__new__", e :: params ->
-		spr ctx "new ";
-		gen_value ctx e;
-		spr ctx "(";
-		concat ctx "," (gen_value ctx) params;
-		spr ctx ")";
-	| TIdent "__js__", [{ eexpr = TConst (TString "this") }] ->
-		spr ctx (this ctx)
-	| TIdent "__js__", [{ eexpr = TConst (TString code) }] ->
-		spr ctx (String.concat "\n" (ExtString.String.nsplit code "\r\n"))
-	| TIdent "__js__", { eexpr = TConst (TString code); epos = p } :: tl ->
-		Codegen.interpolate_code ctx.com code tl (spr ctx) (gen_expr ctx) p
-	| TIdent "__instanceof__",  [o;t] ->
-		spr ctx "(";
-		gen_value ctx o;
-		print ctx " instanceof ";
-		gen_value ctx t;
-		spr ctx ")";
-	| TIdent "__typeof__",  [o] ->
-		spr ctx "typeof(";
-		gen_value ctx o;
-		spr ctx ")";
-	| TIdent "__strict_eq__" , [x;y] ->
-		(* add extra parenthesis here because of operator precedence *)
-		spr ctx "((";
-		gen_value ctx x;
-		spr ctx ") === ";
-		gen_value ctx y;
-		spr ctx ")";
-	| TIdent "__strict_neq__" , [x;y] ->
-		(* add extra parenthesis here because of operator precedence *)
-		spr ctx "((";
-		gen_value ctx x;
-		spr ctx ") !== ";
-		gen_value ctx y;
-		spr ctx ")";
+	| TField (_, FStatic ({ cl_path = ["js"],"Syntax" }, { cf_name = meth })), args ->
+		gen_syntax ctx meth args e.epos
+	| TIdent "__new__", args ->
+		print_deprecation_message ctx.com "__new__ is deprecated, use js.Syntax.new_ instead" e.epos;
+		gen_syntax ctx "new_" args e.epos
+	| TIdent "__js__", args ->
+		(* TODO: add deprecation warning when we figure out what to do with purity here *)
+		gen_syntax ctx "code" args e.epos
+	| TIdent "__instanceof__",  args ->
+		print_deprecation_message ctx.com "__instanceof__ is deprecated, use js.Syntax.instanceof instead" e.epos;
+		gen_syntax ctx "instanceof" args e.epos
+	| TIdent "__typeof__",  args ->
+		print_deprecation_message ctx.com "__typeof__ is deprecated, use js.Syntax.typeof instead" e.epos;
+		gen_syntax ctx "typeof" args e.epos
+	| TIdent "__strict_eq__" , args ->
+		print_deprecation_message ctx.com "__strict_eq__ is deprecated, use js.Syntax.strictEq instead" e.epos;
+		gen_syntax ctx "strictEq" args e.epos
+	| TIdent "__strict_neq__" , args ->
+		print_deprecation_message ctx.com "__strict_neq__ is deprecated, use js.Syntax.strictNeq instead" e.epos;
+		gen_syntax ctx "strictNeq" args e.epos
 	| TIdent "__define_feature__", [_;e] ->
 	| TIdent "__define_feature__", [_;e] ->
 		gen_expr ctx e
 		gen_expr ctx e
 	| TIdent "__feature__", { eexpr = TConst (TString f) } :: eif :: eelse ->
 	| TIdent "__feature__", { eexpr = TConst (TString f) } :: eif :: eelse ->
@@ -410,8 +409,6 @@ let rec gen_call ctx e el in_value =
 		else match eelse with
 		else match eelse with
 			| [] -> ()
 			| [] -> ()
 			| e :: _ -> gen_value ctx e)
 			| e :: _ -> gen_value ctx e)
-	| TIdent "__rethrow__", [] ->
-		spr ctx "throw $hx_rethrow";
 	| TIdent "__resources__", [] ->
 	| TIdent "__resources__", [] ->
 		spr ctx "[";
 		spr ctx "[";
 		concat ctx "," (fun (name,data) ->
 		concat ctx "," (fun (name,data) ->
@@ -436,14 +433,19 @@ let rec gen_call ctx e el in_value =
 			spr ctx "console.log(";
 			spr ctx "console.log(";
 			(match infos.eexpr with
 			(match infos.eexpr with
 			| TObjectDecl (
 			| TObjectDecl (
-				("fileName" , { eexpr = (TConst (TString file)) }) ::
-				("lineNumber" , { eexpr = (TConst (TInt line)) }) :: _) ->
+				(("fileName",_,_) , { eexpr = (TConst (TString file)) }) ::
+				(("lineNumber",_,_) , { eexpr = (TConst (TInt line)) }) :: _) ->
 					print ctx "\"%s:%i:\"," file (Int32.to_int line)
 					print ctx "\"%s:%i:\"," file (Int32.to_int line)
 			| _ ->
 			| _ ->
 				());
 				());
 			gen_value ctx e;
 			gen_value ctx e;
 			spr ctx ")";
 			spr ctx ")";
 		end
 		end
+	| TField (x,f), [] when field_name f = "iterator" && is_dynamic_iterator ctx e ->
+		add_feature ctx "use.$getIterator";
+		print ctx "$getIterator(";
+		gen_value ctx x;
+		print ctx ")";
 	| _ ->
 	| _ ->
 		gen_value ctx e;
 		gen_value ctx e;
 		spr ctx "(";
 		spr ctx "(";
@@ -464,7 +466,7 @@ and add_objectdecl_parens e =
 	loop e
 	loop e
 
 
 and gen_expr ctx e =
 and gen_expr ctx e =
-	Option.may (fun smap -> add_mapping smap false e) ctx.smap;
+	let clear_mapping = add_mapping ctx e in
 	(match e.eexpr with
 	(match e.eexpr with
 	| TConst c -> gen_constant ctx e.epos c
 	| TConst c -> gen_constant ctx e.epos c
 	| TLocal v -> spr ctx (ident v.v_name)
 	| TLocal v -> spr ctx (ident v.v_name)
@@ -490,6 +492,17 @@ and gen_expr ctx e =
 		print ctx "$iterator(";
 		print ctx "$iterator(";
 		gen_value ctx x;
 		gen_value ctx x;
 		print ctx ")";
 		print ctx ")";
+	(* Don't generate `$iterator(value)` for exprs like `value.iterator--` *)
+	| TUnop (op,flag,({eexpr = TField (x,f)} as fe)) when field_name f = "iterator" && is_dynamic_iterator ctx fe ->
+		(match flag with
+			| Prefix ->
+				spr ctx (Ast.s_unop op);
+				gen_value ctx x;
+				spr ctx ".iterator"
+			| Postfix ->
+				gen_value ctx x;
+				spr ctx ".iterator";
+				spr ctx (Ast.s_unop op))
 	| TField (x,FClosure (Some ({cl_path=[],"Array"},_), {cf_name="push"})) ->
 	| TField (x,FClosure (Some ({cl_path=[],"Array"},_), {cf_name="push"})) ->
 		(* see https://github.com/HaxeFoundation/haxe/issues/1997 *)
 		(* see https://github.com/HaxeFoundation/haxe/issues/1997 *)
 		add_feature ctx "use.$arrayPush";
 		add_feature ctx "use.$arrayPush";
@@ -654,9 +667,9 @@ and gen_expr ctx e =
 		ctx.in_loop <- old_in_loop
 		ctx.in_loop <- old_in_loop
 	| TObjectDecl fields ->
 	| TObjectDecl fields ->
 		spr ctx "{ ";
 		spr ctx "{ ";
-		concat ctx ", " (fun (f,e) -> (match e.eexpr with
-			| TMeta((Meta.QuotedField,_,_),e) -> print ctx "\"%s\" : " (Ast.s_escape f);
-			| _ -> print ctx "%s : " (anon_field f));
+		concat ctx ", " (fun ((f,_,qs),e) -> (match qs with
+			| DoubleQuotes -> print ctx "\"%s\" : " (Ast.s_escape f);
+			| NoQuotes -> print ctx "%s : " (anon_field f));
 			gen_value ctx e
 			gen_value ctx e
 		) fields;
 		) fields;
 		spr ctx "}";
 		spr ctx "}";
@@ -685,110 +698,14 @@ and gen_expr ctx e =
 		newline ctx;
 		newline ctx;
 		spr ctx "}";
 		spr ctx "}";
 		ctx.in_loop <- old_in_loop
 		ctx.in_loop <- old_in_loop
-	| TTry (e,catchs) ->
+	| TTry (etry,[(v,ecatch)]) ->
 		spr ctx "try ";
 		spr ctx "try ";
-		gen_expr ctx e;
-		let vname = (match catchs with [(v,_)] -> check_var_declaration v; v.v_name | _ ->
-			let id = ctx.id_counter in
-			ctx.id_counter <- ctx.id_counter + 1;
-			"$e" ^ string_of_int id
-		) in
-		print ctx " catch( %s ) {" vname;
-		let bend = open_block ctx in
-		let last = ref false in
-		let else_block = ref false in
-
-		if ctx.store_exception_stack then begin
-			newline ctx;
-			print ctx "%s.lastException = %s" (ctx.type_accessor (TClassDecl { null_class with cl_path = ["haxe"],"CallStack" })) vname
-		end;
-
-		if (has_feature ctx "js.Lib.rethrow") then begin
-			let has_rethrow (_,e) =
-				let rec loop e = match e.eexpr with
-				| TCall({eexpr = TIdent "__rethrow__"}, []) -> raise Exit
-				| _ -> Type.iter loop e
-				in
-				try (loop e; false) with Exit -> true
-			in
-			if List.exists has_rethrow catchs then begin
-				newline ctx;
-				print ctx "var $hx_rethrow = %s" vname;
-			end
-		end;
-
-		if (has_feature ctx "js.Boot.HaxeError") then begin
-			let catch_var_used =
-				try
-					List.iter (fun (v,e) ->
-						match follow v.v_type with
-						| TDynamic _ -> (* Dynamic catch - unrap if the catch value is used *)
-							let rec loop e = match e.eexpr with
-							| TLocal v2 when v2 == v -> raise Exit
-							| _ -> Type.iter loop e
-							in
-							loop e
-						| _ -> (* not a Dynamic catch - we need to unwrap the error for type-checking *)
-							raise Exit
-					) catchs;
-					false
-				with Exit ->
-					true
-			in
-			if catch_var_used then begin
-				newline ctx;
-				print ctx "if (%s instanceof %s) %s = %s.val" vname (ctx.type_accessor (TClassDecl { null_class with cl_path = ["js";"_Boot"],"HaxeError" })) vname vname;
-			end;
-		end;
-
-		List.iter (fun (v,e) ->
-			if !last then () else
-			let t = (match follow v.v_type with
-			| TEnum (e,_) -> Some (TEnumDecl e)
-			| TInst (c,_) -> Some (TClassDecl c)
-			| TAbstract (a,_) -> Some (TAbstractDecl a)
-			| TFun _
-			| TLazy _
-			| TType _
-			| TAnon _ ->
-				assert false
-			| TMono _
-			| TDynamic _ ->
-				None
-			) in
-			match t with
-			| None ->
-				last := true;
-				if !else_block then print ctx "{";
-				if vname <> v.v_name then begin
-					newline ctx;
-					print ctx "var %s = %s" v.v_name vname;
-				end;
-				gen_block_element ctx e;
-				if !else_block then begin
-					newline ctx;
-					print ctx "}";
-				end
-			| Some t ->
-				if not !else_block then newline ctx;
-				print ctx "if( %s.__instanceof(%s," (ctx.type_accessor (TClassDecl { null_class with cl_path = ["js"],"Boot" })) vname;
-				gen_value ctx (mk (TTypeExpr t) (mk_mono()) e.epos);
-				spr ctx ") ) {";
-				let bend = open_block ctx in
-				if vname <> v.v_name then begin
-					newline ctx;
-					print ctx "var %s = %s" v.v_name vname;
-				end;
-				gen_block_element ctx e;
-				bend();
-				newline ctx;
-				spr ctx "} else ";
-				else_block := true
-		) catchs;
-		if not !last then print ctx "throw(%s)" vname;
-		bend();
-		newline ctx;
-		spr ctx "}";
+		gen_expr ctx etry;
+		check_var_declaration v;
+		print ctx " catch( %s ) " v.v_name;
+		gen_expr ctx ecatch
+	| TTry _ ->
+		abort "Unhandled try/catch, please report" e.epos
 	| TSwitch (e,cases,def) ->
 	| TSwitch (e,cases,def) ->
 		spr ctx "switch";
 		spr ctx "switch";
 		gen_value ctx e;
 		gen_value ctx e;
@@ -834,8 +751,7 @@ and gen_expr ctx e =
 	| TIdent s ->
 	| TIdent s ->
 		spr ctx s
 		spr ctx s
 	);
 	);
-	Option.may (fun smap -> smap.current_expr <- None) ctx.smap
-
+	clear_mapping ()
 
 
 and gen_block_element ?(after=false) ctx e =
 and gen_block_element ?(after=false) ctx e =
 	match e.eexpr with
 	match e.eexpr with
@@ -858,7 +774,7 @@ and gen_block_element ?(after=false) ctx e =
 		if after then newline ctx
 		if after then newline ctx
 
 
 and gen_value ctx e =
 and gen_value ctx e =
-	Option.may (fun smap -> add_mapping smap false e) ctx.smap;
+	let clear_mapping = add_mapping ctx e in
 	let assign e =
 	let assign e =
 		mk (TBinop (Ast.OpAssign,
 		mk (TBinop (Ast.OpAssign,
 			mk (TLocal (match ctx.in_value with None -> assert false | Some v -> v)) t_dynamic e.epos,
 			mk (TLocal (match ctx.in_value with None -> assert false | Some v -> v)) t_dynamic e.epos,
@@ -972,8 +888,71 @@ and gen_value ctx e =
 			List.map (fun (v,e) -> v, block (assign e)) catchs
 			List.map (fun (v,e) -> v, block (assign e)) catchs
 		)) e.etype e.epos);
 		)) e.etype e.epos);
 		v());
 		v());
-	Option.may (fun smap -> smap.current_expr <- None) ctx.smap
+	clear_mapping ()
 
 
+and gen_syntax ctx meth args pos =
+	match meth, args with
+	| "new_", cl :: params ->
+		spr ctx "new ";
+		begin
+			match cl.eexpr with
+			| TConst (TString cl) ->
+				spr ctx cl
+			| _ ->
+				gen_value ctx cl
+		end;
+		spr ctx "(";
+		concat ctx "," (gen_value ctx) params;
+		spr ctx ")"
+	| "instanceof", [o;t] ->
+		spr ctx "(";
+		gen_value ctx o;
+		print ctx " instanceof ";
+		gen_value ctx t;
+		spr ctx ")"
+	| "typeof", [o] ->
+		spr ctx "typeof(";
+		gen_value ctx o;
+		spr ctx ")"
+	| "strictEq" , [x;y] ->
+		(* add extra parenthesis here because of operator precedence *)
+		spr ctx "((";
+		gen_value ctx x;
+		spr ctx ") === ";
+		gen_value ctx y;
+		spr ctx ")";
+	| "strictNeq" , [x;y] ->
+		(* add extra parenthesis here because of operator precedence *)
+		spr ctx "((";
+		gen_value ctx x;
+		spr ctx ") !== ";
+		gen_value ctx y;
+		spr ctx ")";
+	| "delete" , [o;f] ->
+		spr ctx "delete(";
+		gen_value ctx o;
+		spr ctx "[";
+		gen_value ctx f;
+		spr ctx "]";
+		spr ctx ")";
+	| "code", code :: args ->
+		let code, code_pos =
+			match code.eexpr with
+			| TConst (TString s) -> s, code.epos
+			| _ -> abort "The `code` argument for js.Syntax must be a string constant" code.epos
+		in
+		begin
+			match args with
+			| [] ->
+				if code = "this" then
+					spr ctx (this ctx)
+				else
+					spr ctx (String.concat "\n" (ExtString.String.nsplit code "\r\n"))
+			| _ ->
+				Codegen.interpolate_code ctx.com code args (spr ctx) (gen_expr ctx) code_pos
+		end
+	| _ ->
+		abort (Printf.sprintf "Unknown js.Syntax method `%s` with %d arguments" meth (List.length args)) pos
 
 
 let generate_package_create ctx (p,_) =
 let generate_package_create ctx (p,_) =
 	let rec loop acc = function
 	let rec loop acc = function
@@ -1224,7 +1203,7 @@ let generate_enum ctx e =
 		print ctx "%s.__empty_constructs__ = [%s]" p (String.concat "," (List.map (fun s -> Printf.sprintf "%s.%s" p s) ctors_without_args));
 		print ctx "%s.__empty_constructs__ = [%s]" p (String.concat "," (List.map (fun s -> Printf.sprintf "%s.%s" p s) ctors_without_args));
 		newline ctx
 		newline ctx
 	end;
 	end;
-	begin match Codegen.build_metadata ctx.com (TEnumDecl e) with
+	begin match Texpr.build_metadata ctx.com.basic (TEnumDecl e) with
 	| None -> ()
 	| None -> ()
 	| Some e ->
 	| Some e ->
 		print ctx "%s.__meta__ = " p;
 		print ctx "%s.__meta__ = " p;
@@ -1290,9 +1269,7 @@ let alloc_ctx com =
 	let smap =
 	let smap =
 		if com.debug || Common.defined com Define.JsSourceMap then
 		if com.debug || Common.defined com Define.JsSourceMap then
 			Some {
 			Some {
-				source_last_line = 0;
-				source_last_col = 0;
-				source_last_file = 0;
+				source_last_pos = { file = 0; line = 0; col = 0};
 				print_comma = false;
 				print_comma = false;
 				output_last_col = 0;
 				output_last_col = 0;
 				output_current_col = 0;
 				output_current_col = 0;
@@ -1313,7 +1290,6 @@ 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 = (try int_of_string (Common.defined_value com Define.JsEs) with _ -> 0);
 		es_version = (try int_of_string (Common.defined_value com Define.JsEs) with _ -> 0);
-		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 = [];
 		current = null_class;
 		current = null_class;
@@ -1516,6 +1492,10 @@ let generate com =
 		print ctx "function $iterator(o) { if( o instanceof Array ) return function() { return HxOverrides.iter(o); }; return typeof(o.iterator) == 'function' ? $bind(o,o.iterator) : o.iterator; }";
 		print ctx "function $iterator(o) { if( o instanceof Array ) return function() { return HxOverrides.iter(o); }; return typeof(o.iterator) == 'function' ? $bind(o,o.iterator) : o.iterator; }";
 		newline ctx;
 		newline ctx;
 	end;
 	end;
+	if has_feature ctx "use.$getIterator" then begin
+		print ctx "function $getIterator(o) { if( o instanceof Array ) return HxOverrides.iter(o); else return o.iterator(); }";
+		newline ctx;
+	end;
 	if has_feature ctx "use.$bind" then begin
 	if has_feature ctx "use.$bind" then begin
 		print ctx "var $_, $fid = 0";
 		print ctx "var $_, $fid = 0";
 		newline ctx;
 		newline ctx;

+ 102 - 90
src/generators/genlua.ml

@@ -24,6 +24,7 @@ open Ast
 open Type
 open Type
 open Common
 open Common
 open ExtList
 open ExtList
+open Error
 
 
 type pos = Globals.pos
 type pos = Globals.pos
 
 
@@ -74,7 +75,7 @@ let get_exposed ctx path meta = try
         (match args with
         (match args with
          | [ EConst (String s), _ ] -> [s]
          | [ EConst (String s), _ ] -> [s]
          | [] -> [path]
          | [] -> [path]
-         | _ -> abort "Invalid @:expose parameters" pos)
+         | _ -> error "Invalid @:expose parameters" pos)
     with Not_found -> []
     with Not_found -> []
 
 
 let dot_path = Globals.s_type_path
 let dot_path = Globals.s_type_path
@@ -158,7 +159,7 @@ let println ctx =
             newline ctx
             newline ctx
         end)
         end)
 
 
-let unsupported p = abort "This expression cannot be compiled to Lua" p
+let unsupported p = error "This expression cannot be compiled to Lua" p
 
 
 let basename path =
 let basename path =
     try
     try
@@ -189,7 +190,7 @@ let fun_block ctx f p =
     let e = List.fold_left (fun e (a,c) ->
     let e = List.fold_left (fun e (a,c) ->
         match c with
         match c with
         | None | Some TNull -> e
         | None | Some TNull -> e
-        | Some c -> Type.concat (Codegen.set_default ctx.com a c p) e
+        | Some c -> Type.concat (Texpr.set_default ctx.com.basic a c p) e
     ) f.tf_expr f.tf_args in
     ) f.tf_expr f.tf_args in
     e
     e
 
 
@@ -243,7 +244,7 @@ let index_of f l =
 (* create a __lua__ call *)
 (* create a __lua__ call *)
 let mk_lua_code com code args t pos =
 let mk_lua_code com code args t pos =
     let lua_local = mk (TIdent "__lua__") t_dynamic pos in
     let lua_local = mk (TIdent "__lua__") t_dynamic pos in
-    let code_const = Codegen.ExprBuilder.make_string com code pos in
+    let code_const = Texpr.Builder.make_string com code pos in
     mk (TCall (lua_local, code_const :: args)) t pos
     mk (TCall (lua_local, code_const :: args)) t pos
 
 
 (* create a multi-return boxing call for given expr *)
 (* create a multi-return boxing call for given expr *)
@@ -257,7 +258,7 @@ let mk_mr_box ctx e =
     add_feature ctx "use._hx_box_mr";
     add_feature ctx "use._hx_box_mr";
     add_feature ctx "use._hx_table";
     add_feature ctx "use._hx_table";
     let code = Printf.sprintf "_hx_box_mr(_hx_table.pack({0}), {%s})" s_fields in
     let code = Printf.sprintf "_hx_box_mr(_hx_table.pack({0}), {%s})" s_fields in
-    mk_lua_code ctx.com code [e] e.etype e.epos
+    mk_lua_code ctx.com.basic code [e] e.etype e.epos
 
 
 (* create a multi-return select call for given expr and field name *)
 (* create a multi-return select call for given expr and field name *)
 let mk_mr_select com e ecall name =
 let mk_mr_select com e ecall name =
@@ -337,44 +338,66 @@ let gen_constant ctx p = function
     | TThis -> spr ctx (this ctx)
     | TThis -> spr ctx (this ctx)
     | TSuper -> assert false
     | TSuper -> assert false
 
 
-let rec gen_call ctx e el =
+
+let rec is_function_type t = match follow(t) with
+        | TFun _ -> true
+        | _ -> false
+
+and gen_argument ctx e = begin
+    match e.eexpr with
+    | TField (x,(FInstance (_,_,f) | FAnon(f)))  when (is_function_type e.etype) ->
+            add_feature ctx "use._hx_bind";
+            print ctx "_hx_bind(";
+            gen_value ctx x;
+            print ctx ",";
+            gen_value ctx x;
+            print ctx "%s)" (if Meta.has Meta.SelfCall f.cf_meta then "" else (field f.cf_name))
+    | _ ->
+        gen_value ctx e;
+end
+
+and gen_paren_arguments ctx el = begin
+    spr ctx "(";
+    concat ctx ", " (gen_argument ctx) el;
+    spr ctx ")";
+end
+
+and gen_call ctx e el =
     ctx.iife_assign <- true;
     ctx.iife_assign <- true;
     (match e.eexpr , el with
     (match e.eexpr , el with
      | TConst TSuper , params ->
      | TConst TSuper , params ->
          (match ctx.current.cl_super with
          (match ctx.current.cl_super with
-          | None -> abort "Missing api.setCurrentClass" e.epos
+          | None -> error "Missing api.setCurrentClass" e.epos
           | Some (c,_) ->
           | Some (c,_) ->
               print ctx "%s.super(%s" (ctx.type_accessor (TClassDecl c)) (this ctx);
               print ctx "%s.super(%s" (ctx.type_accessor (TClassDecl c)) (this ctx);
-              List.iter (fun p -> print ctx ","; gen_value ctx p) params;
+              List.iter (fun p -> print ctx ","; gen_argument ctx p) params;
               spr ctx ")";
               spr ctx ")";
          );
          );
      | TField ({ eexpr = TConst TSuper },f) , params ->
      | TField ({ eexpr = TConst TSuper },f) , params ->
          (match ctx.current.cl_super with
          (match ctx.current.cl_super with
-          | None -> abort "Missing api.setCurrentClass" e.epos
+          | None -> error "Missing api.setCurrentClass" e.epos
           | Some (c,_) ->
           | Some (c,_) ->
               let name = field_name f in
               let name = field_name f in
               print ctx "%s.prototype%s(%s" (ctx.type_accessor (TClassDecl c)) (field name) (this ctx);
               print ctx "%s.prototype%s(%s" (ctx.type_accessor (TClassDecl c)) (field name) (this ctx);
-              List.iter (fun p -> print ctx ","; gen_value ctx p) params;
+              List.iter (fun p -> print ctx ","; gen_argument ctx p) params;
               spr ctx ")";
               spr ctx ")";
          );
          );
      | TCall (x,_) , el when (match x.eexpr with TIdent "__lua__" -> false | _ -> true) ->
      | TCall (x,_) , el when (match x.eexpr with TIdent "__lua__" -> false | _ -> true) ->
          gen_paren ctx [e];
          gen_paren ctx [e];
-         gen_paren ctx el;
+         gen_paren_arguments ctx el;
      | TIdent "__new__", { eexpr = TConst (TString cl) } :: params ->
      | TIdent "__new__", { eexpr = TConst (TString cl) } :: params ->
-         print ctx "%s.new(" cl;
-         concat ctx "," (gen_value ctx) params;
-         spr ctx ")";
+         print ctx "%s.new" cl;
+         gen_paren_arguments ctx params;
      | TIdent "__new__", e :: params ->
      | TIdent "__new__", e :: params ->
          gen_value ctx e;
          gen_value ctx e;
-         spr ctx ".new(";
-         concat ctx "," (gen_value ctx) params;
-         spr ctx ")";
+         spr ctx ".new";
+         gen_paren_arguments ctx params;
      | TIdent "__callself__", { eexpr = TConst (TString head) } :: { eexpr = TConst (TString tail) } :: el ->
      | TIdent "__callself__", { eexpr = TConst (TString head) } :: { eexpr = TConst (TString tail) } :: el ->
          print ctx "%s:%s" head tail;
          print ctx "%s:%s" head tail;
-         gen_paren ctx el;
+         gen_paren_arguments ctx el;
      | TIdent "__call__", { eexpr = TConst (TString code) } :: el ->
      | TIdent "__call__", { eexpr = TConst (TString code) } :: el ->
          spr ctx code;
          spr ctx code;
-         gen_paren ctx el;
+         gen_paren_arguments ctx el;
      | TIdent "__lua_length__", [e]->
      | TIdent "__lua_length__", [e]->
          spr ctx "#"; gen_value ctx e;
          spr ctx "#"; gen_value ctx e;
      | TIdent "__lua_table__", el ->
      | TIdent "__lua_table__", el ->
@@ -388,14 +411,14 @@ let rec gen_call ctx e el =
                   if List.length(arr) > 0 then incr count;
                   if List.length(arr) > 0 then incr count;
               | { eexpr = TObjectDecl fields } ->
               | { eexpr = TObjectDecl fields } ->
                   if (!count > 0 && List.length(fields) > 0) then spr ctx ",";
                   if (!count > 0 && List.length(fields) > 0) then spr ctx ",";
-                  concat ctx ", " (fun (f,e) ->
+                  concat ctx ", " (fun ((f,_,_),e) ->
                       print ctx "%s = " (anon_field f);
                       print ctx "%s = " (anon_field f);
                       gen_value ctx e
                       gen_value ctx e
                   ) fields;
                   ) fields;
                   if List.length(fields) > 0 then incr count;
                   if List.length(fields) > 0 then incr count;
               | { eexpr = TConst(TNull)} -> ()
               | { eexpr = TConst(TNull)} -> ()
               | _ ->
               | _ ->
-                  abort "__lua_table__ only accepts array or anonymous object arguments" e.epos;
+                  error "__lua_table__ only accepts array or anonymous object arguments" e.epos;
              )) el;
              )) el;
          spr ctx "})";
          spr ctx "})";
      | TIdent "__lua__", [{ eexpr = TConst (TString code) }] ->
      | TIdent "__lua__", [{ eexpr = TConst (TString code) }] ->
@@ -457,7 +480,7 @@ let rec gen_call ctx e el =
          gen_value ctx e;
          gen_value ctx e;
          print ctx ",'%s'" (field_name ef);
          print ctx ",'%s'" (field_name ef);
          spr ctx ")(";
          spr ctx ")(";
-         concat ctx "," (gen_value ctx) (e::el);
+         concat ctx "," (gen_argument ctx) (e::el);
          spr ctx ")";
          spr ctx ")";
      | TField (e, ((FInstance _ | FAnon _ | FDynamic _) as ef)), el ->
      | TField (e, ((FInstance _ | FAnon _ | FDynamic _) as ef)), el ->
          let s = (field_name ef) in
          let s = (field_name ef) in
@@ -467,7 +490,7 @@ let rec gen_call ctx e el =
              gen_value ctx e;
              gen_value ctx e;
              print ctx ",\"%s\"" (field_name ef);
              print ctx ",\"%s\"" (field_name ef);
              if List.length(el) > 0 then spr ctx ",";
              if List.length(el) > 0 then spr ctx ",";
-             concat ctx "," (gen_value ctx) el;
+             concat ctx "," (gen_argument ctx) el;
              spr ctx ")";
              spr ctx ")";
          end else begin
          end else begin
              gen_value ctx e;
              gen_value ctx e;
@@ -475,11 +498,11 @@ let rec gen_call ctx e el =
                  print ctx ".%s" (field_name ef)
                  print ctx ".%s" (field_name ef)
              else
              else
                  print ctx ":%s" (field_name ef);
                  print ctx ":%s" (field_name ef);
-             gen_paren ctx el;
+             gen_paren_arguments ctx el;
          end;
          end;
      | _ ->
      | _ ->
          gen_value ctx e;
          gen_value ctx e;
-         gen_paren ctx el);
+         gen_paren_arguments ctx el);
     ctx.iife_assign <- false;
     ctx.iife_assign <- false;
 
 
 and has_continue e =
 and has_continue e =
@@ -562,6 +585,23 @@ and is_possible_string_field e field_name=
             false
             false
 
 
 
 
+and ttype_multireturn t = match t with
+    | TInst (c,_) ->
+            Meta.has Meta.MultiReturn c.cl_meta
+    | TType (c,_) ->
+            Meta.has Meta.MultiReturn c.t_meta
+    | _ ->
+            false
+and check_multireturn_param ctx t pos =
+   match t with
+         TAbstract(_,p) | TInst(_,p) ->
+            if List.exists ttype_multireturn p then
+                error "MultiReturns must not be type parameters" pos
+            else
+                ()
+        | _ ->
+                ();
+
 and gen_expr ?(local=true) ctx e = begin
 and gen_expr ?(local=true) ctx e = begin
     match e.eexpr with
     match e.eexpr with
       TConst c ->
       TConst c ->
@@ -623,7 +663,7 @@ and gen_expr ?(local=true) ctx e = begin
         spr ctx "(function(x) return x.";
         spr ctx "(function(x) return x.";
         print ctx "%s" (field_name ef);
         print ctx "%s" (field_name ef);
         spr ctx " end )({";
         spr ctx " end )({";
-        concat ctx ", " (fun (f,e) -> print ctx "%s = " (anon_field f); gen_value ctx e) fields;
+        concat ctx ", " (fun ((f,_,_),e) -> print ctx "%s = " (anon_field f); gen_value ctx e) fields;
         spr ctx "})";
         spr ctx "})";
     | TField ({eexpr = TLocal v}, f) when Meta.has Meta.MultiReturn v.v_meta ->
     | TField ({eexpr = TLocal v}, f) when Meta.has Meta.MultiReturn v.v_meta ->
         (* field of a multireturn local var is actually just a local var *)
         (* field of a multireturn local var is actually just a local var *)
@@ -860,9 +900,9 @@ and gen_expr ?(local=true) ctx e = begin
         ctx.separator <- true
         ctx.separator <- true
     | TObjectDecl fields ->
     | TObjectDecl fields ->
         spr ctx "_hx_o({__fields__={";
         spr ctx "_hx_o({__fields__={";
-        concat ctx "," (fun (f,e) -> print ctx "%s=" (anon_field f); spr ctx "true") fields;
+        concat ctx "," (fun ((f,_,_),e) -> print ctx "%s=" (anon_field f); spr ctx "true") fields;
         spr ctx "},";
         spr ctx "},";
-        concat ctx "," (fun (f,e) -> print ctx "%s=" (anon_field f); gen_anon_value ctx e) fields;
+        concat ctx "," (fun ((f,_,_),e) -> print ctx "%s=" (anon_field f); gen_anon_value ctx e) fields;
         spr ctx "})";
         spr ctx "})";
         ctx.separator <- true
         ctx.separator <- true
     | TFor (v,it,e2) ->
     | TFor (v,it,e2) ->
@@ -1070,7 +1110,7 @@ and gen_anon_value ctx e =
         ctx.in_value <- fst old;
         ctx.in_value <- fst old;
         ctx.in_loop <- snd old;
         ctx.in_loop <- snd old;
         ctx.separator <- true
         ctx.separator <- true
-    | _ when (is_function_type ctx e.etype) && not (is_const_null e) ->
+    | _ when (is_function_type e.etype) && not (is_const_null e) ->
         spr ctx "function(_,...) return ";
         spr ctx "function(_,...) return ";
         gen_value ctx e;
         gen_value ctx e;
         spr ctx "(...) end";
         spr ctx "(...) end";
@@ -1214,11 +1254,6 @@ and gen_value ctx e =
                                         )) e.etype e.epos);
                                         )) e.etype e.epos);
         v()
         v()
 
 
-and is_function_type ctx t =
-    match follow(t) with
-    | TFun _ -> true
-    | _ -> false;
-
 and gen_tbinop ctx op e1 e2 =
 and gen_tbinop ctx op e1 e2 =
     (match op, e1.eexpr, e2.eexpr with
     (match op, e1.eexpr, e2.eexpr with
      | Ast.OpAssign, TField(e3, FInstance _), TFunction f ->
      | Ast.OpAssign, TField(e3, FInstance _), TFunction f ->
@@ -1263,7 +1298,7 @@ and gen_tbinop ctx op e1 e2 =
               spr ctx "_hx_funcToField(";
               spr ctx "_hx_funcToField(";
               gen_value ctx e2;
               gen_value ctx e2;
               spr ctx ")";
               spr ctx ")";
-          | TField(_, FInstance _ ), TLocal t  when (is_function_type ctx t.v_type)   ->
+          | TField(_, FInstance _ ), TLocal t  when (is_function_type t.v_type)   ->
               gen_value ctx e1;
               gen_value ctx e1;
               print ctx " %s " (Ast.s_binop op);
               print ctx " %s " (Ast.s_binop op);
               add_feature ctx "use._hx_funcToField";
               add_feature ctx "use._hx_funcToField";
@@ -1393,7 +1428,7 @@ and gen_return ctx e eo =
          spr ctx "do return end"
          spr ctx "do return end"
      | Some e ->
      | Some e ->
          (match e.eexpr with
          (match e.eexpr with
-          | TField (e2, ((FClosure (_, tcf) | FAnon tcf |FInstance (_,_,tcf)))) when is_function_type ctx tcf.cf_type ->
+          | TField (e2, ((FClosure (_, tcf) | FAnon tcf |FInstance (_,_,tcf)))) when (is_function_type tcf.cf_type) ->
               (* See issue #6259 *)
               (* See issue #6259 *)
               add_feature ctx "use._hx_bind";
               add_feature ctx "use._hx_bind";
               spr ctx "do return ";
               spr ctx "do return ";
@@ -1436,40 +1471,20 @@ let check_multireturn ctx c =
     match c with
     match c with
     | _ when Meta.has Meta.MultiReturn c.cl_meta ->
     | _ when Meta.has Meta.MultiReturn c.cl_meta ->
         if not c.cl_extern then
         if not c.cl_extern then
-            abort "MultiReturns must be externs" c.cl_pos
+            error "MultiReturns must be externs" c.cl_pos
         else if List.length c.cl_ordered_statics > 0 then
         else if List.length c.cl_ordered_statics > 0 then
-            abort "MultiReturns must not contain static fields" c.cl_pos
+            error "MultiReturns must not contain static fields" c.cl_pos
         else if (List.exists (fun cf -> match cf.cf_kind with Method _ -> true | _-> false) c.cl_ordered_fields) then
         else if (List.exists (fun cf -> match cf.cf_kind with Method _ -> true | _-> false) c.cl_ordered_fields) then
-            abort "MultiReturns must not contain methods" c.cl_pos;
+            error "MultiReturns must not contain methods" c.cl_pos;
     | {cl_super = Some(csup,_)} when Meta.has Meta.MultiReturn csup.cl_meta ->
     | {cl_super = Some(csup,_)} when Meta.has Meta.MultiReturn csup.cl_meta ->
-        abort "Cannot extend a MultiReturn" c.cl_pos
+        error "Cannot extend a MultiReturn" c.cl_pos
     | _ -> ()
     | _ -> ()
 
 
 
 
-let generate_package_create ctx (p,_) =
-    let rec loop acc = function
-        | [] -> ()
-        | p :: l when Hashtbl.mem ctx.packages (p :: acc) -> loop (p :: acc) l
-        | p :: l ->
-            Hashtbl.add ctx.packages (p :: acc) ();
-            (match acc with
-             | [] -> print ctx "local %s = {}" p
-             | _ ->
-                 let p = String.concat "." (List.rev acc) ^ (field p) in
-                 print ctx "%s = {}" p
-            );
-            ctx.separator <- true;
-            newline ctx;
-            loop (p :: acc) l
-    in
-    match p with
-    | [] -> print ctx "local "
-    | _ -> loop [] p
-
 let check_field_name c f =
 let check_field_name c f =
     match f.cf_name with
     match f.cf_name with
     | "prototype" | "__proto__" | "constructor" ->
     | "prototype" | "__proto__" | "constructor" ->
-        abort ("The field name '" ^ f.cf_name ^ "'  is not allowed in Lua") (match f.cf_expr with None -> c.cl_pos | Some e -> e.epos);
+        error ("The field name '" ^ f.cf_name ^ "'  is not allowed in Lua") (match f.cf_expr with None -> c.cl_pos | Some e -> e.epos);
     | _ -> ()
     | _ -> ()
 
 
 (* convert a.b.c to ["a"]["b"]["c"] *)
 (* convert a.b.c to ["a"]["b"]["c"] *)
@@ -1500,11 +1515,11 @@ let gen_class_static_field ctx c f =
 
 
 let gen_class_field ctx c f =
 let gen_class_field ctx c f =
     let p = s_path ctx c.cl_path in
     let p = s_path ctx c.cl_path in
-    print ctx "%s.prototype." p;
     check_field_name c f;
     check_field_name c f;
+    print ctx "%s.prototype%s" p (field f.cf_name);
     match f.cf_expr with
     match f.cf_expr with
     | None ->
     | None ->
-        println ctx "%s = nil;" f.cf_name;
+        println ctx "= nil;"
     | Some e ->
     | Some e ->
         ctx.id_counter <- 0;
         ctx.id_counter <- 0;
         (match e.eexpr with
         (match e.eexpr with
@@ -1512,7 +1527,7 @@ let gen_class_field ctx c f =
              let old = ctx.in_value, ctx.in_loop in
              let old = ctx.in_value, ctx.in_loop in
              ctx.in_value <- None;
              ctx.in_value <- None;
              ctx.in_loop <- false;
              ctx.in_loop <- false;
-             print ctx "%s = function" f.cf_name;
+             print ctx " = function";
              print ctx "(%s) " (String.concat "," ("self" :: List.map ident (List.map arg_name f2.tf_args)));
              print ctx "(%s) " (String.concat "," ("self" :: List.map ident (List.map arg_name f2.tf_args)));
              let fblock = fun_block ctx f2 e.epos in
              let fblock = fun_block ctx f2 e.epos in
              (match fblock.eexpr with
              (match fblock.eexpr with
@@ -1557,7 +1572,7 @@ let generate_class ctx c =
     ctx.current <- c;
     ctx.current <- c;
     ctx.id_counter <- 0;
     ctx.id_counter <- 0;
     (match c.cl_path with
     (match c.cl_path with
-     | [],"Function" -> abort "This class redefines a native one" c.cl_pos
+     | [],"Function" -> error "This class redefines a native one" c.cl_pos
      | _ -> ());
      | _ -> ());
     let p = s_path ctx c.cl_path in
     let p = s_path ctx c.cl_path in
     let hxClasses = has_feature ctx "Type.resolveClass" in
     let hxClasses = has_feature ctx "Type.resolveClass" in
@@ -1732,7 +1747,7 @@ let generate_static ctx (c,f,e) =
 let generate_enumMeta_fields ctx = function
 let generate_enumMeta_fields ctx = function
     | TEnumDecl e -> begin
     | TEnumDecl e -> begin
             let p = s_path ctx e.e_path in
             let p = s_path ctx e.e_path in
-            match Codegen.build_metadata ctx.com (TEnumDecl e) with
+            match Texpr.build_metadata ctx.com.basic (TEnumDecl e) with
             | None -> ()
             | None -> ()
             | Some e ->
             | Some e ->
                 print ctx "%s.__meta__ = " p;
                 print ctx "%s.__meta__ = " p;
@@ -1745,15 +1760,13 @@ let generate_require ctx path meta =
     let _, args, mp = Meta.get Meta.LuaRequire meta in
     let _, args, mp = Meta.get Meta.LuaRequire meta in
     let p = (s_path ctx path) in
     let p = (s_path ctx path) in
 
 
-    (* generate_package_create ctx path; *)
-
     (match args with
     (match args with
      | [(EConst(String(module_name)),_)] ->
      | [(EConst(String(module_name)),_)] ->
          print ctx "%s = _G.require(\"%s\")" p module_name
          print ctx "%s = _G.require(\"%s\")" p module_name
      | [(EConst(String(module_name)),_) ; (EConst(String(object_path)),_)] ->
      | [(EConst(String(module_name)),_) ; (EConst(String(object_path)),_)] ->
          print ctx "%s = _G.require(\"%s\").%s" p module_name object_path
          print ctx "%s = _G.require(\"%s\").%s" p module_name object_path
      | _ ->
      | _ ->
-         abort "Unsupported @:luaRequire format" mp);
+         error "Unsupported @:luaRequire format" mp);
 
 
     newline ctx
     newline ctx
 
 
@@ -1768,13 +1781,9 @@ let generate_type ctx = function
         if p = "Std" && c.cl_ordered_statics = [] then
         if p = "Std" && c.cl_ordered_statics = [] then
             ()
             ()
         else if (not c.cl_extern) && Meta.has Meta.LuaDotMethod c.cl_meta then
         else if (not c.cl_extern) && Meta.has Meta.LuaDotMethod c.cl_meta then
-            abort "LuaDotMethod is valid for externs only" c.cl_pos
+            error "LuaDotMethod is valid for externs only" c.cl_pos
         else if not c.cl_extern then
         else if not c.cl_extern then
-            generate_class ctx c
-        else if Meta.has Meta.InitPackage c.cl_meta then
-            (match c.cl_path with
-             | ([],_) -> ()
-             | _ -> generate_package_create ctx c.cl_path);
+            generate_class ctx c;
         check_multireturn ctx c;
         check_multireturn ctx c;
     | TEnumDecl e ->
     | TEnumDecl e ->
         if not e.e_extern then generate_enum ctx e
         if not e.e_extern then generate_enum ctx e
@@ -1785,8 +1794,9 @@ let generate_type_forward ctx = function
     | TClassDecl c ->
     | TClassDecl c ->
         if not c.cl_extern then
         if not c.cl_extern then
             begin
             begin
-                generate_package_create ctx c.cl_path;
                 let p = s_path ctx c.cl_path in
                 let p = s_path ctx c.cl_path in
+                let l,c = c.cl_path in
+                if List.length(l) == 0 then spr ctx "local ";
                 println ctx "%s = _hx_e()" p
                 println ctx "%s = _hx_e()" p
             end
             end
         else if Meta.has Meta.LuaRequire c.cl_meta && is_directly_used ctx.com c.cl_meta then
         else if Meta.has Meta.LuaRequire c.cl_meta && is_directly_used ctx.com c.cl_meta then
@@ -1795,8 +1805,9 @@ let generate_type_forward ctx = function
         if Meta.has Meta.LuaRequire e.e_meta && is_directly_used ctx.com e.e_meta then
         if Meta.has Meta.LuaRequire e.e_meta && is_directly_used ctx.com e.e_meta then
             generate_require ctx e.e_path e.e_meta;
             generate_require ctx e.e_path e.e_meta;
     | TEnumDecl e ->
     | TEnumDecl e ->
-        generate_package_create ctx e.e_path;
         let p = s_path ctx e.e_path in
         let p = s_path ctx e.e_path in
+        let l,c = e.e_path in
+        if List.length(l) == 0 then spr ctx "local ";
         println ctx "%s = _hx_e()" p;
         println ctx "%s = _hx_e()" p;
     | TTypeDecl _ | TAbstractDecl _ -> ()
     | TTypeDecl _ | TAbstractDecl _ -> ()
 
 
@@ -1821,7 +1832,7 @@ let alloc_ctx com =
         found_expose = false;
         found_expose = false;
         lua_jit = Common.defined com Define.LuaJit;
         lua_jit = Common.defined com Define.LuaJit;
         lua_ver = try
         lua_ver = try
-                float_of_string (PMap.find "lua_ver" com.defines)
+                float_of_string (PMap.find "lua_ver" com.defines.Define.values)
             with | Not_found -> 5.2;
             with | Not_found -> 5.2;
     } in
     } in
     ctx.type_accessor <- (fun t ->
     ctx.type_accessor <- (fun t ->
@@ -1838,19 +1849,20 @@ let alloc_ctx com =
 let transform_multireturn ctx = function
 let transform_multireturn ctx = function
     | TClassDecl c ->
     | TClassDecl c ->
         let transform_field f =
         let transform_field f =
+            check_multireturn_param ctx f.cf_type f.cf_pos;
             match f.cf_expr with
             match f.cf_expr with
             | Some e ->
             | Some e ->
+                let is_multireturn t =
+                    match follow t with
+                    | TInst (c, _) when Meta.has Meta.MultiReturn c.cl_meta -> true
+                    | _ -> false
+                in
                 let rec loop e =
                 let rec loop e =
-                    let is_multireturn t =
-                        match follow t with
-                        | TInst (c, _) when Meta.has Meta.MultiReturn c.cl_meta -> true
-                        | _ -> false
-                    in
                     match e.eexpr with
                     match e.eexpr with
-     (*
-						if we found a var declaration initialized by a multi-return call, mark it with @:multiReturn meta,
-						so it will later be generated as multiple locals unpacking the value
-					*)
+                    (*
+                        if we found a var declaration initialized by a multi-return call, mark it with @:multiReturn meta,
+                        so it will later be generated as multiple locals unpacking the value
+                    *)
                     | TVar (v, Some ({ eexpr = TCall _ } as ecall)) when is_multireturn v.v_type ->
                     | TVar (v, Some ({ eexpr = TCall _ } as ecall)) when is_multireturn v.v_type ->
                         v.v_meta <- (Meta.MultiReturn,[],v.v_pos) :: v.v_meta;
                         v.v_meta <- (Meta.MultiReturn,[],v.v_pos) :: v.v_meta;
                         let ecall = Type.map_expr loop ecall in
                         let ecall = Type.map_expr loop ecall in
@@ -1859,7 +1871,7 @@ let transform_multireturn ctx = function
                     (* if we found a field access for the multi-return call, generate select call *)
                     (* if we found a field access for the multi-return call, generate select call *)
                     | TField ({ eexpr = TCall _ } as ecall, f) when is_multireturn ecall.etype ->
                     | TField ({ eexpr = TCall _ } as ecall, f) when is_multireturn ecall.etype ->
                         let ecall = Type.map_expr loop ecall in
                         let ecall = Type.map_expr loop ecall in
-                        mk_mr_select ctx.com e ecall (field_name f)
+                        mk_mr_select ctx.com.basic e ecall (field_name f)
 
 
                     (* if we found a multi-return call used as a value, box it *)
                     (* if we found a multi-return call used as a value, box it *)
                     | TCall _ when is_multireturn e.etype ->
                     | TCall _ when is_multireturn e.etype ->
@@ -1881,7 +1893,7 @@ let transform_multireturn ctx = function
                         e
                         e
                     | TReturn Some(e2) ->
                     | TReturn Some(e2) ->
                         if is_multireturn e2.etype then
                         if is_multireturn e2.etype then
-                            failwith "You cannot return a multireturn type from a haxe function"
+                            error "You cannot return a multireturn type from a haxe function" e2.epos
                         else
                         else
                             Type.map_expr loop e;
                             Type.map_expr loop e;
      (*
      (*
@@ -2035,7 +2047,7 @@ let generate com =
     List.iter (generate_static ctx) (List.rev ctx.statics);
     List.iter (generate_static ctx) (List.rev ctx.statics);
     (* Localize init variables inside a do-block *)
     (* Localize init variables inside a do-block *)
     (* Note: __init__ logic can modify static variables. *)
     (* Note: __init__ logic can modify static variables. *)
-    (* Generate statics *)
+    (* Generate static inits *)
     List.iter (gen_block_element ctx) (List.rev ctx.inits);
     List.iter (gen_block_element ctx) (List.rev ctx.inits);
     b();
     b();
     newline ctx;
     newline ctx;

+ 4 - 4
src/generators/genneko.ml

@@ -260,7 +260,7 @@ and gen_expr ctx e =
 		gen_expr ctx e
 		gen_expr ctx e
 	| TObjectDecl fl ->
 	| TObjectDecl fl ->
 		let hasToString = ref false in
 		let hasToString = ref false in
-		let fl = List.map (fun (f,e) -> if f = "toString" then hasToString := (match follow e.etype with TFun ([],_) -> true | _ -> false); f , gen_expr ctx e) fl in
+		let fl = List.map (fun ((f,_,_),e) -> if f = "toString" then hasToString := (match follow e.etype with TFun ([],_) -> true | _ -> false); f , gen_expr ctx e) fl in
 		(EObject (if !hasToString then ("__string",ident p "@default__string") :: fl else fl),p)
 		(EObject (if !hasToString then ("__string",ident p "@default__string") :: fl else fl),p)
 	| TArrayDecl el ->
 	| TArrayDecl el ->
 		call p (field p (ident p "Array") "new1") [array p (List.map (gen_expr ctx) el); int p (List.length el)]
 		call p (field p (ident p "Array") "new1") [array p (List.map (gen_expr ctx) el); int p (List.length el)]
@@ -296,7 +296,7 @@ and gen_expr ctx e =
 			in
 			in
 			match c with
 			match c with
 			| None | Some TNull -> acc
 			| None | Some TNull -> acc
-			| Some c ->	gen_expr ctx (Codegen.set_default ctx.com a c e.epos) :: acc
+			| Some c ->	gen_expr ctx (Texpr.set_default ctx.com.basic a c e.epos) :: acc
 		) [] f.tf_args in
 		) [] f.tf_args in
 		let e = gen_expr ctx f.tf_expr in
 		let e = gen_expr ctx f.tf_expr in
 		let e = (match inits with [] -> e | _ -> EBlock (List.rev (e :: inits)),p) in
 		let e = (match inits with [] -> e | _ -> EBlock (List.rev (e :: inits)),p) in
@@ -630,7 +630,7 @@ let gen_name ctx acc t =
 		let setname = (EBinop ("=",field p path "__ename__",arr),p) in
 		let setname = (EBinop ("=",field p path "__ename__",arr),p) in
 		let arr = call p (field p (ident p "Array") "new1") [array p (List.map (fun n -> gen_constant ctx e.e_pos (TString n)) e.e_names); int p (List.length e.e_names)] in
 		let arr = call p (field p (ident p "Array") "new1") [array p (List.map (fun n -> gen_constant ctx e.e_pos (TString n)) e.e_names); int p (List.length e.e_names)] in
 		let setconstrs = (EBinop ("=", field p path "__constructs__", arr),p) in
 		let setconstrs = (EBinop ("=", field p path "__constructs__", arr),p) in
-		let meta = (match Codegen.build_metadata ctx.com (TEnumDecl e) with
+		let meta = (match Texpr.build_metadata ctx.com.basic (TEnumDecl e) with
 			| None -> []
 			| None -> []
 			| Some e -> [EBinop ("=",field p path "__meta__", gen_expr ctx e),p]
 			| Some e -> [EBinop ("=",field p path "__meta__", gen_expr ctx e),p]
 		) in
 		) in
@@ -794,7 +794,7 @@ let generate com =
 	let use_nekoc = Common.defined com Define.UseNekoc in
 	let use_nekoc = Common.defined com Define.UseNekoc in
 	if not use_nekoc then begin
 	if not use_nekoc then begin
 		try
 		try
-			mkdir_from_path com.file;
+			Path.mkdir_from_path com.file;
 			let ch = IO.output_channel (open_out_bin com.file) in
 			let ch = IO.output_channel (open_out_bin com.file) in
 			Nbytecode.write ch (Ncompile.compile ctx.version e);
 			Nbytecode.write ch (Ncompile.compile ctx.version e);
 			IO.close_out ch;
 			IO.close_out ch;

+ 0 - 2437
src/generators/genphp.ml

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

+ 164 - 199
src/generators/genphp7.ml

@@ -1,5 +1,5 @@
 (**
 (**
-	Compatible with PHP 7+
+	Compatible with PHP 7.0+
 *)
 *)
 
 
 open Ast
 open Ast
@@ -184,9 +184,9 @@ let get_php_prefix ctx =
 		| Some prefix -> prefix
 		| Some prefix -> prefix
 		| None ->
 		| None ->
 			let lst =
 			let lst =
-				match ctx.php_prefix with
-					| None -> []
-					| Some str ->
+				match Common.defined_value_safe ctx Define.PhpPrefix with
+					| "" -> []
+					| str ->
 						if String.length str = 0 then
 						if String.length str = 0 then
 							[]
 							[]
 						else
 						else
@@ -238,20 +238,21 @@ let error_message pos message = (stringify_pos pos) ^ ": " ^ message
 (**
 (**
 	Terminates compiler process and prints user-friendly instructions about filing an issue in compiler repo.
 	Terminates compiler process and prints user-friendly instructions about filing an issue in compiler repo.
 *)
 *)
-let fail hxpos mlpos =
+let fail ?msg hxpos mlpos =
+	let msg =
+		error_message
+			hxpos
+			(
+				(match msg with Some msg -> msg | _ -> "")
+				^ " Unexpected expression. Please submit an issue with expression example and following information:"
+			)
+	in
 	match mlpos with
 	match mlpos with
 		| (file, line, _, _) ->
 		| (file, line, _, _) ->
-			Printf.printf "%s\n" (error_message hxpos "Unexpected expression. Please submit an issue with expression example and following information:");
-			Printf.printf "%s:%d\n" file line;
+			Printf.eprintf "%s\n" msg;
+			Printf.eprintf "%s:%d\n" file line;
 			assert false
 			assert false
 
 
-(**
-	Print compilation error message and abort compilation process.
-*)
-let error_and_exit pos message =
-	Printf.printf "%s" (error_message pos message);
-	exit 1
-
 (**
 (**
 	Check if `target` is a `Dynamic` type
 	Check if `target` is a `Dynamic` type
 *)
 *)
@@ -295,10 +296,15 @@ let is_string_type t = match follow t with TInst ({ cl_path = ([], "String") },
 *)
 *)
 let is_string expr = is_string_type expr.etype
 let is_string expr = is_string_type expr.etype
 
 
+(**
+	Check if specified type represents a function
+*)
+let is_function_type t = match follow t with TFun _ -> true | _ -> false
+
 (**
 (**
 	Check if `expr` is an access to a method of special `php.PHP` class
 	Check if `expr` is an access to a method of special `php.PHP` class
 *)
 *)
-let is_lang_extern expr =
+let is_syntax_extern expr =
 	match expr.eexpr with
 	match expr.eexpr with
 		| TField ({ eexpr = TTypeExpr (TClassDecl { cl_path = path }) }, _) when path = syntax_type_path -> true
 		| TField ({ eexpr = TTypeExpr (TClassDecl { cl_path = path }) }, _) when path = syntax_type_path -> true
 		| _ -> false
 		| _ -> false
@@ -361,7 +367,7 @@ let parenthesis expr = {eexpr = TParenthesis expr; etype = expr.etype; epos = ex
 	Check if `current` binary should be surrounded with parenthesis
 	Check if `current` binary should be surrounded with parenthesis
 *)
 *)
 let need_parenthesis_for_binop current parent =
 let need_parenthesis_for_binop current parent =
-	if current = parent then
+	if current = parent && current != OpNotEq && current != OpEq then
 		false
 		false
 	else
 	else
 		match (current, parent) with
 		match (current, parent) with
@@ -393,7 +399,7 @@ let needs_dereferencing for_assignment expr =
 			(* some of `php.Syntax` methods *)
 			(* some of `php.Syntax` methods *)
 			| TCall ({ eexpr = TField (_, FStatic ({ cl_path = syntax_type_path }, { cf_name = name })) }, _) ->
 			| TCall ({ eexpr = TField (_, FStatic ({ cl_path = syntax_type_path }, { cf_name = name })) }, _) ->
 				(match name with
 				(match name with
-					| "binop" | "object" | "array" -> for_assignment
+					| "codeDeref" -> for_assignment
 					| _ -> false
 					| _ -> false
 				)
 				)
 			| _ -> false
 			| _ -> false
@@ -619,7 +625,7 @@ let inject_defaults (ctx:Common.context) (func:tfunc) =
 			| (_, None) :: rest -> inject rest body_exprs
 			| (_, None) :: rest -> inject rest body_exprs
 			| (_, Some TNull) :: rest -> inject rest body_exprs
 			| (_, Some TNull) :: rest -> inject rest body_exprs
 			| (var, Some const) :: rest ->
 			| (var, Some const) :: rest ->
-				let expr = Codegen.set_default ctx var const func.tf_expr.epos in
+				let expr = Texpr.set_default ctx.basic var const func.tf_expr.epos in
 			 	expr :: (inject rest body_exprs)
 			 	expr :: (inject rest body_exprs)
 	in
 	in
 	let exprs =
 	let exprs =
@@ -718,10 +724,21 @@ let need_boot_equal expr1 expr2 =
 	if is_constant_null expr1 || is_constant_null expr2 then
 	if is_constant_null expr1 || is_constant_null expr2 then
 		false
 		false
 	else
 	else
-		(is_int expr1 && (is_float expr2 || is_unknown_type expr2.etype))
-		|| (is_float expr1 && (is_float expr2 || is_int expr2 || is_unknown_type expr2.etype))
-		|| (is_unknown_type expr1.etype && (is_int expr2 || is_float expr2))
-		|| (is_unknown_type expr1.etype && is_unknown_type expr2.etype)
+		let unknown1 = is_unknown_type expr1.etype
+		and unknown2 = is_unknown_type expr2.etype in
+		if unknown1 && unknown2 then
+			true
+		else if is_function_type expr1.etype || is_function_type expr2.etype then
+			true
+		else
+			let int1 = is_int expr1
+			and int2 = is_int expr2
+			and float1 = is_float expr1
+			and float2 = is_float expr2 in
+			(int1 && float2)
+			|| (float1 && (float2 || int2))
+			|| (unknown1 && (int2 || float2))
+			|| ((int1 || float1) && unknown2)
 
 
 (**
 (**
 	Adds `return` expression to block if it does not have one already
 	Adds `return` expression to block if it does not have one already
@@ -761,7 +778,7 @@ let unpack_single_expr_block expr =
 	Check if specified type has rtti meta
 	Check if specified type has rtti meta
 *)
 *)
 let has_rtti_meta ctx mtype =
 let has_rtti_meta ctx mtype =
-	match Codegen.build_metadata ctx mtype with
+	match Texpr.build_metadata ctx.basic mtype with
 		| None -> false
 		| None -> false
 		| Some _ -> true
 		| Some _ -> true
 
 
@@ -818,8 +835,13 @@ let is_object_declaration expr =
 	Check if `subject_arg` and `type_arg` can be generated as `$subject instanceof Type` expression.
 	Check if `subject_arg` and `type_arg` can be generated as `$subject instanceof Type` expression.
 *)
 *)
 let instanceof_compatible (subject_arg:texpr) (type_arg:texpr) : bool =
 let instanceof_compatible (subject_arg:texpr) (type_arg:texpr) : bool =
+	let is_real_class path =
+		match path with
+			| ([], "String") | ([], "Class") | (["php";"_NativeArray"], "NativeArray_Impl_") -> false
+			| _ -> true
+	in
 	match (reveal_expr_with_parenthesis type_arg).eexpr with
 	match (reveal_expr_with_parenthesis type_arg).eexpr with
-		| TTypeExpr (TClassDecl { cl_path = path }) when path <> ([], "String") && path <> ([], "Class") ->
+		| TTypeExpr (TClassDecl { cl_path = path }) when is_real_class path ->
 			let subject_arg = reveal_expr_with_parenthesis subject_arg in
 			let subject_arg = reveal_expr_with_parenthesis subject_arg in
 			(match subject_arg.eexpr with
 			(match subject_arg.eexpr with
 				| TLocal _ | TField _ | TCall _ | TArray _ | TConst TThis -> not (is_magic subject_arg)
 				| TLocal _ | TField _ | TCall _ | TArray _ | TConst TThis -> not (is_magic subject_arg)
@@ -1306,9 +1328,12 @@ class code_writer (ctx:Common.context) hx_type_path php_name =
 						let alias_source = ref (List.rev module_path) in
 						let alias_source = ref (List.rev module_path) in
 						let get_alias_next_part () =
 						let get_alias_next_part () =
 							match !alias_source with
 							match !alias_source with
-								| [] ->  failwith ("Failed to find already used type: " ^ get_full_type_name type_path)
+								| [] ->  fail ~msg:("Failed to find already used type: " ^ get_full_type_name type_path) self#pos __POS__
 								| name :: rest ->
 								| name :: rest ->
-									alias_source := rest;
+									alias_source := (match rest with
+										| [] -> [name]
+										| _ -> rest
+									);
 									String.capitalize name
 									String.capitalize name
 						and added = ref false
 						and added = ref false
 						and alias = ref (get_type_name type_path) in
 						and alias = ref (get_type_name type_path) in
@@ -1350,13 +1375,13 @@ class code_writer (ctx:Common.context) hx_type_path php_name =
 				| TFun _ -> self#use ~prefix:false ([], "Closure")
 				| TFun _ -> self#use ~prefix:false ([], "Closure")
 				| TAnon _ -> "object"
 				| TAnon _ -> "object"
 				| TDynamic _ -> "mixed"
 				| TDynamic _ -> "mixed"
-				| TLazy _ -> failwith "TLazy not implemented"
+				| TLazy _ -> fail ~msg:"TLazy not implemented" self#pos __POS__
 				| TMono mono ->
 				| TMono mono ->
 					(match !mono with
 					(match !mono with
 						| None -> "mixed"
 						| None -> "mixed"
 						| Some t -> self#use_t t
 						| Some t -> self#use_t t
 					)
 					)
-				| TType _ -> failwith "TType not implemented"
+				| TType _ -> fail ~msg:"TType not implemented" self#pos __POS__
 				| TAbstract (abstr, _) ->
 				| TAbstract (abstr, _) ->
 					match abstr.a_path with
 					match abstr.a_path with
 						| ([],"Int") -> "int"
 						| ([],"Int") -> "int"
@@ -1547,17 +1572,19 @@ class code_writer (ctx:Common.context) hx_type_path php_name =
 			Hashtbl.iter write use_table
 			Hashtbl.iter write use_table
 		(**
 		(**
 			Writes array item declaration to output buffer and appends ",\n"
 			Writes array item declaration to output buffer and appends ",\n"
+			Adds indentation and ",\n" if `separate_line` is `true`.
 		*)
 		*)
-		method write_array_item ?key value_expr =
+		method write_array_item ?separate_line ?key value_expr =
+			let separate_line = match separate_line with Some true -> true | _ -> false in
+			if separate_line then self#write_indentation;
 			(match key with
 			(match key with
 				| None ->
 				| None ->
-					self#write_indentation;
 					self#write_expr value_expr;
 					self#write_expr value_expr;
 				| Some key_str ->
 				| Some key_str ->
-					self#write (indentation  ^ "\"" ^ (String.escaped key_str) ^ "\" => ");
+					self#write ("\"" ^ (String.escaped key_str) ^ "\" => ");
 					self#write_expr value_expr
 					self#write_expr value_expr
 			);
 			);
-			self#write ",\n"
+			if separate_line then self#write ",\n"
 		(**
 		(**
 			Writes expression to output buffer
 			Writes expression to output buffer
 		*)
 		*)
@@ -1584,11 +1611,14 @@ class code_writer (ctx:Common.context) hx_type_path php_name =
 					self#write ")"
 					self#write ")"
 				| TObjectDecl fields -> self#write_expr_object_declaration fields
 				| TObjectDecl fields -> self#write_expr_object_declaration fields
 				| TArrayDecl exprs -> self#write_expr_array_decl exprs
 				| TArrayDecl exprs -> self#write_expr_array_decl exprs
-				| TCall (target, [arg1; arg2]) when is_std_is target && instanceof_compatible arg1 arg2 -> self#write_expr_lang_instanceof [arg1; arg2]
-				| TCall (_, [arg]) when is_native_struct_array_cast expr && is_object_declaration arg -> self#write_assoc_array_decl arg
-				| TCall ({ eexpr = TIdent name}, args) when is_magic expr -> self#write_expr_magic name args
+				| TCall (target, [arg1; arg2]) when is_std_is target && instanceof_compatible arg1 arg2 -> self#write_expr_syntax_instanceof [arg1; arg2]
+				| TCall (_, [arg]) when is_native_struct_array_cast expr && is_object_declaration arg ->
+					(match (reveal_expr arg).eexpr with TObjectDecl fields -> self#write_assoc_array_decl fields | _ -> fail self#pos __POS__)
+				| TCall ({ eexpr = TIdent name}, args) when is_magic expr ->
+					ctx.warning ("untyped " ^ name ^ " is deprecated. Use php.Syntax instead.") self#pos;
+					self#write_expr_magic name args
 				| TCall ({ eexpr = TField (expr, access) }, args) when is_string expr -> self#write_expr_call_string expr access args
 				| TCall ({ eexpr = TField (expr, access) }, args) when is_string expr -> self#write_expr_call_string expr access args
-				| TCall (expr, args) when is_lang_extern expr -> self#write_expr_call_lang_extern expr args
+				| TCall (expr, args) when is_syntax_extern expr -> self#write_expr_call_syntax_extern expr args
 				| TCall (target, args) when is_sure_var_field_access target -> self#write_expr_call (parenthesis target) args
 				| TCall (target, args) when is_sure_var_field_access target -> self#write_expr_call (parenthesis target) args
 				| TCall (target, args) -> self#write_expr_call target args
 				| TCall (target, args) -> self#write_expr_call target args
 				| TNew (_, _, args) when is_string expr -> write_args self#write self#write_expr args
 				| TNew (_, _, args) when is_string expr -> write_args self#write self#write_expr args
@@ -1672,35 +1702,28 @@ class code_writer (ctx:Common.context) hx_type_path php_name =
 				| _ ->
 				| _ ->
 					self#write ((self#use array_type_path) ^ "::wrap([\n");
 					self#write ((self#use array_type_path) ^ "::wrap([\n");
 					self#indent_more;
 					self#indent_more;
-					List.iter (fun expr -> self#write_array_item expr) exprs;
+					List.iter (fun expr -> self#write_array_item ~separate_line:true expr) exprs;
 					self#indent_less;
 					self#indent_less;
 					self#write_indentation;
 					self#write_indentation;
 					self#write "])"
 					self#write "])"
 		(**
 		(**
-			Write associative array declaration (used for NativeStructArray)
+			Write associative array declaration
 		*)
 		*)
-		method write_assoc_array_decl object_decl =
-			match (reveal_expr object_decl).eexpr with
-				| TObjectDecl fields ->
-					if List.length fields = 0 then
-						self#write "[]"
-					else begin
-						self#write "[\n";
-						self#indent_more;
-						List.iter
-							(fun (name, field) ->
-								self#write_indentation;
-								self#write_const_string name;
-								self#write " => ";
-								self#write_expr field;
-								self#write ",\n"
-							)
-							fields;
-						self#indent_less;
-						self#write_indentation;
-						self#write "]";
-					end
-				| _ -> fail object_decl.epos __POS__
+		method write_assoc_array_decl fields =
+			match fields with
+				| [] -> self#write "[]"
+				| [((key, _, _), value)] ->
+					self#write "[";
+					self#write_array_item ~key:key value;
+					self#write "]"
+				| _ ->
+					self#write "[\n";
+					self#indent_more;
+					let write_field ((key,_,_), value) = self#write_array_item ~separate_line:true ~key:key value in
+					List.iter write_field fields;
+					self#indent_less;
+					self#write_indentation;
+					self#write "]"
 		(**
 		(**
 			Writes TArray to output buffer
 			Writes TArray to output buffer
 		*)
 		*)
@@ -1980,9 +2003,9 @@ class code_writer (ctx:Common.context) hx_type_path php_name =
 			@see http://old.haxe.org/doc/advanced/magic#php-magic
 			@see http://old.haxe.org/doc/advanced/magic#php-magic
 		*)
 		*)
 		method write_expr_magic name args =
 		method write_expr_magic name args =
-			let error = error_message self#pos ("Invalid arguments for " ^ name ^ " magic call") in
+			let error = ("Invalid arguments for " ^ name ^ " magic call") in
 			match args with
 			match args with
-				| [] -> failwith error
+				| [] -> fail ~msg:error self#pos __POS__
 				| { eexpr = TConst (TString code) } as expr :: args ->
 				| { eexpr = TConst (TString code) } as expr :: args ->
 					(match name with
 					(match name with
 						| "__php__" ->
 						| "__php__" ->
@@ -1998,7 +2021,7 @@ class code_writer (ctx:Common.context) hx_type_path php_name =
 						| "__physeq__" ->
 						| "__physeq__" ->
 							(match args with
 							(match args with
 								| [expr2] -> self#write_expr_binop OpEq expr expr2
 								| [expr2] -> self#write_expr_binop OpEq expr expr2
-								| _ -> failwith error
+								| _ -> fail ~msg:error self#pos __POS__
 							)
 							)
 						| "__var__" ->
 						| "__var__" ->
 							(match args with
 							(match args with
@@ -2008,20 +2031,20 @@ class code_writer (ctx:Common.context) hx_type_path php_name =
 									self#write ("$" ^ code ^ "[");
 									self#write ("$" ^ code ^ "[");
 									self#write_expr expr2;
 									self#write_expr expr2;
 									self#write "]"
 									self#write "]"
-								| _ -> failwith error
+								| _ -> fail ~msg:error self#pos __POS__
 							)
 							)
-						| _ -> failwith error
+						| _ -> fail ~msg:error self#pos __POS__
 					)
 					)
 				| [expr1; expr2] ->
 				| [expr1; expr2] ->
 					(match name with
 					(match name with
 						| "__physeq__" ->
 						| "__physeq__" ->
 							(match args with
 							(match args with
 								| [expr1; expr2] -> self#write_expr_binop OpEq expr1 expr2
 								| [expr1; expr2] -> self#write_expr_binop OpEq expr1 expr2
-								| _ -> failwith error
+								| _ -> fail ~msg:error self#pos __POS__
 							)
 							)
-						| _ -> failwith error
+						| _ -> fail ~msg:error self#pos __POS__
 					)
 					)
-				| _ -> failwith error
+				| _ -> fail ~msg:error self#pos __POS__
 		(**
 		(**
 			Writes TTypeExpr to output buffer
 			Writes TTypeExpr to output buffer
 		*)
 		*)
@@ -2096,10 +2119,6 @@ class code_writer (ctx:Common.context) hx_type_path php_name =
 						write_method ((self#use boot_type_path) ^ "::addOrConcat")
 						write_method ((self#use boot_type_path) ^ "::addOrConcat")
 					else
 					else
 						write_binop " + "
 						write_binop " + "
-				| OpMult -> write_binop " * "
-				| OpDiv -> write_binop " / "
-				| OpSub -> write_binop " - "
-				| OpAssign -> write_binop " = "
 				| OpEq ->
 				| OpEq ->
 					if need_boot_equal expr1 expr2 then
 					if need_boot_equal expr1 expr2 then
 						write_method ((self#use boot_type_path) ^ "::equal")
 						write_method ((self#use boot_type_path) ^ "::equal")
@@ -2113,17 +2132,6 @@ class code_writer (ctx:Common.context) hx_type_path php_name =
 						end
 						end
 					else
 					else
 						write_binop " !== "
 						write_binop " !== "
-				| OpGt -> compare " > "
-				| OpGte -> compare " >= "
-				| OpLt -> compare " < "
-				| OpLte -> compare " <= "
-				| OpAnd -> write_binop " & "
-				| OpOr -> write_binop " | "
-				| OpXor -> write_binop " ^ "
-				| OpBoolAnd -> write_binop " && "
-				| OpBoolOr -> write_binop " || "
-				| OpShl  -> write_binop " << "
-				| OpShr -> write_binop " >> "
 				| OpMod ->
 				| OpMod ->
 					if is_int expr1 && is_int expr2 then
 					if is_int expr1 && is_int expr2 then
 						write_binop " % "
 						write_binop " % "
@@ -2145,14 +2153,6 @@ class code_writer (ctx:Common.context) hx_type_path php_name =
 						end
 						end
 					else
 					else
 						write_binop " += "
 						write_binop " += "
-				| OpAssignOp OpMult -> write_binop " *= "
-				| OpAssignOp OpDiv -> write_binop " /= "
-				| OpAssignOp OpSub -> write_binop " -= "
-				| OpAssignOp OpAnd -> write_binop " &= "
-				| OpAssignOp OpOr -> write_binop " |= "
-				| OpAssignOp OpXor -> write_binop " ^= "
-				| OpAssignOp OpShl  -> write_binop " <<= "
-				| OpAssignOp OpShr -> write_binop " >>= "
 				| OpAssignOp OpMod ->
 				| OpAssignOp OpMod ->
 					if is_int expr1 && is_int expr2 then
 					if is_int expr1 && is_int expr2 then
 						write_binop " %= "
 						write_binop " %= "
@@ -2162,26 +2162,21 @@ class code_writer (ctx:Common.context) hx_type_path php_name =
 					self#write_expr expr1;
 					self#write_expr expr1;
 					self#write " = ";
 					self#write " = ";
 					write_method ((self#use boot_type_path) ^ "::shiftRightUnsigned")
 					write_method ((self#use boot_type_path) ^ "::shiftRightUnsigned")
-				| _ -> fail self#pos __POS__
+				| OpGt | OpGte | OpLt | OpLte ->
+					compare (" " ^ (Ast.s_binop operation) ^ " ")
+				| _ ->
+					write_binop (" " ^ (Ast.s_binop operation) ^ " ")
 		(**
 		(**
 			Writes TUnOp to output buffer
 			Writes TUnOp to output buffer
 		*)
 		*)
 		method write_expr_unop operation flag expr =
 		method write_expr_unop operation flag expr =
-			let write_unop operation =
-				match operation with
-					| Increment -> self#write "++"
-					| Decrement -> self#write "--"
-					| Not -> self#write "!"
-					| Neg -> self#write "-"
-					| NegBits -> self#write "~"
-			in
 			match flag with
 			match flag with
 				| Prefix ->
 				| Prefix ->
-					write_unop operation;
+					self#write (Ast.s_unop operation);
 					self#write_expr expr
 					self#write_expr expr
 				| Postfix ->
 				| Postfix ->
 					self#write_expr expr;
 					self#write_expr expr;
-					write_unop operation
+					self#write (Ast.s_unop operation)
 		method private write_expr_for_field_access expr access_str field_str =
 		method private write_expr_for_field_access expr access_str field_str =
 			let access_str = ref access_str in
 			let access_str = ref access_str in
 			(match (reveal_expr expr).eexpr with
 			(match (reveal_expr expr).eexpr with
@@ -2357,13 +2352,9 @@ class code_writer (ctx:Common.context) hx_type_path php_name =
 			match fields with
 			match fields with
 				| [] ->  self#write ("new " ^ (self#use hxanon_type_path) ^ "()")
 				| [] ->  self#write ("new " ^ (self#use hxanon_type_path) ^ "()")
 				| _ ->
 				| _ ->
-					self#write ("new " ^ (self#use hxanon_type_path)  ^ "([\n");
-					self#indent_more;
-					let write_field (key, value) = self#write_array_item ~key:key value in
-					List.iter write_field fields;
-					self#indent_less;
-					self#write_indentation;
-					self#write "])"
+					self#write ("new " ^ (self#use hxanon_type_path)  ^ "(");
+					self#write_assoc_array_decl fields;
+					self#write ")"
 		(**
 		(**
 			Writes specified type to output buffer depending on type of expression.
 			Writes specified type to output buffer depending on type of expression.
 		*)
 		*)
@@ -2382,43 +2373,40 @@ class code_writer (ctx:Common.context) hx_type_path php_name =
 		(**
 		(**
 			Write language specific expression declared in `php.Syntax` extern
 			Write language specific expression declared in `php.Syntax` extern
 		*)
 		*)
-		method write_expr_call_lang_extern expr args =
+		method write_expr_call_syntax_extern expr args =
 			let name = match expr.eexpr with
 			let name = match expr.eexpr with
 				| TField (_, FStatic (_, field)) -> field_name field
 				| TField (_, FStatic (_, field)) -> field_name field
 				| _ -> fail self#pos __POS__
 				| _ -> fail self#pos __POS__
 			in
 			in
 			match name with
 			match name with
-				| "int" | "float"
-				| "string" | "bool"
-				| "object" | "array" -> self#write_expr_lang_cast name args
-				| "binop" -> self#write_expr_lang_binop args
-				| "instanceof" -> self#write_expr_lang_instanceof args
-				| "foreach" -> self#write_expr_lang_foreach args
-				| "construct" -> self#write_expr_lang_construct args
-				| "getField" -> self#write_expr_lang_get_field args
-				| "setField" -> self#write_expr_lang_set_field args
-				| "getStaticField" -> self#write_expr_lang_get_static_field args
-				| "setStaticField" -> self#write_expr_lang_set_static_field args
-				| "call" -> self#write_expr_lang_call args
-				| "staticCall" -> self#write_expr_lang_static_call args
-				| "arrayDecl" -> self#write_expr_lang_array_decl args
-				| "splat" -> self#write_expr_lang_splat args
-				| "suppress" -> self#write_expr_lang_suppress args
+				| "code" | "codeDeref" -> self#write_expr_syntax_code args
+				| "instanceof" -> self#write_expr_syntax_instanceof args
+				| "foreach" -> self#write_expr_syntax_foreach args
+				| "construct" -> self#write_expr_syntax_construct args
+				| "getField" -> self#write_expr_syntax_get_field args
+				| "setField" -> self#write_expr_syntax_set_field args
+				| "getStaticField" -> self#write_expr_syntax_get_static_field args
+				| "setStaticField" -> self#write_expr_syntax_set_static_field args
+				| "call" -> self#write_expr_syntax_call args
+				| "staticCall" -> self#write_expr_syntax_static_call args
+				| "arrayDecl" -> self#write_expr_syntax_array_decl args
+				| "assocDecl" -> self#write_expr_syntax_assoc_decl args
+				| "suppress" -> self#write_expr_syntax_suppress args
 				| "keepVar" -> ()
 				| "keepVar" -> ()
-				| _ -> fail self#pos __POS__
+				| _ -> ctx.error ("php.Syntax." ^ name ^ "() is not supported.") self#pos
 		(**
 		(**
-			Writes splat operator (for `php.Syntax.splat()`)
+			Writes plain php code (for `php.Syntax.php()`)
 		*)
 		*)
-		method write_expr_lang_splat args =
+		method write_expr_syntax_code args =
 			match args with
 			match args with
-				| [ args_expr ] ->
-					self#write "...";
-					self#write_expr args_expr
-				| _ -> fail self#pos __POS__
+				| [] -> fail self#pos __POS__
+				| { eexpr = TConst (TString php) } :: args ->
+					Codegen.interpolate_code ctx php args self#write self#write_expr self#pos
+				| _ -> ctx.error "First argument of php.Syntax.php() must be a constant string." self#pos
 		(**
 		(**
 			Writes error suppression operator (for `php.Syntax.suppress()`)
 			Writes error suppression operator (for `php.Syntax.suppress()`)
 		*)
 		*)
-		method write_expr_lang_suppress args =
+		method write_expr_syntax_suppress args =
 			match args with
 			match args with
 				| [ args_expr ] ->
 				| [ args_expr ] ->
 					self#write "@";
 					self#write "@";
@@ -2427,14 +2415,22 @@ class code_writer (ctx:Common.context) hx_type_path php_name =
 		(**
 		(**
 			Writes native array declaration (for `php.Syntax.arrayDecl()`)
 			Writes native array declaration (for `php.Syntax.arrayDecl()`)
 		*)
 		*)
-		method write_expr_lang_array_decl args =
+		method write_expr_syntax_array_decl args =
 			self#write "[";
 			self#write "[";
 			write_args self#write (fun e -> self#write_expr e) args;
 			write_args self#write (fun e -> self#write_expr e) args;
 			self#write "]"
 			self#write "]"
+		(**
+			Writes native array declaration (for `php.Syntax.arrayDecl()`)
+		*)
+		method write_expr_syntax_assoc_decl args =
+			match args with
+				| [] -> self#write_assoc_array_decl []
+				| { eexpr = TObjectDecl fields } :: [] -> self#write_assoc_array_decl fields
+				| _ -> ctx.error "php.Syntax.assocDecl() accepts object declaration only." self#pos
 		(**
 		(**
 			Writes a call to instance method (for `php.Syntax.call()`)
 			Writes a call to instance method (for `php.Syntax.call()`)
 		*)
 		*)
-		method write_expr_lang_call args =
+		method write_expr_syntax_call args =
 			match args with
 			match args with
 				| obj_expr :: method_expr :: args ->
 				| obj_expr :: method_expr :: args ->
 					self#write_expr obj_expr;
 					self#write_expr obj_expr;
@@ -2447,7 +2443,7 @@ class code_writer (ctx:Common.context) hx_type_path php_name =
 		(**
 		(**
 			Writes a call to a static method (for `php.Syntax.staticCall()`)
 			Writes a call to a static method (for `php.Syntax.staticCall()`)
 		*)
 		*)
-		method write_expr_lang_static_call args =
+		method write_expr_syntax_static_call args =
 			match args with
 			match args with
 				| type_expr :: method_expr :: args ->
 				| type_expr :: method_expr :: args ->
 					self#write_type type_expr;
 					self#write_type type_expr;
@@ -2460,7 +2456,7 @@ class code_writer (ctx:Common.context) hx_type_path php_name =
 		(**
 		(**
 			Writes field access for reading (for `php.Syntax.getField()`)
 			Writes field access for reading (for `php.Syntax.getField()`)
 		*)
 		*)
-		method write_expr_lang_get_field args =
+		method write_expr_syntax_get_field args =
 			match args with
 			match args with
 				| obj_expr :: field_expr :: [] ->
 				| obj_expr :: field_expr :: [] ->
 					self#write_expr obj_expr;
 					self#write_expr obj_expr;
@@ -2471,7 +2467,7 @@ class code_writer (ctx:Common.context) hx_type_path php_name =
 		(**
 		(**
 			Writes field access for writing (for `php.Syntax.setField()`)
 			Writes field access for writing (for `php.Syntax.setField()`)
 		*)
 		*)
-		method write_expr_lang_set_field args =
+		method write_expr_syntax_set_field args =
 			match args with
 			match args with
 				| obj_expr :: field_expr :: value_expr :: [] ->
 				| obj_expr :: field_expr :: value_expr :: [] ->
 					self#write_expr obj_expr;
 					self#write_expr obj_expr;
@@ -2484,7 +2480,7 @@ class code_writer (ctx:Common.context) hx_type_path php_name =
 		(**
 		(**
 			Writes static field access for reading (for `php.Syntax.getStaticField()`)
 			Writes static field access for reading (for `php.Syntax.getStaticField()`)
 		*)
 		*)
-		method write_expr_lang_get_static_field args =
+		method write_expr_syntax_get_static_field args =
 			match args with
 			match args with
 				| type_expr :: field_expr :: [] ->
 				| type_expr :: field_expr :: [] ->
 					self#write_type type_expr;
 					self#write_type type_expr;
@@ -2495,7 +2491,7 @@ class code_writer (ctx:Common.context) hx_type_path php_name =
 		(**
 		(**
 			Writes static field access for writing (for `php.Syntax.setField()`)
 			Writes static field access for writing (for `php.Syntax.setField()`)
 		*)
 		*)
-		method write_expr_lang_set_static_field args =
+		method write_expr_syntax_set_static_field args =
 			match args with
 			match args with
 				| type_expr :: field_expr :: value_expr :: [] ->
 				| type_expr :: field_expr :: value_expr :: [] ->
 					self#write_expr type_expr;
 					self#write_expr type_expr;
@@ -2508,7 +2504,7 @@ class code_writer (ctx:Common.context) hx_type_path php_name =
 		(**
 		(**
 			Writes `new` expression with class name taken local variable (for `php.Syntax.construct()`)
 			Writes `new` expression with class name taken local variable (for `php.Syntax.construct()`)
 		*)
 		*)
-		method write_expr_lang_construct args =
+		method write_expr_syntax_construct args =
 			let (class_expr, args) = match args with
 			let (class_expr, args) = match args with
 				| class_expr :: args -> (class_expr, args)
 				| class_expr :: args -> (class_expr, args)
 				| _ -> fail self#pos __POS__
 				| _ -> fail self#pos __POS__
@@ -2518,42 +2514,10 @@ class code_writer (ctx:Common.context) hx_type_path php_name =
 			self#write "(";
 			self#write "(";
 			write_args self#write (fun e -> self#write_expr e) args;
 			write_args self#write (fun e -> self#write_expr e) args;
 			self#write ")"
 			self#write ")"
-		(**
-			Writes native php type conversion to output buffer (e.g. `php.Syntax.int()`)
-		*)
-		method write_expr_lang_cast type_name args =
-			match args with
-				| expr :: [] ->
-					let add_parentheses = match self#parent_expr with Some e -> is_access e | None -> false
-					and expr = match expr.eexpr with
-						| TLocal e -> expr
-						| _ -> parenthesis expr
-					in
-					if add_parentheses then self#write "(";
-					self#write ("(" ^ type_name ^")");
-					self#write_expr expr;
-					if add_parentheses then self#write ")"
-				| _ -> fail self#pos __POS__
-		(**
-			Generates binary operation to output buffer (for `php.Syntax.binop()`)
-		*)
-		method write_expr_lang_binop args =
-			match args with
-				| val_expr1 :: operator_expr :: val_expr2 :: [] ->
-					let operator = match operator_expr.eexpr with
-						| TConst (TString operator) -> operator
-						| _ -> error_and_exit self#pos "Second argument for php.Syntax.binop() must be a constant string"
-					in
-					self#write "(";
-					self#write_expr val_expr1;
-					self#write (" " ^ operator ^ " ");
-					self#write_expr val_expr2;
-					self#write ")"
-				| _ -> fail self#pos __POS__
 		(**
 		(**
 			Writes `instanceof` expression to output buffer (for `php.Syntax.instanceof()`)
 			Writes `instanceof` expression to output buffer (for `php.Syntax.instanceof()`)
 		*)
 		*)
-		method write_expr_lang_instanceof args =
+		method write_expr_syntax_instanceof args =
 			match args with
 			match args with
 				| val_expr :: type_expr :: [] ->
 				| val_expr :: type_expr :: [] ->
 					self#write "(";
 					self#write "(";
@@ -2571,7 +2535,7 @@ class code_writer (ctx:Common.context) hx_type_path php_name =
 		(**
 		(**
 			Writes `foreach` expression to output buffer (for `php.Syntax.foreach()`)
 			Writes `foreach` expression to output buffer (for `php.Syntax.foreach()`)
 		*)
 		*)
-		method write_expr_lang_foreach args =
+		method write_expr_syntax_foreach args =
 			match args with
 			match args with
 				| collection_expr :: { eexpr = TFunction fn } :: [] ->
 				| collection_expr :: { eexpr = TFunction fn } :: [] ->
 					let (key_name, value_name) = match fn.tf_args with
 					let (key_name, value_name) = match fn.tf_args with
@@ -2589,7 +2553,7 @@ class code_writer (ctx:Common.context) hx_type_path php_name =
 					self#write (" as $" ^ key_name ^ " => $" ^ value_name ^ ") ");
 					self#write (" as $" ^ key_name ^ " => $" ^ value_name ^ ") ");
 					self#write_as_block fn.tf_expr
 					self#write_as_block fn.tf_expr
 				| _ ->
 				| _ ->
-					error_and_exit self#pos "PHP.foreach() only accepts anonymous function declaration for second argument."
+					ctx.error "php.Syntax.foreach() only accepts anonymous function declaration for second argument." self#pos
 		(**
 		(**
 			Writes TCall to output buffer
 			Writes TCall to output buffer
 		*)
 		*)
@@ -2978,7 +2942,7 @@ class virtual type_builder ctx (wrapper:type_wrapper) =
 			Writes rtti meta to output buffer
 			Writes rtti meta to output buffer
 		*)
 		*)
 		method write_rtti_meta =
 		method write_rtti_meta =
-			match Codegen.build_metadata ctx wrapper#get_module_type with
+			match Texpr.build_metadata ctx.basic wrapper#get_module_type with
 				| None -> ()
 				| None -> ()
 				| Some meta_expr ->
 				| Some meta_expr ->
 					let boot_class = writer#use boot_type_path in
 					let boot_class = writer#use boot_type_path in
@@ -3102,17 +3066,27 @@ class enum_builder ctx (enm:tenum) =
 			write_args writer#write (writer#write_arg true) args;
 			write_args writer#write (writer#write_arg true) args;
 			writer#write ") {\n";
 			writer#write ") {\n";
 			writer#indent_more;
 			writer#indent_more;
-			writer#write_indentation;
-			writer#write "return ";
 			let index_str = string_of_int field.ef_index in
 			let index_str = string_of_int field.ef_index in
+			let write_construction args =
+				writer#write ("new " ^ self#get_name ^ "('" ^ name ^ "', " ^ index_str ^", [");
+				write_args writer#write (fun (name, _, _) -> writer#write ("$" ^ name)) args;
+				writer#write "])"
+			in
 			(match args with
 			(match args with
-				| [] -> writer#write ((writer#use hxenum_type_path) ^ "::singleton(static::class, '" ^ name ^ "', " ^ index_str ^")")
+				| [] ->
+					(* writer#write ((writer#use hxenum_type_path) ^ "::singleton(static::class, '" ^ name ^ "', " ^ index_str ^")") *)
+					writer#write_line "static $inst = null;";
+					writer#write_indentation;
+					writer#write "if (!$inst) $inst = ";
+					write_construction [];
+					writer#write ";\n";
+					writer#write_line "return $inst;"
 				| args ->
 				| args ->
-					writer#write ("new " ^ self#get_name ^ "('" ^ name ^ "', " ^ index_str ^", [");
-					write_args writer#write (fun (name, _, _) -> writer#write ("$" ^ name)) args;
-					writer#write "])"
+					writer#write_indentation;
+					writer#write "return ";
+					write_construction args;
+					writer#write ";\n";
 			);
 			);
-			writer#write ";\n";
 			writer#indent_less;
 			writer#indent_less;
 			writer#write_line "}"
 			writer#write_line "}"
 		(**
 		(**
@@ -3296,15 +3270,8 @@ class class_builder ctx (cls:tclass) =
 						None
 						None
 					else
 					else
 						Some {
 						Some {
-							cf_name = "new";
-							cf_type = TFun ([], get_void ctx);
-							cf_public = true;
-							cf_pos = cls.cl_pos;
-							cf_name_pos = cls.cl_pos;
-							cf_doc = None;
-							cf_meta = [];
+							(mk_field "new" (TFun ([], get_void ctx)) cls.cl_pos cls.cl_pos) with
 							cf_kind = Method MethNormal;
 							cf_kind = Method MethNormal;
-							cf_params = [];
 							cf_expr = Some {
 							cf_expr = Some {
 								eexpr = TFunction {
 								eexpr = TFunction {
 									tf_args = [];
 									tf_args = [];
@@ -3314,8 +3281,6 @@ class class_builder ctx (cls:tclass) =
 								epos = cls.cl_pos;
 								epos = cls.cl_pos;
 								etype = get_void ctx;
 								etype = get_void ctx;
 							};
 							};
-							cf_expr_unoptimized = None;
-							cf_overloads = [];
 						}
 						}
 		(**
 		(**
 			Writes type body to output buffer.
 			Writes type body to output buffer.
@@ -3693,10 +3658,11 @@ class generator (ctx:context) =
 			match self#get_entry_point with
 			match self#get_entry_point with
 				| None -> ()
 				| None -> ()
 				| Some (uses, entry_point) ->
 				| Some (uses, entry_point) ->
-					let filename = match ctx.php_front with None -> "index.php" | Some n -> n in
+					let filename = Common.defined_value_safe ~default:"index.php" ctx Define.PhpFront in
 					let channel = open_out (root_dir ^ "/" ^ filename) in
 					let channel = open_out (root_dir ^ "/" ^ filename) in
 					output_string channel "<?php\n";
 					output_string channel "<?php\n";
 					output_string channel uses;
 					output_string channel uses;
+					output_string channel "\n";
 					output_string channel ("set_include_path(__DIR__.'/" ^ (String.concat "/" self#get_lib_path) ^ "');\n");
 					output_string channel ("set_include_path(__DIR__.'/" ^ (String.concat "/" self#get_lib_path) ^ "');\n");
 					output_string channel "spl_autoload_register(\n";
 					output_string channel "spl_autoload_register(\n";
 					output_string channel "	function($class){\n";
 					output_string channel "	function($class){\n";
@@ -3724,9 +3690,8 @@ class generator (ctx:context) =
 			Returns path from `index.php` to directory which will contain all generated classes
 			Returns path from `index.php` to directory which will contain all generated classes
 		*)
 		*)
 		method private get_lib_path : string list =
 		method private get_lib_path : string list =
-			match ctx.php_lib with
-				| None -> ["lib"];
-				| Some path -> (Str.split (Str.regexp "/")  path)
+			let path = Common.defined_value_safe ~default:"lib" ctx Define.PhpLib in
+			(Str.split (Str.regexp "/")  path)
 		(**
 		(**
 			Returns PHP code for entry point
 			Returns PHP code for entry point
 		*)
 		*)

+ 18 - 11
src/generators/genpy.ml

@@ -21,7 +21,7 @@ open Globals
 open Ast
 open Ast
 open Type
 open Type
 open Common
 open Common
-open Codegen.ExprBuilder
+open Texpr.Builder
 
 
 module Utils = struct
 module Utils = struct
 	let class_of_module_type mt = match mt with
 	let class_of_module_type mt = match mt with
@@ -430,7 +430,7 @@ module Transformer = struct
 			let mk_or e1 e2 = mk (TBinop(OpOr,e1,e2)) !t_bool (punion e1.epos e2.epos) in
 			let mk_or e1 e2 = mk (TBinop(OpOr,e1,e2)) !t_bool (punion e1.epos e2.epos) in
 			let mk_if (el,e) eo =
 			let mk_if (el,e) eo =
 				let eif = List.fold_left (fun eacc e -> mk_or eacc (mk_eq e1 e)) (mk_eq e1 (List.hd el)) (List.tl el) in
 				let eif = List.fold_left (fun eacc e -> mk_or eacc (mk_eq e1 e)) (mk_eq e1 (List.hd el)) (List.tl el) in
-				mk (TIf(Codegen.mk_parent eif,e,eo)) e.etype e.epos
+				mk (TIf(mk_parent eif,e,eo)) e.etype e.epos
 			in
 			in
 			let cases = Hashtbl.fold (fun i el acc ->
 			let cases = Hashtbl.fold (fun i el acc ->
 				let eint = mk (TConst (TInt (Int32.of_int i))) !t_int e1.epos in
 				let eint = mk (TConst (TInt (Int32.of_int i))) !t_int e1.epos in
@@ -1314,7 +1314,7 @@ module Printer = struct
 				begin match follow e.etype with
 				begin match follow e.etype with
 					| TAnon an ->
 					| TAnon an ->
 						PMap.iter (fun s cf ->
 						PMap.iter (fun s cf ->
-							if not (List.mem_assoc s fl) then fl2 := (s,null cf.cf_type cf.cf_pos) :: !fl2
+							if not (Expr.field_mem_assoc s fl) then fl2 := ((s,null_pos,NoQuotes),null cf.cf_type cf.cf_pos) :: !fl2
 						) an.a_fields
 						) an.a_fields
 					| _ ->
 					| _ ->
 						()
 						()
@@ -1426,6 +1426,8 @@ module Printer = struct
 				Printf.sprintf "len(%s)" (print_expr pctx e1)
 				Printf.sprintf "len(%s)" (print_expr pctx e1)
 			| FInstance(c,_,{cf_name = "length"}) when (is_type "" "str")(TClassDecl c) ->
 			| FInstance(c,_,{cf_name = "length"}) when (is_type "" "str")(TClassDecl c) ->
 				Printf.sprintf "len(%s)" (print_expr pctx e1)
 				Printf.sprintf "len(%s)" (print_expr pctx e1)
+			| FAnon({cf_name = "length"}) | FDynamic ("length") ->
+				Printf.sprintf "HxOverrides.length(%s)" (print_expr pctx e1)
 			| FStatic(c,{cf_name = "fromCharCode"}) when (is_type "" "str")(TClassDecl c) ->
 			| FStatic(c,{cf_name = "fromCharCode"}) when (is_type "" "str")(TClassDecl c) ->
 				Printf.sprintf "HxString.fromCharCode"
 				Printf.sprintf "HxString.fromCharCode"
 			| FStatic({cl_path = ["python";"internal"],"UBuiltins"},{cf_name = s}) ->
 			| FStatic({cl_path = ["python";"internal"],"UBuiltins"},{cf_name = s}) ->
@@ -1469,13 +1471,16 @@ module Printer = struct
 			let assign = if is_empty_expr then "" else Printf.sprintf "%s = _hx_e1\n%s" v.v_name indent in
 			let assign = if is_empty_expr then "" else Printf.sprintf "%s = _hx_e1\n%s" v.v_name indent in
 			let handle_base_type bt =
 			let handle_base_type bt =
 				let t = print_base_type bt in
 				let t = print_base_type bt in
+				let print_custom_check t_str =
+					Printf.sprintf "if %s:\n%s    %s    %s" t_str indent assign (print_expr {pctx with pc_indent = "    " ^ pctx.pc_indent} e)
+				in
 				let print_type_check t_str =
 				let print_type_check t_str =
-					Printf.sprintf "if isinstance(_hx_e1, %s):\n%s    %s    %s" t_str indent assign (print_expr {pctx with pc_indent = "    " ^ pctx.pc_indent} e)
+					print_custom_check ("isinstance(_hx_e1, " ^ t_str ^ ")")
 				in
 				in
 				let res = match t with
 				let res = match t with
 				| "str" -> print_type_check "str"
 				| "str" -> print_type_check "str"
 				| "Bool" -> print_type_check "bool"
 				| "Bool" -> print_type_check "bool"
-				| "Int" -> print_type_check "int"
+				| "Int" -> print_custom_check "(isinstance(_hx_e1, int) and not isinstance(_hx_e1, bool))" (* for historic reasons bool extends int *)
 				| "Float" -> print_type_check "float"
 				| "Float" -> print_type_check "float"
 				| t -> print_type_check t
 				| t -> print_type_check t
 				in
 				in
@@ -1616,7 +1621,7 @@ module Printer = struct
 					"print(" ^ (print_expr pctx e) ^ ")"
 					"print(" ^ (print_expr pctx e) ^ ")"
 				else
 				else
 					"print(str(" ^ (print_expr pctx e) ^ "))"
 					"print(str(" ^ (print_expr pctx e) ^ "))"
-			| TField(e1,((FAnon {cf_name = (("join" | "push" | "map" | "filter") as s)}) | FDynamic (("join" | "push" | "map" | "filter") as s))), [x] ->
+			| TField(e1,((FAnon {cf_name = (("split" | "join" | "push" | "map" | "filter") as s)}) | FDynamic (("split" | "join" | "push" | "map" | "filter") as s))), [x] ->
 				Printf.sprintf "HxOverrides.%s(%s, %s)" s (print_expr pctx e1) (print_expr pctx x)
 				Printf.sprintf "HxOverrides.%s(%s, %s)" s (print_expr pctx e1) (print_expr pctx x)
 			| TField(e1,((FAnon {cf_name = (("iterator" | "toUpperCase" | "toLowerCase" | "pop" | "shift") as s)}) | FDynamic (("iterator" | "toUpperCase" | "toLowerCase" | "pop" | "shift") as s))), [] ->
 			| TField(e1,((FAnon {cf_name = (("iterator" | "toUpperCase" | "toLowerCase" | "pop" | "shift") as s)}) | FDynamic (("iterator" | "toUpperCase" | "toLowerCase" | "pop" | "shift") as s))), [] ->
 				Printf.sprintf "HxOverrides.%s(%s)" s (print_expr pctx e1)
 				Printf.sprintf "HxOverrides.%s(%s)" s (print_expr pctx e1)
@@ -1683,10 +1688,10 @@ 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" (Ast.s_escape (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
 		Printf.sprintf "%s" args
 		Printf.sprintf "%s" args
 	let handle_keywords s =
 	let handle_keywords s =
 		KeywordHandler.handle_keywords s
 		KeywordHandler.handle_keywords s
@@ -2153,7 +2158,7 @@ module Generator = struct
 		gen_class_init ctx c
 		gen_class_init ctx c
 
 
 	let gen_enum_metadata ctx en p =
 	let gen_enum_metadata ctx en p =
-		let meta = Codegen.build_metadata ctx.com (TEnumDecl en) in
+		let meta = Texpr.build_metadata ctx.com.basic (TEnumDecl en) in
 		match meta with
 		match meta with
 			| None ->
 			| None ->
 				()
 				()
@@ -2370,7 +2375,9 @@ module Generator = struct
 			spr ctx "class _hx_AnonObject:\n";
 			spr ctx "class _hx_AnonObject:\n";
 			if with_body then begin
 			if with_body then begin
 				spr ctx "    def __init__(self, fields):\n";
 				spr ctx "    def __init__(self, fields):\n";
-				spr ctx "        self.__dict__ = fields"
+				spr ctx "        self.__dict__ = fields\n";
+				spr ctx "    def __repr__(self):\n";
+				spr ctx "        return repr(self.__dict__)"
 			end else
 			end else
 				spr ctx "    pass";
 				spr ctx "    pass";
 			Hashtbl.add used_paths ([],"_hx_AnonObject") true;
 			Hashtbl.add used_paths ([],"_hx_AnonObject") true;
@@ -2428,7 +2435,7 @@ module Generator = struct
 		gen_static_inits ctx;
 		gen_static_inits ctx;
 		gen_main ctx;
 		gen_main ctx;
 
 
-		mkdir_from_path com.file;
+		Path.mkdir_from_path com.file;
 		let ch = open_out_bin com.file in
 		let ch = open_out_bin com.file in
 		output_string ch (Buffer.contents ctx.buf);
 		output_string ch (Buffer.contents ctx.buf);
 		close_out ch
 		close_out ch

+ 2 - 2
src/generators/genswf.ml

@@ -85,7 +85,7 @@ let build_dependencies t =
 		| TDynamic t2 ->
 		| TDynamic t2 ->
 			add_type_rec (t::l) t2;
 			add_type_rec (t::l) t2;
 		| TLazy f ->
 		| TLazy f ->
-			add_type_rec l ((!f)())
+			add_type_rec l (lazy_type f)
 		| TMono r ->
 		| TMono r ->
 			(match !r with
 			(match !r with
 			| None -> ()
 			| None -> ()
@@ -638,7 +638,7 @@ let generate swf_header com =
 		{header with h_frame_count = header.h_frame_count + 1},loop tags
 		{header with h_frame_count = header.h_frame_count + 1},loop tags
 	| _ -> swf in
 	| _ -> swf in
 	(* write swf/swc *)
 	(* write swf/swc *)
-	let t = Common.timer ["write";"swf"] in
+	let t = Timer.timer ["write";"swf"] in
 	let level = (try int_of_string (Common.defined_value com Define.SwfCompressLevel) with Not_found -> 9) in
 	let level = (try int_of_string (Common.defined_value com Define.SwfCompressLevel) with Not_found -> 9) in
 	SwfParser.init Extc.input_zip (Extc.output_zip ~level);
 	SwfParser.init Extc.input_zip (Extc.output_zip ~level);
 	(match swc with
 	(match swc with

+ 5 - 14
src/generators/genswf9.ml

@@ -188,7 +188,7 @@ let rec follow_basic t =
 		| Some t -> follow_basic t
 		| Some t -> follow_basic t
 		| _ -> t)
 		| _ -> t)
 	| TLazy f ->
 	| TLazy f ->
-		follow_basic (!f())
+		follow_basic (lazy_type f)
 	| TAbstract ({ a_path = [],"Null" },[tp]) ->
 	| TAbstract ({ a_path = [],"Null" },[tp]) ->
 		(match follow_basic tp with
 		(match follow_basic tp with
 		| TMono _
 		| TMono _
@@ -1025,7 +1025,7 @@ let rec gen_expr_content ctx retval e =
 	| TParenthesis e | TMeta (_,e) ->
 	| TParenthesis e | TMeta (_,e) ->
 		gen_expr ctx retval e
 		gen_expr ctx retval e
 	| TObjectDecl fl ->
 	| TObjectDecl fl ->
-		List.iter (fun (name,e) ->
+		List.iter (fun ((name,_,_),e) ->
 			write ctx (HString (reserved name));
 			write ctx (HString (reserved name));
 			gen_expr ctx true e
 			gen_expr ctx true e
 		) fl;
 		) fl;
@@ -1788,7 +1788,7 @@ let generate_construct ctx fdata c =
 	(* if skip_constructor, then returns immediatly *)
 	(* if skip_constructor, then returns immediatly *)
 	if ctx.need_ctor_skip then (match c.cl_kind with
 	if ctx.need_ctor_skip then (match c.cl_kind with
 	| KGenericInstance _ -> ()
 	| KGenericInstance _ -> ()
-	| _ when not (Codegen.constructor_side_effects fdata.tf_expr) -> ()
+	| _ when not (Texpr.constructor_side_effects fdata.tf_expr) -> ()
 	| _ ->
 	| _ ->
 		let id = ident "skip_constructor" in
 		let id = ident "skip_constructor" in
 		getvar ctx (VGlobal (type_path ctx (["flash"],"Boot")));
 		getvar ctx (VGlobal (type_path ctx (["flash"],"Boot")));
@@ -2133,18 +2133,9 @@ let generate_class ctx c =
 	let fields = if c.cl_path <> ctx.boot then fields else begin
 	let fields = if c.cl_path <> ctx.boot then fields else begin
 		{
 		{
 			hlf_name = make_name {
 			hlf_name = make_name {
-				cf_name = "init";
+				(mk_field "init" (TFun ([],t_dynamic)) c.cl_pos null_pos) with
 				cf_public = ctx.swc && ctx.swf_protected;
 				cf_public = ctx.swc && ctx.swf_protected;
-				cf_meta = [];
-				cf_doc = None;
-				cf_pos = c.cl_pos;
-				cf_name_pos = null_pos;
-				cf_type = TFun ([],t_dynamic);
-				cf_params = [];
-				cf_expr = None;
-				cf_expr_unoptimized = None;
 				cf_kind = Method MethNormal;
 				cf_kind = Method MethNormal;
-				cf_overloads = [];
 			} false;
 			} false;
 			hlf_slot = 0;
 			hlf_slot = 0;
 			hlf_kind = (HFMethod {
 			hlf_kind = (HFMethod {
@@ -2336,7 +2327,7 @@ let rec generate_type ctx t =
 		if e.e_extern then
 		if e.e_extern then
 			None
 			None
 		else
 		else
-			let meta = Codegen.build_metadata ctx.com t in
+			let meta = Texpr.build_metadata ctx.com.basic t in
 			let hlc = generate_enum ctx e meta in
 			let hlc = generate_enum ctx e meta in
 			let init = begin_fun ctx [] ctx.com.basic.tvoid [ethis] false e.e_pos in
 			let init = begin_fun ctx [] ctx.com.basic.tvoid [ethis] false e.e_pos in
 			generate_enum_init ctx e hlc meta;
 			generate_enum_init ctx e hlc meta;

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