瀏覽代碼

Merge branch 'development' into out_of_curiosity_(don't_freak_out)

# Conflicts:
#	.github/workflows/main.yml
#	libs/ilib/dune
#	libs/ilib/peReader.ml
#	libs/javalib/dune
#	src-json/define.json
#	src/codegen/dotnet.ml
#	src/codegen/gencommon/castDetect.ml
#	src/codegen/gencommon/closuresToClass.ml
#	src/codegen/gencommon/dynamicFieldAccess.ml
#	src/codegen/gencommon/dynamicOperators.ml
#	src/codegen/gencommon/enumToClass.ml
#	src/codegen/gencommon/enumToClass2.ml
#	src/codegen/gencommon/expressionUnwrap.ml
#	src/codegen/gencommon/filterClosures.ml
#	src/codegen/gencommon/fixOverrides.ml
#	src/codegen/gencommon/gencommon.ml
#	src/codegen/gencommon/initFunction.ml
#	src/codegen/gencommon/overloadingConstructor.ml
#	src/codegen/gencommon/realTypeParams.ml
#	src/codegen/gencommon/reflectionCFs.ml
#	src/codegen/gencommon/switchToIf.ml
#	src/codegen/gencommon/unnecessaryCastsRemoval.ml
#	src/codegen/gencommon/unreachableCodeEliminationSynf.ml
#	src/codegen/java.ml
#	src/codegen/javaModern.ml
#	src/context/common.ml
#	src/dune
#	src/filters/filters.ml
#	src/generators/gencs.ml
#	src/generators/genjava.ml
#	src/generators/genshared.ml
#	src/optimization/analyzerTexpr.ml
#	src/typing/matcher.ml
#	src/typing/typeloadCheck.ml
#	src/typing/typeloadFields.ml
#	src/typing/typeloadModule.ml
#	src/typing/typer.ml
#	std/cs/_std/Type.hx
#	tests/server/src/cases/ServerTests.hx
Simon Krajewski 1 年之前
父節點
當前提交
f1acd1a098
共有 100 個文件被更改,包括 2484 次插入1570 次删除
  1. 130 98
      .github/workflows/main.yml
  2. 4 0
      .vscode/schemas/define.schema.json
  3. 4 1
      Earthfile
  4. 1 1
      Makefile.win
  5. 2 1
      dune
  6. 1 1
      extra/BUILDING.md
  7. 50 1
      extra/CHANGES.txt
  8. 1 1
      extra/EnvVarUpdate.nsh
  9. 37 38
      extra/ImportAll.hx
  10. 3 4
      extra/github-actions/build-mac.yml
  11. 8 1
      extra/github-actions/build-windows.yml
  12. 0 6
      extra/github-actions/cache-opam.yml
  13. 4 2
      extra/github-actions/install-nsis.yml
  14. 2 7
      extra/github-actions/install-ocaml-libs-windows.yml
  15. 30 8
      extra/github-actions/install-ocaml-windows.yml
  16. 11 7
      extra/github-actions/install-ocaml-windows64.yml
  17. 4 0
      extra/github-actions/test-windows.yml
  18. 49 46
      extra/github-actions/workflows/main.yml
  19. 14 10
      extra/release-checklist.txt
  20. 5 4
      haxe.opam
  21. 3 3
      libs/extc/extc.ml
  22. 21 21
      libs/extc/extc_stubs.c
  23. 2 2
      libs/extc/process_stubs.c
  24. 7 1
      libs/extlib-leftovers/dune
  25. 5 5
      libs/extlib-leftovers/multiArray.ml
  26. 1 1
      libs/extlib-leftovers/uTF8.ml
  27. 7 1
      libs/neko/dune
  28. 2 2
      libs/neko/ncompile.ml
  29. 27 4
      libs/objsize/c_objsize.c
  30. 7 1
      libs/swflib/dune
  31. 1 1
      libs/swflib/swfParser.ml
  32. 1 1
      libs/swflib/swfPic.ml
  33. 7 1
      libs/ttflib/dune
  34. 1 1
      libs/ttflib/tTFParser.ml
  35. 7 1
      libs/ziplib/dune
  36. 8 8
      libs/ziplib/zip.ml
  37. 7 1
      plugins/example/dune
  38. 50 30
      src-json/define.json
  39. 10 0
      src-json/warning.json
  40. 7 1
      src-prebuild/dune
  41. 56 28
      src-prebuild/prebuild.ml
  42. 6 11
      src/codegen/codegen.ml
  43. 85 3
      src/codegen/javaModern.ml
  44. 0 6
      src/codegen/overloads.ml
  45. 3 3
      src/codegen/swfLoader.ml
  46. 5 1
      src/compiler/args.ml
  47. 11 11
      src/compiler/compilationContext.ml
  48. 107 57
      src/compiler/compiler.ml
  49. 3 7
      src/compiler/displayOutput.ml
  50. 10 10
      src/compiler/displayProcessing.ml
  51. 11 9
      src/compiler/generate.ml
  52. 14 3
      src/compiler/helper.ml
  53. 388 0
      src/compiler/messageReporting.ml
  54. 12 14
      src/compiler/retyper.ml
  55. 67 402
      src/compiler/server.ml
  56. 1 1
      src/compiler/serverCompilationContext.ml
  57. 2 1
      src/compiler/serverConfig.ml
  58. 7 1
      src/compiler/serverMessage.ml
  59. 15 16
      src/context/abstractCast.ml
  60. 183 63
      src/context/common.ml
  61. 39 55
      src/context/display/deprecationCheck.ml
  62. 33 35
      src/context/display/diagnostics.ml
  63. 20 17
      src/context/display/diagnosticsPrinter.ml
  64. 1 4
      src/context/display/display.ml
  65. 12 2
      src/context/display/displayEmitter.ml
  66. 8 8
      src/context/display/displayException.ml
  67. 24 20
      src/context/display/displayFields.ml
  68. 9 3
      src/context/display/displayJson.ml
  69. 3 6
      src/context/display/displayTexpr.ml
  70. 4 5
      src/context/display/displayToplevel.ml
  71. 1 1
      src/context/display/documentSymbols.ml
  72. 1 3
      src/context/display/findReferences.ml
  73. 64 58
      src/context/display/importHandling.ml
  74. 1 4
      src/context/display/statistics.ml
  75. 9 7
      src/context/memory.ml
  76. 1 2
      src/context/nativeLibraries.ml
  77. 2 2
      src/context/purityState.ml
  78. 248 0
      src/context/resolution.ml
  79. 1 3
      src/context/sourcemaps.ml
  80. 126 81
      src/context/typecore.ml
  81. 2 4
      src/core/abstract.ml
  82. 5 5
      src/core/ast.ml
  83. 8 2
      src/core/define.ml
  84. 6 4
      src/core/displayTypes.ml
  85. 51 35
      src/core/error.ml
  86. 68 29
      src/core/globals.ml
  87. 3 5
      src/core/inheritDoc.ml
  88. 8 6
      src/core/json/genjson.ml
  89. 6 0
      src/core/meta.ml
  90. 2 2
      src/core/path.ml
  91. 12 3
      src/core/tFunctions.ml
  92. 4 4
      src/core/tOther.ml
  93. 34 96
      src/core/tPrinting.ml
  94. 33 4
      src/core/tType.ml
  95. 9 9
      src/core/tUnification.ml
  96. 79 65
      src/core/texpr.ml
  97. 4 2
      src/core/timer.ml
  98. 3 3
      src/core/warning.ml
  99. 13 5
      src/dune
  100. 0 1
      src/filters/defaultArguments.ml

+ 130 - 98
.github/workflows/main.yml

@@ -10,13 +10,9 @@ jobs:
     env:
       ACTIONS_ALLOW_UNSECURE_COMMANDS: true
       PLATFORM: windows64
-      OPAMYES: 1
-      OPAMROOT: D:\.opam
-      CYG_MIRROR: http://mirrors.kernel.org/sourceware/cygwin/
       ARCH: 64
       MINGW_ARCH: x86_64
-      CYGWIN_SETUP: https://cygwin.com/setup-x86_64.exe
-      CYG_ROOT: C:/cygwin64
+      CYG_ROOT: D:\cygwin
     steps:
       - uses: actions/checkout@main
         with:
@@ -27,12 +23,20 @@ jobs:
           echo "C:\msys64\usr\bin" | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append
           rm C:\msys64\usr\bin\bash.exe
 
-      - name: Cache opam
-        id: cache-opam
-        uses: actions/[email protected]
+      - name: choco install nsis
+        uses: nick-invision/retry@v2
         with:
-          path: D:\.opam
-          key: ${{ runner.os }}64-${{ hashFiles('./opam', './libs/') }}
+          timeout_minutes: 10
+          max_attempts: 10
+          command: choco install --no-progress nsis.portable --version 3.09 -y
+
+      - name: choco install things
+        shell: pwsh
+        run: choco install --no-progress curl wget 7zip.portable -y
+
+      - name: Prepend Chocolatey path
+        shell: pwsh
+        run: Write-Host "::add-path::C:\ProgramData\chocolatey\bin"
 
       - name: Install Neko from S3
         shell: pwsh
@@ -46,47 +50,33 @@ jobs:
       - name: Print Neko version
         run: neko -version 2>&1
 
-      - name: choco install nsis
-        uses: nick-invision/retry@v1
+      - name: Setup ocaml
+        uses: ocaml/setup-ocaml@v2
         with:
-          timeout_minutes: 10
-          max_attempts: 10
-          command: choco install --no-progress nsis.portable --version 3.02 -y
-      - name: choco install things
-        shell: pwsh
-        run: choco install --no-progress curl wget 7zip.portable -y
-      - name: Prepend Chocolatey path
-        shell: pwsh
-        run: Write-Host "::add-path::C:\ProgramData\chocolatey\bin"
+          ocaml-compiler: 4.08.1
+          opam-repositories: |
+            opam-repository-mingw: https://github.com/ocaml-opam/opam-repository-mingw.git#sunset
+            default: https://github.com/ocaml/opam-repository.git
+          opam-local-packages: |
+            haxe.opam
 
-      - name: Install OCaml
+      - name: Install dependencies
         shell: pwsh
         run: |
           Set-PSDebug -Trace 1
-          curl.exe -fsSL -o cygwin-setup.exe --retry 3 $($env:CYGWIN_SETUP)
-          Start-Process -FilePath "cygwin-setup.exe" -ArgumentList "-B -q -R $($env:CYG_ROOT) -l C:/tmp -s $($env:CYG_MIRROR) -P default -P make -P git -P zlib-devel -P rsync -P patch -P diffutils -P curl -P unzip -P tar -P m4 -P perl -P libpcre2-devel -P mbedtls-devel -P mingw64-$($env:MINGW_ARCH)-zlib -P mingw64-$($env:MINGW_ARCH)-gcc-core -P mingw64-$($env:MINGW_ARCH)-pcre2" -Wait -RedirectStandardOutput cygwin-setup-out.txt
-          Get-Content cygwin-setup-out.txt
-          curl.exe -fsSL -o "opam.tar.xz" --retry 3 https://github.com/fdopen/opam-repository-mingw/releases/download/0.0.0.2/opam$($env:ARCH).tar.xz
           curl.exe -fsSL -o "libmbedtls.tar.xz" --retry 3 https://github.com/Simn/mingw64-mbedtls/releases/download/2.16.3/mingw64-$($env:MINGW_ARCH)-mbedtls-2.16.3-1.tar.xz
           & "$($env:CYG_ROOT)/bin/bash.exe" @('-lc', 'curl -L https://cpanmin.us | perl - App::cpanminus')
           & "$($env:CYG_ROOT)/bin/bash.exe" @('-lc', 'cpanm IPC::System::Simple module')
           & "$($env:CYG_ROOT)/bin/bash.exe" @('-lc', 'cpanm String::ShellQuote')
           & "$($env:CYG_ROOT)/bin/bash.exe" @('-lc', 'echo "$OLDPWD"')
           & "$($env:CYG_ROOT)/bin/bash.exe" @('-lc', 'cd "$OLDPWD" && tar -C / -xvf libmbedtls.tar.xz')
-          & "$($env:CYG_ROOT)/bin/bash.exe" @('-lc', 'cd "$OLDPWD" && tar -xf opam.tar.xz')
-          & "$($env:CYG_ROOT)/bin/bash.exe" @('-lc', 'cd "$OLDPWD" && bash opam${ARCH}/install.sh')
 
       - name: Install OCaml libraries
-        if: steps.cache-opam.outputs.cache-hit != 'true'
         shell: pwsh
         run: |
           Set-PSDebug -Trace 1
-          & "$($env:CYG_ROOT)/bin/bash.exe" @('-lc', 'opam init mingw "https://github.com/fdopen/opam-repository-mingw.git#opam2" --comp 4.07.0+mingw${ARCH}c --switch 4.07.0+mingw${ARCH}c --auto-setup --yes 2>&1')
-          & "$($env:CYG_ROOT)/bin/bash.exe" @('-lc', 'opam update --yes 2>&1')
-          & "$($env:CYG_ROOT)/bin/bash.exe" @('-lc', 'cd "$OLDPWD" && opam pin add haxe . --kind=path --no-action --yes 2>&1')
-          & "$($env:CYG_ROOT)/bin/bash.exe" @('-lc', 'opam install haxe --deps-only --yes 2>&1')
-          & "$($env:CYG_ROOT)/bin/bash.exe" @('-lc', 'opam list')
-          & "$($env:CYG_ROOT)/bin/bash.exe" @('-lc', 'ocamlopt -v')
+          opam install haxe --deps-only
+          opam list
 
       - name: Expose mingw dll files
         shell: pwsh
@@ -116,8 +106,15 @@ jobs:
           & "$($env:CYG_ROOT)/bin/bash.exe" @('-lc', 'cd "$OLDPWD" && cygcheck ./haxelib.exe')
           & "$($env:CYG_ROOT)/bin/bash.exe" @('-lc', 'cd "$OLDPWD" && ls ./out')
 
+      - name: Check artifact
+        shell: bash
+        run: |
+          ls out
+          # Output should contain binaries zip, installer zip and nupkg
+          [ $(ls -1 out | wc -l) -eq "3" ]
+
       - name: Upload artifact
-        uses: actions/[email protected]
+        uses: actions/upload-artifact@v3
         with:
           name: win${{env.ARCH}}Binaries
           path: out
@@ -128,13 +125,9 @@ jobs:
     env:
       ACTIONS_ALLOW_UNSECURE_COMMANDS: true
       PLATFORM: windows
-      OPAMYES: 1
-      OPAMROOT: D:\.opam
-      CYG_MIRROR: http://mirrors.kernel.org/sourceware/cygwin-archive/20221123
       ARCH: 32
       MINGW_ARCH: i686
-      CYGWIN_SETUP: https://cygwin.com/setup-x86.exe
-      CYG_ROOT: C:/cygwin
+      CYG_ROOT: D:\cygwin
     steps:
       - uses: actions/checkout@main
         with:
@@ -145,12 +138,20 @@ jobs:
           echo "C:\msys64\usr\bin" | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append
           rm C:\msys64\usr\bin\bash.exe
 
-      - name: Cache opam
-        id: cache-opam
-        uses: actions/[email protected]
+      - name: choco install nsis
+        uses: nick-invision/retry@v2
         with:
-          path: D:\.opam
-          key: ${{ runner.os }}32-${{ hashFiles('./opam', './libs/') }}
+          timeout_minutes: 10
+          max_attempts: 10
+          command: choco install --no-progress nsis.portable --version 3.09 -y
+
+      - name: choco install things
+        shell: pwsh
+        run: choco install --no-progress curl wget 7zip.portable -y
+
+      - name: Prepend Chocolatey path
+        shell: pwsh
+        run: Write-Host "::add-path::C:\ProgramData\chocolatey\bin"
 
       - name: Install Neko from S3
         shell: pwsh
@@ -164,48 +165,52 @@ jobs:
       - name: Print Neko version
         run: neko -version 2>&1
 
-      - name: choco install nsis
-        uses: nick-invision/retry@v1
+      - name: Setup ocaml
+        id: ocaml
+        continue-on-error: true
+        uses: kLabz/setup-ocaml@win32
         with:
-          timeout_minutes: 10
-          max_attempts: 10
-          command: choco install --no-progress nsis.portable --version 3.02 -y
-      - name: choco install things
-        shell: pwsh
-        run: choco install --no-progress curl wget 7zip.portable -y
-      - name: Prepend Chocolatey path
-        shell: pwsh
-        run: Write-Host "::add-path::C:\ProgramData\chocolatey\bin"
+          ocaml-compiler: 4.08.1
+          opam-depext: false
+          opam-repositories: |
+            opam-repository-mingw: https://github.com/ocaml-opam/opam-repository-mingw.git#sunset
+            default: https://github.com/ocaml/opam-repository.git
+          opam-local-packages: |
+            haxe.opam
+          cache-prefix: w32-v1
+
+      # TODO make it work on first try
+      # (when cygwin cache doesn't exist, ocaml install fails with a curl error)
+      - name: Setup ocaml (second chance)
+        if: steps.ocaml.outcome == 'failure'
+        uses: kLabz/setup-ocaml@win32
+        with:
+          ocaml-compiler: 4.08.1
+          opam-depext: false
+          opam-repositories: |
+            opam-repository-mingw: https://github.com/ocaml-opam/opam-repository-mingw.git#sunset
+            default: https://github.com/ocaml/opam-repository.git
+          opam-local-packages: |
+            haxe.opam
+          cache-prefix: w32-v1
 
-      - name: Install OCaml
+      - name: Install dependencies
         shell: pwsh
         run: |
           Set-PSDebug -Trace 1
-          curl.exe -fsSL -o cygwin-setup.exe --retry 3 $($env:CYGWIN_SETUP)
-          Start-Process -FilePath "cygwin-setup.exe" -ArgumentList "-B -q -R $($env:CYG_ROOT) -l C:/tmp -s $($env:CYG_MIRROR) -P default -P make -P git -P zlib-devel -P rsync -P patch -P diffutils -P curl -P unzip -P tar -P m4 -P perl -P libpcre2-devel -P mbedtls-devel -P mingw64-$($env:MINGW_ARCH)-zlib -P mingw64-$($env:MINGW_ARCH)-gcc-core -P mingw64-$($env:MINGW_ARCH)-pcre2 --allow-unsupported-windows" -Wait -RedirectStandardOutput cygwin-setup-out.txt
-          Get-Content cygwin-setup-out.txt
-          & "$($env:CYG_ROOT)/bin/bash.exe" @('--norc', '--noprofile', '/etc/postinstall/ca-certificates.sh')
-          curl.exe -fsSL -o "opam.tar.xz" --retry 3 https://github.com/fdopen/opam-repository-mingw/releases/download/0.0.0.2/opam$($env:ARCH).tar.xz
           curl.exe -fsSL -o "libmbedtls.tar.xz" --retry 3 https://github.com/Simn/mingw64-mbedtls/releases/download/2.16.3/mingw64-$($env:MINGW_ARCH)-mbedtls-2.16.3-1.tar.xz
           & "$($env:CYG_ROOT)/bin/bash.exe" @('-lc', 'curl -L https://cpanmin.us | perl - App::cpanminus')
           & "$($env:CYG_ROOT)/bin/bash.exe" @('-lc', 'cpanm IPC::System::Simple module')
           & "$($env:CYG_ROOT)/bin/bash.exe" @('-lc', 'cpanm String::ShellQuote')
           & "$($env:CYG_ROOT)/bin/bash.exe" @('-lc', 'echo "$OLDPWD"')
           & "$($env:CYG_ROOT)/bin/bash.exe" @('-lc', 'cd "$OLDPWD" && tar -C / -xvf libmbedtls.tar.xz')
-          & "$($env:CYG_ROOT)/bin/bash.exe" @('-lc', 'cd "$OLDPWD" && tar -xf opam.tar.xz')
-          & "$($env:CYG_ROOT)/bin/bash.exe" @('-lc', 'cd "$OLDPWD" && bash opam${ARCH}/install.sh')
 
       - name: Install OCaml libraries
-        if: steps.cache-opam.outputs.cache-hit != 'true'
         shell: pwsh
         run: |
           Set-PSDebug -Trace 1
-          & "$($env:CYG_ROOT)/bin/bash.exe" @('-lc', 'opam init mingw "https://github.com/fdopen/opam-repository-mingw.git#opam2" --comp 4.07.0+mingw${ARCH}c --switch 4.07.0+mingw${ARCH}c --auto-setup --yes 2>&1')
-          & "$($env:CYG_ROOT)/bin/bash.exe" @('-lc', 'opam update --yes 2>&1')
-          & "$($env:CYG_ROOT)/bin/bash.exe" @('-lc', 'cd "$OLDPWD" && opam pin add haxe . --kind=path --no-action --yes 2>&1')
-          & "$($env:CYG_ROOT)/bin/bash.exe" @('-lc', 'opam install haxe --deps-only --yes 2>&1')
-          & "$($env:CYG_ROOT)/bin/bash.exe" @('-lc', 'opam list')
-          & "$($env:CYG_ROOT)/bin/bash.exe" @('-lc', 'ocamlopt -v')
+          opam install haxe --deps-only
+          opam list
 
       - name: Expose mingw dll files
         shell: pwsh
@@ -235,8 +240,15 @@ jobs:
           & "$($env:CYG_ROOT)/bin/bash.exe" @('-lc', 'cd "$OLDPWD" && cygcheck ./haxelib.exe')
           & "$($env:CYG_ROOT)/bin/bash.exe" @('-lc', 'cd "$OLDPWD" && ls ./out')
 
+      - name: Check artifact
+        shell: bash
+        run: |
+          ls out
+          # Output should contain binaries zip, installer zip and nupkg
+          [ $(ls -1 out | wc -l) -eq "3" ]
+
       - name: Upload artifact
-        uses: actions/[email protected]
+        uses: actions/upload-artifact@v3
         with:
           name: win${{env.ARCH}}Binaries
           path: out
@@ -247,6 +259,10 @@ jobs:
     env:
       PLATFORM: linux64
       OPAMYES: 1
+    strategy:
+      fail-fast: false
+      matrix:
+        ocaml: ["4.08.1", "5.0.0"]
     steps:
       - uses: actions/checkout@main
         with:
@@ -257,7 +273,7 @@ jobs:
         uses: actions/[email protected]
         with:
           path: ~/.opam/
-          key: ${{ runner.os }}-${{ hashFiles('./opam', './libs/') }}-2
+          key: ${{ runner.os }}-${{ matrix.ocaml }}-${{ hashFiles('./haxe.opam', './libs/') }}
 
       - name: Install Neko from S3
         run: |
@@ -291,6 +307,7 @@ jobs:
           set -ex
           opam init # --disable-sandboxing
           opam update
+          opam switch create ${{ matrix.ocaml }}
           opam pin add haxe . --no-action
           opam install haxe --deps-only --assume-depexts
           opam list
@@ -315,9 +332,10 @@ jobs:
       - name: Extract branch name
         id: extract_branch
         shell: bash
-        run: echo "##[set-output name=branch;]$(echo ${GITHUB_REF#refs/heads/})"
+        run: echo "branch=${GITHUB_REF#refs/heads/}" >> $GITHUB_OUTPUT
 
       - name: Build xmldoc
+        if: matrix.ocaml == '4.08.1'
         run: |
           set -ex
           make -s xmldoc
@@ -329,13 +347,14 @@ jobs:
           EOL
 
       - name: Upload artifact
-        uses: actions/upload-artifact@v1.0.0
+        uses: actions/upload-artifact@v3
         with:
-          name: linuxBinaries
+          name: linuxBinaries${{ (matrix.ocaml == '5.0.0' && '_ocaml5') || '' }}
           path: out
 
       - name: Upload xmldoc artifact
-        uses: actions/[email protected]
+        uses: actions/upload-artifact@v3
+        if: matrix.ocaml == '4.08.1'
         with:
           name: xmldoc
           path: extra/doc
@@ -351,7 +370,8 @@ jobs:
     strategy:
       fail-fast: false
       matrix:
-        target: [macro, js, hl, cpp, 'jvm', php, python, lua, flash, neko]
+        ocaml: ["4.08.1", "5.0.0"]
+        target: [macro, js, hl, cpp, 'jvm', cs, php, python, lua, flash, neko]
         include:
           - target: hl
             APT_PACKAGES: cmake ninja-build libturbojpeg-dev
@@ -365,9 +385,10 @@ jobs:
       - uses: actions/checkout@main
         with:
           submodules: recursive
-      - uses: actions/download-artifact@v1
+      - uses: actions/download-artifact@v3
         with:
-          name: linuxBinaries
+          name: linuxBinaries${{ (matrix.ocaml == '5.0.0' && '_ocaml5') || '' }}
+          path: linuxBinaries
 
       - name: Install Neko from S3
         run: |
@@ -434,12 +455,13 @@ jobs:
         with:
           submodules: recursive
 
-      - uses: actions/download-artifact@v1
+      - uses: actions/download-artifact@v3
         with:
           name: linuxBinaries
+          path: linuxBinaries
 
       - name: Download xmldoc artifact
-        uses: actions/download-artifact@v2
+        uses: actions/download-artifact@v3
         with:
           name: xmldoc
           path: xmldoc
@@ -508,7 +530,7 @@ jobs:
       FORCE_COLOR: 1
     steps:
       - name: Login to GitHub Container Registry
-        uses: docker/login-action@v1
+        uses: docker/login-action@v2
         with:
           registry: ghcr.io
           username: ${{ github.actor }}
@@ -519,7 +541,7 @@ jobs:
 
       - name: Set up QEMU
         id: qemu
-        uses: docker/setup-qemu-action@v1
+        uses: docker/setup-qemu-action@v2
         with:
             image: tonistiigi/binfmt:latest
             platforms: all
@@ -551,7 +573,7 @@ jobs:
           EARTHLY_REMOTE_CACHE: "ghcr.io/${{env.CONTAINER_REG}}_cache:build-${{env.CONTAINER_TAG}}-arm64"
 
       - name: Upload artifact
-        uses: actions/upload-artifact@v1.0.0
+        uses: actions/upload-artifact@v3
         with:
           name: linuxArm64Binaries
           path: out/linux/arm64
@@ -572,7 +594,7 @@ jobs:
         uses: actions/[email protected]
         with:
           path: ~/.opam/
-          key: ${{ runner.os }}-${{ hashFiles('./opam', './libs/') }}-2
+          key: ${{ runner.os }}-${{ hashFiles('./haxe.opam', './libs/') }}
 
       - name: Install Neko from S3
         run: |
@@ -594,7 +616,7 @@ jobs:
       - name: Install dependencies
         env:
           # For compatibility with macOS 10.13
-          ZLIB_VERSION: 1.2.13
+          ZLIB_VERSION: 1.3
           MBEDTLS_VERSION: 2.25.0
           PCRE2_VERSION: 10.42
         run: |
@@ -625,14 +647,13 @@ jobs:
           make && make install
           cd ..
 
-
       - name: Install OCaml libraries
         if: steps.cache-opam.outputs.cache-hit != 'true'
         run: |
           set -ex
           opam init # --disable-sandboxing
           opam update
-          opam switch create 4.07.1
+          opam switch create 4.08.1
           eval $(opam env)
           opam env
           opam pin add ctypes 0.17.1 --yes
@@ -657,7 +678,7 @@ jobs:
           otool -L ./haxelib
 
       - name: Upload artifact
-        uses: actions/upload-artifact@v1.0.0
+        uses: actions/upload-artifact@v3
         with:
           name: macBinaries
           path: out
@@ -681,9 +702,10 @@ jobs:
       - uses: actions/checkout@main
         with:
           submodules: recursive
-      - uses: actions/download-artifact@v1
+      - uses: actions/download-artifact@v3
         with:
           name: win${{env.ARCH}}Binaries
+          path: win${{env.ARCH}}Binaries
 
       - name: Install Neko from S3
         shell: pwsh
@@ -697,6 +719,10 @@ jobs:
       - name: Print Neko version
         run: neko -version 2>&1
 
+      - uses: actions/setup-node@v3
+        with:
+          node-version: 18.17.1
+
       # - name: Quick test
       #   shell: pwsh
       #   run: |
@@ -773,9 +799,10 @@ jobs:
       - uses: actions/checkout@main
         with:
           submodules: recursive
-      - uses: actions/download-artifact@v1
+      - uses: actions/download-artifact@v3
         with:
           name: win${{env.ARCH}}Binaries
+          path: win${{env.ARCH}}Binaries
 
       - name: Install Neko from S3
         shell: pwsh
@@ -789,6 +816,10 @@ jobs:
       - name: Print Neko version
         run: neko -version 2>&1
 
+      - uses: actions/setup-node@v3
+        with:
+          node-version: 18.17.1
+
       # - name: Quick test
       #   shell: pwsh
       #   run: |
@@ -865,9 +896,10 @@ jobs:
       - uses: actions/checkout@main
         with:
           submodules: recursive
-      - uses: actions/download-artifact@v1
+      - uses: actions/download-artifact@v3
         with:
           name: macBinaries
+          path: macBinaries
 
       - name: Install Neko from S3
         run: |
@@ -932,7 +964,7 @@ jobs:
         uses: actions/checkout@main
 
       - name: Download build artifacts
-        uses: actions/download-artifact@v2
+        uses: actions/download-artifact@v3
 
       - name: Install awscli
         run: |
@@ -944,7 +976,7 @@ jobs:
       - name: Extract branch name
         id: extract_branch
         shell: bash
-        run: echo "##[set-output name=branch;]$(echo ${GITHUB_REF#refs/heads/})"
+        run: echo "branch=${GITHUB_REF#refs/heads/}" >> $GITHUB_OUTPUT
 
       - name: Upload binaries
         shell: bash
@@ -1007,7 +1039,7 @@ jobs:
           sudo apt-get install -qqy libc6
 
       - name: Download Haxe
-        uses: actions/download-artifact@v2
+        uses: actions/download-artifact@v3
         with:
           name: linuxBinaries
           path: linuxBinaries
@@ -1023,7 +1055,7 @@ jobs:
           sudo ln -s `pwd`/linuxBinaries/std /usr/local/share/haxe/std
 
       - name: Download xmldoc artifact
-        uses: actions/download-artifact@v2
+        uses: actions/download-artifact@v3
         with:
           name: xmldoc
           path: xmldoc

+ 4 - 0
.vscode/schemas/define.schema.json

@@ -61,6 +61,10 @@
 			"reserved": {
 				"type": "boolean",
 				"markdownDescription": "Reserved defines may not be defined from the command line."
+			},
+			"deprecated": {
+				"type": "string",
+				"markdownDescription": "Reason for the define to be deprecated."
 			}
 		},
 		"required": [

+ 4 - 1
Earthfile

@@ -91,8 +91,11 @@ devcontainer:
     RUN git config --global codespaces-theme.hide-status 1
 
     # Install OCaml libraries
-    COPY opam .
+    COPY haxe.opam .
     RUN opam init --disable-sandboxing
+    RUN opam switch create 4.08.1
+    RUN eval $(opam env)
+    RUN opam env
     RUN opam install . --yes --deps-only --no-depexts
     RUN opam list
     RUN ocamlopt -v

+ 1 - 1
Makefile.win

@@ -83,7 +83,7 @@ package_choco:
 	rm -rf out/choco
 
 $(INSTALLER_TMP_DIR)/neko-win.zip: $(INSTALLER_TMP_DIR)
-	wget -nv https://github.com/HaxeFoundation/neko/releases/download/$(NEKO_VERSION_TAG)/neko-$(NEKO_VERSION)-win$(NEKO_ARCH_STR).zip -O installer/neko-win.zip
+	curl -L https://github.com/HaxeFoundation/neko/releases/download/$(NEKO_VERSION_TAG)/neko-$(NEKO_VERSION)-win$(NEKO_ARCH_STR).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)

+ 2 - 1
dune

@@ -1 +1,2 @@
-(data_only_dirs extra lib std tests)
+(dirs :standard \ tests std extra)
+(data_only_dirs lib)

+ 1 - 1
extra/BUILDING.md

@@ -36,7 +36,7 @@ You need to install some native libraries as well as some OCaml libraries.
 To install the native libraries, use the appropriate system package manager.
 
  * Mac OS X
-    * Use [Homebrew](https://brew.sh/), `brew install zlib pcre2`.
+    * Use [Homebrew](https://brew.sh/), `brew install zlib pcre2 mbedtls@2`.
  * Debian / Ubuntu
     * `sudo apt install libpcre2-dev zlib1g-dev libmbedtls-dev`.
  * Windows (Cygwin)

+ 50 - 1
extra/CHANGES.txt

@@ -1,4 +1,53 @@
-2023-04-06: 4.3.0
+2023-09-01 4.3.2
+
+	General improvements:
+
+	all : do not raise error on no-op reification outside macro
+
+	Bugfixes:
+
+	all : don't infer Null<?> if it already is Null<?> (#11286)
+	all : fix ?? inference and precedence (#11252)
+	all : bring back forced inline (#11217)
+	all : allow non constant "inline" var init with -D no-inline (#11192)
+	all : improve @:enum abstract deprecation warning handling (#11302)
+	all : fix some stack overflow with pretty errors
+	display : fix go to definition with final (#11173)
+	display : fix completion requests with @:forwardStatics (#11294)
+	eval : fix MainLoop.add not repeating (#11202)
+	hl/eval/neko : fix exception stack when wrapping native exceptions (#11249)
+	macro : map `this` when restoring typed expressions (#11212)
+	macro : safe navigation fix for ExprTools.map (#11204)
+	macro : safe navigation fix for haxe.macro.Printer (#11206)
+	macro : macro generated EVars position fixes (#11163)
+	macro : fix abstract casts for local statics (#11301)
+	macro : add flags to TDAbstract to be able to construct enum abstracts (#11230)
+	nullsafety : make break/continue expressions not-nullable (#11269)
+	nullsafety : handle return in assignment (#11114)
+
+2023-04-28 4.3.1
+
+	Breaking changes:
+
+	all : namespace message reporting defines (#11142)
+
+	General improvements:
+
+	all : support deprecation for defines
+
+	Bugfixes:
+
+	all : fix --times with compilation server (#11091)
+	all : fix default type parameters not respecting imports (#11161)
+	all : fix bytecode bindings issues (#11098)
+	macro : allow local statics in macro functions (#11096)
+	cpp : fix AtomicInt warnings on cppia (#11105)
+	cpp : fix deprecated implicit casts of cpp.Int64 (#10998)
+	cpp : add white space around template type syntax (#11107)
+	java : don't check native signatures on extern functions (#11131)
+	lua : remove non existent luautf8 charCodeAt extern (#11097)
+
+2023-04-06 4.3.0
 
 	New features:
 

+ 1 - 1
extra/EnvVarUpdate.nsh

@@ -43,7 +43,7 @@
   !ifndef Un${StrFuncName}_INCLUDED
     ${Un${StrFuncName}}
   !endif
-  !define un.${StrFuncName} "${Un${StrFuncName}}"
+  !define un.${StrFuncName} '${Un${StrFuncName}}'
 !macroend
 
 !insertmacro _IncludeStrFunction StrTok

+ 37 - 38
extra/ImportAll.hx

@@ -26,7 +26,7 @@ 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
+		       Context.defined("lua") || Context.defined("hl") || Context.defined("eval");
 	}
 
 	public static function run( ?pack ) {
@@ -34,9 +34,6 @@ class ImportAll {
 			pack = "";
 			haxe.macro.Compiler.define("doc_gen");
 		}
-		if (Context.defined("interp")) {
-			haxe.macro.Compiler.define("macro");
-		}
 		switch( pack ) {
 		case "php":
 			if( !Context.defined("php") ) return;
@@ -72,42 +69,44 @@ class ImportAll {
 			if (!Context.defined("neko") && !Context.defined("cpp")) return;
 		case "tools", "build-tool", "jar-tool": return;
 		}
-		for( p in Context.getClassPath() ) {
-			if( p == "/" || p == "" )
-				continue;
-			// skip if we have a classpath to haxe
-			if( pack.length == 0 && sys.FileSystem.exists(p+"std") )
-				continue;
-			var p = p + pack.split(".").join("/");
-			if( StringTools.endsWith(p,"/") )
-				p = p.substr(0,-1);
-			if( !sys.FileSystem.exists(p) || !sys.FileSystem.isDirectory(p) )
-				continue;
-			for( file in sys.FileSystem.readDirectory(p) ) {
-				if( file == ".svn" || file == "_std" )
+		Context.onAfterInitMacros(() -> {
+			for( p in Context.getClassPath() ) {
+				if( p == "/" || p == "" )
+					continue;
+				// skip if we have a classpath to haxe
+				if( pack.length == 0 && sys.FileSystem.exists(p+"std") )
 					continue;
-				var full = (pack == "") ? file : pack + "." + file;
-				if( StringTools.endsWith(file, ".hx") && file.substr(0, file.length - 3).indexOf(".") < 0 ) {
-					var cl = full.substr(0, full.length - 3);
-					switch( cl ) {
-					case "ImportAll", "neko.db.MacroManager": continue;
-					case "haxe.TimerQueue": 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.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.SyncSocketConnection": if( !(Context.defined("neko") || Context.defined("php") || Context.defined("cpp")) ) continue;
-					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;
-					case "haxe.atomic.AtomicBool" if(!Context.defined("target.atomics")): continue;
-					case "haxe.atomic.AtomicInt" if(!Context.defined("target.atomics")): continue;
-					case "haxe.atomic.AtomicObject" if(!Context.defined("target.atomics") || Context.defined("js") || Context.defined("cpp")): continue;
-					}
-					Context.getModule(cl);
-				} else if( sys.FileSystem.isDirectory(p + "/" + file) )
-					run(full);
+				var p = p + pack.split(".").join("/");
+				if( StringTools.endsWith(p,"/") )
+					p = p.substr(0,-1);
+				if( !sys.FileSystem.exists(p) || !sys.FileSystem.isDirectory(p) )
+					continue;
+				for( file in sys.FileSystem.readDirectory(p) ) {
+					if( file == ".svn" || file == "_std" )
+						continue;
+					var full = (pack == "") ? file : pack + "." + file;
+					if( StringTools.endsWith(file, ".hx") && file.substr(0, file.length - 3).indexOf(".") < 0 ) {
+						var cl = full.substr(0, full.length - 3);
+						switch( cl ) {
+						case "ImportAll", "neko.db.MacroManager": continue;
+						case "haxe.TimerQueue": 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.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.SyncSocketConnection": if( !(Context.defined("neko") || Context.defined("php") || Context.defined("cpp")) ) continue;
+						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;
+						case "haxe.atomic.AtomicBool" if(!Context.defined("target.atomics")): continue;
+						case "haxe.atomic.AtomicInt" if(!Context.defined("target.atomics")): continue;
+						case "haxe.atomic.AtomicObject" if(!Context.defined("target.atomics") || Context.defined("js") || Context.defined("cpp")): continue;
+						}
+						Context.getModule(cl);
+					} else if( sys.FileSystem.isDirectory(p + "/" + file) )
+						run(full);
+				}
 			}
-		}
+		});
 	}
 
 }

+ 3 - 4
extra/github-actions/build-mac.yml

@@ -1,7 +1,7 @@
 - name: Install dependencies
   env:
     # For compatibility with macOS 10.13
-    ZLIB_VERSION: 1.2.13
+    ZLIB_VERSION: 1.3
     MBEDTLS_VERSION: 2.25.0
     PCRE2_VERSION: 10.42
   run: |
@@ -32,14 +32,13 @@
     make && make install
     cd ..
 
-
 - name: Install OCaml libraries
   if: steps.cache-opam.outputs.cache-hit != 'true'
   run: |
     set -ex
     opam init # --disable-sandboxing
     opam update
-    opam switch create 4.07.1
+    opam switch create 4.08.1
     eval $(opam env)
     opam env
     opam pin add ctypes 0.17.1 --yes
@@ -64,7 +63,7 @@
     otool -L ./haxelib
 
 - name: Upload artifact
-  uses: actions/upload-artifact@v1.0.0
+  uses: actions/upload-artifact@v3
   with:
     name: macBinaries
     path: out

+ 8 - 1
extra/github-actions/build-windows.yml

@@ -26,8 +26,15 @@
     & "$($env:CYG_ROOT)/bin/bash.exe" @('-lc', 'cd "$OLDPWD" && cygcheck ./haxelib.exe')
     & "$($env:CYG_ROOT)/bin/bash.exe" @('-lc', 'cd "$OLDPWD" && ls ./out')
 
+- name: Check artifact
+  shell: bash
+  run: |
+    ls out
+    # Output should contain binaries zip, installer zip and nupkg
+    [ $(ls -1 out | wc -l) -eq "3" ]
+
 - name: Upload artifact
-  uses: actions/[email protected]
+  uses: actions/upload-artifact@v3
   with:
     name: win${{env.ARCH}}Binaries
     path: out

+ 0 - 6
extra/github-actions/cache-opam.yml

@@ -1,6 +0,0 @@
-- name: Cache opam
-  id: cache-opam
-  uses: actions/[email protected]
-  with:
-    path: ~/.opam/
-    key: ${{ runner.os }}-${{ hashFiles('./opam', './libs/') }}-2

+ 4 - 2
extra/github-actions/install-nsis.yml

@@ -1,12 +1,14 @@
 - name: choco install nsis
-  uses: nick-invision/retry@v1
+  uses: nick-invision/retry@v2
   with:
     timeout_minutes: 10
     max_attempts: 10
-    command: choco install --no-progress nsis.portable --version 3.02 -y
+    command: choco install --no-progress nsis.portable --version 3.09 -y
+
 - name: choco install things
   shell: pwsh
   run: choco install --no-progress curl wget 7zip.portable -y
+
 - name: Prepend Chocolatey path
   shell: pwsh
   run: Write-Host "::add-path::C:\ProgramData\chocolatey\bin"

+ 2 - 7
extra/github-actions/install-ocaml-libs-windows.yml

@@ -1,11 +1,6 @@
 - name: Install OCaml libraries
-  if: steps.cache-opam.outputs.cache-hit != 'true'
   shell: pwsh
   run: |
     Set-PSDebug -Trace 1
-    & "$($env:CYG_ROOT)/bin/bash.exe" @('-lc', 'opam init mingw "https://github.com/fdopen/opam-repository-mingw.git#opam2" --comp 4.07.0+mingw${ARCH}c --switch 4.07.0+mingw${ARCH}c --auto-setup --yes 2>&1')
-    & "$($env:CYG_ROOT)/bin/bash.exe" @('-lc', 'opam update --yes 2>&1')
-    & "$($env:CYG_ROOT)/bin/bash.exe" @('-lc', 'cd "$OLDPWD" && opam pin add haxe . --kind=path --no-action --yes 2>&1')
-    & "$($env:CYG_ROOT)/bin/bash.exe" @('-lc', 'opam install haxe --deps-only --yes 2>&1')
-    & "$($env:CYG_ROOT)/bin/bash.exe" @('-lc', 'opam list')
-    & "$($env:CYG_ROOT)/bin/bash.exe" @('-lc', 'ocamlopt -v')
+    opam install haxe --deps-only
+    opam list

+ 30 - 8
extra/github-actions/install-ocaml-windows.yml

@@ -1,17 +1,39 @@
-- name: Install OCaml
+- name: Setup ocaml
+  id: ocaml
+  continue-on-error: true
+  uses: kLabz/setup-ocaml@win32
+  with:
+    ocaml-compiler: 4.08.1
+    opam-depext: false
+    opam-repositories: |
+      opam-repository-mingw: https://github.com/ocaml-opam/opam-repository-mingw.git#sunset
+      default: https://github.com/ocaml/opam-repository.git
+    opam-local-packages: |
+      haxe.opam
+    cache-prefix: w32-v1
+
+# TODO make it work on first try
+# (when cygwin cache doesn't exist, ocaml install fails with a curl error)
+- name: Setup ocaml (second chance)
+  if: steps.ocaml.outcome == 'failure'
+  uses: kLabz/setup-ocaml@win32
+  with:
+    ocaml-compiler: 4.08.1
+    opam-depext: false
+    opam-repositories: |
+      opam-repository-mingw: https://github.com/ocaml-opam/opam-repository-mingw.git#sunset
+      default: https://github.com/ocaml/opam-repository.git
+    opam-local-packages: |
+      haxe.opam
+    cache-prefix: w32-v1
+
+- name: Install dependencies
   shell: pwsh
   run: |
     Set-PSDebug -Trace 1
-    curl.exe -fsSL -o cygwin-setup.exe --retry 3 $($env:CYGWIN_SETUP)
-    Start-Process -FilePath "cygwin-setup.exe" -ArgumentList "-B -q -R $($env:CYG_ROOT) -l C:/tmp -s $($env:CYG_MIRROR) -P default -P make -P git -P zlib-devel -P rsync -P patch -P diffutils -P curl -P unzip -P tar -P m4 -P perl -P libpcre2-devel -P mbedtls-devel -P mingw64-$($env:MINGW_ARCH)-zlib -P mingw64-$($env:MINGW_ARCH)-gcc-core -P mingw64-$($env:MINGW_ARCH)-pcre2 --allow-unsupported-windows" -Wait -RedirectStandardOutput cygwin-setup-out.txt
-    Get-Content cygwin-setup-out.txt
-    & "$($env:CYG_ROOT)/bin/bash.exe" @('--norc', '--noprofile', '/etc/postinstall/ca-certificates.sh')
-    curl.exe -fsSL -o "opam.tar.xz" --retry 3 https://github.com/fdopen/opam-repository-mingw/releases/download/0.0.0.2/opam$($env:ARCH).tar.xz
     curl.exe -fsSL -o "libmbedtls.tar.xz" --retry 3 https://github.com/Simn/mingw64-mbedtls/releases/download/2.16.3/mingw64-$($env:MINGW_ARCH)-mbedtls-2.16.3-1.tar.xz
     & "$($env:CYG_ROOT)/bin/bash.exe" @('-lc', 'curl -L https://cpanmin.us | perl - App::cpanminus')
     & "$($env:CYG_ROOT)/bin/bash.exe" @('-lc', 'cpanm IPC::System::Simple module')
     & "$($env:CYG_ROOT)/bin/bash.exe" @('-lc', 'cpanm String::ShellQuote')
     & "$($env:CYG_ROOT)/bin/bash.exe" @('-lc', 'echo "$OLDPWD"')
     & "$($env:CYG_ROOT)/bin/bash.exe" @('-lc', 'cd "$OLDPWD" && tar -C / -xvf libmbedtls.tar.xz')
-    & "$($env:CYG_ROOT)/bin/bash.exe" @('-lc', 'cd "$OLDPWD" && tar -xf opam.tar.xz')
-    & "$($env:CYG_ROOT)/bin/bash.exe" @('-lc', 'cd "$OLDPWD" && bash opam${ARCH}/install.sh')

+ 11 - 7
extra/github-actions/install-ocaml-windows64.yml

@@ -1,16 +1,20 @@
-- name: Install OCaml
+- name: Setup ocaml
+  uses: ocaml/setup-ocaml@v2
+  with:
+    ocaml-compiler: 4.08.1
+    opam-repositories: |
+      opam-repository-mingw: https://github.com/ocaml-opam/opam-repository-mingw.git#sunset
+      default: https://github.com/ocaml/opam-repository.git
+    opam-local-packages: |
+      haxe.opam
+
+- name: Install dependencies
   shell: pwsh
   run: |
     Set-PSDebug -Trace 1
-    curl.exe -fsSL -o cygwin-setup.exe --retry 3 $($env:CYGWIN_SETUP)
-    Start-Process -FilePath "cygwin-setup.exe" -ArgumentList "-B -q -R $($env:CYG_ROOT) -l C:/tmp -s $($env:CYG_MIRROR) -P default -P make -P git -P zlib-devel -P rsync -P patch -P diffutils -P curl -P unzip -P tar -P m4 -P perl -P libpcre2-devel -P mbedtls-devel -P mingw64-$($env:MINGW_ARCH)-zlib -P mingw64-$($env:MINGW_ARCH)-gcc-core -P mingw64-$($env:MINGW_ARCH)-pcre2" -Wait -RedirectStandardOutput cygwin-setup-out.txt
-    Get-Content cygwin-setup-out.txt
-    curl.exe -fsSL -o "opam.tar.xz" --retry 3 https://github.com/fdopen/opam-repository-mingw/releases/download/0.0.0.2/opam$($env:ARCH).tar.xz
     curl.exe -fsSL -o "libmbedtls.tar.xz" --retry 3 https://github.com/Simn/mingw64-mbedtls/releases/download/2.16.3/mingw64-$($env:MINGW_ARCH)-mbedtls-2.16.3-1.tar.xz
     & "$($env:CYG_ROOT)/bin/bash.exe" @('-lc', 'curl -L https://cpanmin.us | perl - App::cpanminus')
     & "$($env:CYG_ROOT)/bin/bash.exe" @('-lc', 'cpanm IPC::System::Simple module')
     & "$($env:CYG_ROOT)/bin/bash.exe" @('-lc', 'cpanm String::ShellQuote')
     & "$($env:CYG_ROOT)/bin/bash.exe" @('-lc', 'echo "$OLDPWD"')
     & "$($env:CYG_ROOT)/bin/bash.exe" @('-lc', 'cd "$OLDPWD" && tar -C / -xvf libmbedtls.tar.xz')
-    & "$($env:CYG_ROOT)/bin/bash.exe" @('-lc', 'cd "$OLDPWD" && tar -xf opam.tar.xz')
-    & "$($env:CYG_ROOT)/bin/bash.exe" @('-lc', 'cd "$OLDPWD" && bash opam${ARCH}/install.sh')

+ 4 - 0
extra/github-actions/test-windows.yml

@@ -1,3 +1,7 @@
+- uses: actions/setup-node@v3
+  with:
+    node-version: 18.17.1
+
 # - name: Quick test
 #   shell: pwsh
 #   run: |

+ 49 - 46
extra/github-actions/workflows/main.yml

@@ -9,13 +9,9 @@ jobs:
     env:
       ACTIONS_ALLOW_UNSECURE_COMMANDS: true
       PLATFORM: windows64
-      OPAMYES: 1
-      OPAMROOT: D:\.opam
-      CYG_MIRROR: http://mirrors.kernel.org/sourceware/cygwin/
       ARCH: 64
       MINGW_ARCH: x86_64
-      CYGWIN_SETUP: https://cygwin.com/setup-x86_64.exe
-      CYG_ROOT: C:/cygwin64
+      CYG_ROOT: D:\cygwin
     steps:
       - uses: actions/checkout@main
         with:
@@ -26,15 +22,8 @@ jobs:
           echo "C:\msys64\usr\bin" | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append
           rm C:\msys64\usr\bin\bash.exe
 
-      - name: Cache opam
-        id: cache-opam
-        uses: actions/[email protected]
-        with:
-          path: D:\.opam
-          key: ${{ runner.os }}64-${{ hashFiles('./opam', './libs/') }}
-
-      @import install-neko-windows.yml
       @import install-nsis.yml
+      @import install-neko-windows.yml
       @import install-ocaml-windows64.yml
       @import install-ocaml-libs-windows.yml
       @import build-windows.yml
@@ -44,13 +33,9 @@ jobs:
     env:
       ACTIONS_ALLOW_UNSECURE_COMMANDS: true
       PLATFORM: windows
-      OPAMYES: 1
-      OPAMROOT: D:\.opam
-      CYG_MIRROR: http://mirrors.kernel.org/sourceware/cygwin-archive/20221123
       ARCH: 32
       MINGW_ARCH: i686
-      CYGWIN_SETUP: https://cygwin.com/setup-x86.exe
-      CYG_ROOT: C:/cygwin
+      CYG_ROOT: D:\cygwin
     steps:
       - uses: actions/checkout@main
         with:
@@ -61,15 +46,8 @@ jobs:
           echo "C:\msys64\usr\bin" | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append
           rm C:\msys64\usr\bin\bash.exe
 
-      - name: Cache opam
-        id: cache-opam
-        uses: actions/[email protected]
-        with:
-          path: D:\.opam
-          key: ${{ runner.os }}32-${{ hashFiles('./opam', './libs/') }}
-
-      @import install-neko-windows.yml
       @import install-nsis.yml
+      @import install-neko-windows.yml
       @import install-ocaml-windows.yml
       @import install-ocaml-libs-windows.yml
       @import build-windows.yml
@@ -79,12 +57,22 @@ jobs:
     env:
       PLATFORM: linux64
       OPAMYES: 1
+    strategy:
+      fail-fast: false
+      matrix:
+        ocaml: ["4.08.1", "5.0.0"]
     steps:
       - uses: actions/checkout@main
         with:
           submodules: recursive
 
-      @import cache-opam.yml
+      - name: Cache opam
+        id: cache-opam
+        uses: actions/[email protected]
+        with:
+          path: ~/.opam/
+          key: ${{ runner.os }}-${{ matrix.ocaml }}-${{ hashFiles('./haxe.opam', './libs/') }}
+
       @import install-neko-unix.yml
 
       - name: Install dependencies
@@ -101,6 +89,7 @@ jobs:
           set -ex
           opam init # --disable-sandboxing
           opam update
+          opam switch create ${{ matrix.ocaml }}
           opam pin add haxe . --no-action
           opam install haxe --deps-only --assume-depexts
           opam list
@@ -125,9 +114,10 @@ jobs:
       - name: Extract branch name
         id: extract_branch
         shell: bash
-        run: echo "##[set-output name=branch;]$(echo ${GITHUB_REF#refs/heads/})"
+        run: echo "branch=${GITHUB_REF#refs/heads/}" >> $GITHUB_OUTPUT
 
       - name: Build xmldoc
+        if: matrix.ocaml == '4.08.1'
         run: |
           set -ex
           make -s xmldoc
@@ -139,13 +129,14 @@ jobs:
           EOL
 
       - name: Upload artifact
-        uses: actions/upload-artifact@v1.0.0
+        uses: actions/upload-artifact@v3
         with:
-          name: linuxBinaries
+          name: linuxBinaries${{ (matrix.ocaml == '5.0.0' && '_ocaml5') || '' }}
           path: out
 
       - name: Upload xmldoc artifact
-        uses: actions/[email protected]
+        uses: actions/upload-artifact@v3
+        if: matrix.ocaml == '4.08.1'
         with:
           name: xmldoc
           path: extra/doc
@@ -161,6 +152,7 @@ jobs:
     strategy:
       fail-fast: false
       matrix:
+        ocaml: ["4.08.1", "5.0.0"]
         target: [macro, js, hl, cpp, 'java,jvm', cs, php, python, lua, flash, neko]
         include:
           - target: hl
@@ -175,9 +167,10 @@ jobs:
       - uses: actions/checkout@main
         with:
           submodules: recursive
-      - uses: actions/download-artifact@v1
+      - uses: actions/download-artifact@v3
         with:
-          name: linuxBinaries
+          name: linuxBinaries${{ (matrix.ocaml == '5.0.0' && '_ocaml5') || '' }}
+          path: linuxBinaries
 
       @import install-neko-unix.yml
 
@@ -228,12 +221,13 @@ jobs:
         with:
           submodules: recursive
 
-      - uses: actions/download-artifact@v1
+      - uses: actions/download-artifact@v3
         with:
           name: linuxBinaries
+          path: linuxBinaries
 
       - name: Download xmldoc artifact
-        uses: actions/download-artifact@v2
+        uses: actions/download-artifact@v3
         with:
           name: xmldoc
           path: xmldoc
@@ -286,7 +280,7 @@ jobs:
       FORCE_COLOR: 1
     steps:
       - name: Login to GitHub Container Registry
-        uses: docker/login-action@v1
+        uses: docker/login-action@v2
         with:
           registry: ghcr.io
           username: ${{ github.actor }}
@@ -297,7 +291,7 @@ jobs:
 
       - name: Set up QEMU
         id: qemu
-        uses: docker/setup-qemu-action@v1
+        uses: docker/setup-qemu-action@v2
         with:
             image: tonistiigi/binfmt:latest
             platforms: all
@@ -329,7 +323,7 @@ jobs:
           EARTHLY_REMOTE_CACHE: "ghcr.io/${{env.CONTAINER_REG}}_cache:build-${{env.CONTAINER_TAG}}-arm64"
 
       - name: Upload artifact
-        uses: actions/upload-artifact@v1.0.0
+        uses: actions/upload-artifact@v3
         with:
           name: linuxArm64Binaries
           path: out/linux/arm64
@@ -345,7 +339,13 @@ jobs:
         with:
           submodules: recursive
 
-      @import cache-opam.yml
+      - name: Cache opam
+        id: cache-opam
+        uses: actions/[email protected]
+        with:
+          path: ~/.opam/
+          key: ${{ runner.os }}-${{ hashFiles('./haxe.opam', './libs/') }}
+
       @import install-neko-unix.yml
       @import build-mac.yml
 
@@ -367,9 +367,10 @@ jobs:
       - uses: actions/checkout@main
         with:
           submodules: recursive
-      - uses: actions/download-artifact@v1
+      - uses: actions/download-artifact@v3
         with:
           name: win${{env.ARCH}}Binaries
+          path: win${{env.ARCH}}Binaries
 
       @import install-neko-windows.yml
       @import test-windows.yml
@@ -393,9 +394,10 @@ jobs:
       - uses: actions/checkout@main
         with:
           submodules: recursive
-      - uses: actions/download-artifact@v1
+      - uses: actions/download-artifact@v3
         with:
           name: win${{env.ARCH}}Binaries
+          path: win${{env.ARCH}}Binaries
 
       @import install-neko-windows.yml
       @import test-windows.yml
@@ -419,9 +421,10 @@ jobs:
       - uses: actions/checkout@main
         with:
           submodules: recursive
-      - uses: actions/download-artifact@v1
+      - uses: actions/download-artifact@v3
         with:
           name: macBinaries
+          path: macBinaries
 
       @import install-neko-unix.yml
       @import test-mac.yml
@@ -438,7 +441,7 @@ jobs:
         uses: actions/checkout@main
 
       - name: Download build artifacts
-        uses: actions/download-artifact@v2
+        uses: actions/download-artifact@v3
 
       - name: Install awscli
         run: |
@@ -450,7 +453,7 @@ jobs:
       - name: Extract branch name
         id: extract_branch
         shell: bash
-        run: echo "##[set-output name=branch;]$(echo ${GITHUB_REF#refs/heads/})"
+        run: echo "branch=${GITHUB_REF#refs/heads/}" >> $GITHUB_OUTPUT
 
       - name: Upload binaries
         shell: bash
@@ -513,7 +516,7 @@ jobs:
           sudo apt-get install -qqy libc6
 
       - name: Download Haxe
-        uses: actions/download-artifact@v2
+        uses: actions/download-artifact@v3
         with:
           name: linuxBinaries
           path: linuxBinaries
@@ -529,7 +532,7 @@ jobs:
           sudo ln -s `pwd`/linuxBinaries/std /usr/local/share/haxe/std
 
       - name: Download xmldoc artifact
-        uses: actions/download-artifact@v2
+        uses: actions/download-artifact@v3
         with:
           name: xmldoc
           path: xmldoc

+ 14 - 10
extra/release-checklist.txt

@@ -9,22 +9,26 @@
 
 - Make sure CHANGES.txt has a proper date set!
 - Make sure `version` in globals.ml has the correct value
-- Update `version` in `./opam`
+- Make sure the copyright year in args.ml has the correct value
+- Update `version` in `haxe.opam`
 - Check if the protocolVersion in displayJson.ml has to be updated
-- Make an empty GitHub release in https://github.com/HaxeFoundation/haxe/releases (do this first because we need the tag for the builds)
-- Wait for the CI to build (check https://build.haxe.org/builds/haxe/)
-- Get https://github.com/simn/hxgithub
-- Store your GitHub personal access token in .github-token
-- Run something like this: `neko release.n -h 4.0.0-rc.1 -u -uw -ur -d haxe_2019-02-01_development_1fdd3d5.zip --dry`
-- Tell yourself that you're gonna fix `-doc` generation next time
-- Write the announcement to `./haxe-version/RELEASE.md`
-- If everything was working, run the command again without `--dry` (and probably without the `-d`)
+- Create a version tag and push it with above changes (CI needs to run on the tag)
+- Make an empty GitHub release in https://github.com/HaxeFoundation/haxe/releases
+- Wait for the CI to build (check https://build.haxe.org/builds/haxe/, look for `haxe_[date]_refs/tags`)
+- Get https://github.com/HaxeFoundation/hxgithub
+- Follow "Haxe releases" section of hxgithub README, with the equivalent of `-d haxe_2023-04-28_refs/tags/4.3.1_964c84c.tar.gz`
+	- Tell yourself that you're gonna fix `-doc` generation next time
+	- Make sure changelog isn't empty in `./haxe-version/CHANGES.md`
+	- 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
+- Wait for staging to update, check everything related to release and merge to master
 
 # Cleanup
 
 - Remove issues with released fixes from the "Hotfix" milestone: https://github.com/HaxeFoundation/haxe/milestone/18
+- Set back the version in `globals.ml` to something appropriate for nightlies
 
 # Announcing the release
 
-- Find someone to announce the release on our various communication channels
+- Find someone to announce the release on our various communication channels

+ 5 - 4
opam → haxe.opam

@@ -19,17 +19,18 @@ build: [
 install: [make "install" "INSTALL_DIR=%{prefix}%"]
 remove: [make "uninstall" "INSTALL_DIR=%{prefix}%"]
 depends: [
-  "ocaml" {>= "4.02"}
+  ("ocaml" {>= "5.0"} & ("camlp5" {build}))
+    | ("ocaml" {>= "4.08" & < "5.0"} & ("camlp5" {build & = "8.00"}))
   "ocamlfind" {build}
   "dune" {>= "1.11"}
-  "camlp5" {build & = "8.00"}
   "sedlex" {>= "2.0"}
   "xml-light"
   "extlib" {>= "1.7.8"}
-  "ptmap" {>= "2.0.0"}
   "sha"
+  "camlp-streams"
   "conf-libpcre2-8"
   "conf-zlib"
   "conf-neko"
-  "luv"
+  "luv" {>= "0.5.12"}
+  "ipaddr"
 ]

+ 3 - 3
libs/extc/extc.ml

@@ -110,10 +110,10 @@ let input_zip ?(bufsize=65536) ch =
 	let buf = ref "" in
 	let p = ref 0 in
 	let z = zlib_inflate_init() in
-	let rec fill_buffer() =
+	let fill_buffer() =
 		let rec loop pos len =
 			if len > 0 || pos = 0 then begin
-				let r = zlib_inflate z (Bytes.unsafe_to_string tmp_in) pos len tmp_out 0 bufsize (if pos = 0 && len = 0 then Z_FINISH else Z_SYNC_FLUSH) in
+				let r = zlib_inflate z ~src:(Bytes.unsafe_to_string tmp_in) ~spos:pos ~slen:len ~dst:tmp_out ~dpos:0 ~dlen:bufsize (if pos = 0 && len = 0 then Z_FINISH else Z_SYNC_FLUSH) in
 				Buffer.add_subbytes tmp_buf tmp_out 0 r.z_wrote;
 				loop (pos + r.z_read) (len - r.z_read);
 			end
@@ -155,7 +155,7 @@ let output_zip ?(bufsize=65536) ?(level=9) ch =
 	let tmp_out = Bytes.create bufsize in
 	let p = ref 0 in
 	let rec flush finish =
-		let r = zlib_deflate z (Bytes.unsafe_to_string out) 0 !p tmp_out 0 bufsize (if finish then Z_FINISH else Z_SYNC_FLUSH) in
+		let r = zlib_deflate z ~src:(Bytes.unsafe_to_string out) ~spos:0 ~slen:!p ~dst:tmp_out ~dpos:0 ~dlen:bufsize (if finish then Z_FINISH else Z_SYNC_FLUSH) in
 		ignore(IO.really_output ch tmp_out 0 r.z_wrote);
 		let remain = !p - r.z_read in
 		Bytes.blit out r.z_read out 0 remain;

+ 21 - 21
libs/extc/extc_stubs.c

@@ -92,7 +92,7 @@ int Zflush_val(value zflush_val) {
 		case 4: return Z_FINISH;
 		// TODO: support Z_BLOCK and Z_TREE
 		// TODO: append the received value
-		default: failwith("Error in `Zflush_val` (extc_stubs.c): Unknown zflush value");
+		default: caml_failwith("Error in `Zflush_val` (extc_stubs.c): Unknown zflush value");
 	}
 	assert(0);
 }
@@ -222,14 +222,14 @@ CAMLprim value zlib_deflate_init2(value level_val, value window_bits_val) {
 			break;
 		case Z_STREAM_ERROR:
 			// TODO: use stream->msg to get _zlib_'s text message
-			failwith("Error in `zlib_deflate_init2` (extc_stubs.c): call to `deflateInit2` failed: Z_STREAM_ERROR");
+			caml_failwith("Error in `zlib_deflate_init2` (extc_stubs.c): call to `deflateInit2` failed: Z_STREAM_ERROR");
 			break;
 		case Z_VERSION_ERROR:
 			// TODO: use stream->msg to get _zlib_'s text message
-			failwith("Error in `zlib_deflate_init2` (extc_stubs.c): call to `deflateInit2` failed: Z_VERSION_ERROR");
+			caml_failwith("Error in `zlib_deflate_init2` (extc_stubs.c): call to `deflateInit2` failed: Z_VERSION_ERROR");
 			break;
 		default:
-			failwith("Error in `zlib_deflate_init2` (extc_stubs.c): unknown return code from `deflateInit2`");
+			caml_failwith("Error in `zlib_deflate_init2` (extc_stubs.c): unknown return code from `deflateInit2`");
 	}
 	assert(0);
 }
@@ -275,7 +275,7 @@ CAMLprim value zlib_deflate(value stream_val, value src, value spos, value slen,
 	if (deflate_result == Z_OK || deflate_result == Z_STREAM_END) {
 		stream->next_in = NULL;
 		stream->next_out = NULL;
-		value zresult = alloc_small(3, 0);
+		value zresult = caml_alloc_small(3, 0);
 		// z_finish
 		Field(zresult, 0) = Val_bool(deflate_result == Z_STREAM_END);
 		// z_read
@@ -291,14 +291,14 @@ CAMLprim value zlib_deflate(value stream_val, value src, value spos, value slen,
 			break;
 		case Z_STREAM_ERROR:
 			// TODO: use stream->msg to get _zlib_'s text message
-			failwith("Error in `zlib_deflate` (extc_stubs.c): call to `deflate` failed: Z_STREAM_ERROR");
+			caml_failwith("Error in `zlib_deflate` (extc_stubs.c): call to `deflate` failed: Z_STREAM_ERROR");
 			break;
 		case Z_BUF_ERROR:
 			// TODO: use stream->msg to get _zlib_'s text message
-			failwith("Error in `zlib_deflate` (extc_stubs.c): call to `deflate` failed: Z_BUF_ERROR");
+			caml_failwith("Error in `zlib_deflate` (extc_stubs.c): call to `deflate` failed: Z_BUF_ERROR");
 			break;
 		default:
-			failwith("Error in `zlib_deflate` (extc_stubs.c): unknown return code from `deflate`");
+			caml_failwith("Error in `zlib_deflate` (extc_stubs.c): unknown return code from `deflate`");
 	}
 	assert(0);
 }
@@ -309,14 +309,14 @@ CAMLprim value zlib_deflate_bytecode(value *arg, int nargs) {
 
 CAMLprim value zlib_deflate_end(value zv) {
 	if( deflateEnd(ZStreamP_val(zv)) != 0 )
-		failwith("zlib_deflate_end");
+		caml_failwith("zlib_deflate_end");
 	return Val_unit;
 }
 
 CAMLprim value zlib_inflate_init(value wbits) {
 	value z = zlib_new_stream();
 	if( inflateInit2(ZStreamP_val(z),Int_val(wbits)) != Z_OK )
-		failwith("zlib_inflate_init");
+		caml_failwith("zlib_inflate_init");
 	return z;
 }
 
@@ -330,12 +330,12 @@ CAMLprim value zlib_inflate( value zv, value src, value spos, value slen, value
 	z->avail_in = Int_val(slen);
 	z->avail_out = Int_val(dlen);
 	if( (r = inflate(z,Int_val(flush))) < 0 )
-		failwith("zlib_inflate");
+		caml_failwith("zlib_inflate");
 
 	z->next_in = NULL;
 	z->next_out = NULL;
 
-	res = alloc_small(3, 0);
+	res = caml_alloc_small(3, 0);
 	Field(res, 0) = Val_bool(r == Z_STREAM_END);
 	Field(res, 1) = Val_int(Int_val(slen) - z->avail_in);
 	Field(res, 2) = Val_int(Int_val(dlen) - z->avail_out);
@@ -348,7 +348,7 @@ CAMLprim value zlib_inflate_bytecode(value * arg, int nargs) {
 
 CAMLprim value zlib_inflate_end(value zv) {
 	if( inflateEnd(ZStreamP_val(zv)) != 0 )
-		failwith("zlib_inflate_end");
+		caml_failwith("zlib_inflate_end");
 	return Val_unit;
 }
 
@@ -368,13 +368,13 @@ CAMLprim value executable_path(value u) {
 #ifdef _WIN32
 	char path[MAX_PATH];
 	if( GetModuleFileName(NULL,path,MAX_PATH) == 0 )
-		failwith("executable_path");
+		caml_failwith("executable_path");
 	return caml_copy_string(path);
 #elif __APPLE__
 	char path[MAXPATHLEN+1];
 	uint32_t path_len = MAXPATHLEN;
 	if ( _NSGetExecutablePath(path, &path_len) )
-		failwith("executable_path");
+		caml_failwith("executable_path");
 	return caml_copy_string(path);
 #elif __FreeBSD__
 	char path[PATH_MAX];
@@ -387,7 +387,7 @@ CAMLprim value executable_path(value u) {
 	len = sizeof(path);
 	error = sysctl(name, 4, path, &len, NULL, 0);
 	if( error < 0 )
-		failwith("executable_path");
+		caml_failwith("executable_path");
 	return caml_copy_string(path);
 #else
 	char path[PATH_MAX];
@@ -397,7 +397,7 @@ CAMLprim value executable_path(value u) {
 		if( p != NULL )
 			return caml_copy_string(p);
 		else
-			failwith("executable_path");
+			caml_failwith("executable_path");
 	}
 	path[length] = '\0';
 	return caml_copy_string(path);
@@ -408,12 +408,12 @@ CAMLprim value get_full_path( value f ) {
 #ifdef _WIN32
 	char path[MAX_PATH];
 	if( GetFullPathName(String_val(f),MAX_PATH,path,NULL) == 0 )
-		failwith("get_full_path");
+		caml_failwith("get_full_path");
 	return caml_copy_string(path);
 #else
 	char path[4096];
 	if( realpath(String_val(f),path) == NULL )
-		failwith("get_full_path");
+		caml_failwith("get_full_path");
 	return caml_copy_string(path);
 #endif
 }
@@ -428,7 +428,7 @@ CAMLprim value get_real_path( value path ) {
 
 	// this will ensure the full class path with proper casing
 	if( GetFullPathName(String_val(path),MAX_PATH,out,NULL) == 0 )
-		failwith("get_real_path");
+		caml_failwith("get_real_path");
 
 	len = strlen(out);
 	i = 0;
@@ -501,7 +501,7 @@ CAMLprim value sys_time() {
 		ULARGE_INTEGER ui;
 		GetSystemTime(&t);
 		if( !SystemTimeToFileTime(&t,&ft) )
-			failwith("sys_cpu_time");
+			caml_failwith("sys_cpu_time");
 		ui.LowPart = ft.dwLowDateTime;
 		ui.HighPart = ft.dwHighDateTime;
 		return caml_copy_double( ((double)ui.QuadPart) / 10000000.0 - EPOCH_DIFF );

+ 2 - 2
libs/extc/process_stubs.c

@@ -67,10 +67,10 @@
 #define val_null Val_int(0)
 #define val_some(v) Field(v,0)
 #define val_int(v) Int_val(v)
-#define neko_error() failwith(__FUNCTION__)
+#define neko_error() caml_failwith(__FUNCTION__)
 
 static value alloc_private( int size ) {
-	return alloc((size + sizeof(value) - 1) / sizeof(value), Abstract_tag);
+	return caml_alloc((size + sizeof(value) - 1) / sizeof(value), Abstract_tag);
 }
 
 // --- buffer api

+ 7 - 1
libs/extlib-leftovers/dune

@@ -1,7 +1,13 @@
 (include_subdirs no)
 
+(env
+	(_
+		(flags (-w -3 -w -27 -w -32))
+	)
+)
+
 (library
 	(name extlib_leftovers)
 	(libraries extlib)
 	; (wrapped false)
-)
+)

+ 5 - 5
libs/extlib-leftovers/multiArray.ml

@@ -77,7 +77,7 @@ let init len f =
 			len = len;
 			arr = imake 0 0;
 			darr = Some arr;
-		}		
+		}
 	end
 
 let make len e =
@@ -124,7 +124,7 @@ let set d idx v =
 	| None -> iset (iget d.arr (idx lsr nbits)) (idx land mask) v
 	| Some arr -> iset arr idx v
 
-let rec add d v =
+let add d v =
 	(match d.darr with
 	| None ->
 		let asize = ilen d.arr in
@@ -140,7 +140,7 @@ let rec add d v =
 	| Some arr ->
 		if d.len < ilen arr then begin
 			(* set *)
-			iset arr d.len v;			
+			iset arr d.len v;
 		end else if d.len lsl 1 >= Sys.max_array_length then begin
 			(* promote *)
 			let count = (d.len + size) lsr nbits in
@@ -180,7 +180,7 @@ let of_list src =
 	let c = create() in
 	List.iter (add c) src;
 	c
-	
+
 let iter f d = match d.darr with
 	| None ->
 	 	let max = ilen d.arr - 1 in
@@ -281,4 +281,4 @@ let fold_left f acc d = match d.darr with
 		for i = 0 to d.len - 1 do
 			acc := f !acc (iget arr i)
 		done;
-		!acc
+		!acc

+ 1 - 1
libs/extlib-leftovers/uTF8.ml

@@ -177,7 +177,7 @@ let rec iter_aux proc s i =
 
 let iter proc s = iter_aux proc s 0
 
-let compare s1 s2 = Pervasives.compare s1 s2
+let compare s1 s2 = Stdlib.compare s1 s2
 
 exception Malformed_code
 

+ 7 - 1
libs/neko/dune

@@ -1,7 +1,13 @@
 (include_subdirs no)
 
+(env
+	(_
+		(flags (-w -27))
+	)
+)
+
 (library
 	(name neko)
 	(libraries extlib)
 	(wrapped false)
-)
+)

+ 2 - 2
libs/neko/ncompile.ml

@@ -673,8 +673,8 @@ and compile_builtin ctx tail b el p =
 			write ctx (Call 1);
 			(* // insert an infinite loop in order to
 			// comply with bytecode checker *)
-			let _ = jmp ctx in
-			()
+			let _jmp = jmp ctx in
+			ignore(_jmp)
 		) dtraps;
 	| ("goto" , _) ->
 		error "Invalid $goto statement" p

+ 27 - 4
libs/objsize/c_objsize.c

@@ -12,6 +12,11 @@
 #include "util.h"
 
 #include <caml/memory.h>
+#include <caml/version.h>
+
+#if OCAML_VERSION_MAJOR >= 5
+#include <caml/address_class.h>
+#endif
 
 // FROM byterun/gc.h
 #define Caml_white (0 << 8)
@@ -38,6 +43,7 @@
 #define In_static_data 4
 #define In_code_area 8
 
+#if OCAML_VERSION_MAJOR < 5
 #ifdef ARCH_SIXTYFOUR
 
 // 64 bits: Represent page table as a sparse hash table
@@ -63,6 +69,23 @@ CAMLextern unsigned char * caml_page_table[Pagetable1_size];
 
 #define Is_in_heap_or_young(a) (Classify_addr(a) & (In_heap | In_young))
 
+void store_explicit(header_t hd, value v, int col)
+ {
+  Hd_val(v) = Coloredhd_hd(hd, col);
+ }
+
+#else
+
+void store_explicit(header_t hd, value v, int col)
+ {
+  atomic_store_explicit(
+	Hp_atomic_val(v),
+	Coloredhd_hd(hd, col),
+	memory_order_release);
+ }
+
+#endif
+
 //--------------------------------------------------------
 
 
@@ -352,7 +375,7 @@ void c_rec_objsize(value v, size_t depth)
 
   DBG(printf("COL: w %08lx %i\n", v, col));
 
-  Hd_val(v) = Coloredhd_hd(hd, Col_blue);
+  store_explicit(hd, v, Col_blue);
 
   if (Tag_val(v) < No_scan_tag)
    {
@@ -378,7 +401,7 @@ void restore_colors(value v)
 
   col = readcolor();
   DBG(printf("COL: r %08lx %i\n", v, col));
-  Hd_val(v) = Coloredhd_hd(Hd_val(v), col);
+  store_explicit(Hd_val(v), v, col);
 
   if (Tag_val(v) < No_scan_tag)
    {
@@ -417,7 +440,7 @@ int c_objsize(value v, value scan, value reach, size_t* headers, size_t* data, s
 	head = Field(head,1);
 	if( col == Col_blue ) continue;
 	writecolor(col);
-	Hd_val(v) = Coloredhd_hd(hd, Col_blue);
+	store_explicit(hd, v, Col_blue);
  }
 
  acc_data = 0;
@@ -444,7 +467,7 @@ int c_objsize(value v, value scan, value reach, size_t* headers, size_t* data, s
 	head = Field(head,1);
 	if( Colornum_hd(Hd_val(v)) != Col_blue ) continue;
 	col = readcolor();
-	Hd_val(v) = Coloredhd_hd(Hd_val(v), col);
+	store_explicit(Hd_val(v), v, col);
  }
 
   while( COND_BLOCK(reach) ) {

+ 7 - 1
libs/swflib/dune

@@ -1,8 +1,14 @@
 (include_subdirs no)
 
+(env
+	(_
+		(flags (-w -3 -w -27))
+	)
+)
+
 (library
 	(name swflib)
 	(libraries extc extlib extlib_leftovers)
 	(modules_without_implementation as3 as3hl)
 	(wrapped false)
-)
+)

+ 1 - 1
libs/swflib/swfParser.ml

@@ -444,7 +444,7 @@ and tag_length t =
 (* READ PRIMS *)
 
 let skip ch n =
-	seek_in ch ((Pervasives.pos_in ch) + n)
+	seek_in ch ((Stdlib.pos_in ch) + n)
 
 let read_rgba ch =
 	let r = read_byte ch in

+ 1 - 1
libs/swflib/swfPic.ml

@@ -59,7 +59,7 @@ let load_picture file id =
 	let len = String.length file in
 	let p = (try String.rindex file '.' with Not_found -> len) in
 	let ext = String.sub file (p + 1) (len - (p + 1)) in
-	match String.uppercase ext with
+	match ExtString.String.uppercase ext with
 	| "PNG" ->
 		let png , header, data = (try
 			let p = Png.parse ch in

+ 7 - 1
libs/ttflib/dune

@@ -1,8 +1,14 @@
 (include_subdirs no)
 
+(env
+	(_
+		(flags (-w -3 -w -27 -w -35))
+	)
+)
+
 (library
 	(name ttflib)
 	(libraries extlib extlib_leftovers swflib unix)
 	(modules (:standard \ main))
 	(wrapped false)
-)
+)

+ 1 - 1
libs/ttflib/tTFParser.ml

@@ -24,7 +24,7 @@ open TTFData
 open IO
 
 type ctx = {
-	file : Pervasives.in_channel;
+	file : Stdlib.in_channel;
 	ch : input;
 	mutable entry : entry;
 }

+ 7 - 1
libs/ziplib/dune

@@ -1,7 +1,13 @@
 (include_subdirs no)
 
+(env
+	(_
+		(flags (-w -3 -w -27 -w -35 -w -50))
+	)
+)
+
 (library
 	(name ziplib)
 	(libraries extc unix)
 	(wrapped false)
-)
+)

+ 8 - 8
libs/ziplib/zip.ml

@@ -62,7 +62,7 @@ type entry =
 
 type in_file =
   { if_filename: string;
-    if_channel: Pervasives.in_channel;
+    if_channel: Stdlib.in_channel;
     if_entries: entry list;
     if_directory: (string, entry) Hashtbl.t;
     if_comment: string }
@@ -72,7 +72,7 @@ let comment ifile = ifile.if_comment
 
 type out_file =
   { of_filename: string;
-    of_channel: Pervasives.out_channel;
+    of_channel: Stdlib.out_channel;
     mutable of_entries: entry list;
     of_comment: string }
 
@@ -217,7 +217,7 @@ let read_cd filename ic cd_entries cd_offset cd_bound =
 (* Open a ZIP file for reading *)
 
 let open_in filename =
-  let ic = Pervasives.open_in_bin filename in
+  let ic = Stdlib.open_in_bin filename in
   let (cd_entries, cd_size, cd_offset, cd_comment) = read_ecd filename ic in
   let entries =
     read_cd filename ic cd_entries cd_offset (Int32.add cd_offset cd_size) in
@@ -232,7 +232,7 @@ let open_in filename =
 (* Close a ZIP file opened for reading *)
 
 let close_in ifile =
-  Pervasives.close_in ifile.if_channel
+  Stdlib.close_in ifile.if_channel
 
 (* Return the info associated with an entry *)
 
@@ -369,7 +369,7 @@ let open_out ?(comment = "") filename =
   if String.length comment >= 0x10000 then
     raise(Error(filename, "", "comment too long"));
   { of_filename = filename;
-    of_channel = Pervasives.open_out_bin filename;
+    of_channel = Stdlib.open_out_bin filename;
     of_entries = [];
     of_comment = comment }
 
@@ -416,7 +416,7 @@ let close_out ofile =
   write4_int oc start_cd;               (* offset of central dir *)
   write2 oc (String.length ofile.of_comment); (* length of comment *)
   writestring oc ofile.of_comment;         (* comment *)
-  Pervasives.close_out oc
+  Stdlib.close_out oc
 
 (* Write a local file header and return the corresponding entry *)
 
@@ -552,9 +552,9 @@ let copy_file_to_entry infilename ofile ?(extra = "") ?(comment = "")
         with Unix.Unix_error(_,_,_) -> None in
   try
     copy_channel_to_entry ic ofile ~extra ~comment ~level ?mtime:mtime' name;
-    Pervasives.close_in ic
+    Stdlib.close_in ic
   with x ->
-    Pervasives.close_in ic; raise x
+    Stdlib.close_in ic; raise x
 
 
 (* Add an entry whose content will be produced by the caller *)

+ 7 - 1
plugins/example/dune

@@ -1,7 +1,13 @@
 (data_only_dirs cmxs hx)
 (include_subdirs unqualified)
 
+(env
+	(_
+		(flags -w -27 -w -50)
+	)
+)
+
 (library
 	(name example)
 	(libraries haxe)
-)
+)

+ 50 - 30
src-json/define.json

@@ -8,7 +8,8 @@
 		"name": "AdvancedTelemetry",
 		"define": "advanced-telemetry",
 		"doc": "Allow the SWF to be measured with Monocle tool.",
-		"platforms": ["flash"]
+		"platforms": ["flash"],
+		"deprecated": "The flash target will be removed for Haxe 5"
 	},
 	{
 		"name": "AnalyzerOptimize",
@@ -168,7 +169,8 @@
 		"name": "Fdb",
 		"define": "fdb",
 		"doc": "Enable full flash debug infos for FDB interactive debugging.",
-		"platforms": ["flash"]
+		"platforms": ["flash"],
+		"deprecated": "The flash target will be removed for Haxe 5"
 	},
 	{
 		"name": "FileExtension",
@@ -180,13 +182,15 @@
 		"name": "FlashStrict",
 		"define": "flash-strict",
 		"doc": "More strict typing for flash target.",
-		"platforms": ["flash"]
+		"platforms": ["flash"],
+		"deprecated": "The flash target will be removed for Haxe 5"
 	},
 	{
 		"name": "FlashUseStage",
 		"define": "flash-use-stage",
 		"doc": "Keep the SWF library initial stage.",
-		"platforms": ["flash"]
+		"platforms": ["flash"],
+		"deprecated": "The flash target will be removed for Haxe 5"
 	},
 	{
 		"name": "ForceNativeProperty",
@@ -197,13 +201,15 @@
 	{
 		"name": "Haxe3Compat",
 		"define": "haxe3compat",
-		"doc": "Gives warnings about transition from Haxe 3.x to Haxe 4.0."
+		"doc": "Gives warnings about transition from Haxe 3.x to Haxe 4.0.",
+		"deprecated": "This flag is no longer supported in Haxe 5"
 	},
 	{
 		"name": "HaxeBoot",
 		"define": "haxe-boot",
 		"doc": "Give the name 'haxe' to the flash boot class instead of a generated name.",
-		"platforms": ["flash"]
+		"platforms": ["flash"],
+		"deprecated": "The flash target will be removed for Haxe 5"
 	},
 	{
 		"name": "HaxeVer",
@@ -382,7 +388,8 @@
 		"name": "NetworkSandbox",
 		"define": "network-sandbox",
 		"doc": "Use local network sandbox instead of local file access one.",
-		"platforms": ["flash"]
+		"platforms": ["flash"],
+		"deprecated": "The flash target will be removed for Haxe 5"
 	},
 	{
 		"name": "NoCompilation",
@@ -404,7 +411,8 @@
 		"name": "NoFlashOverride",
 		"define": "no-flash-override",
 		"doc": "Change overrides on some basic classes into HX suffixed methods",
-		"platforms": ["flash"]
+		"platforms": ["flash"],
+		"deprecated": "The flash target will be removed for Haxe 5"
 	},
 	{
 		"name": "NoOpt",
@@ -432,7 +440,8 @@
 		"name": "NoSwfCompress",
 		"define": "no-swf-compress",
 		"doc": "Disable SWF output compression.",
-		"platforms": ["flash"]
+		"platforms": ["flash"],
+		"deprecated": "The flash target will be removed for Haxe 5"
 	},
 	{
 		"name": "NoTraces",
@@ -529,71 +538,82 @@
 		"define": "swc",
 		"doc": "Output a SWC instead of a SWF.",
 		"platforms": ["flash"],
-		"reserved": true
+		"reserved": true,
+		"deprecated": "The flash target will be removed for Haxe 5"
 	},
 	{
 		"name": "SwfCompressLevel",
 		"define": "swf-compress-level",
 		"doc": "Set the amount of compression for the SWF output.",
 		"platforms": ["flash"],
-		"params": ["level: 1-9"]
+		"params": ["level: 1-9"],
+		"deprecated": "The flash target will be removed for Haxe 5"
 	},
 	{
 		"name": "SwfDebugPassword",
 		"define": "swf-debug-password",
 		"doc": "Set a password for debugging.",
 		"platforms": ["flash"],
-		"params": ["password"]
+		"params": ["password"],
+		"deprecated": "The flash target will be removed for Haxe 5"
 	},
 	{
 		"name": "SwfDirectBlit",
 		"define": "swf-direct-blit",
 		"doc": "Use hardware acceleration to blit graphics.",
-		"platforms": ["flash"]
+		"platforms": ["flash"],
+		"deprecated": "The flash target will be removed for Haxe 5"
 	},
 	{
 		"name": "SwfGpu",
 		"define": "swf-gpu",
 		"doc": "Use GPU compositing features when drawing graphics.",
-		"platforms": ["flash"]
+		"platforms": ["flash"],
+		"deprecated": "The flash target will be removed for Haxe 5"
 	},
 	{
 		"name": "SwfHeader",
 		"define": "swf-header",
 		"doc": "define SWF header (width:height:fps:color)",
-		"platforms": ["flash"]
+		"platforms": ["flash"],
+		"deprecated": "The flash target will be removed for Haxe 5"
 	},
 	{
 		"name": "SwfMetadata",
 		"define": "swf-metadata",
 		"doc": "Include contents of the given file as metadata in the SWF.",
 		"platforms": ["flash"],
-		"params": ["file"]
+		"params": ["file"],
+		"deprecated": "The flash target will be removed for Haxe 5"
 	},
 	{
 		"name": "SwfPreloaderFrame",
 		"define": "swf-preloader-frame",
 		"doc": "Insert empty first frame in SWF.",
-		"platforms": ["flash"]
+		"platforms": ["flash"],
+		"deprecated": "The flash target will be removed for Haxe 5"
 	},
 	{
 		"name": "SwfProtected",
 		"define": "swf-protected",
 		"doc": "Compile Haxe `private` as `protected` in the SWF instead of `public`.",
-		"platforms": ["flash"]
+		"platforms": ["flash"],
+		"deprecated": "The flash target will be removed for Haxe 5"
 	},
 	{
 		"name": "SwfScriptTimeout",
 		"define": "swf-script-timeout",
 		"doc": "Maximum ActionScript processing time before script stuck dialog box displays.",
 		"platforms": ["flash"],
-		"params": ["time in seconds"]
+		"params": ["time in seconds"],
+		"deprecated": "The flash target will be removed for Haxe 5"
 	},
 	{
 		"name": "SwfUseDoAbc",
 		"define": "swf-use-doabc",
 		"doc": "Use `DoAbc` SWF-tag instead of `DoAbcDefine`.",
-		"platforms": ["flash"]
+		"platforms": ["flash"],
+		"deprecated": "The flash target will be removed for Haxe 5"
 	},
 	{
 		"name": "Sys",
@@ -631,24 +651,24 @@
 	},
 	{
 		"name": "MessageReporting",
-		"define": "message-reporting",
+		"define": "message.reporting",
 		"doc": "Select message reporting mode for compiler output. (default: classic)",
 		"params": ["mode: classic | pretty | indent"]
 	},
 	{
-		"name": "NoColor",
-		"define": "no-color",
-		"doc": "Disable ANSI color codes when using rich output."
+		"name": "MessageNoColor",
+		"define": "message.no-color",
+		"doc": "Disable ANSI color codes in message reporting."
 	},
 	{
-		"name": "MessagesLogFile",
-		"define": "messages-log-file",
-		"doc": "Path to a text file to write messages log to, in addition to regular output."
+		"name": "MessageLogFile",
+		"define": "message.log-file",
+		"doc": "Path to a text file to write message reporting to, in addition to regular output."
 	},
 	{
-		"name": "MessagesLogFormat",
-		"define": "messages-log-format",
-		"doc": "Select message reporting mode for messages log output. (default: indent)",
+		"name": "MessageLogFormat",
+		"define": "message.log-format",
+		"doc": "Select message reporting mode for message log file. (default: indent)",
 		"params": ["format: classic | pretty | indent"]
 	}
 ]

+ 10 - 0
src-json/warning.json

@@ -58,6 +58,16 @@
 		"name": "WDeprecated",
 		"doc": "This is deprecated and should no longer be used"
 	},
+	{
+		"name": "WDeprecatedDefine",
+		"doc": "This define is deprecated and should no longer be used",
+		"parent": "WDeprecated"
+	},
+	{
+		"name": "WDeprecatedEnumAbstract",
+		"doc": "`@:enum abstract` is deprecated, `enum abstract` should be used instead",
+		"parent": "WDeprecated"
+	},
 	{
 		"name": "WVarInit",
 		"doc": "A local variable might be used before being assigned a value",

+ 7 - 1
src-prebuild/dune

@@ -1,8 +1,14 @@
 (include_subdirs no)
 
+(env
+	(_
+		(flags (-w -9 -w -32))
+	)
+)
+
 (executable
 	(name prebuild)
 	(public_name haxe_prebuild)
 	(package haxe_prebuild)
 	(libraries extlib json)
-)
+)

+ 56 - 28
src-prebuild/prebuild.ml

@@ -9,6 +9,17 @@ type parsed_warning = {
 	w_generic : bool;
 }
 
+type parsed_meta = {
+	m_name : string;
+	m_meta : string;
+	m_doc : string;
+	m_params : string list;
+	m_platforms : string list;
+	m_targets : string list;
+	m_internal : bool;
+	m_links : string list;
+}
+
 let as_string = function
 	| JString s -> Some s
 	| _ -> None
@@ -103,21 +114,24 @@ let parse_define json =
 	(* doc *) get_field "doc" as_string fields,
 	(* params *) get_optional_field "params" as_params [] fields,
 	(* platforms *) get_optional_field "platforms" as_platforms [] fields,
-	(* links *) get_optional_field "links" as_links [] fields
+	(* links *) get_optional_field "links" as_links [] fields,
+	(* deprecated *) get_optional_field2 "deprecated" as_string fields
 
 let parse_meta json =
 	let fields = match json with
 		| JObject fl -> fl
 		| _ -> raise (Prebuild_error "not an object")
 	in
-	(* name *) get_field "name" as_string fields,
-	(* metadata *) get_field "metadata" as_string fields,
-	(* doc *) get_field "doc" as_string fields,
-	(* params *) get_optional_field "params" as_params [] fields,
-	(* platforms *) get_optional_field "platforms" as_platforms [] fields,
-	(* targets *) get_optional_field "targets" as_targets [] fields,
-	(* internal *) get_optional_field "internal" as_bool false fields,
-	(* links *) get_optional_field "links" as_links [] fields
+	{
+		m_name = get_field "name" as_string fields;
+		m_meta = get_field "metadata" as_string fields;
+		m_doc = get_field "doc" as_string fields;
+		m_params = get_optional_field "params" as_params [] fields;
+		m_platforms = get_optional_field "platforms" as_platforms [] fields;
+		m_targets = get_optional_field "targets" as_targets [] fields;
+		m_internal = get_optional_field "internal" as_bool false fields;
+		m_links = get_optional_field "links" as_links [] fields
+	}
 
 let parse_warning json =
 	let fields = match json with
@@ -164,42 +178,54 @@ let gen_params = List.map (function param -> "HasParam \"" ^ param ^ "\"" )
 let gen_links = List.map (function link -> "Link \"" ^ link ^ "\"" )
 
 let gen_define_type defines =
-	String.concat "\n" (List.map (function (name, _, _, _, _, _) -> "\t| " ^ name) defines)
+	String.concat "\n" (List.map (function (name, _, _, _, _, _, _) -> "\t| " ^ name) defines)
+
+let gen_option f = function
+	| None -> "None"
+	| Some x -> Printf.sprintf "Some(%s)" (f x)
 
 let gen_define_info defines =
+	let deprecations = DynArray.create() in
 	let define_str = List.map (function
-		(name, define, doc, params, platforms, links) ->
+		(name, define, doc, params, platforms, links, deprecated) ->
 			let platforms_str = gen_platforms platforms in
 			let params_str = gen_params params in
 			let links_str = gen_links links in
 			let define = String.concat "_" (ExtString.String.nsplit define "-") in
-			"\t| " ^ name ^ " -> \"" ^ define ^ "\",(" ^ (Printf.sprintf "%S" doc) ^ ",[" ^ (String.concat "; " (platforms_str @ params_str @ links_str)) ^ "])"
+			let deprecated = match deprecated with
+				| None ->
+					[]
+				| Some x ->
+					let quoted = Printf.sprintf "%S" x in
+					DynArray.add deprecations (Printf.sprintf "\t(%S,%S)" define x);
+					[Printf.sprintf "Deprecated(%s)" quoted]
+			in
+			"\t| " ^ name ^ " -> \"" ^ define ^ "\",(" ^ (Printf.sprintf "%S" doc) ^ ",[" ^ (String.concat "; " (platforms_str @ params_str @ links_str @ deprecated)) ^ "])"
 	) defines in
-	String.concat "\n" define_str
+	String.concat "\n" define_str,String.concat ";\n" (DynArray.to_list deprecations)
 
 let gen_meta_type metas =
 	String.concat "\n" (List.map (function
-		| ("InlineConstructorArgument", _, _, _, _, _, _, _) -> "\t| InlineConstructorArgument of int * int"
-		| (name, _, _, _, _, _, _, _) -> "\t| " ^ name
+		| {m_name = "InlineConstructorArgument"} -> "\t| InlineConstructorArgument of int * int"
+		| {m_name = name} -> "\t| " ^ name
 	) metas)
 
 let gen_meta_info metas =
-	let meta_str = List.map (function
-		(name, metadata, doc, params, platforms, targets, internal, links) ->
-			let platforms_str = gen_platforms platforms in
-			let params_str = gen_params params in
-			let targets_str = (match targets with
+	let meta_str = List.map (function meta ->
+			let platforms_str = gen_platforms meta.m_platforms in
+			let params_str = gen_params meta.m_params in
+			let targets_str = (match meta.m_targets with
 				| [] -> []
 				| targets -> ["UsedOn [" ^ (String.concat ";" targets) ^ "]"]
 			) in
-			let internal_str = if internal then ["UsedInternally"] else [] in
-			let links_str = gen_links links in
-			let name = (match name with
+			let internal_str = if meta.m_internal then ["UsedInternally"] else [] in
+			let links_str = gen_links meta.m_links in
+			let name = (match meta.m_name with
 				(* this is a hacky, I know *)
 				| "InlineConstructorArgument" -> "InlineConstructorArgument _"
-				| _ -> name
+				| _ -> meta.m_name
 			) in
-			"\t| " ^ name ^ " -> \"" ^ metadata ^ "\",(" ^ (Printf.sprintf "%S" doc) ^ ",[" ^ (String.concat "; " (platforms_str @ params_str @ targets_str @ internal_str @ links_str)) ^ "])"
+			"\t| " ^ name ^ " -> \"" ^ meta.m_meta ^ "\",(" ^ (Printf.sprintf "%S" meta.m_doc) ^ ",[" ^ (String.concat "; " (platforms_str @ params_str @ targets_str @ internal_str @ links_str)) ^ "])"
 	) metas in
 	String.concat "\n" meta_str
 
@@ -240,7 +266,7 @@ type define_parameter =
 	| HasParam of string
 	| Platforms of platform list
 	| Link of string
-
+	| Deprecated of string
 "
 
 let meta_header = autogen_header ^ "
@@ -289,9 +315,11 @@ match Array.to_list (Sys.argv) with
 		Printf.printf "type strict_defined =\n";
 		Printf.printf "%s" (gen_define_type defines);
 		Printf.printf "\n\t| Last\n\t| Custom of string\n\n";
+		let infos,deprecations = gen_define_info defines in
 		Printf.printf "let infos = function\n";
-		Printf.printf "%s" (gen_define_info defines);
-		Printf.printf "\n\t| Last -> die \"\" __LOC__\n\t| Custom s -> s,(\"\",[])\n"
+		Printf.printf "%s" infos;
+		Printf.printf "\n\t| Last -> die \"\" __LOC__\n\t| Custom s -> s,(\"\",[])\n";
+		Printf.printf "\nlet deprecated_defines = [\n%s\n]\n" deprecations;
 	| [_; "meta"; meta_path]->
 		let metas = parse_file_array meta_path parse_meta in
 		Printf.printf "%s" meta_header;

+ 6 - 11
src/codegen/codegen.ml

@@ -20,7 +20,6 @@
 open Ast
 open Type
 open Common
-open Error
 open Globals
 open Extlib_leftovers
 
@@ -66,12 +65,12 @@ let add_property_field com c =
 		c.cl_statics <- PMap.add cf.cf_name cf c.cl_statics;
 		c.cl_ordered_statics <- cf :: c.cl_ordered_statics
 
-let escape_res_name name allow_dirs =
+let escape_res_name name allowed =
 	ExtString.String.replace_chars (fun chr ->
 		if (chr >= 'a' && chr <= 'z') || (chr >= 'A' && chr <= 'Z') || (chr >= '0' && chr <= '9') || chr = '_' || chr = '.' then
 			Char.escaped chr
-		else if chr = '/' && allow_dirs then
-			"/"
+		else if List.mem chr allowed then
+			Char.escaped chr
 		else
 			"-x" ^ (string_of_int (Char.code chr))) name
 
@@ -373,7 +372,6 @@ module Dump = struct
 	let dump_types com =
 		match Common.defined_value_safe com Define.Dump with
 			| "pretty" -> dump_types com (Type.s_expr_pretty false "\t" true)
-			| "legacy" -> dump_types com Type.s_expr
 			| "record" -> dump_record com
 			| "position" -> dump_position com
 			| _ -> dump_types com (Type.s_expr_ast (not (Common.defined com Define.DumpIgnoreVarIds)) "\t")
@@ -389,7 +387,8 @@ module Dump = struct
 		let dep = Hashtbl.create 0 in
 		List.iter (fun m ->
 			print "%s:\n" (Path.UniqueKey.lazy_path m.m_extra.m_file);
-			PMap.iter (fun _ m2 ->
+			PMap.iter (fun _ (sign,mpath) ->
+				let m2 = (com.cs#get_context sign)#find_module mpath in
 				let file = Path.UniqueKey.lazy_path m2.m_extra.m_file in
 				print "\t%s\n" file;
 				let l = try Hashtbl.find dep file with Not_found -> [] in
@@ -416,7 +415,7 @@ end
 let default_cast ?(vtmp="$t") com e texpr t p =
 	let api = com.basic in
 	let mk_texpr = function
-		| TClassDecl c -> mk_anon (ref (Statics c))
+		| TClassDecl c -> mk_anon (ref (ClassStatics c))
 		| TEnumDecl e -> mk_anon (ref (EnumStatics e))
 		| TAbstractDecl a -> mk_anon (ref (AbstractStatics a))
 		| TTypeDecl _ -> die "" __LOC__
@@ -478,10 +477,6 @@ let interpolate_code com code tl f_string f_expr p =
 			i := !i + String.length txt;
 			f_string txt;
 			loop tl
-		| Str.Delim a :: Str.Delim b :: tl when a = b ->
-			i := !i + 2;
-			f_string a;
-			loop tl
 		| Str.Delim "{" :: Str.Text n :: Str.Delim "}" :: tl ->
 			begin try
 				let expr = Array.get exprs (int_of_string n) in

+ 85 - 3
src/codegen/javaModern.ml

@@ -40,9 +40,54 @@ module AccessFlags = struct
 		b land (to_int flag) <> 0
 end
 
-open JClass
+module JDataHoldovers = struct
+	type jwildcard =
+		| WExtends (* + *)
+		| WSuper (* -  *)
+		| WNone
+
+	type jtype_argument =
+		| TType of jwildcard * jsignature
+		| TAny (* * *)
+
+	and jsignature =
+		| TByte (* B *)
+		| TChar (* C *)
+		| TDouble (* D *)
+		| TFloat (* F *)
+		| TInt (* I *)
+		| TLong (* J *)
+		| TShort (* S *)
+		| TBool (* Z *)
+		| TObject of path * jtype_argument list (* L Classname *)
+		| TObjectInner of (string list) * (string * jtype_argument list) list (* L Classname ClassTypeSignatureSuffix *)
+		| TArray of jsignature * int option (* [ *)
+		| TMethod of jmethod_signature (* ( *)
+		| TTypeParameter of string (* T *)
+
+	(* ( jsignature list ) ReturnDescriptor (| V | jsignature) *)
+	and jmethod_signature = jsignature list * jsignature option
+
+	type jtypes = (string * jsignature option * jsignature list) list
+
+	type jannotation = {
+		ann_type : jsignature;
+		ann_elements : (string * jannotation_value) list;
+	}
+
+	and jannotation_value =
+		| ValConst of jsignature * int
+		| ValEnum of jsignature * string (* e *)
+		| ValClass of jsignature (* c *) (* V -> Void *)
+		| ValAnnotation of jannotation (* @ *)
+		| ValArray of jannotation_value list (* [ *)
+end
+
+open JDataHoldovers
 
 module JReaderHoldovers = struct
+	open JDataHoldovers
+
 	let rec parse_type_parameter_part s = match s.[0] with
 		| '*' -> TAny, 1
 		| c ->
@@ -223,6 +268,43 @@ module JReaderModern = struct
 		name_and_types : (string * string) array;
 	}
 
+	type jlocal = {
+		ld_start_pc : int;
+		ld_length : int;
+		ld_name : string;
+		ld_descriptor : string;
+		ld_index : int;
+	}
+
+	type jattribute =
+		| AttrCode of jattribute list
+		| AttrDeprecated
+		| AttrLocalVariableTable of jlocal list
+  		| AttrMethodParameters of (string * int) list
+		| AttrSignature of string
+		| AttrVisibleAnnotations of jannotation list
+  		| AttrOther
+
+	type jfield = {
+		jf_name : string;
+		jf_flags : int;
+		jf_types : jtypes;
+		jf_descriptor : jsignature;
+		jf_attributes : jattribute list;
+		jf_code : jattribute list option;
+	}
+
+	type jclass = {
+		jc_path : path;
+		jc_flags : int;
+		jc_super : jsignature;
+		jc_interfaces : jsignature list;
+		jc_types : jtypes;
+		jc_fields : jfield list;
+		jc_methods : jfield list;
+		jc_attributes : jattribute list;
+	}
+
 	let read_constant_pool ch =
 		let count = read_ui16 ch in
 		let strings = Array.make count "" in
@@ -340,7 +422,7 @@ module JReaderModern = struct
 			let len = read_i32 ch in
 			ignore(IO.nread_string ch len); (* code *)
 			let len = read_ui16 ch in
-			for i = 0 to len - 1 do
+			for _ = 0 to len - 1 do
 				ignore(IO.nread_string ch 8);
 			done; (* exceptions *)
 			let attribs = parse_attributes consts ch in
@@ -473,7 +555,7 @@ module PathConverter = struct
 	let jname_to_hx name =
 		let name =
 			if name <> "" && (String.get name 0 < 'A' || String.get name 0 > 'Z') then
-				Char.escaped (Char.uppercase (String.get name 0)) ^ String.sub name 1 (String.length name - 1)
+				Char.escaped (Char.uppercase_ascii (String.get name 0)) ^ String.sub name 1 (String.length name - 1)
 			else
 				name
 		in

+ 0 - 6
src/codegen/overloads.ml

@@ -219,12 +219,6 @@ struct
 		| r :: ret ->
 			rm_duplicates (r :: acc) ret
 
-	let s_options rated =
-		String.concat ",\n" (List.map (fun ((elist,t,_),rate) ->
-			"( " ^ (String.concat "," (List.map (fun(e,_) -> s_expr (s_type (print_context())) e) elist)) ^ " ) => " ^
-			"( " ^ (String.concat "," (List.map (fun (i,i2) -> string_of_int i ^ ":" ^ string_of_int i2) rate)) ^ " ) => " ^ (s_type (print_context()) t)
-		) rated)
-
 	let count_optionals t =
 		match follow t with
 		| TFun(args,_) ->

+ 3 - 3
src/codegen/swfLoader.ml

@@ -33,7 +33,7 @@ let lowercase_pack pack =
 			let name =
 				let fchar = String.get name 0 in
 				if fchar >= 'A' && fchar <= 'Z' then
-					(String.make 1 (Char.lowercase fchar)) ^ String.sub name 1 (String.length name - 1)
+					(String.make 1 (Char.lowercase_ascii fchar)) ^ String.sub name 1 (String.length name - 1)
 				else
 					name
 			in
@@ -454,7 +454,7 @@ let build_class com c file =
 let extract_data (_,tags) =
 	let t = Timer.timer ["read";"swf"] in
 	let h = Hashtbl.create 0 in
-	let rec loop_field f =
+	let loop_field f =
 		match f.hlf_kind with
 		| HFClass c ->
 			let path = make_tpath f.hlf_name in
@@ -647,7 +647,7 @@ let remove_classes toremove lib l =
 					match t.tdata with
 					| TActionScript3 (h,data) ->
 						let data = As3hlparse.parse data in
-						let rec loop f =
+						let loop f =
 							match f.hlf_kind with
 							| HFClass _ ->
 								let path = make_tpath f.hlf_name in

+ 5 - 1
src/compiler/args.ml

@@ -40,7 +40,7 @@ let process_args arg_spec =
 
 let parse_args com =
 	let usage = Printf.sprintf
-		"Haxe Compiler %s - (C)2005-2022 Haxe Foundation\nUsage: haxe%s <target> [options] [hxml files and dot paths...]\n"
+		"Haxe Compiler %s - (C)2005-2023 Haxe Foundation\nUsage: haxe%s <target> [options] [hxml files and dot paths...]\n"
 		s_version_full (if Sys.os_type = "Win32" then ".exe" else "")
 	in
 	let actx = {
@@ -94,6 +94,10 @@ let parse_args com =
 		("Target",["--hl"],["-hl"],Arg.String (fun file ->
 			set_platform com Hl file;
 		),"<file>","generate HashLink .hl bytecode or .c code into target file");
+		("Target",["--custom-target"],["-custom"],Arg.String (fun target ->
+			let name, path = try let split = ExtString.String.split target "=" in split with _ -> target, "" in
+			set_custom_target com name path;
+		),"<name[=path]>","generate code for a custom target");
 		("Target",[],["-x"], Arg.String (fun cl ->
 			let cpath = Path.parse_type_path cl in
 			(match com.main_class with

+ 11 - 11
src/compiler/compilationContext.ml

@@ -44,7 +44,7 @@ and compilation_context = {
 
 type compilation_callbacks = {
 	before_anything : compilation_context -> unit;
-	after_arg_parsing : compilation_context -> unit;
+	after_target_init : compilation_context -> unit;
 	after_compilation : compilation_context -> unit;
 }
 
@@ -54,22 +54,22 @@ type server_api = {
 	cache : CompilationCache.t;
 	callbacks : compilation_callbacks;
 	on_context_create : unit -> int;
-	init_wait_socket : string -> int -> server_accept;
-	init_wait_connect : string -> int -> server_accept;
+	init_wait_socket : (Ipaddr.V4.t, Ipaddr.V6.t) Ipaddr.v4v6 -> int -> server_accept;
+	init_wait_connect : (Ipaddr.V4.t, Ipaddr.V6.t) Ipaddr.v4v6 -> int -> server_accept;
 	init_wait_stdio : unit -> server_accept;
 	wait_loop : bool -> server_accept -> int;
-	do_connect : string -> int -> string list -> unit;
+	do_connect : (Ipaddr.V4.t, Ipaddr.V6.t) Ipaddr.v4v6 -> int -> string list -> unit;
 }
 
 let message ctx msg =
 	ctx.messages <- msg :: ctx.messages
 
-let error ctx ?(depth=0) msg p =
-	message ctx (make_compiler_message msg p depth DKCompilerMessage Error);
+let error ctx ?(depth=0) ?(from_macro = false) msg p =
+	message ctx (make_compiler_message ~from_macro msg p depth DKCompilerMessage Error);
 	ctx.has_error <- true
 
-let located_error ctx ?(depth=0) msg = match (extract_located msg) with
-	| [] -> ()
-	| (msg,p) :: tl ->
-		error ~depth ctx msg p;
-		List.iter (fun (msg,p) -> error ~depth:(depth+1) ctx msg p) tl
+let error_ext ctx (err : Error.error) =
+	Error.recurse_error (fun depth err ->
+		error ~depth ~from_macro:err.err_from_macro ctx (Error.error_msg err.err_message) err.err_pos
+	) err
+

+ 107 - 57
src/compiler/compiler.ml

@@ -4,20 +4,24 @@ open CompilationContext
 
 let run_or_diagnose ctx f arg =
 	let com = ctx.com in
-	let handle_diagnostics ?(depth = 0) msg kind =
+	let handle_diagnostics ?(depth = 0) msg p kind =
 		ctx.has_error <- true;
-		add_diagnostics_message ~depth com msg kind Error;
+		add_diagnostics_message ~depth com msg p kind Error;
 		DisplayOutput.emit_diagnostics ctx.com
 	in
 	if is_diagnostics com then begin try
 			f arg
 		with
-		| Error.Error(msg,p,depth) ->
-			handle_diagnostics ~depth (Error.error_msg p msg) DKCompilerMessage
+		| Error.Error err ->
+			ctx.has_error <- true;
+			Error.recurse_error (fun depth err ->
+				add_diagnostics_message ~depth com (Error.error_msg err.err_message) err.err_pos DKCompilerMessage Error
+			) err;
+			DisplayOutput.emit_diagnostics ctx.com
 		| Parser.Error(msg,p) ->
-			handle_diagnostics (located (Parser.error_msg msg) p) DKParserError
+			handle_diagnostics (Parser.error_msg msg) p DKParserError
 		| Lexer.Error(msg,p) ->
-			handle_diagnostics (located (Lexer.error_msg msg) p) DKParserError
+			handle_diagnostics (Lexer.error_msg msg) p DKParserError
 		end
 	else
 		f arg
@@ -67,14 +71,15 @@ let run_command ctx cmd =
 
 module Setup = struct
 	let initialize_target ctx com actx =
+		init_platform com;
 		let add_std dir =
 			com.class_path <- List.filter (fun s -> not (List.mem s com.std_path)) com.class_path @ List.map (fun p -> p ^ dir ^ "/_std/") com.std_path @ com.std_path
 		in
 		match com.platform with
 			| Cross ->
-				(* no platform selected *)
-				set_platform com Cross "";
 				"?"
+			| CustomTarget name ->
+				name
 			| Flash ->
 				let rec loop = function
 					| [] -> ()
@@ -132,13 +137,20 @@ module Setup = struct
 				"python"
 			| Hl ->
 				add_std "hl";
-				if not (Common.defined com Define.HlVer) then Define.define_value com.defines Define.HlVer (try Std.input_file (Common.find_file com "hl/hl_version") with Not_found -> die "" __LOC__);
+				if not (Common.defined com Define.HlVer) then begin
+					let hl_ver = try
+						Std.input_file (Common.find_file com "hl/hl_version")
+					with Not_found ->
+						failwith "The file hl_version could not be found. Please make sure HAXE_STD_PATH is set to the standard library corresponding to the used compiler version."
+					in
+					Define.define_value com.defines Define.HlVer hl_ver
+				end;
 				"hl"
 			| Eval ->
 				add_std "eval";
 				"eval"
 
-	let create_typer_context ctx native_libs =
+	let create_typer_context ctx macros native_libs =
 		let com = ctx.com in
 		Common.log com ("Classpath: " ^ (String.concat ";" com.class_path));
 		let buffer = Buffer.create 64 in
@@ -149,13 +161,12 @@ module Setup = struct
 		) com.defines.values;
 		Buffer.truncate buffer (Buffer.length buffer - 1);
 		Common.log com (Buffer.contents buffer);
-		Typecore.type_expr_ref := (fun ?(mode=MGet) ctx e with_type -> Typer.type_expr ~mode ctx e with_type);
-		com.callbacks#run com.callbacks#get_before_typer_create;
+		com.callbacks#run com.error_ext com.callbacks#get_before_typer_create;
 		(* Native lib pass 1: Register *)
 		let fl = List.map (fun (file,extern) -> NativeLibraryHandler.add_native_lib com file extern) (List.rev native_libs) in
 		(* Native lib pass 2: Initialize *)
 		List.iter (fun f -> f()) fl;
-		Typer.create com
+		Typer.create com macros
 
 	let executable_path() =
 		Extc.executable_path()
@@ -205,8 +216,10 @@ module Setup = struct
 		Common.define_value com Define.Haxe s_version;
 		Common.raw_define com "true";
 		Common.define_value com Define.Dce "std";
-		com.info <- (fun ?(depth=0) msg p -> message ctx (make_compiler_message msg p depth DKCompilerMessage Information));
-		com.warning <- (fun ?(depth=0) w options msg p ->
+		com.info <- (fun ?(depth=0) ?(from_macro=false) msg p ->
+			message ctx (make_compiler_message ~from_macro msg p depth DKCompilerMessage Information)
+		);
+		com.warning <- (fun ?(depth=0) ?(from_macro=false) w options msg p ->
 			match Warning.get_mode w (com.warning_options @ options) with
 			| WMEnable ->
 				let wobj = Warning.warning_obj w in
@@ -215,12 +228,12 @@ module Setup = struct
 				else
 					Printf.sprintf "(%s) %s" wobj.w_name msg
 				in
-				message ctx (make_compiler_message msg p depth DKCompilerMessage Warning)
+				message ctx (make_compiler_message ~from_macro msg p depth DKCompilerMessage Warning)
 			| WMDisable ->
 				()
 		);
-		com.located_error <- located_error ctx;
-		com.error <- (fun ?(depth = 0) msg p -> com.located_error ~depth (located msg p));
+		com.error_ext <- error_ext ctx;
+		com.error <- (fun ?(depth = 0) msg p -> com.error_ext (Error.make_error ~depth (Custom msg) p));
 		let filter_messages = (fun keep_errors predicate -> (List.filter (fun cm ->
 			(match cm.cm_severity with
 			| MessageSeverity.Error -> keep_errors;
@@ -238,35 +251,66 @@ module Setup = struct
 
 end
 
+let check_defines com =
+	if is_next com then begin
+		PMap.iter (fun k _ ->
+			try
+				let reason = Hashtbl.find Define.deprecation_lut k in
+				let p = { pfile = "-D " ^ k; pmin = -1; pmax = -1 } in
+				com.warning WDeprecatedDefine [] reason p
+			with Not_found ->
+				()
+		) com.defines.values
+	end
+
 (** Creates the typer context and types [classes] into it. *)
-let do_type ctx tctx actx =
-	let com = tctx.Typecore.com in
+let do_type ctx mctx actx display_file_dot_path macro_cache_enabled =
+	let com = ctx.com in
 	let t = Timer.timer ["typing"] in
 	let cs = com.cs in
 	CommonCache.maybe_add_context_sign cs com "before_init_macros";
 	com.stage <- CInitMacrosStart;
-	List.iter (MacroContext.call_init_macro tctx) (List.rev actx.config_macros);
+	ServerMessage.compiler_stage com;
+
+	let mctx = List.fold_left (fun mctx path ->
+		Some (MacroContext.call_init_macro ctx.com mctx path)
+	) mctx (List.rev actx.config_macros) in
 	com.stage <- CInitMacrosDone;
+	ServerMessage.compiler_stage com;
+	MacroContext.macro_enable_cache := macro_cache_enabled;
+
+	let macros = match mctx with None -> None | Some mctx -> mctx.g.macros in
+	let tctx = Setup.create_typer_context ctx macros actx.native_libs in
+	let display_file_dot_path = DisplayProcessing.maybe_load_display_file_before_typing tctx display_file_dot_path in
+	check_defines ctx.com;
 	CommonCache.lock_signature com "after_init_macros";
-	com.callbacks#run com.callbacks#get_after_init_macros;
-	run_or_diagnose ctx (fun () ->
-		if com.display.dms_kind <> DMNone then DisplayTexpr.check_display_file tctx cs;
-		List.iter (fun cpath -> ignore(tctx.Typecore.g.Typecore.do_load_module tctx cpath null_pos)) (List.rev actx.classes);
-		Finalization.finalize tctx;
-	) ();
+	Option.may (fun mctx -> MacroContext.finalize_macro_api tctx mctx) mctx;
+	(try begin
+		com.callbacks#run com.error_ext com.callbacks#get_after_init_macros;
+		run_or_diagnose ctx (fun () ->
+			if com.display.dms_kind <> DMNone then DisplayTexpr.check_display_file tctx cs;
+			List.iter (fun cpath -> ignore(tctx.Typecore.g.Typecore.do_load_module tctx cpath null_pos)) (List.rev actx.classes);
+			Finalization.finalize tctx;
+		) ();
+	end with TypeloadParse.DisplayInMacroBlock ->
+		ignore(DisplayProcessing.load_display_module_in_macro tctx display_file_dot_path true)
+	);
 	com.stage <- CTypingDone;
+	ServerMessage.compiler_stage com;
 	(* If we are trying to find references, let's syntax-explore everything we know to check for the
 		identifier we are interested in. We then type only those modules that contain the identifier. *)
 	begin match com.display.dms_kind with
 		| (DMUsage _ | DMImplementation) -> FindReferences.find_possible_references tctx cs;
 		| _ -> ()
 	end;
-	t()
+	t();
+	(tctx, display_file_dot_path)
 
 let finalize_typing ctx tctx =
 	let t = Timer.timer ["finalize"] in
 	let com = ctx.com in
 	com.stage <- CFilteringStart;
+	ServerMessage.compiler_stage com;
 	let main, types, modules = run_or_diagnose ctx Finalization.generate tctx in
 	com.main <- main;
 	com.types <- types;
@@ -276,33 +320,41 @@ let finalize_typing ctx tctx =
 let filter ctx tctx =
 	let t = Timer.timer ["filters"] in
 	DeprecationCheck.run ctx.com;
-	Filters.run ctx.com tctx ctx.com.main;
+	Filters.run tctx ctx.com.main;
 	t()
 
-let compile ctx actx =
+let compile ctx actx callbacks =
 	let com = ctx.com in
 	(* Set up display configuration *)
 	DisplayProcessing.process_display_configuration ctx;
 	let display_file_dot_path = DisplayProcessing.process_display_file com actx in
+	let macro_cache_enabled = !MacroContext.macro_enable_cache in
+	MacroContext.macro_enable_cache := true;
+	let mctx = match com.platform with
+		| CustomTarget name ->
+			begin try
+				Some (MacroContext.call_init_macro com None (Printf.sprintf "%s.Init.init()" name))
+			with (Error.Error { err_message = Module_not_found ([pack],"Init") }) when pack = name ->
+				(* ignore if <target_name>.Init doesn't exist *)
+				None
+			end
+		| _ ->
+			None
+		in
 	(* Initialize target: This allows access to the appropriate std packages and sets the -D defines. *)
 	let ext = Setup.initialize_target ctx com actx in
-	com.config <- get_config com; (* make sure to adapt all flags changes defined after platform *)
+	update_platform_config com; (* make sure to adapt all flags changes defined after platform *)
+	callbacks.after_target_init ctx;
 	let t = Timer.timer ["init"] in
 	List.iter (fun f -> f()) (List.rev (actx.pre_compilation));
 	t();
 	com.stage <- CInitialized;
+	ServerMessage.compiler_stage com;
 	if actx.classes = [([],"Std")] && not actx.force_typing then begin
 		if actx.cmds = [] && not actx.did_something then actx.raise_usage();
 	end else begin
 		(* Actual compilation starts here *)
-		let tctx = Setup.create_typer_context ctx actx.native_libs in
-		com.stage <- CTyperCreated;
-		let display_file_dot_path = DisplayProcessing.maybe_load_display_file_before_typing tctx display_file_dot_path in
-		begin try
-			do_type ctx tctx actx
-		with TypeloadParse.DisplayInMacroBlock ->
-			ignore(DisplayProcessing.load_display_module_in_macro tctx display_file_dot_path true);
-		end;
+		let (tctx,display_file_dot_path) = do_type ctx mctx actx display_file_dot_path macro_cache_enabled in
 		DisplayProcessing.handle_display_after_typing ctx tctx display_file_dot_path;
 		finalize_typing ctx tctx;
 		DisplayProcessing.handle_display_after_finalization ctx tctx display_file_dot_path;
@@ -310,11 +362,13 @@ let compile ctx actx =
 		if ctx.has_error then raise Abort;
 		Generate.check_auxiliary_output com actx;
 		com.stage <- CGenerationStart;
+		ServerMessage.compiler_stage com;
 		if not actx.no_output then Generate.generate ctx tctx ext actx;
 		com.stage <- CGenerationDone;
+		ServerMessage.compiler_stage com;
 	end;
 	Sys.catch_break false;
-	com.callbacks#run com.callbacks#get_after_generation;
+	com.callbacks#run com.error_ext com.callbacks#get_after_generation;
 	if not actx.no_output then begin
 		List.iter (fun c ->
 			let r = run_command ctx c in
@@ -329,10 +383,10 @@ try
 with
 	| Abort ->
 		()
-	| Error.Fatal_error (m,depth) ->
-		located_error ~depth ctx m
-	| Common.Abort msg ->
-		located_error ctx msg
+	| Error.Fatal_error err ->
+		error_ext ctx err
+	| Common.Abort err ->
+		error_ext ctx err
 	| Lexer.Error (m,p) ->
 		error ctx (Lexer.error_msg m) p
 	| Parser.Error (m,p) ->
@@ -345,14 +399,8 @@ with
 			error ctx (Printf.sprintf "You cannot access the %s package while %s (for %s)" pack (if pf = "macro" then "in a macro" else "targeting " ^ pf) (s_type_path m) ) p;
 			List.iter (error ~depth:1 ctx (Error.compl_msg "referenced here")) (List.rev pl);
 		end
-	| Error.Error (Stack stack,_,depth) -> (match stack with
-		| [] -> ()
-		| (e,p) :: stack -> begin
-			located_error ~depth ctx (Error.error_msg p e);
-			List.iter (fun (e,p) -> located_error ~depth:(depth+1) ctx (Error.error_msg p e)) stack;
-		end)
-	| Error.Error (m,p,depth) ->
-		located_error ~depth ctx (Error.error_msg p m)
+	| Error.Error err ->
+		error_ext ctx err
 	| Generic.Generic_Exception(m,p) ->
 		error ctx m p
 	| Arg.Bad msg ->
@@ -402,7 +450,10 @@ let process_actx ctx actx =
 	DisplayProcessing.process_display_arg ctx actx;
 	List.iter (fun s ->
 		ctx.com.warning WDeprecated [] s null_pos
-	) actx.deprecations
+	) actx.deprecations;
+	if defined ctx.com NoDeprecationWarnings then begin
+		ctx.com.warning_options <- [{wo_warning = WDeprecated; wo_mode = WMDisable}] :: ctx.com.warning_options
+	end
 
 let compile_ctx callbacks ctx =
 	let run ctx =
@@ -411,8 +462,7 @@ let compile_ctx callbacks ctx =
 		compile_safe ctx (fun () ->
 			let actx = Args.parse_args ctx.com in
 			process_actx ctx actx;
-			callbacks.after_arg_parsing ctx;
-			compile ctx actx;
+			compile ctx actx callbacks;
 		);
 		finalize ctx;
 		callbacks.after_compilation ctx;
@@ -522,8 +572,8 @@ module HighLevel = struct
 					(* If we are already connected, ignore (issue #10813) *)
 					loop acc l
 				else begin
-					let host, port = (try ExtString.String.split hp ":" with _ -> "127.0.0.1", hp) in
-					server_api.do_connect host (try int_of_string port with _ -> raise (Arg.Bad "Invalid port")) ((List.rev acc) @ l);
+					let host, port = Helper.parse_host_port hp in
+					server_api.do_connect host port ((List.rev acc) @ l);
 					[],None
 				end
 			| "--server-connect" :: hp :: l ->

+ 3 - 7
src/compiler/displayOutput.ml

@@ -1,20 +1,16 @@
 open Globals
 open Ast
 open Common
-open Filename
 open Timer
 open DisplayTypes.DisplayMode
 open DisplayTypes.CompletionResultKind
 open CompletionItem
 open CompletionClassField
 open CompletionEnumField
-open ClassFieldOrigin
 open DisplayException
 open Type
-open Display
 open DisplayTypes
 open CompletionModuleType
-open Typecore
 open Genjson
 open CompilationContext
 open DisplayProcessingGlobals
@@ -213,7 +209,7 @@ let find_doc t =
 	let doc = match follow t with
 		| TAnon an ->
 			begin match !(an.a_status) with
-				| Statics c -> c.cl_doc
+				| ClassStatics c -> c.cl_doc
 				| EnumStatics en -> en.e_doc
 				| AbstractStatics a -> a.a_doc
 				| _ -> None
@@ -348,10 +344,10 @@ let handle_type_path_exception ctx p c is_import pos =
 			| None ->
 				DisplayPath.TypePathHandler.complete_type_path com p
 			| Some (c,cur_package) ->
-				let ctx = Typer.create com in
+				let ctx = Typer.create com None in
 				DisplayPath.TypePathHandler.complete_type_path_inner ctx p c cur_package is_import
 		end with Common.Abort msg ->
-			located_error ctx msg;
+			error_ext ctx msg;
 			None
 	in
 	begin match ctx.com.json_out,fields with

+ 10 - 10
src/compiler/displayProcessing.ml

@@ -48,7 +48,7 @@ let handle_display_argument_old com file_pos actx =
 			| "diagnostics" ->
 				com.report_mode <- RMDiagnostics [file_unique];
 				let dm = create DMNone in
-				{dm with dms_display_file_policy = DFPAlso; dms_per_file = true}
+				{dm with dms_display_file_policy = DFPAlso; dms_per_file = true; dms_populate_cache = !ServerConfig.populate_cache_from_display}
 			| "statistics" ->
 				com.report_mode <- RMStatistics;
 				let dm = create DMNone in
@@ -92,13 +92,14 @@ let process_display_arg ctx actx =
 let process_display_configuration ctx =
 	let com = ctx.com in
 	if is_diagnostics com then begin
-		com.info <- (fun ?depth s p ->
-			add_diagnostics_message ?depth com (located s p) DKCompilerMessage Information
+		com.info <- (fun ?depth ?from_macro s p ->
+			add_diagnostics_message ?depth com s p DKCompilerMessage Information
 		);
-		com.warning <- (fun ?depth w options s p ->
+		com.warning <- (fun ?(depth = 0) ?from_macro w options s p ->
 			match Warning.get_mode w (com.warning_options @ options) with
 			| WMEnable ->
-				add_diagnostics_message ?depth com (located s p) DKCompilerMessage Warning
+				let wobj = Warning.warning_obj w in
+				add_diagnostics_message ~depth ~code:(Some wobj.w_name) com s p DKCompilerMessage Warning
 			| WMDisable ->
 				()
 		);
@@ -192,7 +193,7 @@ let load_display_module_in_macro tctx display_file_dot_path clear = match displa
 		let p = null_pos in
 		begin try
 			let open Typecore in
-			let _, mctx = MacroContext.get_macro_context tctx p in
+			let mctx = MacroContext.get_macro_context tctx in
 			(* Tricky stuff: We want to remove the module from our lookups and load it again in
 				display mode. This covers some cases like --macro typing it in non-display mode (issue #7017). *)
 			if clear then begin
@@ -209,7 +210,7 @@ let load_display_module_in_macro tctx display_file_dot_path clear = match displa
 					()
 				end;
 			end;
-			let _ = MacroContext.load_macro_module tctx cpath true p in
+			let _ = MacroContext.load_macro_module (MacroContext.get_macro_context tctx) tctx.com cpath true p in
 			Finalization.finalize mctx;
 			Some mctx
 		with DisplayException.DisplayException _ | Parser.TypePath _ as exc ->
@@ -268,7 +269,7 @@ let maybe_load_display_file_before_typing tctx display_file_dot_path = match dis
 
 let handle_display_after_typing ctx tctx display_file_dot_path =
 	let com = ctx.com in
-	if ctx.com.display.dms_kind = DMNone & ctx.has_error then raise Abort;
+	if ctx.com.display.dms_kind = DMNone && ctx.has_error then raise Abort;
 	begin match ctx.com.display.dms_kind,!Parser.delayed_syntax_completion with
 		| DMDefault,Some(kind,subj) -> DisplayOutput.handle_syntax_completion com kind subj
 		| _ -> ()
@@ -311,7 +312,6 @@ let process_global_display_mode com tctx =
 		FindReferences.find_references tctx com with_definition
 	| DMImplementation ->
 		FindReferences.find_implementations tctx com
-	| DMModuleSymbols (Some "") -> ()
 	| DMModuleSymbols filter ->
 		let open CompilationCache in
 		let cs = com.cs in
@@ -354,4 +354,4 @@ let handle_display_after_finalization ctx tctx display_file_dot_path =
 		DisplayOutput.emit_statistics tctx
 	| RMNone ->
 		()
-	end
+	end

+ 11 - 9
src/compiler/generate.ml

@@ -56,8 +56,6 @@ let generate ctx tctx ext actx =
 	end;
 	if actx.interp then
 		Std.finally (Timer.timer ["interp"]) MacroContext.interpret tctx
-	else if com.platform = Cross then
-		()
 	else begin
 		let generate,name = match com.platform with
 		| Flash ->
@@ -85,11 +83,15 @@ let generate ctx tctx ext actx =
 			Genhl.generate,"hl"
 		| Eval ->
 			(fun _ -> MacroContext.interpret tctx),"eval"
-		| Cross ->
-			die "" __LOC__
+		| Cross
+		| CustomTarget _ ->
+			(fun _ -> ()),""
 		in
-		Common.log com ("Generating " ^ name ^ ": " ^ com.file);
-		let t = Timer.timer ["generate";name] in
-		generate com;
-		t()
-	end
+		if name = "" then ()
+		else begin
+			Common.log com ("Generating " ^ name ^ ": " ^ com.file);
+			let t = Timer.timer ["generate";name] in
+			generate com;
+			t()
+		end
+	end

+ 14 - 3
src/compiler/helper.ml

@@ -1,3 +1,4 @@
+open Ipaddr
 exception HelpMessage of string
 
 let is_debug_run = try Sys.getenv "HAXEDEBUG" = "1" with _ -> false
@@ -52,6 +53,16 @@ let parse_hxml file =
 	parse_hxml_data data
 
 let parse_host_port hp =
-	let host, port = (try ExtString.String.split hp ":" with _ -> "127.0.0.1", hp) in
-	let port = try int_of_string port with _ -> raise (Arg.Bad "Invalid port") in
-	host, port
+	match (Ipaddr.with_port_of_string ~default:(-1) hp) with
+	(* Short ipv6 notation will be mixed up with port; extract port and rebuild ipv6 *)
+	| Ok (V6 ip, -1) ->
+		let octets = ExtLib.String.split_on_char ':' (V6.to_string ip) in
+		(match (List.rev octets) with
+			| port :: octets -> (try V6 (V6.of_string_exn (ExtLib.String.join ":" (List.rev octets))), int_of_string port with _ -> raise (Arg.Bad "Invalid host/port"))
+			| _ -> raise (Arg.Bad "Invalid host/port")
+		)
+	| Ok (_, -1) -> raise (Arg.Bad "Invalid host/port: missing port")
+	| Ok (ip, port) -> ip, port
+	(* Default to 127.0.0.1 with given port if no host is provided *)
+	| Error _ when Str.string_match (Str.regexp "[0-9]+$") hp 0 -> V4 (V4.of_string_exn "127.0.0.1"), int_of_string hp
+	| Error _ -> raise (Arg.Bad "Invalid host/port")

+ 388 - 0
src/compiler/messageReporting.ml

@@ -0,0 +1,388 @@
+open Extlib_leftovers
+open Globals
+open Common
+open CompilationContext
+
+let resolve_source file l1 p1 l2 p2 =
+	let ch = open_in_bin file in
+	let curline = ref 1 in
+	let lines = ref [] in
+	let rec loop p line =
+		let inc i line =
+			if (!curline >= l1) && (!curline <= l2) then lines := (!curline, line) :: !lines;
+			curline := !curline + 1;
+			(i, "")
+		in
+
+		let input_char_or_done ch line =
+			try input_char ch with End_of_file -> begin
+				ignore(inc 0 line);
+				raise End_of_file
+			end
+		in
+
+		let read_char line = match input_char_or_done ch line with
+			| '\n' -> inc 1 line
+			| '\r' ->
+				ignore(input_char_or_done ch line);
+				inc 2 line
+			| c -> begin
+				let line = ref (line ^ (String.make 1 c)) in
+				let rec skip n =
+					if n > 0 then begin
+						let c = input_char_or_done ch !line in
+						line := !line ^ (String.make 1 c);
+						skip (n - 1)
+					end
+				in
+
+				let code = int_of_char c in
+				if code < 0xC0 then ()
+				else if code < 0xE0 then skip 1
+				else if code < 0xF0 then skip 2
+				else skip 3;
+
+				(1, !line)
+			end
+		in
+
+		let (delta, line) = read_char line in
+		loop (p + delta) line
+	in
+
+	try loop 0 ""; with End_of_file -> close_in ch;
+	List.rev !lines
+
+let resolve_file ctx f =
+		let ext = Common.extension f in
+		let second_ext = Common.extension (Common.remove_extension f) in
+		let platform_ext = "." ^ (platform_name_macro ctx) in
+		if platform_ext = second_ext then
+			(Common.remove_extension (Common.remove_extension f)) ^ ext
+		else
+			f
+
+let error_printer file line = Printf.sprintf "%s:%d:" file line
+
+type error_context = {
+	mutable last_positions : pos IntMap.t;
+	mutable max_lines : int IntMap.t;
+	mutable gutter : int IntMap.t;
+	mutable previous : (pos * MessageSeverity.t * int) option;
+}
+
+let create_error_context () = {
+	last_positions = IntMap.empty;
+	max_lines = IntMap.empty;
+	gutter = IntMap.empty;
+	previous = None;
+}
+
+let compiler_pretty_message_string com ectx cm =
+	match cm.cm_message with
+	(* Filter some messages that don't add much when using this message renderer *)
+	| "End of overload failure reasons" -> None
+	| _ -> begin
+		ectx.last_positions <- (IntMap.add cm.cm_depth cm.cm_pos ectx.last_positions);
+		let is_null_pos = cm.cm_pos = null_pos || cm.cm_pos.pmin = -1 in
+		let is_unknown_file f = f = "" || f = "?" in
+
+		(* Extract informations from position *)
+		let l1, p1, l2, p2, epos, lines =
+			if is_null_pos then begin
+				let epos = if is_unknown_file cm.cm_pos.pfile then "(unknown position)" else cm.cm_pos.pfile in
+				(-1, -1, -1, -1, epos, [])
+			end else try begin
+				let f = resolve_file com cm.cm_pos.pfile in
+				let f = Common.find_file com f in
+				let l1, p1, l2, p2 = Lexer.get_pos_coords cm.cm_pos in
+				let lines = resolve_source f l1 p1 l2 p2 in
+				let epos = Lexer.get_error_pos error_printer cm.cm_pos in
+				(l1, p1, l2, p2, epos, lines)
+			end with Not_found ->
+				(1, 1, 1, 1, cm.cm_pos.pfile, [])
+			in
+
+		(* If 4 lines or less, display all; if more, crop the middle *)
+		let lines = match lines with
+			| _ :: (_ :: (_ :: (_ :: []))) -> lines
+			| hd :: (_ :: (_ :: (_ :: l))) ->
+				let _,line = hd in
+				let indent = ref 0 in
+				let found = ref false in
+
+				while (not !found) && (!indent < (String.length line - 1)) do
+					found := not (Lexer.is_whitespace (String.unsafe_get line !indent));
+					indent := !indent + 1
+				done;
+
+				[hd; (0, (String.make (!indent+1) ' ') ^ "[...]"); List.hd (List.rev l)]
+			| _ -> lines
+		in
+
+		let parent_pos =
+			if cm.cm_depth = 0 then null_pos
+			else (try IntMap.find (cm.cm_depth-1) ectx.last_positions with Not_found -> null_pos)
+		in
+
+		let prev_pos,prev_sev,prev_nl = match ectx.previous with
+			| None -> (None, None, 0)
+			| Some (p, sev, depth) -> (Some p, Some sev, depth)
+		in
+
+		let sev_changed = prev_sev = None || Some cm.cm_severity <> prev_sev in
+		let pos_changed = (prev_pos = None || cm.cm_pos <> Option.get prev_pos || (cm.cm_depth <> prev_nl && cm.cm_depth <> prev_nl + 1)) && (parent_pos = null_pos || cm.cm_pos <> parent_pos) in
+		let file_changed = prev_pos = None || (pos_changed && match (cm.cm_pos.pfile, (Option.get prev_pos).pfile) with
+			| (f1, f2) when (is_unknown_file f1) && (is_unknown_file f2) -> false
+			| (f1, f2) -> f1 <> f2
+		) in
+
+		let display_heading = cm.cm_depth = 0 || sev_changed || file_changed in
+		let has_source = match lines with | [] -> false | _ -> true in
+		let display_source = has_source && (cm.cm_depth = 0 || sev_changed || pos_changed) in
+		let display_pos_marker = (not is_null_pos) && has_source && (cm.cm_depth = 0 || sev_changed || pos_changed) in
+
+		let gutter_len = (try String.length (Printf.sprintf "%d" (IntMap.find cm.cm_depth ectx.max_lines)) with Not_found -> 0) + 2 in
+
+		let no_color = Define.defined com.defines Define.MessageNoColor in
+		let c_reset = if no_color then "" else "\x1b[0m" in
+		let c_bold = if no_color then "" else "\x1b[1m" in
+		let c_dim = if no_color then "" else "\x1b[2m" in
+
+		let (c_sev, c_sev_bg) = if no_color then ("", "") else match cm.cm_severity with
+			| MessageSeverity.Warning -> ("\x1b[33m", "\x1b[30;43m")
+			| Information | Hint -> ("\x1b[34m", "\x1b[30;44m")
+			| Error -> ("\x1b[31m", "\x1b[30;41m")
+		in
+
+		let sev_label = if cm.cm_depth > 0 then " -> " else Printf.sprintf
+			(if no_color then "[%s]" else " %s ")
+			(match cm.cm_severity with
+				| MessageSeverity.Warning -> "WARNING"
+				| Information -> "INFO"
+				| Hint -> "HINT"
+				| Error -> "ERROR"
+			) in
+
+		let out = ref "" in
+
+		if display_heading then
+			out := Printf.sprintf "%s%s%s\n\n"
+				(* Severity heading *)
+				(c_sev_bg ^ sev_label ^ c_reset ^ " ")
+				(* Macro context indicator *)
+				(if cm.cm_from_macro then c_sev ^ "(macro) " ^ c_reset else "")
+				(* File + line pointer *)
+				epos;
+
+		(* Error source *)
+		if display_source then out := List.fold_left (fun out (l, line) ->
+			let nb_len = String.length (string_of_int l) in
+
+			(* Replace tabs with 1 space to avoid column misalignments *)
+			let line = String.concat " " (ExtString.String.nsplit line "\t") in
+			let len = String.length line in
+
+			out ^ Printf.sprintf "%s%s | %s\n"
+				(* left-padded line number *)
+				(String.make (gutter_len-nb_len-1) ' ')
+				(if l = 0 then "-" else Printf.sprintf "%d" l)
+				(* Source code at that line *)
+				(
+					if l = 0 then
+						c_dim ^ line ^ c_reset
+					else if l1 = l2 then
+						(if p1 > 1 then c_dim ^ (String.sub line 0 (p1-1)) else "")
+						^ c_reset ^ c_bold ^ (String.sub line (p1-1) (p2-p1))
+						^ c_reset ^ c_dim ^ (String.sub line (p2-1) (len - p2 + 1))
+						^ c_reset
+					else begin
+						(if (l = l1) then
+							(if p1 > 1 then c_dim ^ (String.sub line 0 (p1-1)) else "")
+							^ c_reset ^ c_bold ^ (String.sub line (p1-1) (len-p1+1))
+							^ c_reset
+						else if (l = l2) then
+							(if p2 > 1 then c_bold ^ (String.sub line 0 (p2-1)) else "")
+							^ c_reset ^ c_dim ^ (String.sub line (p2-1) (len-p2+1))
+							^ c_reset
+						else c_bold ^ line ^ c_reset)
+					end
+				)
+		) !out lines;
+
+		(* Error position marker *)
+		if display_pos_marker then
+			out := Printf.sprintf "%s%s|%s\n"
+				!out
+				(String.make gutter_len ' ')
+				(if l1 = l2 then String.make p1 ' ' ^ c_sev ^ String.make (if p1 = p2 then 1 else p2-p1) '^' ^ c_reset else "");
+
+		(* Error message *)
+		out := List.fold_left (fun out str -> Printf.sprintf "%s%s| %s\n"
+			out
+			(String.make gutter_len ' ')
+			(* Remove "... " prefix *)
+			(if (ExtString.String.starts_with str "... ") then String.sub str 4 ((String.length str) - 4) else str)
+		) !out (ExtString.String.nsplit cm.cm_message "\n");
+
+		ectx.previous <- Some ((if is_null_pos then null_pos else cm.cm_pos), cm.cm_severity, cm.cm_depth);
+		ectx.gutter <- (IntMap.add cm.cm_depth gutter_len ectx.gutter);
+
+		(* Indent sub errors *)
+		let rec indent ?(acc=0) depth =
+			if depth = 0 then acc
+			else indent ~acc:(acc + try IntMap.find (depth-1) ectx.gutter with Not_found -> 3) (depth-1)
+		in
+
+		Some (
+			if cm.cm_depth > 0 then String.concat "\n" (List.map (fun str -> match str with
+				| "" -> ""
+				| _ -> (String.make (indent cm.cm_depth) ' ') ^ str
+			) (ExtString.String.nsplit !out "\n"))
+			else !out
+		)
+	end
+
+let compiler_message_string cm =
+	let str = match cm.cm_severity with
+		| MessageSeverity.Warning -> "Warning : " ^ cm.cm_message
+		| Information | Error | Hint -> cm.cm_message
+	in
+
+	if cm.cm_pos = null_pos then
+		Some str
+	else begin
+		let epos = Lexer.get_error_pos error_printer cm.cm_pos in
+		let str =
+			let lines =
+				match (ExtString.String.nsplit str "\n") with
+				| first :: rest -> first :: List.map Error.compl_msg rest
+				| l -> l
+			in
+			String.concat ("\n" ^ epos ^ " : ") lines
+		in
+		Some (Printf.sprintf "%s : %s" epos str)
+	end
+
+let compiler_indented_message_string cm =
+	match cm.cm_message with
+	(* Filter some messages that don't add much when using this message renderer *)
+	| "End of overload failure reasons" -> None
+	| _ ->
+		let str = match cm.cm_severity with
+			| MessageSeverity.Warning -> "Warning : " ^ cm.cm_message
+			| Information -> "Info : " ^ cm.cm_message
+			| Error | Hint -> cm.cm_message
+		in
+
+		if cm.cm_pos = null_pos then
+			Some str
+		else begin
+			let epos = Lexer.get_error_pos error_printer cm.cm_pos in
+			let lines =
+				match (ExtString.String.nsplit str "\n") with
+				| first :: rest -> (cm.cm_depth, first) :: List.map (fun msg -> (cm.cm_depth+1, msg)) rest
+				| l -> [(cm.cm_depth, List.hd l)]
+			in
+			let rm_prefix str = if (ExtString.String.starts_with str "... ") then String.sub str 4 ((String.length str) - 4) else str in
+			Some (String.concat "\n" (List.map (fun (depth, msg) -> (String.make (depth*2) ' ') ^ epos ^ " : " ^ (rm_prefix msg)) lines))
+		end
+
+let get_max_line max_lines messages =
+	List.fold_left (fun max_lines cm ->
+		let _,_,l2,_ = Lexer.get_pos_coords cm.cm_pos in
+		let old = try IntMap.find cm.cm_depth max_lines with Not_found -> 0 in
+
+		if l2 > old then IntMap.add cm.cm_depth l2 max_lines
+		else max_lines
+	) max_lines messages
+
+exception ConfigError of string
+
+let get_formatter com ectx def default =
+	let format_mode = Define.defined_value_safe ~default com.defines def in
+	match format_mode with
+		| "pretty" -> compiler_pretty_message_string com ectx
+		| "indent" -> compiler_indented_message_string
+		| "classic" -> compiler_message_string
+		| m -> begin
+			let def = Define.get_define_key def in
+			raise (ConfigError (Printf.sprintf "Invalid message reporting mode: \"%s\", expected classic | pretty | indent (for -D %s)." m def))
+		end
+
+let print_error (err : Error.error) =
+	let ret = ref "" in
+	Error.recurse_error (fun depth err ->
+		ret := !ret ^ (Lexer.get_error_pos (Printf.sprintf "%s:%d: ") err.err_pos) ^ (Error.error_msg err.err_message) ^ "\n"
+	) err;
+	!ret
+
+let format_messages com messages =
+	let ectx = create_error_context () in
+	ectx.max_lines <- get_max_line ectx.max_lines messages;
+	let message_formatter = get_formatter com ectx Define.MessageReporting "classic" in
+	let lines = List.rev (
+		List.fold_left (fun lines cm -> match (message_formatter cm) with
+			| None -> lines
+			| Some str -> str :: lines
+		) [] messages
+	) in
+	ExtLib.String.join "\n" lines
+
+let display_messages ctx on_message = begin
+	let ectx = create_error_context () in
+	ectx.max_lines <- get_max_line ectx.max_lines ctx.messages;
+
+	let get_formatter _ _ def default =
+		try get_formatter ctx.com ectx def default
+		with | ConfigError s ->
+			error ctx s null_pos;
+			compiler_message_string
+	in
+
+	let message_formatter = get_formatter ctx.com ectx Define.MessageReporting "classic" in
+	let log_formatter = get_formatter ctx.com ectx Define.MessageLogFormat "indent" in
+
+	let log_messages = ref (Define.defined ctx.com.defines Define.MessageLogFile) in
+	let log_message = ref None in
+	let close_logs = ref None in
+
+	if !log_messages then begin
+		try begin
+			let buf = Rbuffer.create 16000 in
+
+			let file = Define.defined_value ctx.com.defines Define.MessageLogFile in
+			let chan =
+				Path.mkdir_from_path file;
+				open_out_bin file
+			in
+
+			log_message := (Some (fun msg ->
+				match (log_formatter msg) with
+					| None -> ()
+					| Some str -> Rbuffer.add_string buf (str ^ "\n")));
+
+			close_logs := (Some (fun () ->
+				Rbuffer.output_buffer chan buf;
+				Rbuffer.clear buf;
+				close_out chan
+			));
+		end with
+			| Failure e | Sys_error e -> begin
+				let def = Define.get_define_key Define.MessageLogFile in
+				error ctx (Printf.sprintf "Error opening log file: %s. Logging to file disabled (-D %s)" e def) null_pos;
+				log_messages := false;
+			end
+	end;
+
+	List.iter (fun cm ->
+		if !log_messages then (Option.get !log_message) cm;
+
+		match (message_formatter cm) with
+			| None -> ()
+			| Some str -> on_message cm.cm_severity str
+	) (List.rev ctx.messages);
+
+	if !log_messages then (Option.get !close_logs) ();
+end
+

+ 12 - 14
src/compiler/retyper.ml

@@ -21,7 +21,7 @@ let disable_typeloading rctx ctx f =
 	ctx.g.load_only_cached_modules <- true;
 	try
 		Std.finally (fun () -> ctx.g.load_only_cached_modules <- old) f ()
-	with (Error.Error (Module_not_found path,_,_)) ->
+	with (Error.Error { err_message = Module_not_found path }) ->
 		fail rctx (Printf.sprintf "Could not load [Module %s]" (s_type_path path))
 
 let pair_type th t = match th with
@@ -74,13 +74,13 @@ let pair_class_field rctx ctx cctx fctx cf cff p =
 				remove_class_field_flag cf CfPostProcessed;
 		)
 
-let pair_classes rctx context_init c d p =
+let pair_classes rctx c d p =
 	let rctx = {rctx with
 		print_stack = (Printf.sprintf "[Class %s]" (s_type_path c.cl_path)) :: rctx.print_stack
 	} in
 	c.cl_restore();
 	(* TODO: What do we do with build macros? *)
-	let cctx = create_class_context c context_init p in
+	let cctx = create_class_context c p in
 	let ctx = create_typer_context_for_class rctx.typer cctx p in
 	let _ =
 		let rctx = {rctx with
@@ -130,7 +130,7 @@ let pair_classes rctx context_init c d p =
 			print_stack = (Printf.sprintf "[Field %s]" name) :: rctx.print_stack
 		} in
 		let display_modifier = Typeload.check_field_access ctx cff in
-		let fctx = create_field_context cctx cff ctx.is_display_file display_modifier in
+		let fctx = create_field_context ctx cctx cff ctx.is_display_file display_modifier in
 		let cf = match fctx.field_kind with
 			| FKConstructor ->
 				begin match c.cl_constructor with
@@ -180,14 +180,14 @@ let pair_typedefs ctx rctx td d =
 	ignore (disable_typeloading rctx ctx (fun () -> Typeload.load_complex_type ctx false d.d_data));
 	[]
 
-let pair_abstracts ctx rctx context_init a d p =
+let pair_abstracts ctx rctx a d p =
 	let rctx = {rctx with
 		print_stack = (Printf.sprintf "[Abstract %s]" (s_type_path a.a_path)) :: rctx.print_stack
 	} in
 	match a.a_impl with
 	| Some c ->
 		c.cl_restore();
-		let cctx = create_class_context c context_init p in
+		let cctx = create_class_context c p in
 		let ctx = create_typer_context_for_class rctx.typer cctx p in
 		let fl = List.map (fun cff ->
 			let cff = TypeloadFields.transform_abstract_field2 ctx a cff in
@@ -196,7 +196,7 @@ let pair_abstracts ctx rctx context_init a d p =
 				print_stack = (Printf.sprintf "[Field %s]" name) :: rctx.print_stack
 			} in
 			let display_modifier = Typeload.check_field_access ctx cff in
-			let fctx = create_field_context cctx cff ctx.is_display_file display_modifier in
+			let fctx = create_field_context ctx cctx cff ctx.is_display_file display_modifier in
 			let cf = try
 				PMap.find name c.cl_statics
 			with Not_found ->
@@ -218,7 +218,6 @@ let attempt_retyping ctx m p =
 		print_stack = [Printf.sprintf "[Module %s]" (s_type_path m.m_path)];
 	} in
 	(* log rctx 0 (Printf.sprintf "Retyping module %s" (s_type_path m.m_path)); *)
-	let context_init = new TypeloadFields.context_init in
 	let find_type name = try
 		List.find (fun t -> snd (t_infos t).mt_path = name) ctx.m.curmod.m_types
 	with Not_found ->
@@ -230,11 +229,11 @@ let attempt_retyping ctx m p =
 		| (d,p) :: decls ->
 			begin match d with
 			| EImport (path,mode) ->
-				ImportHandling.init_import ctx context_init path mode p;
+				ImportHandling.init_import ctx path mode p;
 				ImportHandling.commit_import ctx path mode p;
 				loop acc decls
 			| EUsing path ->
-				ImportHandling.init_using ctx context_init path p;
+				ImportHandling.init_using ctx path p;
 				loop acc decls
 			| EClass c ->
 				let mt = find_type (fst c.d_name) in
@@ -257,18 +256,17 @@ let attempt_retyping ctx m p =
 		let pairs = loop [] decls in
 		let fl = List.map (fun (d,mt) -> match d,mt with
 			| EClass d,TClassDecl c ->
-				pair_classes rctx context_init c d p
+				pair_classes rctx c d p
 			| EEnum d,TEnumDecl en ->
 				pair_enums ctx rctx en d
 			| ETypedef d,TTypeDecl td ->
 				pair_typedefs ctx rctx td d
 			| EAbstract d,TAbstractDecl a ->
-				pair_abstracts ctx rctx context_init a d p
+				pair_abstracts ctx rctx a d p
 			| _ ->
 				fail rctx "?"
 		) pairs in
 		(* If we get here we know that the everything is ok. *)
-		delay ctx PConnectField (fun () -> context_init#run);
 		List.iter (fun fl ->
 			List.iter (fun f -> f()) fl
 		) fl;
@@ -276,4 +274,4 @@ let attempt_retyping ctx m p =
 		m.m_extra.m_time <- Common.file_time file;
 		None
 	with Fail s ->
-		Some s
+		Some s

+ 67 - 402
src/compiler/server.ml

@@ -1,15 +1,13 @@
-open Extlib_leftovers
-open Printf
 open Globals
-open Ast
 open Common
 open CompilationCache
 open Timer
 open Type
 open DisplayProcessingGlobals
+open Ipaddr
 open Json
-open Compiler
 open CompilationContext
+open MessageReporting
 
 exception Dirty of module_skip_reason
 exception ServerError of string
@@ -21,7 +19,7 @@ let check_display_flush ctx f_otherwise = match ctx.com.json_out with
 	| None ->
 		if is_diagnostics ctx.com then begin
 			List.iter (fun cm ->
-				add_diagnostics_message ~depth:cm.cm_depth ctx.com (located cm.cm_message cm.cm_pos) cm.cm_kind cm.cm_severity
+				add_diagnostics_message ~depth:cm.cm_depth ctx.com cm.cm_message cm.cm_pos cm.cm_kind cm.cm_severity
 			) (List.rev ctx.messages);
 			raise (Completion (Diagnostics.print ctx.com))
 		end else
@@ -87,365 +85,6 @@ let parse_file cs com file p =
 open ServerCompilationContext
 
 module Communication = struct
-	type error_context = {
-		mutable last_positions : pos IntMap.t;
-		mutable max_lines : int IntMap.t;
-		mutable gutter : int IntMap.t;
-		mutable previous : (pos * MessageSeverity.t * int) option;
-	}
-
-	let create_error_context () = {
-		last_positions = IntMap.empty;
-		max_lines = IntMap.empty;
-		gutter = IntMap.empty;
-		previous = None;
-	}
-
-	let error_printer file line = Printf.sprintf "%s:%d:" file line
-
-	let resolve_source file l1 p1 l2 p2 =
-		let ch = open_in_bin file in
-		let curline = ref 1 in
-		let lines = ref [] in
-		let rec loop p line =
-			let inc i line =
-				if (!curline >= l1) && (!curline <= l2) then lines := (!curline, line) :: !lines;
-				curline := !curline + 1;
-				(i, "")
-			in
-
-			let input_char_or_done ch line =
-				try input_char ch with End_of_file -> begin
-					ignore(inc 0 line);
-					raise End_of_file
-				end
-			in
-
-			try
-				let read_char line = match input_char_or_done ch line with
-					| '\n' -> inc 1 line
-					| '\r' ->
-						ignore(input_char_or_done ch line);
-						inc 2 line
-					| c -> begin
-						let line = ref (line ^ (String.make 1 c)) in
-						let rec skip n =
-							if n > 0 then begin
-								let c = input_char_or_done ch !line in
-								line := !line ^ (String.make 1 c);
-								skip (n - 1)
-							end
-						in
-
-						let code = int_of_char c in
-						if code < 0xC0 then ()
-						else if code < 0xE0 then skip 1
-						else if code < 0xF0 then skip 2
-						else skip 3;
-
-						(1, !line)
-					end
-				in
-
-				let (delta, line) = read_char line in
-				loop (p + delta) line
-			with End_of_file ->
-				close_in ch;
-		in
-
-		loop 0 "";
-		List.rev !lines
-
-	let resolve_file ctx f =
-			let ext = Common.extension f in
-			let second_ext = Common.extension (Common.remove_extension f) in
-			let platform_ext = "." ^ (platform_name_macro ctx) in
-			if platform_ext = second_ext then
-				(Common.remove_extension (Common.remove_extension f)) ^ ext
-			else
-				f
-
-	let compiler_pretty_message_string ctx ectx cm =
-		match cm.cm_message with
-		(* Filter some messages that don't add much when using this message renderer *)
-		| "End of overload failure reasons" -> None
-		| _ -> begin
-			ectx.last_positions <- (IntMap.add cm.cm_depth cm.cm_pos ectx.last_positions);
-			let is_null_pos = cm.cm_pos = null_pos || cm.cm_pos.pmin = -1 in
-			let is_unknown_file f = f = "" || f = "?" in
-
-			(* Extract informations from position *)
-			let l1, p1, l2, p2, epos, lines =
-				if is_null_pos then begin
-					let epos = if is_unknown_file cm.cm_pos.pfile then "(unknown position)" else cm.cm_pos.pfile in
-					(-1, -1, -1, -1, epos, [])
-				end else begin
-					let f = resolve_file ctx.com cm.cm_pos.pfile in
-					let f =
-						try Common.find_file ctx.com f
-						with Not_found -> failwith ("File not found '" ^ cm.cm_pos.pfile ^ "'")
-						in
-
-					let l1, p1, l2, p2 = Lexer.get_pos_coords cm.cm_pos in
-					let lines = resolve_source f l1 p1 l2 p2 in
-					let epos = Lexer.get_error_pos error_printer cm.cm_pos in
-					(l1, p1, l2, p2, epos, lines)
-				end in
-
-			(* If 4 lines or less, display all; if more, crop the middle *)
-			let lines = match lines with
-				| _ :: (_ :: (_ :: (_ :: []))) -> lines
-				| hd :: (_ :: (_ :: (_ :: l))) ->
-					let _,line = hd in
-					let indent = ref 0 in
-					let found = ref false in
-
-					while (not !found) && (!indent < (String.length line - 1)) do
-						found := not (Lexer.is_whitespace (String.unsafe_get line !indent));
-						indent := !indent + 1
-					done;
-
-					[hd; (0, (String.make (!indent+1) ' ') ^ "[...]"); List.hd (List.rev l)]
-				| _ -> lines
-			in
-
-			let parent_pos =
-				if cm.cm_depth = 0 then null_pos
-				else (try IntMap.find (cm.cm_depth-1) ectx.last_positions with Not_found -> null_pos)
-			in
-
-			let prev_pos,prev_sev,prev_nl = match ectx.previous with
-				| None -> (None, None, 0)
-				| Some (p, sev, depth) -> (Some p, Some sev, depth)
-			in
-
-			let sev_changed = prev_sev = None || Some cm.cm_severity <> prev_sev in
-			let pos_changed = (prev_pos = None || cm.cm_pos <> Option.get prev_pos || (cm.cm_depth <> prev_nl && cm.cm_depth <> prev_nl + 1)) && (parent_pos = null_pos || cm.cm_pos <> parent_pos) in
-			let file_changed = prev_pos = None || (pos_changed && match (cm.cm_pos.pfile, (Option.get prev_pos).pfile) with
-				| (f1, f2) when (is_unknown_file f1) && (is_unknown_file f2) -> false
-				| (f1, f2) -> f1 <> f2
-			) in
-
-			let display_heading = cm.cm_depth = 0 || sev_changed || file_changed in
-			let display_source = cm.cm_depth = 0 || sev_changed || pos_changed in
-			let display_pos_marker = (not is_null_pos) && (cm.cm_depth = 0 || sev_changed || pos_changed) in
-
-			let gutter_len = (try String.length (Printf.sprintf "%d" (IntMap.find cm.cm_depth ectx.max_lines)) with Not_found -> 0) + 2 in
-
-			let no_color = Define.defined ctx.com.defines Define.NoColor in
-			let c_reset = if no_color then "" else "\x1b[0m" in
-			let c_bold = if no_color then "" else "\x1b[1m" in
-			let c_dim = if no_color then "" else "\x1b[2m" in
-
-			let (c_sev, c_sev_bg) = if no_color then ("", "") else match cm.cm_severity with
-				| MessageSeverity.Warning -> ("\x1b[33m", "\x1b[30;43m")
-				| Information | Hint -> ("\x1b[34m", "\x1b[30;44m")
-				| Error -> ("\x1b[31m", "\x1b[30;41m")
-			in
-
-			let sev_label = if cm.cm_depth > 0 then " -> " else Printf.sprintf
-				(if no_color then "[%s]" else " %s ")
-				(match cm.cm_severity with
-					| MessageSeverity.Warning -> "WARNING"
-					| Information -> "INFO"
-					| Hint -> "HINT"
-					| Error -> "ERROR"
-				) in
-
-			let out = ref "" in
-
-			if display_heading then
-				out := Printf.sprintf "%s%s\n\n"
-					(* Severity heading *)
-					(c_sev_bg ^ sev_label ^ c_reset ^ " ")
-					(* File + line pointer *)
-					epos;
-
-			(* Error source *)
-			if display_source then out := List.fold_left (fun out (l, line) ->
-				let nb_len = String.length (string_of_int l) in
-
-				(* Replace tabs with 1 space to avoid column misalignments *)
-				let line = String.concat " " (ExtString.String.nsplit line "\t") in
-				let len = String.length line in
-
-				out ^ Printf.sprintf "%s%s | %s\n"
-					(* left-padded line number *)
-					(String.make (gutter_len-nb_len-1) ' ')
-					(if l = 0 then "-" else Printf.sprintf "%d" l)
-					(* Source code at that line *)
-					(
-						if l = 0 then
-							c_dim ^ line ^ c_reset
-						else if l1 = l2 then
-							(if p1 > 1 then c_dim ^ (String.sub line 0 (p1-1)) else "")
-							^ c_reset ^ c_bold ^ (String.sub line (p1-1) (p2-p1))
-							^ c_reset ^ c_dim ^ (String.sub line (p2-1) (len - p2 + 1))
-							^ c_reset
-						else begin
-							(if (l = l1) then
-								(if p1 > 1 then c_dim ^ (String.sub line 0 (p1-1)) else "")
-								^ c_reset ^ c_bold ^ (String.sub line (p1-1) (len-p1+1))
-								^ c_reset
-							else if (l = l2) then
-								(if p2 > 1 then c_bold ^ (String.sub line 0 (p2-1)) else "")
-								^ c_reset ^ c_dim ^ (String.sub line (p2-1) (len-p2+1))
-								^ c_reset
-							else c_bold ^ line ^ c_reset)
-						end
-					)
-			) !out lines;
-
-			(* Error position marker *)
-			if display_pos_marker then
-				out := Printf.sprintf "%s%s|%s\n"
-					!out
-					(String.make gutter_len ' ')
-					(if l1 = l2 then String.make p1 ' ' ^ c_sev ^ String.make (if p1 = p2 then 1 else p2-p1) '^' ^ c_reset else "");
-
-			(* Error message *)
-			out := List.fold_left (fun out str -> Printf.sprintf "%s%s| %s\n"
-				out
-				(String.make gutter_len ' ')
-				(* Remove "... " prefix *)
-				(if (ExtString.String.starts_with str "... ") then String.sub str 4 ((String.length str) - 4) else str)
-			) !out (ExtString.String.nsplit cm.cm_message "\n");
-
-			ectx.previous <- Some ((if is_null_pos then null_pos else cm.cm_pos), cm.cm_severity, cm.cm_depth);
-			ectx.gutter <- (IntMap.add cm.cm_depth gutter_len ectx.gutter);
-
-			(* Indent sub errors *)
-			let rec indent ?(acc=0) depth =
-				if depth = 0 then acc
-				else indent ~acc:(acc + try IntMap.find (depth-1) ectx.gutter with Not_found -> 3) (depth-1)
-			in
-
-			Some (
-				if cm.cm_depth > 0 then String.concat "\n" (List.map (fun str -> match str with
-					| "" -> ""
-					| _ -> (String.make (indent cm.cm_depth) ' ') ^ str
-				) (ExtString.String.nsplit !out "\n"))
-				else !out
-			)
-		end
-
-	let compiler_message_string ctx ectx cm =
-		let str = match cm.cm_severity with
-			| MessageSeverity.Warning -> "Warning : " ^ cm.cm_message
-			| Information | Error | Hint -> cm.cm_message
-		in
-
-		if cm.cm_pos = null_pos then
-			Some str
-		else begin
-			let epos = Lexer.get_error_pos error_printer cm.cm_pos in
-			let str =
-				let lines =
-					match (ExtString.String.nsplit str "\n") with
-					| first :: rest -> first :: List.map Error.compl_msg rest
-					| l -> l
-				in
-				String.concat ("\n" ^ epos ^ " : ") lines
-			in
-			Some (Printf.sprintf "%s : %s" epos str)
-		end
-
-	let compiler_indented_message_string ctx ectx cm =
-		match cm.cm_message with
-		(* Filter some messages that don't add much when using this message renderer *)
-		| "End of overload failure reasons" -> None
-		| _ ->
-			let str = match cm.cm_severity with
-				| MessageSeverity.Warning -> "Warning : " ^ cm.cm_message
-				| Information -> "Info : " ^ cm.cm_message
-				| Error | Hint -> cm.cm_message
-			in
-
-			if cm.cm_pos = null_pos then
-				Some str
-			else begin
-				let epos = Lexer.get_error_pos error_printer cm.cm_pos in
-				let lines =
-					match (ExtString.String.nsplit str "\n") with
-					| first :: rest -> (cm.cm_depth, first) :: List.map (fun msg -> (cm.cm_depth+1, msg)) rest
-					| l -> [(cm.cm_depth, List.hd l)]
-				in
-				let rm_prefix str = if (ExtString.String.starts_with str "... ") then String.sub str 4 ((String.length str) - 4) else str in
-				Some (String.concat "\n" (List.map (fun (depth, msg) -> (String.make (depth*2) ' ') ^ epos ^ " : " ^ (rm_prefix msg)) lines))
-			end
-
-	let get_max_line max_lines messages =
-		List.fold_left (fun max_lines cm ->
-			let _,_,l2,_ = Lexer.get_pos_coords cm.cm_pos in
-			let old = try IntMap.find cm.cm_depth max_lines with Not_found -> 0 in
-
-			if l2 > old then IntMap.add cm.cm_depth l2 max_lines
-			else max_lines
-		) max_lines messages
-
-	let display_messages ctx on_message = begin
-		let ectx = create_error_context () in
-		ectx.max_lines <- get_max_line ectx.max_lines ctx.messages;
-
-		let get_formatter def default =
-			let format_mode = Define.defined_value_safe ~default ctx.com.defines def in
-			match format_mode with
-				| "pretty" -> compiler_pretty_message_string ctx ectx
-				| "indent" -> compiler_indented_message_string ctx ectx
-				| "classic" -> compiler_message_string ctx ectx
-				| m -> begin
-					let def = Define.get_define_key def in
-					error ctx (Printf.sprintf "Invalid message reporting mode: \"%s\", expected classic | pretty | indent (for -D %s)." m def) null_pos;
-					compiler_message_string ctx ectx
-				end
-			in
-
-		let message_formatter = get_formatter Define.MessageReporting "classic" in
-		let log_formatter = get_formatter Define.MessagesLogFormat "indent" in
-
-		let log_messages = ref (Define.defined ctx.com.defines Define.MessagesLogFile) in
-		let log_message = ref None in
-		let close_logs = ref None in
-
-		if !log_messages then begin
-			try begin
-				let buf = Rbuffer.create 16000 in
-
-				let file = Define.defined_value ctx.com.defines Define.MessagesLogFile in
-				let chan =
-					Path.mkdir_from_path file;
-					open_out_bin file
-				in
-
-				log_message := (Some (fun msg ->
-					match (log_formatter msg) with
-						| None -> ()
-						| Some str -> Rbuffer.add_string buf (str ^ "\n")));
-
-				close_logs := (Some (fun () ->
-					Rbuffer.output_buffer chan buf;
-					Rbuffer.clear buf;
-					close_out chan
-				));
-			end with
-				| Failure e | Sys_error e -> begin
-					let def = Define.get_define_key Define.MessagesLogFile in
-					error ctx (Printf.sprintf "Error opening log file: %s. Logging to file disabled (-D %s)" e def) null_pos;
-					log_messages := false;
-				end
-		end;
-
-		List.iter (fun cm ->
-			if !log_messages then (Option.get !log_message) cm;
-
-			match (message_formatter cm) with
-				| None -> ()
-				| Some str -> on_message cm.cm_severity str
-		) (List.rev ctx.messages);
-
-		if !log_messages then (Option.get !close_logs) ();
-	end
-
 	let create_stdio () =
 		let rec self = {
 			write_out = (fun s ->
@@ -479,32 +118,38 @@ module Communication = struct
 		} in
 		self
 
-	let create_pipe sctx write = {
-		write_out = (fun s ->
-			write ("\x01" ^ String.concat "\x01" (ExtString.String.nsplit s "\n") ^ "\n")
-		);
-		write_err = (fun s ->
-			write s
-		);
-		flush = (fun ctx ->
-			check_display_flush ctx (fun () ->
-				display_messages ctx (fun _ output ->
-					write (output ^ "\n");
-					ServerMessage.message output;
-				);
-
-				sctx.was_compilation <- ctx.com.display.dms_full_typing;
-				if has_error ctx then begin
-					measure_times := false;
-					write "\x02\n"
-				end
-			)
-		);
-		exit = (fun i ->
-			()
-		);
-		is_server = true;
-	}
+	let create_pipe sctx write =
+		let rec self = {
+			write_out = (fun s ->
+				write ("\x01" ^ String.concat "\x01" (ExtString.String.nsplit s "\n") ^ "\n")
+			);
+			write_err = (fun s ->
+				write s
+			);
+			flush = (fun ctx ->
+				check_display_flush ctx (fun () ->
+					display_messages ctx (fun _ output ->
+						write (output ^ "\n");
+						ServerMessage.message output;
+					);
+
+					sctx.was_compilation <- ctx.com.display.dms_full_typing;
+					if has_error ctx then begin
+						measure_times := false;
+						write "\x02\n"
+					end else begin
+						Timer.close_times();
+						if !Timer.measure_times then Timer.report_times (fun s -> self.write_err (s ^ "\n"));
+					end
+				)
+			);
+			exit = (fun i ->
+				()
+			);
+			is_server = true;
+		}
+		in
+		self
 end
 
 let stat dir =
@@ -643,7 +288,7 @@ let check_module sctx ctx m p =
 					raise (ServerError ("Infinite loop in Haxe server detected. "
 						^ "Probably caused by shadowing a module of the standard library. "
 						^ "Make sure shadowed module does not pull macro context."));
-				let _, mctx = MacroContext.get_macro_context ctx p in
+				let mctx = MacroContext.get_macro_context ctx in
 				check_module_shadowing (get_changed_directories sctx mctx) m
 		in
 		let has_policy policy = List.mem policy m.m_extra.m_check_policy || match policy with
@@ -663,7 +308,9 @@ let check_module sctx ctx m p =
 			end
 		in
 		let check_dependencies () =
-			PMap.iter (fun _ m2 -> match check m2 with
+			PMap.iter (fun _ (sign,mpath) ->
+				let m2 = (com.cs#get_context sign)#find_module mpath in
+				match check m2 with
 				| None -> ()
 				| Some reason -> raise (Dirty (DependencyDirty(m2.m_path,reason)))
 			) m.m_extra.m_deps;
@@ -763,7 +410,10 @@ let add_modules sctx ctx m p =
 				) m.m_types;
 				TypeloadModule.ModuleLevel.add_module ctx m p;
 				PMap.iter (Hashtbl.replace com.resources) m.m_extra.m_binded_res;
-				PMap.iter (fun _ m2 -> add_modules (tabs ^ "  ") m0 m2) m.m_extra.m_deps
+				PMap.iter (fun _ (sign,mpath) ->
+					let m2 = (com.cs#get_context sign)#find_module mpath in
+					add_modules (tabs ^ "  ") m0 m2
+				) m.m_extra.m_deps
 			)
 		end
 	in
@@ -798,7 +448,7 @@ let type_module sctx (ctx:Typecore.typer) mpath p =
 let before_anything sctx ctx =
 	ensure_macro_setup sctx
 
-let after_arg_parsing sctx ctx =
+let after_target_init sctx ctx =
 	let com = ctx.com in
 	let cs = sctx.cs in
 	let sign = Define.get_signature com.defines in
@@ -893,9 +543,16 @@ let init_wait_stdio() =
 	mk_length_prefixed_communication false stdin stderr
 
 (* The connect function to connect to [host] at [port] and send arguments [args]. *)
-let do_connect host port args =
-	let sock = Unix.socket Unix.PF_INET Unix.SOCK_STREAM 0 in
-	(try Unix.connect sock (Unix.ADDR_INET (Unix.inet_addr_of_string host,port)) with _ -> failwith ("Couldn't connect on " ^ host ^ ":" ^ string_of_int port));
+let do_connect ip port args =
+	let (domain, host) = match ip with
+		| V4 ip -> (Unix.PF_INET, V4.to_string ip)
+		| V6 ip -> (Unix.PF_INET6, V6.to_string ip)
+	in
+	let sock = Unix.socket domain Unix.SOCK_STREAM 0 in
+	(try Unix.connect sock (Unix.ADDR_INET (Unix.inet_addr_of_string host,port)) with
+		| Unix.Unix_error(code,_,_) -> failwith("Couldn't connect on " ^ host ^ ":" ^ string_of_int port ^ " (" ^ (Unix.error_message code) ^ ")");
+		| _ -> failwith ("Couldn't connect on " ^ host ^ ":" ^ string_of_int port)
+	);
 	let rec display_stdin args =
 		match args with
 		| [] -> ""
@@ -910,7 +567,7 @@ let do_connect host port args =
 	let s = (String.concat "" (List.map (fun a -> a ^ "\n") args)) ^ (display_stdin args) in
 	ssend sock (Bytes.of_string (s ^ "\000"));
 	let has_error = ref false in
-	let rec print line =
+	let print line =
 		match (if line = "" then '\x00' else line.[0]) with
 		| '\x01' ->
 			print_string (String.concat "\n" (List.tl (ExtString.String.nsplit line "\x01")));
@@ -961,7 +618,7 @@ let rec process sctx comm args =
 		cache = sctx.cs;
 		callbacks = {
 			before_anything = before_anything sctx;
-			after_arg_parsing = after_arg_parsing sctx;
+			after_target_init = after_target_init sctx;
 			after_compilation = after_compilation sctx;
 		};
 		init_wait_socket = init_wait_socket;
@@ -1058,14 +715,22 @@ and wait_loop verbose accept =
 	0
 
 (* Connect to given host/port and return accept function for communication *)
-and init_wait_connect host port =
+and init_wait_connect ip port =
+	let host = match ip with
+		| V4 ip -> V4.to_string ip
+		| V6 ip -> V6.to_string ip
+	in
 	let host = Unix.inet_addr_of_string host in
 	let chin, chout = Unix.open_connection (Unix.ADDR_INET (host,port)) in
 	mk_length_prefixed_communication true chin chout
 
 (* The accept-function to wait for a socket connection. *)
-and init_wait_socket host port =
-	let sock = Unix.socket Unix.PF_INET Unix.SOCK_STREAM 0 in
+and init_wait_socket ip port =
+	let (domain, host) = match ip with
+		| V4 ip -> (Unix.PF_INET, V4.to_string ip)
+		| V6 ip -> (Unix.PF_INET6, V6.to_string ip)
+	in
+	let sock = Unix.socket domain Unix.SOCK_STREAM 0 in
 	(try Unix.setsockopt sock Unix.SO_REUSEADDR true with _ -> ());
 	(try Unix.bind sock (Unix.ADDR_INET (Unix.inet_addr_of_string host,port)) with _ -> failwith ("Couldn't wait on " ^ host ^ ":" ^ string_of_int port));
 	ServerMessage.socket_message ("Waiting on " ^ host ^ ":" ^ string_of_int port);

+ 1 - 1
src/compiler/serverCompilationContext.ml

@@ -58,7 +58,7 @@ let reset sctx =
 	Helper.start_time := get_time()
 
 let maybe_cache_context sctx com =
-	if com.display.dms_full_typing then begin
+	if com.display.dms_full_typing && com.display.dms_populate_cache then begin
 		CommonCache.cache_context sctx.cs com;
 		ServerMessage.cached_modules com "" (List.length com.modules);
 	end

+ 2 - 1
src/compiler/serverConfig.ml

@@ -1,2 +1,3 @@
 let do_not_check_modules = ref false
-let legacy_completion = ref false
+let populate_cache_from_display = ref true
+let legacy_completion = ref false

+ 7 - 1
src/compiler/serverMessage.ml

@@ -2,9 +2,9 @@ open Globals
 open Common
 open CompilationCache
 open Type
-open Json
 
 type server_message_options = {
+	mutable print_compiler_stage : bool;
 	mutable print_added_directory : bool;
 	mutable print_found_directories : bool;
 	mutable print_changed_directories : bool;
@@ -31,6 +31,7 @@ type server_message_options = {
 }
 
 let config = {
+	print_compiler_stage = false;
 	print_added_directory = false;
 	print_found_directories = false;
 	print_changed_directories = false;
@@ -62,6 +63,9 @@ let sign_string com =
 	let	sign_id = (cs#get_context sign)#get_index in
 	Printf.sprintf "%2i,%3s: " sign_id (short_platform_name com.platform)
 
+let compiler_stage com =
+	if config.print_compiler_stage then print_endline (Printf.sprintf "compiler stage: %s" (s_compiler_stage com.stage))
+
 let added_directory com tabs dir =
 	if config.print_added_directory then print_endline (Printf.sprintf "%sadded directory %s" (sign_string com) dir)
 
@@ -157,6 +161,7 @@ let uncaught_error s =
 	if config.print_uncaught_error then print_endline ("Uncaught Error : " ^ s)
 
 let enable_all () =
+	config.print_compiler_stage <- true;
 	config.print_added_directory <- true;
 	config.print_found_directories <- true;
 	config.print_changed_directories <- true;
@@ -181,6 +186,7 @@ let enable_all () =
 	config.print_new_context <- true
 
 let set_by_name name value = match name with
+	| "compilerStage" -> config.print_compiler_stage <- value
 	| "addedDirectory" -> config.print_added_directory <- value
 	| "foundDirectories" -> config.print_found_directories <- value;
 	| "changedDirectories" -> config.print_changed_directories <- value;

+ 15 - 16
src/context/abstractCast.ml

@@ -4,7 +4,6 @@ open Ast
 open Type
 open Typecore
 open Error
-open CallUnification
 
 let cast_stack = new_rec_stack()
 
@@ -19,12 +18,12 @@ let rec make_static_call ctx c cf a pl args t p =
 					| None ->  type_expr ctx (EConst (Ident "null"),p) WithType.value
 				in
 				ctx.with_type_stack <- List.tl ctx.with_type_stack;
-				let e = try cast_or_unify_raise ctx t e p with Error(Unify _,_,_) -> raise Not_found in
+				let e = try cast_or_unify_raise ctx t e p with Error { err_message = Unify _ } -> raise Not_found in
 				f();
 				e
 			| _ -> die "" __LOC__
 	end else
-		Typecore.make_static_call ctx c cf (apply_params a.a_params pl) args t p
+		make_static_abstract_call ctx a pl c cf args p
 
 and do_check_cast ctx uctx tleft eright p =
 	let recurse cf f =
@@ -38,10 +37,10 @@ and do_check_cast ctx uctx tleft eright p =
 				(try
 					Type.unify_custom uctx eright.etype tleft;
 				with Unify_error l ->
-					raise (Error (Unify l, eright.epos,0)))
+					raise_error_msg (Unify l) eright.epos)
 			| _ -> ()
 		end;
-		if cf == ctx.curfield || rec_stack_memq cf cast_stack then typing_error "Recursive implicit cast" p;
+		if cf == ctx.curfield || rec_stack_memq cf cast_stack then raise_typing_error "Recursive implicit cast" p;
 		rec_stack_loop cast_stack cf f ()
 	in
 	let make (a,tl,(tcf,cf)) =
@@ -112,8 +111,8 @@ and cast_or_unify_raise ctx ?(uctx=None) tleft eright p =
 and cast_or_unify ctx tleft eright p =
 	try
 		cast_or_unify_raise ctx tleft eright p
-	with Error (Unify l,p,_) ->
-		raise_or_display ctx l p;
+	with Error ({ err_message = Unify _ } as err) ->
+		raise_or_display_error ctx err;
 		eright
 
 let prepare_array_access_field ctx a pl cf p =
@@ -146,7 +145,7 @@ let find_array_read_access_raise ctx a pl e1 p =
 					let e1 = cast_or_unify_raise ctx ta1 e1 p in
 					check_constraints();
 					cf,tf,r,e1
-				with Unify_error _ | Error (Unify _,_,_) ->
+				with Unify_error _ | Error { err_message = Unify _ } ->
 					loop cfl
 				end
 			| _ -> loop cfl
@@ -167,7 +166,7 @@ let find_array_write_access_raise ctx a pl e1 e2  p =
 					let e2 = cast_or_unify_raise ctx ta2 e2 p in
 					check_constraints();
 					cf,tf,r,e1,e2
-				with Unify_error _ | Error (Unify _,_,_) ->
+				with Unify_error _ | Error { err_message = Unify _ } ->
 					loop cfl
 				end
 			| _ -> loop cfl
@@ -179,14 +178,14 @@ let find_array_read_access ctx a tl e1 p =
 		find_array_read_access_raise ctx a tl e1 p
 	with Not_found ->
 		let s_type = s_type (print_context()) in
-		typing_error (Printf.sprintf "No @:arrayAccess function for %s accepts argument of %s" (s_type (TAbstract(a,tl))) (s_type e1.etype)) p
+		raise_typing_error (Printf.sprintf "No @:arrayAccess function for %s accepts argument of %s" (s_type (TAbstract(a,tl))) (s_type e1.etype)) p
 
 let find_array_write_access ctx a tl e1 e2 p =
 	try
 		find_array_write_access_raise ctx a tl e1 e2 p
 	with Not_found ->
 		let s_type = s_type (print_context()) in
-		typing_error (Printf.sprintf "No @:arrayAccess function for %s accepts arguments of %s and %s" (s_type (TAbstract(a,tl))) (s_type e1.etype) (s_type e2.etype)) p
+		raise_typing_error (Printf.sprintf "No @:arrayAccess function for %s accepts arguments of %s and %s" (s_type (TAbstract(a,tl))) (s_type e1.etype) (s_type e2.etype)) p
 
 let find_multitype_specialization com a pl p =
 	let uctx = default_unification_context in
@@ -202,7 +201,7 @@ let find_multitype_specialization com a pl p =
 					stack := t :: !stack;
 					match follow t with
 					| TAbstract ({ a_path = [],"Class" },_) ->
-						typing_error (Printf.sprintf "Cannot use %s as key type to Map because Class<T> is not comparable on JavaScript" (s_type (print_context()) t1)) p;
+						raise_typing_error (Printf.sprintf "Cannot use %s as key type to Map because Class<T> is not comparable on JavaScript" (s_type (print_context()) t1)) p;
 					| TEnum(en,tl) ->
 						PMap.iter (fun _ ef -> ignore(loop ef.ef_type)) en.e_constrs;
 						Type.map loop t
@@ -219,16 +218,16 @@ let find_multitype_specialization com a pl p =
 			if List.exists (fun t -> has_mono t) definitive_types then begin
 				let at = apply_params a.a_params pl a.a_this in
 				let st = s_type (print_context()) at in
-				typing_error ("Type parameters of multi type abstracts must be known (for " ^ st ^ ")") p
+				raise_typing_error ("Type parameters of multi type abstracts must be known (for " ^ st ^ ")") p
 			end;
 			t
 		with Not_found ->
 			let at = apply_params a.a_params pl a.a_this in
 			let st = s_type (print_context()) at in
 			if has_mono at then
-				typing_error ("Type parameters of multi type abstracts must be known (for " ^ st ^ ")") p
+				raise_typing_error ("Type parameters of multi type abstracts must be known (for " ^ st ^ ")") p
 			else
-				typing_error ("Abstract " ^ (s_type_path a.a_path) ^ " has no @:to function that accepts " ^ st) p;
+				raise_typing_error ("Abstract " ^ (s_type_path a.a_path) ^ " has no @:to function that accepts " ^ st) p;
 	in
 	cf, follow m
 
@@ -240,7 +239,7 @@ let handle_abstract_casts ctx e =
 					let's construct the underlying type. *)
 				match Abstract.get_underlying_type a pl with
 				| TInst(c,tl) as t -> {e with eexpr = TNew(c,tl,el); etype = t}
-				| _ -> typing_error ("Cannot construct " ^ (s_type (print_context()) (TAbstract(a,pl)))) e.epos
+				| _ -> raise_typing_error ("Cannot construct " ^ (s_type (print_context()) (TAbstract(a,pl)))) e.epos
 			end else begin
 				(* a TNew of an abstract implementation is only generated if it is a multi type abstract *)
 				let cf,m = find_multitype_specialization ctx.com a pl e.epos in

+ 183 - 63
src/context/common.ml

@@ -201,14 +201,14 @@ class compiler_callbacks = object(self)
 	method add_null_safety_report (f : (string*pos) list -> unit) : unit =
 		null_safety_report <- f :: null_safety_report
 
-	method run r =
+	method run handle_error r =
 		match !r with
 		| [] ->
 			()
 		| l ->
 			r := [];
-			List.iter (fun f -> f()) (List.rev l);
-			self#run r
+			List.iter (fun f -> try f() with Error.Error err -> handle_error err) (List.rev l);
+			self#run handle_error r
 
 	method get_before_typer_create = before_typer_create
 	method get_after_init_macros = after_init_macros
@@ -233,7 +233,7 @@ class file_keys = object(self)
 end
 
 type shared_display_information = {
-	mutable diagnostics_messages : (string * pos * MessageKind.t * MessageSeverity.t * int (* depth *)) list;
+	mutable diagnostics_messages : diagnostic list;
 }
 
 type display_information = {
@@ -256,7 +256,6 @@ type json_api = {
 type compiler_stage =
 	| CCreated          (* Context was just created *)
 	| CInitialized      (* Context was initialized (from CLI args and such). *)
-	| CTyperCreated     (* The typer context was just created. *)
 	| CInitMacrosStart  (* Init macros are about to run. *)
 	| CInitMacrosDone   (* Init macros did run - at this point the signature is locked. *)
 	| CTypingDone       (* The typer is done - at this point com.types/modules/main is filled. *)
@@ -271,6 +270,23 @@ type compiler_stage =
 	| CGenerationStart  (* Generation is about to begin. *)
 	| CGenerationDone   (* Generation just finished. *)
 
+let s_compiler_stage = function
+	| CCreated          -> "CCreated"
+	| CInitialized      -> "CInitialized"
+	| CInitMacrosStart  -> "CInitMacrosStart"
+	| CInitMacrosDone   -> "CInitMacrosDone"
+	| CTypingDone       -> "CTypingDone"
+	| CFilteringStart   -> "CFilteringStart"
+	| CAnalyzerStart    -> "CAnalyzerStart"
+	| CAnalyzerDone     -> "CAnalyzerDone"
+	| CSaveStart        -> "CSaveStart"
+	| CSaveDone         -> "CSaveDone"
+	| CDceStart         -> "CDceStart"
+	| CDceDone          -> "CDceDone"
+	| CFilteringDone    -> "CFilteringDone"
+	| CGenerationStart  -> "CGenerationStart"
+	| CGenerationDone   -> "CGenerationDone"
+
 type report_mode =
 	| RMNone
 	| RMDiagnostics of Path.UniqueKey.t list
@@ -363,9 +379,9 @@ type context = {
 	(* communication *)
 	mutable print : string -> unit;
 	mutable error : ?depth:int -> string -> pos -> unit;
-	mutable located_error : ?depth:int -> located -> unit;
-	mutable info : ?depth:int -> string -> pos -> unit;
-	mutable warning : ?depth:int -> warning -> Warning.warning_option list list -> string -> pos -> unit;
+	mutable error_ext : Error.error -> unit;
+	mutable info : ?depth:int -> ?from_macro:bool -> string -> pos -> unit;
+	mutable warning : ?depth:int -> ?from_macro:bool -> warning -> Warning.warning_option list list -> string -> pos -> unit;
 	mutable warning_options : Warning.warning_option list list;
 	mutable get_messages : unit -> compiler_message list;
 	mutable filter_messages : (compiler_message -> bool) -> unit;
@@ -379,6 +395,7 @@ type context = {
 	mutable user_metas : (string, Meta.user_meta) Hashtbl.t;
 	mutable get_macros : unit -> context option;
 	(* typing state *)
+	mutable global_metadata : (string list * metadata_entry * (bool * bool * bool)) list;
 	shared : shared_context;
 	display_information : display_information;
 	file_lookup_cache : (string,string option) lookup;
@@ -415,12 +432,11 @@ type context = {
 	memory_marker : float array;
 }
 
-exception Abort of located
+exception Abort of Error.error
 
 let ignore_error com =
 	let b = com.display.dms_error_policy = EPIgnore in
-	if b then
-		if b then com.has_error <- true;
+	if b then com.has_error <- true;
 	b
 
 (* Defines *)
@@ -453,6 +469,8 @@ let define_value com k v =
 let convert_define k =
 	String.concat "_" (ExtString.String.nsplit k "-")
 
+let is_next com = defined com HaxeNext
+
 let external_defined ctx k =
 	Define.raw_defined ctx.defines (convert_define k)
 
@@ -462,7 +480,7 @@ let external_defined_value ctx k =
 let reserved_flags = [
 	"true";"false";"null";"cross";"js";"lua";"neko";"flash";"php";"cpp";"cs";"java";"python";
 	"swc";"macro";"sys";"static";"utf16";"haxe";"haxe_ver"
-	]
+]
 
 let reserved_flag_namespaces = ["target"]
 
@@ -482,17 +500,9 @@ let convert_and_validate k =
 let external_define_value ctx k v =
 	raw_define_value ctx.defines (convert_and_validate k) v
 
-(* TODO: Temporary function until #8690, remove after *)
-let external_define_value_no_check ctx k v =
-	Define.raw_define_value ctx.defines (convert_define k) v
-
 let external_define ctx k =
 	Define.raw_define ctx.defines (convert_and_validate k)
 
-(* TODO: Temporary function until #8690, remove after *)
-let external_define_no_check ctx k =
-	Define.raw_define ctx.defines (convert_define k)
-
 let defines_for_external ctx =
 	PMap.foldi (fun k v acc ->
 		let added_underscore = PMap.add k v acc in
@@ -516,6 +526,7 @@ let short_platform_name = function
 	| Python -> "py"
 	| Hl -> "hl"
 	| Eval -> "evl"
+	| CustomTarget n -> "c_" ^ n
 
 let stats =
 	{
@@ -561,6 +572,9 @@ let get_config com =
 	match com.platform with
 	| Cross ->
 		default_config
+	| CustomTarget _ ->
+		(* impossible to reach. see update_platform_config *)
+		raise Exit
 	| Js ->
 		let es6 = get_es_version com >= 6 in
 		{
@@ -723,6 +737,10 @@ let get_config com =
 			pf_pad_nulls = true;
 			pf_supports_threads = true;
 			pf_supports_atomics = true;
+			pf_scoping = {
+				vs_scope = BlockScope;
+				vs_flags = [NoShadowing]
+			};
 		}
 	| Eval ->
 		{
@@ -773,6 +791,7 @@ let create compilation_step cs version args =
 		file = "";
 		types = [];
 		callbacks = new compiler_callbacks;
+		global_metadata = [];
 		modules = [];
 		module_lut = new hashtbl_lookup;
 		module_nonexistent_lut = new hashtbl_lookup;
@@ -795,11 +814,11 @@ let create compilation_step cs version args =
 		user_defines = Hashtbl.create 0;
 		user_metas = Hashtbl.create 0;
 		get_macros = (fun() -> None);
-		info = (fun ?depth _ _ -> die "" __LOC__);
-		warning = (fun ?depth _ _ _ -> die "" __LOC__);
+		info = (fun ?depth ?from_macro _ _ -> die "" __LOC__);
+		warning = (fun ?depth ?from_macro _ _ _ -> die "" __LOC__);
 		warning_options = [];
 		error = (fun ?depth _ _ -> die "" __LOC__);
-		located_error = (fun ?depth _ -> die "" __LOC__);
+		error_ext = (fun _ -> die "" __LOC__);
 		get_messages = (fun() -> []);
 		filter_messages = (fun _ -> ());
 		pass_debug_messages = DynArray.create();
@@ -897,12 +916,22 @@ let flash_version_tag = function
 	| 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)
 
-let init_platform com pf =
-	com.platform <- pf;
-	let name = platform_name pf in
+let update_platform_config com =
+	match com.platform with
+	| CustomTarget _ ->
+		() (* do nothing, configured with macro api *)
+	| _ ->
+		com.config <- get_config com
+
+let init_platform com =
+	let name = platform_name com.platform in
+	if (com.platform = Flash) && Path.file_extension com.file = "swc" then define com Define.Swc;
+	(* Set the source header, unless the user has set one already or the platform sets a custom one *)
+	if not (defined com Define.SourceHeader) && (com.platform <> Hl) then
+		define_value com Define.SourceHeader ("Generated by Haxe " ^ s_version_full);
 	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 ("java" :: (List.map platform_name platforms));
-	com.config <- get_config com;
+	com.package_rules <- List.fold_left forbid com.package_rules ("jvm" :: (List.map platform_name platforms));
+	update_platform_config com;
 	if com.config.pf_static then begin
 		raw_define com "target.static";
 		define com Define.Static;
@@ -923,26 +952,26 @@ let init_platform com pf =
 		raw_define com "target.unicode";
 	end;
 	raw_define_value com.defines "target.name" name;
-	raw_define com name;
+	raw_define com (match com.platform with | CustomTarget _ -> "custom_target" | _ -> name);
 	if com.config.pf_supports_atomics then begin
 		raw_define com "target.atomics"
 	end
 
 let set_platform com pf file =
 	if com.platform <> Cross then failwith "Multiple targets";
-	init_platform com pf;
-	com.file <- file;
-	begin match pf with
-		| Flash ->
-			if Path.file_extension file = "swc" then define com Define.Swc;
-		| Jvm ->
-			raw_define com "java"
-		| _ ->
-			()
-	end;
-	(* Set the source header, unless the user has set one already or the platform sets a custom one *)
-	if not (defined com Define.SourceHeader) && (pf <> Hl) then
-		define_value com Define.SourceHeader ("Generated by Haxe " ^ s_version_full)
+	com.platform <- pf;
+	com.file <- file
+
+let set_custom_target com name path =
+	if List.find_opt (fun pf -> (platform_name pf) = name) platforms <> None then
+		raise (Arg.Bad (Printf.sprintf "--custom-target cannot use reserved name %s" name));
+	if String.length name > max_custom_target_len then
+		raise (Arg.Bad (Printf.sprintf "--custom-target name %s exceeds the maximum of %d characters" name max_custom_target_len));
+	let name_regexp = Str.regexp "^[a-zA-Z0-9\\_]+$" in
+	if Str.string_match name_regexp name 0 then
+		set_platform com (CustomTarget name) path
+	else
+		raise (Arg.Bad (Printf.sprintf "--custom-target name %s may only contain alphanumeric or underscore characters" name))
 
 let add_feature com f =
 	Hashtbl.replace com.features f true
@@ -994,13 +1023,13 @@ let allow_package ctx s =
 	with Not_found ->
 		()
 
-let abort_located ?depth msg = raise (Abort msg)
-let abort ?depth msg p = abort_located ~depth (located msg p)
+let abort ?(depth = 0) msg p = raise (Abort (Error.make_error ~depth (Custom msg) p))
 
 let platform ctx p = ctx.platform = p
 
 let platform_name_macro com =
-	if defined com Define.Macro then "macro" else platform_name com.platform
+	if defined com Define.Macro then "macro"
+	else platform_name com.platform
 
 let remove_extension file =
 	try String.sub file 0 (String.rindex file '.')
@@ -1199,33 +1228,27 @@ let utf16_to_utf8 str =
 	loop 0;
 	Buffer.contents b
 
-let add_diagnostics_message ?(depth = 0) com msg kind sev =
+let add_diagnostics_message ?(depth = 0) ?(code = None) com s p kind sev =
 	if sev = MessageSeverity.Error then com.has_error <- true;
 	let di = com.shared.shared_display_information in
-	match (extract_located msg) with
-	| [] -> ()
-	| (s,p) :: [] ->
-		di.diagnostics_messages <- (s,p,kind,sev,depth) :: di.diagnostics_messages
-	| (s,p) :: stack ->
-		let stack_diag = (List.map (fun (s,p) -> (s,p,kind,sev,depth+1)) (List.rev stack)) in
-		di.diagnostics_messages <- stack_diag @ ((s,p,kind,sev,depth) :: di.diagnostics_messages)
-
-let located_display_error com ?(depth = 0) msg =
-	if is_diagnostics com then
-		add_diagnostics_message ~depth com msg MessageKind.DKCompilerMessage MessageSeverity.Error
-	else
-		com.located_error msg ~depth
+	di.diagnostics_messages <- (make_diagnostic ~depth ~code s p kind sev) :: di.diagnostics_messages
 
-let display_error com ?(depth = 0) msg p =
-	located_display_error com ~depth (Globals.located msg p)
+let display_error_ext com err =
+	if is_diagnostics com then begin
+		Error.recurse_error (fun depth err ->
+			add_diagnostics_message ~depth com (Error.error_msg err.err_message) err.err_pos MessageKind.DKCompilerMessage MessageSeverity.Error;
+		) err;
+	end else
+		com.error_ext err
 
-open Printer
+let display_error com ?(depth = 0) msg p =
+	display_error_ext com (Error.make_error ~depth (Custom msg) p)
 
 let dump_path com =
 	Define.defined_value_safe ~default:"dump" com.defines Define.DumpPath
 
 let adapt_defines_to_macro_context defines =
-	let to_remove = "java" :: List.map Globals.platform_name Globals.platforms in
+	let to_remove = List.map Globals.platform_name Globals.platforms in
 	let to_remove = List.fold_left (fun acc d -> Define.get_define_key d :: acc) to_remove [Define.NoTraces] in
 	let to_remove = List.fold_left (fun acc (_, d) -> ("flash" ^ d) :: acc) to_remove flash_versions in
 	let macro_defines = {
@@ -1257,3 +1280,100 @@ let get_entry_point com =
 		let e = Option.get com.main in (* must be present at this point *)
 		(snd path, c, e)
 	) com.main_class
+
+let format_string com s p process_expr =
+	let e = ref None in
+	let pmin = ref p.pmin in
+	let min = ref (p.pmin + 1) in
+	let add_expr (enext,p) len =
+		min := !min + len;
+		let enext = process_expr enext p in
+		match !e with
+		| None -> e := Some enext
+		| Some prev ->
+			e := Some (EBinop (OpAdd,prev,enext),punion (pos prev) p)
+	in
+	let add enext len =
+		let p = { p with pmin = !min; pmax = !min + len } in
+		add_expr (enext,p) len
+	in
+	let add_sub start pos =
+		let len = pos - start in
+		if len > 0 || !e = None then add (EConst (String (String.sub s start len,SDoubleQuotes))) len
+	in
+	let len = String.length s in
+	let rec parse start pos =
+		if pos = len then add_sub start pos else
+		let c = String.unsafe_get s pos in
+		let pos = pos + 1 in
+		if c = '\'' then begin
+			incr pmin;
+			incr min;
+		end;
+		if c <> '$' || pos = len then parse start pos else
+		match String.unsafe_get s pos with
+		| '$' ->
+			(* double $ *)
+			add_sub start pos;
+			parse (pos + 1) (pos + 1)
+		| '{' ->
+			parse_group start pos '{' '}' "brace"
+		| 'a'..'z' | 'A'..'Z' | '_' ->
+			add_sub start (pos - 1);
+			incr min;
+			let rec loop i =
+				if i = len then i else
+				let c = String.unsafe_get s i in
+				match c with
+				| 'a'..'z' | 'A'..'Z' | '0'..'9' | '_' -> loop (i+1)
+				| _ -> i
+			in
+			let iend = loop (pos + 1) in
+			let len = iend - pos in
+			add (EConst (Ident (String.sub s pos len))) len;
+			parse (pos + len) (pos + len)
+		| _ ->
+			(* keep as-it *)
+			parse start pos
+	and parse_group start pos gopen gclose gname =
+		add_sub start (pos - 1);
+		let rec loop groups i =
+			if i = len then
+				match groups with
+				| [] -> die "" __LOC__
+				| g :: _ -> Error.raise_typing_error ("Unclosed " ^ gname) { p with pmin = !pmin + g + 1; pmax = !pmin + g + 2 }
+			else
+				let c = String.unsafe_get s i in
+				if c = gopen then
+					loop (i :: groups) (i + 1)
+				else if c = gclose then begin
+					let groups = List.tl groups in
+					if groups = [] then i else loop groups (i + 1)
+				end else
+					loop groups (i + 1)
+		in
+		let send = loop [pos] (pos + 1) in
+		let slen = send - pos - 1 in
+		let scode = String.sub s (pos + 1) slen in
+		min := !min + 2;
+		begin
+			let e =
+				let ep = { p with pmin = !pmin + pos + 2; pmax = !pmin + send + 1 } in
+				let error msg pos =
+					if Lexer.string_is_whitespace scode then Error.raise_typing_error "Expression cannot be empty" ep
+					else Error.raise_typing_error msg pos
+				in
+				match ParserEntry.parse_expr_string com.defines scode ep error true with
+					| ParseSuccess(data,_,_) -> data
+					| ParseError(_,(msg,p),_) -> error (Parser.error_msg msg) p
+			in
+			add_expr e slen
+		end;
+		min := !min + 1;
+		parse (send + 1) (send + 1)
+	in
+	parse 0 0;
+	match !e with
+	| None -> die "" __LOC__
+	| Some e -> e
+

+ 39 - 55
src/context/display/deprecationCheck.ml

@@ -3,37 +3,46 @@ open Type
 open Common
 open Ast
 
-let curclass = ref null_class
-let curfield = ref null_field
+type deprecation_context = {
+	com        : Common.context;
+	class_meta : metadata_entry list;
+	field_meta : metadata_entry list;
+}
+
+let create_context com = {
+	com = com;
+	class_meta = [];
+	field_meta = [];
+}
 
 let warned_positions = Hashtbl.create 0
 
-let warn_deprecation com s p_usage =
+let warn_deprecation dctx s p_usage =
 	let pkey p = (p.pfile,p.pmin) in
 	if not (Hashtbl.mem warned_positions (pkey p_usage)) then begin
 		Hashtbl.add warned_positions (pkey p_usage) (s,p_usage);
-		if not (is_diagnostics com) then begin
-			let options = Warning.from_meta (!curclass.cl_meta @ !curfield.cf_meta) in
-			com.warning WDeprecated options s p_usage;
+		if not (is_diagnostics dctx.com) then begin
+			let options = Warning.from_meta (dctx.class_meta @ dctx.field_meta) in
+			dctx.com.warning WDeprecated options s p_usage;
 		end
 	end
 
-let print_deprecation_message com meta s p_usage =
+let print_deprecation_message dctx meta s p_usage =
 	let s = match meta with
 		| _,[EConst(String(s,_)),_],_ -> s
 		| _ -> Printf.sprintf "Usage of this %s is deprecated" s
 	in
-	warn_deprecation com s p_usage
+	warn_deprecation dctx s p_usage
 
-let check_meta com meta s p_usage =
+let check_meta dctx meta s p_usage =
 	try
-		print_deprecation_message com (Meta.get Meta.Deprecated meta) s p_usage;
+		print_deprecation_message dctx (Meta.get Meta.Deprecated meta) s p_usage;
 	with Not_found ->
 		()
 
 let check_cf com cf p = check_meta com cf.cf_meta "field" p
 
-let check_class com c p = if c != !curclass then check_meta com c.cl_meta "class" p
+let check_class dctx c p = check_meta dctx c.cl_meta "class" p
 
 let check_enum com en p = check_meta com en.e_meta "enum" p
 
@@ -83,56 +92,31 @@ let run_on_expr com e =
 	in
 	expr e
 
-let run_on_field com cf =
+let run_on_field dctx cf =
 	match cf.cf_expr with
-	| None ->
+	| Some e when not (Meta.has Meta.Deprecated cf.cf_meta) ->
+		run_on_expr {dctx with field_meta = cf.cf_meta} e
+	| _ ->
 		()
-	| Some e ->
-		curfield := cf;
-		run_on_expr com e;
-		curfield := null_field
 
 let run com =
+	let dctx = create_context com in
 	List.iter (fun t -> match t with
-		| TClassDecl c ->
-			curclass := c;
-			(match c.cl_constructor with None -> () | Some cf -> run_on_field com cf);
-			(match c.cl_init with None -> () | Some e -> run_on_expr com e);
-			List.iter (run_on_field com) c.cl_ordered_statics;
-			List.iter (run_on_field com) c.cl_ordered_fields;
-			curclass := null_class;
+		| TClassDecl c when not (Meta.has Meta.Deprecated c.cl_meta) ->
+			let dctx = {dctx with class_meta = c.cl_meta} in
+			(match c.cl_constructor with None -> () | Some cf -> run_on_field dctx cf);
+			(match c.cl_init with None -> () | Some e -> run_on_expr dctx e);
+			List.iter (run_on_field dctx) c.cl_ordered_statics;
+			List.iter (run_on_field dctx) c.cl_ordered_fields;
 		| _ ->
 			()
 	) com.types
 
-let if_enabled ?(force=false) com fn =
-	if force || not (defined com Define.NoDeprecationWarnings) then fn()
-
-let warn_deprecation ?(force=false) com s p_usage = if_enabled ~force com (fun() -> warn_deprecation com s p_usage)
-
-let print_deprecation_message ?(force=false) com meta s p_usage = if_enabled ~force com (fun() -> print_deprecation_message com meta s p_usage)
-
-let check_meta ?(force=false) com meta s p_usage = if_enabled ~force com (fun() -> check_meta com meta s p_usage)
-
-let check_cf ?(force=false) com cf p = if_enabled ~force com (fun() -> check_cf com cf p)
-
-let check_class ?(force=false) com c p = if_enabled ~force com (fun() -> check_class com c p)
-
-let check_enum ?(force=false) com en p = if_enabled ~force com (fun() -> check_enum com en p)
-
-let check_ef ?(force=false) com ef p = if_enabled ~force com (fun() -> check_ef com ef p)
-
-let check_typedef ?(force=false) com t p = if_enabled ~force com (fun() -> check_typedef com t p)
-
-let check_module_type ?(force=false) com mt p = if_enabled ~force com (fun() -> check_module_type com mt p)
-
-let run_on_expr ?(force=false) com e = if_enabled ~force com (fun() -> run_on_expr com e)
-
-let run_on_field ?(force=false) com cf = if_enabled ~force com (fun() -> run_on_field com cf)
-
-let run ?(force=false) com = if_enabled ~force com (fun() -> run com)
-
-let check_is com name meta p =
-	()
-	(* if name = "is" && not (Meta.has Meta.Deprecated meta) then
-		warn_deprecation com "Using \"is\" as an identifier is deprecated" p *)
+let check_is com cl_meta cf_meta name meta p =
+	let dctx = {
+		com = com;
+		class_meta = cl_meta;
+		field_meta = cf_meta;
+	} in
+	if is_next dctx.com && name = "is" && not (Meta.has Meta.Deprecated meta) then
+		warn_deprecation dctx "Using \"is\" as an identifier is deprecated" p

+ 33 - 35
src/context/display/diagnostics.ml

@@ -1,12 +1,8 @@
 open Globals
 open Ast
 open Type
-open Typecore
 open Common
-open Display
-open DisplayTypes.DisplayMode
 open DisplayTypes
-open DisplayException
 
 let add_removable_code ctx s p prange =
 	ctx.removable_code <- (s,p,prange) :: ctx.removable_code
@@ -43,23 +39,23 @@ let find_unused_variables com e =
 let check_other_things com e =
 	let had_effect = ref false in
 	let no_effect p =
-		add_diagnostics_message com (located "This code has no effect" p) DKCompilerMessage Warning;
+		add_diagnostics_message com "This code has no effect" p DKCompilerMessage Warning;
 	in
 	let pointless_compound s p =
-		add_diagnostics_message com (located (Printf.sprintf "This %s has no effect, but some of its sub-expressions do" s) p) DKCompilerMessage Warning;
+		add_diagnostics_message com (Printf.sprintf "This %s has no effect, but some of its sub-expressions do" s) p DKCompilerMessage Warning;
 	in
-	let rec compound s el p =
+	let rec compound compiler_generated s el p =
 		let old = !had_effect in
 		had_effect := false;
-		List.iter (loop true) el;
-		if not !had_effect then no_effect p else pointless_compound s p;
+		List.iter (loop true compiler_generated) el;
+		if not !had_effect then no_effect p else if not compiler_generated then pointless_compound s p;
 		had_effect := old;
-	and loop in_value e = match e.eexpr with
+	and loop in_value compiler_generated e = match e.eexpr with
 		| TBlock el ->
 			let rec loop2 el = match el with
 				| [] -> ()
-				| [e] -> loop in_value e
-				| e :: el -> loop false e; loop2 el
+				| [e] -> loop in_value compiler_generated e
+				| e :: el -> loop false compiler_generated e; loop2 el
 			in
 			loop2 el
 		| TMeta((Meta.Extern,_,_),_) ->
@@ -71,42 +67,46 @@ let check_other_things com e =
 			()
 		| TField (_, fa) when PurityState.is_explicitly_impure fa -> ()
 		| TFunction tf ->
-			loop false tf.tf_expr
-		| TCall({eexpr = TField(e1,fa)},el) when not in_value && PurityState.is_pure_field_access fa -> compound "call" el e.epos
+			loop false compiler_generated tf.tf_expr
+		| TCall({eexpr = TField(e1,fa)},el) when not in_value && PurityState.is_pure_field_access fa -> compound compiler_generated "call" el e.epos
 		| TNew _ | TCall _ | TBinop ((Ast.OpAssignOp _ | Ast.OpAssign),_,_) | TUnop ((Ast.Increment | Ast.Decrement),_,_)
 		| TReturn _ | TBreak | TContinue | TThrow _ | TCast (_,Some _)
 		| TIf _ | TTry _ | TSwitch _ | TWhile _ | TFor _ ->
 			had_effect := true;
-			Type.iter (loop true) e
+			Type.iter (loop true compiler_generated) e
+		| TMeta((Meta.CompilerGenerated,_,_),e1) ->
+			loop in_value true e1
 		| TParenthesis e1 | TMeta(_,e1) ->
-			loop in_value e1
+			loop in_value compiler_generated e1
 		| TArray _ | TCast (_,None) | TBinop _ | TUnop _
 		| TField _ | TArrayDecl _ | TObjectDecl _ when in_value ->
-			Type.iter (loop true) e;
-		| TArray(e1,e2) -> compound "array access" [e1;e2] e.epos
-		| TCast(e1,None) -> compound "cast" [e1] e.epos
-		| TBinop(op,e1,e2) -> compound (Printf.sprintf "'%s' operator" (s_binop op)) [e1;e2] e.epos
-		| TUnop(op,_,e1) -> compound (Printf.sprintf "'%s' operator" (s_unop op)) [e1] e.epos
-		| TField(e1,_) -> compound "field access" [e1] e.epos
-		| TArrayDecl el -> compound "array declaration" el e.epos
-		| TObjectDecl fl -> compound "object declaration" (List.map snd fl) e.epos
+			Type.iter (loop true compiler_generated) e;
+		| TArray(e1,e2) -> compound compiler_generated "array access" [e1;e2] e.epos
+		| TCast(e1,None) -> compound compiler_generated "cast" [e1] e.epos
+		| TBinop(op,e1,e2) -> compound compiler_generated (Printf.sprintf "'%s' operator" (s_binop op)) [e1;e2] e.epos
+		| TUnop(op,_,e1) -> compound compiler_generated (Printf.sprintf "'%s' operator" (s_unop op)) [e1] e.epos
+		| TField(e1,_) -> compound compiler_generated "field access" [e1] e.epos
+		| TArrayDecl el -> compound compiler_generated "array declaration" el e.epos
+		| TObjectDecl fl -> compound compiler_generated "object declaration" (List.map snd fl) e.epos
 	in
-	loop true e
+	loop true false e
 
-let prepare_field dctx com cf = match cf.cf_expr with
+let prepare_field dctx dectx com cf = match cf.cf_expr with
 	| None -> ()
 	| Some e ->
 		find_unused_variables dctx e;
 		check_other_things com e;
-		DeprecationCheck.run_on_expr ~force:true com e
+		DeprecationCheck.run_on_expr {dectx with field_meta = cf.cf_meta} e
 
 let collect_diagnostics dctx com =
 	let open CompilationCache in
+	let dectx = DeprecationCheck.create_context com in
 	List.iter (function
 		| TClassDecl c when DiagnosticsPrinter.is_diagnostics_file com (com.file_keys#get c.cl_pos.pfile) ->
-			List.iter (prepare_field dctx com) c.cl_ordered_fields;
-			List.iter (prepare_field dctx com) c.cl_ordered_statics;
-			(match c.cl_constructor with None -> () | Some cf -> prepare_field dctx com cf);
+			let dectx = {dectx with class_meta = c.cl_meta} in
+			List.iter (prepare_field dctx dectx com) c.cl_ordered_fields;
+			List.iter (prepare_field dctx dectx com) c.cl_ordered_statics;
+			(match c.cl_constructor with None -> () | Some cf -> prepare_field dctx dectx com cf);
 		| _ ->
 			()
 	) com.types;
@@ -143,7 +143,7 @@ let prepare com =
 		unresolved_identifiers = [];
 		missing_fields = PMap.empty;
 	} in
-	if not (List.exists (fun (_,_,_,sev,_) -> sev = MessageSeverity.Error) com.shared.shared_display_information.diagnostics_messages) then
+	if not (List.exists (fun diag -> diag.diag_severity = MessageSeverity.Error) com.shared.shared_display_information.diagnostics_messages) then
 		collect_diagnostics dctx com;
 	let process_modules com =
 		List.iter (fun m ->
@@ -178,9 +178,7 @@ let prepare com =
 	dctx
 
 let secure_generated_code ctx e =
-	(* This causes problems and sucks in general... need a different solution. But I forgot which problem this solved anyway. *)
-	(* mk (TMeta((Meta.Extern,[],e.epos),e)) e.etype e.epos *)
-	e
+	if is_diagnostics ctx then mk (TMeta((Meta.CompilerGenerated,[],e.epos),e)) e.etype e.epos else e
 
 let print com =
 	let dctx = prepare com in
@@ -188,4 +186,4 @@ let print com =
 
 let run com =
 	let dctx = prepare com in
-	dctx
+	dctx

+ 20 - 17
src/context/display/diagnosticsPrinter.ml

@@ -2,7 +2,6 @@ open Globals
 open Common
 open Json
 open DisplayTypes
-open DisplayTypes
 open Type
 open Genjson
 open MessageKind
@@ -11,14 +10,16 @@ type t = {
 	diag_kind : MessageKind.t;
 	diag_pos : pos;
 	diag_severity : MessageSeverity.t;
+	diag_code : string option;
 	diag_args : Json.t;
 	mutable diag_related_information : (pos * int * string) list;
 }
 
-let make_diagnostic kd p sev args = {
+let make_diagnostic kd p sev code args = {
 	diag_kind = kd;
 	diag_pos = p;
 	diag_severity = sev;
+	diag_code = code;
 	diag_args = args;
 	diag_related_information = [];
 }
@@ -60,7 +61,7 @@ let json_of_diagnostics com dctx =
 			Hashtbl.replace diagnostics file (diag :: fdiag)
 	in
 	let file_keys = new Common.file_keys in
-	let add dk p sev args =
+	let add dk p sev code args =
 		let append = match dk with
 			| DKUnusedImport
 			| DKRemovableCode
@@ -74,7 +75,7 @@ let json_of_diagnostics com dctx =
 				true
 		in
 		if p = null_pos || is_diagnostics_file com (file_keys#get p.pfile) then begin
-			let diag = make_diagnostic dk p sev args in
+			let diag = make_diagnostic dk p sev code args in
 			current := Some diag;
 			add append diag
 		end else current := None
@@ -97,19 +98,19 @@ let json_of_diagnostics com dctx =
 					"name",JString s;
 				])
 		) suggestions in
-		add DKUnresolvedIdentifier p MessageSeverity.Error (JArray suggestions);
+		add DKUnresolvedIdentifier p MessageSeverity.Error None (JArray suggestions);
 	) dctx.unresolved_identifiers;
-	List.iter (fun (s,p,kind,sev,depth) -> match (depth, !current) with
-		| d, Some diag when d > 0 ->
-			let lines = ExtString.String.nsplit s "\n" in
+	List.iter (fun d -> match (d.diag_depth, !current) with
+		| depth, Some diag when depth > 0 ->
+			let lines = ExtString.String.nsplit d.diag_message "\n" in
 			(match lines with
 				| [] -> ()
 				| s :: sub ->
-					let related = List.fold_left (fun acc s -> (p,d,Error.compl_msg s) :: acc) diag.diag_related_information sub in
-					diag.diag_related_information <- (p,d,s) :: related;
+					let related = List.fold_left (fun acc s -> (d.diag_pos,depth,Error.compl_msg s) :: acc) [] (List.rev sub) in
+					diag.diag_related_information <- List.append diag.diag_related_information ((d.diag_pos,depth,s) :: related);
 			)
 		| 0, _ ->
-			add kind p sev (JString s)
+			add d.diag_kind d.diag_pos d.diag_severity d.diag_code (JString d.diag_message)
 		| _ ->
 			(* Do not add errors with depth greater than one as top level diagnostic. *)
 			(* This could happen when running diagnostics for a file that is wentioned in *)
@@ -177,22 +178,23 @@ let json_of_diagnostics com dctx =
 			"moduleFile",jstring (Path.UniqueKey.lazy_path (t_infos mt).mt_module.m_extra.m_file);
 			"entries",jarray l
 		] in
-		add DKMissingFields p MessageSeverity.Error j
+		add DKMissingFields p MessageSeverity.Error None j
 	) dctx.missing_fields;
 	(* non-append from here *)
 	begin match Warning.get_mode WDeprecated com.warning_options with
 	| WMEnable ->
 		Hashtbl.iter (fun _ (s,p) ->
-			add DKDeprecationWarning p MessageSeverity.Warning (JString s);
+			let wobj = Warning.warning_obj WDeprecated in
+			add DKDeprecationWarning p MessageSeverity.Warning (Some wobj.w_name) (JString s);
 		) DeprecationCheck.warned_positions;
 	| WMDisable ->
 		()
 	end;
 	PMap.iter (fun p r ->
-		if not !r then add DKUnusedImport p MessageSeverity.Warning (JArray [])
+		if not !r then add DKUnusedImport p MessageSeverity.Warning None (JArray [])
 	) dctx.import_positions;
 	List.iter (fun (s,p,prange) ->
-		add DKRemovableCode p MessageSeverity.Warning (JObject ["description",JString s;"range",if prange = null_pos then JNull else Genjson.generate_pos_as_range prange])
+		add DKRemovableCode p MessageSeverity.Warning None (JObject ["description",JString s;"range",if prange = null_pos then JNull else Genjson.generate_pos_as_range prange])
 	) dctx.removable_code;
 	Hashtbl.iter (fun file ranges ->
 		List.iter (fun (p,e) ->
@@ -201,7 +203,7 @@ let json_of_diagnostics com dctx =
 					"string",JString (Ast.Printer.s_expr e)
 				]
 			] in
-			add DKInactiveBlock p MessageSeverity.Hint jo
+			add DKInactiveBlock p MessageSeverity.Hint None jo
 		) ranges
 	) dctx.dead_blocks;
 	let jl = Hashtbl.fold (fun file diag acc ->
@@ -211,8 +213,9 @@ let json_of_diagnostics com dctx =
 				"severity",JInt (MessageSeverity.to_int diag.diag_severity);
 				"range",Genjson.generate_pos_as_range diag.diag_pos;
 				"args",diag.diag_args;
+				"code",(match diag.diag_code with None -> JNull | Some c -> JString c);
 				"relatedInformation",JArray (
-					List.rev_map (fun (pos,depth,msg) -> (JObject [
+					List.map (fun (pos,depth,msg) -> (JObject [
 						"location",Genjson.generate_pos_as_location pos;
 						"depth",JInt depth;
 						"message",JString msg;

+ 1 - 4
src/context/display/display.ml

@@ -2,13 +2,10 @@ open Ast
 open Common
 open DisplayTypes
 open DisplayMode
-open DisplayPosition
 open CompletionItem
-open CompletionResultKind
 open Type
 open Typecore
 open Globals
-open Genjson
 open DisplayPosition
 open ImportStatus
 
@@ -290,7 +287,7 @@ let sort_fields l with_type tk =
 	in
 	let l = match with_type with
 		| WithType.WithType(t,_) when (match follow t with TMono _ -> false | _ -> true) ->
-			let rec comp item = match item.ci_type with
+			let comp item = match item.ci_type with
 				| None -> 9
 				| Some (t',_) ->
 				(* For enum constructors, we consider the return type of the constructor function

+ 12 - 2
src/context/display/displayEmitter.ml

@@ -6,7 +6,6 @@ open DisplayException
 open DisplayTypes
 open DisplayMode
 open CompletionItem
-open CompletionType
 open ClassFieldOrigin
 open DisplayTypes.CompletionResultKind
 open Common
@@ -19,6 +18,17 @@ let symbol_of_module_type = function
 	| TTypeDecl td -> SKTypedef td
 	| TAbstractDecl a -> SKAbstract a
 
+let display_alias ctx name t p = match ctx.com.display.dms_kind with
+	| DMDefinition | DMTypeDefinition ->
+		raise_positions [p];
+	| DMUsage _ | DMImplementation ->
+		ReferencePosition.set (name,p,SKOther)
+	| DMHover ->
+		let ct = CompletionType.from_type (get_import_status ctx) t in
+		raise_hover (make_ci_literal name (t,ct)) None p
+	| _ ->
+		()
+
 let display_module_type ctx mt p = match ctx.com.display.dms_kind with
 	| DMDefinition | DMTypeDefinition ->
 		begin match mt with
@@ -192,4 +202,4 @@ let check_field_modifiers ctx c cf override display_modifier =
 			) missing_fields [] in
 			let l = sort_fields l NoValue TKOverride in
 			raise_fields l CROverride (make_subject (Some cf.cf_name) cf.cf_name_pos)
-		| _ -> ()
+		| _ -> ()

+ 8 - 8
src/context/display/displayException.ml

@@ -23,9 +23,9 @@ let max_completion_items = ref 0
 let filter_somehow ctx items kind subj =
 	let subject = match subj.s_name with
 		| None -> ""
-		| Some name-> String.lowercase name
+		| Some name-> ExtString.String.lowercase name
 	in
-	let subject_length = String.length subject in
+	let subject_length = ExtString.String.length subject in
 	let determine_cost s =
 		let get_initial_cost o =
 			if o = 0 then
@@ -33,7 +33,7 @@ let filter_somehow ctx items kind subj =
 			else begin
 				(* Consider `.` as anchors and determine distance from closest one. Penalize starting distance by factor 2. *)
 				try
-					let last_anchor = String.rindex_from s o '.' in
+					let last_anchor = ExtString.String.rindex_from s o '.' in
 					(o - (last_anchor + 1)) * 2
 				with Not_found ->
 					o * 2
@@ -54,12 +54,12 @@ let filter_somehow ctx items kind subj =
 				let o',new_cost = index_from o subject.[i] in
 				loop (i + 1) o' (cost + new_cost)
 			end else
-				cost + (if o = String.length s - 1 then 0 else 1) (* Slightly penalize for not-exact matches. *)
+				cost + (if o = ExtString.String.length s - 1 then 0 else 1) (* Slightly penalize for not-exact matches. *)
 		in
 		if subject_length = 0 then
 			0
 		else try
-			let o = String.index s subject.[0] in
+			let o = ExtString.String.index s subject.[0] in
 			loop 1 o (get_initial_cost o);
 		with Not_found | Invalid_argument _ ->
 			-1
@@ -67,7 +67,7 @@ let filter_somehow ctx items kind subj =
 	let rec loop acc items index =
 		match items with
 		| item :: items ->
-			let name = String.lowercase (get_filter_name item) in
+			let name = ExtString.String.lowercase (get_filter_name item) in
 			let cost = determine_cost name in
 			let acc = if cost >= 0 then
 				(item,index,cost) :: acc
@@ -102,8 +102,8 @@ let patch_completion_subject subj =
 	match subj.s_name with
 	| Some name ->
 		let delta = p.pmax - p.pmin in
-		let name = if delta > 0 && delta < String.length name then
-			String.sub name 0 delta
+		let name = if delta > 0 && delta < ExtString.String.length name then
+			ExtString.String.sub name 0 delta
 		else
 			name
 		in

+ 24 - 20
src/context/display/displayFields.ml

@@ -75,7 +75,7 @@ let collect_static_extensions ctx items e p =
 					let item = make_ci_class_field (CompletionClassField.make f CFSMember origin true) (f.cf_type,ct) in
 					PMap.add f.cf_name item acc
 				end
-			with Error (Unify _,_,_) | Unify_error _ ->
+			with Error { err_message = Unify _ } | Unify_error _ ->
 				acc
 			end
 		| _ ->
@@ -228,21 +228,25 @@ let collect ctx e_ast e dk with_type p =
 		| TAnon an ->
 			(* @:forwardStatics *)
 			let items = match !(an.a_status) with
-				| Statics { cl_kind = KAbstractImpl { a_meta = meta; a_this = TInst (c,_) }} when Meta.has Meta.ForwardStatics meta ->
-					let items = List.fold_left (fun acc cf ->
-						if should_access c cf true && is_new_item acc cf.cf_name then begin
-							let origin = Self(TClassDecl c) in
-							let item = make_class_field origin cf in
-							PMap.add cf.cf_name item acc
-						end else
-							acc
-					) items c.cl_ordered_statics in
-					PMap.foldi (fun name item acc ->
-						if is_new_item acc name then
-							PMap.add name item acc
-						else
-							acc
-					) PMap.empty items
+				| ClassStatics { cl_kind = KAbstractImpl { a_meta = meta; a_this}} when Meta.has Meta.ForwardStatics meta ->
+					begin match follow a_this with
+					| TInst (c,_) ->
+						let items = List.fold_left (fun acc cf ->
+							if should_access c cf true && is_new_item acc cf.cf_name then begin
+								let origin = Self(TClassDecl c) in
+								let item = make_class_field origin cf in
+								PMap.add cf.cf_name item acc
+							end else
+								acc
+						) items c.cl_ordered_statics in
+						PMap.foldi (fun name item acc ->
+							if is_new_item acc name then
+								PMap.add name item acc
+							else
+								acc
+						) PMap.empty items
+					| _ -> items
+					end
 				| _ -> items
 			in
 			(* Anon own fields *)
@@ -257,7 +261,7 @@ let collect ctx e_ast e dk with_type p =
 						PMap.add name (make_field (CompletionClassField.make cf CFSMember origin true) (cf.cf_type,ct)) acc
 					in
 					match !(an.a_status) with
-						| Statics ({cl_kind = KAbstractImpl a} as c) ->
+						| ClassStatics ({cl_kind = KAbstractImpl a} as c) ->
 							if allow_static_abstract_access c cf then
 								let make = if has_class_field_flag cf CfEnum then
 										(make_ci_enum_abstract_field a)
@@ -267,7 +271,7 @@ let collect ctx e_ast e dk with_type p =
 								add (Self (TAbstractDecl a)) make
 							else
 								acc;
-						| Statics c ->
+						| ClassStatics c ->
 							Display.merge_core_doc ctx (TClassDecl c);
 							if should_access c cf true then add (Self (TClassDecl c)) make_ci_class_field else acc;
 						| EnumStatics en ->
@@ -373,7 +377,7 @@ let handle_missing_field_raise ctx tthis i mode with_type pfield =
 		| TAbstract(a,_) -> TAbstractDecl a,CFSMember,true
 		| TAnon an ->
 			begin match !(an.a_status) with
-			| Statics c -> TClassDecl c,CFSStatic,not (can_access ctx c cf true)
+			| ClassStatics c -> TClassDecl c,CFSStatic,not (can_access ctx c cf true)
 			| EnumStatics en -> TEnumDecl en,CFSStatic,true
 			| AbstractStatics a -> TAbstractDecl a,CFSStatic,true
 			| _ -> raise Exit
@@ -409,4 +413,4 @@ let handle_missing_ident ctx i mode with_type p =
 			handle_missing_field_raise ctx ctx.tthis i mode with_type p
 		with Exit ->
 			()
-		end
+		end

+ 9 - 3
src/context/display/displayJson.ml

@@ -1,5 +1,4 @@
 open Globals
-open Json.Reader
 open JsonRpc
 open Jsonrpc_handler
 open Json
@@ -183,13 +182,14 @@ let handler =
 		"server/module", (fun hctx ->
 			let sign = Digest.from_hex (hctx.jsonrpc#get_string_param "signature") in
 			let path = Path.parse_path (hctx.jsonrpc#get_string_param "path") in
-			let cc = hctx.display#get_cs#get_context sign in
+			let cs = hctx.display#get_cs in
+			let cc = cs#get_context sign in
 			let m = try
 				cc#find_module path
 			with Not_found ->
 				hctx.send_error [jstring "No such module"]
 			in
-			hctx.send_result (generate_module cc m)
+			hctx.send_result (generate_module cs cc m)
 		);
 		"server/type", (fun hctx ->
 			let sign = Digest.from_hex (hctx.jsonrpc#get_string_param "signature") in
@@ -297,6 +297,12 @@ let handler =
 				l := jstring ("Legacy completion " ^ (if b then "enabled" else "disabled")) :: !l;
 				()
 			) ();
+			hctx.jsonrpc#get_opt_param (fun () ->
+				let b = hctx.jsonrpc#get_bool_param "populateCacheFromDisplay" in
+				ServerConfig.populate_cache_from_display := b;
+				l := jstring ("Compilation cache refill from display " ^ (if b then "enabled" else "disabled")) :: !l;
+				()
+			) ();
 			hctx.send_result (jarray !l)
 		);
 		"server/memory",(fun hctx ->

+ 3 - 6
src/context/display/displayTexpr.ml

@@ -4,9 +4,7 @@ open Ast
 open Type
 open Typecore
 open DisplayPosition
-open CompletionItem
 open CompilationCache
-open ClassFieldOrigin
 
 let find_field_by_position sc p =
 	List.find (fun cff ->
@@ -59,12 +57,11 @@ let find_abstract_by_position decls p =
 	loop decls
 
 let actually_check_display_field ctx c cff p =
-	let context_init = new TypeloadFields.context_init in
-	let cctx = TypeloadFields.create_class_context c context_init p in
+	let cctx = TypeloadFields.create_class_context c p in
 	let ctx = TypeloadFields.create_typer_context_for_class ctx cctx p in
 	let cff = TypeloadFields.transform_field (ctx,cctx) c cff (ref []) (pos cff.cff_name) in
 	let display_modifier = Typeload.check_field_access ctx cff in
-	let fctx = TypeloadFields.create_field_context cctx cff true display_modifier in
+	let fctx = TypeloadFields.create_field_context ctx cctx cff true display_modifier in
 	let cf = TypeloadFields.init_field (ctx,cctx,fctx) cff in
 	flush_pass ctx PTypeField "check_display_field";
 	ignore(follow cf.cf_type)
@@ -184,4 +181,4 @@ let check_display_file ctx cs =
 			cs#taint_modules fkey "check_display_file";
 		end
 	| None ->
-		()
+		()

+ 4 - 5
src/context/display/displayToplevel.ml

@@ -24,7 +24,6 @@ open Typecore
 open CompletionItem
 open ClassFieldOrigin
 open DisplayTypes
-open Genjson
 open Globals
 
 (* Merges argument and return types from macro and non-macro context, preferring the one that isn't Dynamic.
@@ -188,7 +187,7 @@ module CollectionContext = struct
 			Shadowed
 		with Not_found ->
 			let check_wildcard () =
-				List.exists (fun (sl,_) -> (sl,snd path) = path) ctx.ctx.m.wildcard_packages
+				List.exists (fun (sl,_) -> (sl,snd path) = path) ctx.ctx.m.import_resolution#extract_wildcard_packages
 			in
 			if is_import || (fst path = []) || check_wildcard () then Imported else Unimported
 
@@ -378,7 +377,7 @@ let collect ctx tk with_type sort =
 				()
 		in
 		List.iter enum_ctors ctx.m.curmod.m_types;
-		List.iter enum_ctors (List.map fst ctx.m.module_imports);
+		List.iter enum_ctors (List.map fst ctx.m.import_resolution#extract_type_imports);
 
 		(* enum constructors of expected type *)
 		begin match with_type with
@@ -415,7 +414,7 @@ let collect ctx tk with_type sort =
 					| _ -> raise Not_found
 			with Not_found ->
 				()
-		) ctx.m.module_globals;
+		) ctx.m.import_resolution#extract_field_imports;
 
 		(* literals *)
 		add (make_ci_literal "null" (tpair t_dynamic)) (Some "null");
@@ -460,7 +459,7 @@ let collect ctx tk with_type sort =
 	List.iter add_type ctx.m.curmod.m_types;
 
 	(* module imports *)
-	List.iter add_type (List.rev_map fst ctx.m.module_imports); (* reverse! *)
+	List.iter add_type (List.rev_map fst ctx.m.import_resolution#extract_type_imports); (* reverse! *)
 
 	(* types from files *)
 	let cs = ctx.com.cs in

+ 1 - 1
src/context/display/documentSymbols.ml

@@ -56,7 +56,7 @@ let collect_module_symbols mname with_locals (pack,decls) =
 		| FFun f ->
 			add_field (
 				if fst cff_name = "new" then Constructor
-				else if ((parent_kind = EnumAbstract or parent_kind = Abstract) && Meta.has_one_of [Meta.Op; Meta.ArrayAccess; Meta.Resolve] cff_meta) then Operator
+				else if ((parent_kind = EnumAbstract || parent_kind = Abstract) && Meta.has_one_of [Meta.Op; Meta.ArrayAccess; Meta.Resolve] cff_meta) then Operator
 				else Method
 			);
 			if with_locals then func field_parent f

+ 1 - 3
src/context/display/findReferences.ml

@@ -1,10 +1,8 @@
 open Globals
-open Ast
 open DisplayTypes
 open Common
 open Type
 open Typecore
-open ImportHandling
 
 let find_possible_references tctx cs =
 	let name,_,kind = Display.ReferencePosition.get () in
@@ -164,4 +162,4 @@ let find_implementations tctx com name pos kind =
 let find_implementations tctx com =
 	let name,pos,kind = Display.ReferencePosition.get () in
 	if pos <> null_pos then find_implementations tctx com name pos kind
-	else DisplayException.raise_positions []
+	else DisplayException.raise_positions []

+ 64 - 58
src/context/display/importHandling.ml

@@ -5,6 +5,7 @@ open Common
 open Type
 open Error
 open Typecore
+open Resolution
 
 type import_display_kind =
 	| IDKPackage of string list
@@ -61,7 +62,7 @@ let commit_import ctx path mode p =
 	ctx.m.import_statements <- (path,mode) :: ctx.m.import_statements;
 	if Filename.basename p.pfile <> "import.hx" then add_import_position ctx p path
 
-let init_import ctx context_init path mode p =
+let init_import ctx path mode p =
 	let rec loop acc = function
 		| x :: l when is_lower_ident (fst x) -> loop (x::acc) l
 		| rest -> List.rev acc, rest
@@ -71,19 +72,19 @@ let init_import ctx context_init path mode p =
 	| [] ->
 		(match mode with
 		| IAll ->
-			ctx.m.wildcard_packages <- (List.map fst pack,p) :: ctx.m.wildcard_packages
+			ctx.m.import_resolution#add (wildcard_package_resolution (List.map fst pack) p)
 		| _ ->
 			(match List.rev path with
 			(* p spans `import |` (to the display position), so we take the pmax here *)
 			| [] -> DisplayException.raise_fields (DisplayToplevel.collect ctx TKType NoValue true) CRImport (DisplayTypes.make_subject None {p with pmin = p.pmax})
-			| (_,p) :: _ -> Error.typing_error "Module name must start with an uppercase letter" p))
+			| (_,p) :: _ -> Error.raise_typing_error "Module name must start with an uppercase letter" p))
 	| (tname,p2) :: rest ->
 		let p1 = (match pack with [] -> p2 | (_,p1) :: _ -> p1) in
 		let p_type = punion p1 p2 in
 		let md = ctx.g.do_load_module ctx (List.map fst pack,tname) p_type in
 		let types = md.m_types in
-		let no_private (t,_) = not (t_infos t).mt_private in
-		let error_private p = typing_error "Importing private declarations from a module is not allowed" p in
+		let not_private mt = not (t_infos mt).mt_private in
+		let error_private p = raise_typing_error "Importing private declarations from a module is not allowed" p in
 		let chk_private t p = if ctx.m.curmod != (t_infos t).mt_module && (t_infos t).mt_private then error_private p in
 		let has_name name t = snd (t_infos t).mt_path = name in
 
@@ -93,7 +94,7 @@ let init_import ctx context_init path mode p =
 				| 'a'..'z' -> "field", PMap.foldi (fun n _ acc -> n :: acc) (try (Option.get md.m_statics).cl_statics with | _ -> PMap.empty) []
 				| _ -> "type", List.map (fun mt -> snd (t_infos mt).mt_path) types
 			in
-			typing_error (StringError.string_error name
+			raise_typing_error (StringError.string_error name
 				candidates
 				("Module " ^ s_type_path md.m_path ^ " does not define " ^ target_kind ^ " " ^ name)
 			) p
@@ -109,66 +110,70 @@ let init_import ctx context_init path mode p =
 			chk_private t p_type;
 			t
 		in
-		let rebind t name p =
+		let check_alias mt name pname =
 			if not (name.[0] >= 'A' && name.[0] <= 'Z') then
-				typing_error "Type aliases must start with an uppercase letter" p;
-			let _, _, f = ctx.g.do_build_instance ctx t p_type in
-			(* create a temp private typedef, does not register it in module *)
-			let t_path = (fst md.m_path @ ["_" ^ snd md.m_path],name) in
-			let t_type = f (extract_param_types (t_infos t).mt_params) in
-			let mt = TTypeDecl {(mk_typedef ctx.m.curmod t_path p p t_type) with
-				t_private = true;
-				t_params = (t_infos t).mt_params
-			} in
-			if ctx.is_display_file && DisplayPosition.display_position#enclosed_in p then
-				DisplayEmitter.display_module_type ctx mt p;
-			mt
+				raise_typing_error "Type aliases must start with an uppercase letter" pname;
+			if ctx.is_display_file && DisplayPosition.display_position#enclosed_in pname then
+				DisplayEmitter.display_alias ctx name (type_of_module_type mt) pname;
 		in
 		let add_static_init t name s =
-			let name = (match name with None -> s | Some (n,_) -> n) in
 			match resolve_typedef t with
-			| TClassDecl c | TAbstractDecl {a_impl = Some c} ->
+			| TClassDecl c ->
 				ignore(c.cl_build());
-				ignore(PMap.find s c.cl_statics);
-				ctx.m.module_globals <- PMap.add name (TClassDecl c,s,p) ctx.m.module_globals
-			| TEnumDecl e ->
-				ignore(PMap.find s e.e_constrs);
-				ctx.m.module_globals <- PMap.add name (TEnumDecl e,s,p) ctx.m.module_globals
+				let cf = PMap.find s c.cl_statics in
+				static_field_resolution c cf name p
+			| TAbstractDecl ({a_impl = Some c} as a) ->
+				ignore(c.cl_build());
+				let cf = PMap.find s c.cl_statics in
+				static_abstract_field_resolution a c cf name p
+			| TEnumDecl en ->
+				let ef = PMap.find s en.e_constrs in
+				enum_constructor_resolution en ef name p
 			| _ ->
 				raise Not_found
 		in
+		let add_lazy_resolution f =
+			ctx.m.import_resolution#add (lazy_resolution f)
+		in
 		(match mode with
 		| INormal | IAsName _ ->
 			let name = (match mode with IAsName n -> Some n | _ -> None) in
 			(match rest with
 			| [] ->
-				(match name with
+				begin match name with
 				| None ->
-					ctx.m.module_imports <- List.filter no_private (List.map (fun t -> t,p) types) @ ctx.m.module_imports;
+					List.iter (fun mt ->
+						if not_private mt then
+							ctx.m.import_resolution#add (module_type_resolution mt None p)
+					) (List.rev types);
 					Option.may (fun c ->
-						context_init#add (fun () ->
-							ignore(c.cl_build());
-							List.iter (fun cf ->
-								if has_class_field_flag cf CfPublic then
-									ctx.m.module_globals <- PMap.add cf.cf_name (TClassDecl c,cf.cf_name,p) ctx.m.module_globals
-							) c.cl_ordered_statics
-						);
+						ctx.m.import_resolution#add (class_statics_resolution c p)
 					) md.m_statics
 				| Some(newname,pname) ->
-					ctx.m.module_imports <- (rebind (get_type tname) newname pname,p) :: ctx.m.module_imports);
+					let mt = get_type tname in
+					check_alias mt newname pname;
+					ctx.m.import_resolution#add (module_type_resolution mt (Some newname) p2)
+				end
 			| [tsub,p2] ->
 				let pu = punion p1 p2 in
 				(try
 					let tsub = List.find (has_name tsub) types in
 					chk_private tsub pu;
-					ctx.m.module_imports <- ((match name with None -> tsub | Some(n,pname) -> rebind tsub n pname),p) :: ctx.m.module_imports
+					let alias = match name with
+						| None ->
+							None
+						| Some(name,pname) ->
+							check_alias tsub name pname;
+							Some name
+					in
+					ctx.m.import_resolution#add (module_type_resolution tsub alias p2);
 				with Not_found ->
 					(* this might be a static property, wait later to check *)
 					let find_main_type_static () =
 						try
 							let tmain = find_type tname in
 							begin try
-								add_static_init tmain name tsub
+								Some (add_static_init tmain (Option.map fst name) tsub)
 							with Not_found ->
 								let parent,target_kind,candidates = match resolve_typedef tmain with
 									| TClassDecl c ->
@@ -189,13 +194,13 @@ let init_import ctx context_init path mode p =
 										(* TODO: cleaner way to get module fields? *)
 										PMap.foldi (fun n _ acc -> n :: acc) (try (Option.get md.m_statics).cl_statics with | _ -> PMap.empty) []
 								in
-
-								display_error ctx.com (StringError.string_error tsub candidates (parent ^ " has no " ^ target_kind ^ " " ^ tsub)) p
+								display_error ctx.com (StringError.string_error tsub candidates (parent ^ " has no " ^ target_kind ^ " " ^ tsub)) p;
+								None
 							end
 						with Not_found ->
 							fail_usefully tsub p
 					in
-					context_init#add (fun() ->
+					add_lazy_resolution (fun() ->
 						match md.m_statics with
 						| Some c ->
 							(try
@@ -208,8 +213,7 @@ let init_import ctx context_init path mode p =
 											if not (has_class_field_flag cf CfPublic) then
 												error_private p
 											else
-												let imported_name = match name with None -> tsub | Some (n,pname) -> n in
-												ctx.m.module_globals <- PMap.add imported_name (TClassDecl c,tsub,p) ctx.m.module_globals;
+												Some (static_field_resolution c cf (Option.map fst name) p)
 										else
 											loop rest
 								in
@@ -223,31 +227,31 @@ let init_import ctx context_init path mode p =
 			| (tsub,p2) :: (fname,p3) :: rest ->
 				(match rest with
 				| [] -> ()
-				| (n,p) :: _ -> typing_error ("Unexpected " ^ n) p);
+				| (n,p) :: _ -> raise_typing_error ("Unexpected " ^ n) p);
 				let tsub = get_type tsub in
-				context_init#add (fun() ->
+				add_lazy_resolution (fun() ->
 					try
-						add_static_init tsub name fname
+						Some (add_static_init tsub (Option.map fst name) fname)
 					with Not_found ->
-						display_error ctx.com (s_type_path (t_infos tsub).mt_path ^ " has no field " ^ fname) (punion p p3)
+						display_error ctx.com (s_type_path (t_infos tsub).mt_path ^ " has no field " ^ fname) (punion p p3);
+						None
 				);
 			)
 		| IAll ->
 			let t = (match rest with
 				| [] -> get_type tname
 				| [tsub,_] -> get_type tsub
-				| _ :: (n,p) :: _ -> typing_error ("Unexpected " ^ n) p
+				| _ :: (n,p) :: _ -> raise_typing_error ("Unexpected " ^ n) p
 			) in
-			context_init#add (fun() ->
+			add_lazy_resolution (fun() ->
 				match resolve_typedef t with
 				| TClassDecl c
 				| TAbstractDecl {a_impl = Some c} ->
-					ignore(c.cl_build());
-					PMap.iter (fun _ cf -> if not (has_meta Meta.NoImportGlobal cf.cf_meta) then ctx.m.module_globals <- PMap.add cf.cf_name (TClassDecl c,cf.cf_name,p) ctx.m.module_globals) c.cl_statics
-				| TEnumDecl e ->
-					PMap.iter (fun _ c -> if not (has_meta Meta.NoImportGlobal c.ef_meta) then ctx.m.module_globals <- PMap.add c.ef_name (TEnumDecl e,c.ef_name,p) ctx.m.module_globals) e.e_constrs
+					Some (class_statics_resolution c p)
+				| TEnumDecl en ->
+					Some (enum_statics_resolution en p)
 				| _ ->
-					typing_error "No statics to import from this type" p
+					raise_typing_error "No statics to import from this type" p
 			)
 		))
 
@@ -270,7 +274,6 @@ let handle_using ctx path p =
 			let t = ctx.g.do_load_type_def ctx p t in
 			[t]
 	) in
-	(* delay the using since we need to resolve typedefs *)
 	let filter_classes types =
 		let rec loop acc types = match types with
 			| td :: l ->
@@ -286,8 +289,11 @@ let handle_using ctx path p =
 	in
 	types,filter_classes
 
-let init_using ctx context_init path p =
+let init_using ctx path p =
 	let types,filter_classes = handle_using ctx path p in
 	(* do the import first *)
-	ctx.m.module_imports <- (List.map (fun t -> t,p) types) @ ctx.m.module_imports;
-	context_init#add (fun() -> ctx.m.module_using <- filter_classes types @ ctx.m.module_using)
+	List.iter (fun mt ->
+		ctx.m.import_resolution#add (module_type_resolution mt None p)
+	) (List.rev types);
+	(* delay the using since we need to resolve typedefs *)
+	delay_late ctx PConnectField (fun () -> ctx.m.module_using <- filter_classes types @ ctx.m.module_using)

+ 1 - 4
src/context/display/statistics.ml

@@ -1,12 +1,9 @@
 open Globals
-open Ast
 open Type
 open Common
 open Typecore
 open DisplayTypes
 
-open ImportHandling
-
 type relation =
 	| Implemented
 	| Extended
@@ -367,4 +364,4 @@ module Printer = struct
 			]) :: acc
 		) files [] in
 		string_of_json (JArray ja)
-end
+end

+ 9 - 7
src/context/memory.ml

@@ -1,5 +1,4 @@
 open Globals
-open CompilationCache
 open Common
 open Type
 open Genjson
@@ -34,12 +33,14 @@ let update_module_type_deps deps md =
 	) md.m_types;
 	!deps
 
-let rec scan_module_deps m h =
+let rec scan_module_deps cs m h =
 	if Hashtbl.mem h m.m_id then
 		()
 	else begin
 		Hashtbl.add h m.m_id m;
-		PMap.iter (fun _ m -> scan_module_deps m h) m.m_extra.m_deps
+		PMap.iter (fun _ (sign,mpath) ->
+			let m = (cs#get_context sign)#find_module mpath in
+			scan_module_deps cs m h) m.m_extra.m_deps
 	end
 
 let module_sign key md =
@@ -62,7 +63,7 @@ let get_out out =
 
 let get_module_memory cs all_modules m =
 	let mdeps = Hashtbl.create 0 in
-	scan_module_deps m mdeps;
+	scan_module_deps cs m mdeps;
 	let deps = ref [Obj.repr null_module] in
 	let out = ref all_modules in
 	let deps = Hashtbl.fold (fun _ md deps ->
@@ -273,8 +274,9 @@ let display_memory com =
 			());
 		if verbose then begin
 			print (Printf.sprintf "      %d total deps" (List.length deps));
-			PMap.iter (fun _ md ->
-				print (Printf.sprintf "      dep %s%s" (s_type_path md.m_path) (module_sign key md));
+			PMap.iter (fun _ (sign,mpath) ->
+				let md = (com.cs#get_context sign)#find_module mpath in
+				print (Printf.sprintf "      dep %s%s" (s_type_path mpath) (module_sign key md));
 			) m.m_extra.m_deps;
 		end;
 		flush stdout
@@ -283,4 +285,4 @@ let display_memory com =
 		if k1 = k2 then s1 - s2 else if k1 > k2 then 1 else -1
 	) modules);
 	if !mcount > 0 then print ("*** " ^ string_of_int !mcount ^ " modules have leaks !");
-	print "Cache dump complete"
+	print "Cache dump complete"

+ 1 - 2
src/context/nativeLibraries.ml

@@ -18,7 +18,6 @@
  *)
 
 open Globals
-open ExtString
 
 type native_lib_flags =
 	| FlagIsStd
@@ -54,4 +53,4 @@ let create_native_libs () = {
 	java_libs = [];
 	swf_libs = [];
 	all_libs = [];
-}
+}

+ 2 - 2
src/context/purityState.ml

@@ -29,12 +29,12 @@ let get_purity_from_meta meta =
 			| "true" | "inferredPure" -> Pure
 			| "false" -> Impure
 			| "expect" -> ExpectPure p
-			| _ -> typing_error ("Unsupported purity value " ^ s ^ ", expected true or false") p
+			| _ -> raise_typing_error ("Unsupported purity value " ^ s ^ ", expected true or false") p
 			end
 		| (_,[],_) ->
 			Pure
 		| (_,_,p) ->
-			typing_error "Unsupported purity value" p
+			raise_typing_error "Unsupported purity value" p
 		end
 	with Not_found ->
 		MaybePure

+ 248 - 0
src/context/resolution.ml

@@ -0,0 +1,248 @@
+open Globals
+open Type
+
+type resolution_kind =
+	| RTypeImport of string* module_type
+	| RClassFieldImport of string * tclass * tclass_field
+	| RAbstractFieldImport of string * tabstract * tclass * tclass_field
+	| REnumConstructorImport of string * tenum * tenum_field
+	| RWildcardPackage of string list
+	| RClassStatics of tclass
+	| REnumStatics of tenum
+	| RLazy of (unit -> resolution option)
+
+and resolution = {
+	r_kind : resolution_kind;
+	r_pos : pos;
+}
+
+let mk_resolution kind p = {
+	r_kind = kind;
+	r_pos = p;
+}
+
+let lazy_resolution f =
+	mk_resolution (RLazy f) null_pos
+
+let module_type_resolution mt alias p =
+	mk_resolution (RTypeImport((Option.default (t_name mt) alias),mt)) p
+
+let static_field_resolution c cf alias p =
+	mk_resolution (RClassFieldImport((Option.default cf.cf_name alias),c,cf)) p
+
+let static_abstract_field_resolution a c cf alias p =
+	mk_resolution (RAbstractFieldImport((Option.default cf.cf_name alias),a,c,cf)) p
+
+let enum_constructor_resolution en ef alias p =
+	mk_resolution (REnumConstructorImport((Option.default ef.ef_name alias),en,ef)) p
+
+let class_statics_resolution c p =
+	mk_resolution (RClassStatics c) p
+
+let enum_statics_resolution en p =
+	mk_resolution (REnumStatics en) p
+
+let wildcard_package_resolution sl p =
+	mk_resolution (RWildcardPackage sl) p
+
+let as_importable_static c cf p =
+	if not (has_meta Meta.NoImportGlobal cf.cf_meta) then begin match c.cl_kind with
+		| KAbstractImpl a ->
+			if a.a_enum && not (has_class_field_flag cf CfEnum) then
+				None
+			else
+				Some (cf.cf_name,static_abstract_field_resolution a c cf None p)
+		| _ ->
+			Some (cf.cf_name,static_field_resolution c cf None p)
+	end else
+		None
+
+let s_resolution_kind = function
+	| RTypeImport(_,mt) -> Printf.sprintf "RTypeImport(%s)" (s_type_path (t_infos mt).mt_path)
+	| RClassFieldImport(_,c,cf) -> Printf.sprintf "RClassFieldImport(%s, %s)" (s_type_path c.cl_path) cf.cf_name
+	| RAbstractFieldImport(_,a,c,cf) -> Printf.sprintf "RAbstractFieldImport(%s, %s)" (s_type_path a.a_path) cf.cf_name
+	| REnumConstructorImport(_,en,ef) -> Printf.sprintf "REnumConstructorImport(%s, %s)" (s_type_path en.e_path) ef.ef_name
+	| RWildcardPackage sl -> Printf.sprintf "RWildcardPackage(%s)" (String.concat "." sl)
+	| RClassStatics c -> Printf.sprintf "RClassStatics(%s)" (s_type_path c.cl_path)
+	| REnumStatics en -> Printf.sprintf "REnumStatics(%s)" (s_type_path en.e_path)
+	| RLazy _ -> "RLazy"
+
+class resolution_list (id : string list) = object(self)
+	val mutable l = []
+	val mutable resolved_lazies = true
+	val mutable cached_type_imports = true
+	val mutable type_import_cache = StringMap.empty
+
+	method add (res : resolution) =
+		l <- res :: l;
+		(* If we import a type, we automatically want to import all its constructors in case of
+		   enums and enum abstracts. We add a RLazy in front of the list so that it takes priority
+		   over the type itself. When resolved, it will insert its fields into the resolution list. *)
+		begin match res.r_kind with
+		| RTypeImport(_,mt) ->
+			Option.may (fun res -> l <- res :: l) (self#expand_enum_constructors mt);
+			cached_type_imports <- false;
+		| RLazy _ ->
+			resolved_lazies <- false;
+		| _ ->
+			()
+		end
+
+	method resolve_lazies =
+		let rec loop acc l = match l with
+			| {r_kind = RLazy f} :: l ->
+				begin match f() with
+				| None ->
+					loop acc l
+				| Some res ->
+					loop acc (res :: l)
+				end
+			| res :: l ->
+				loop (res :: acc) l
+			| [] ->
+				List.rev acc
+		in
+		if not resolved_lazies then begin
+			resolved_lazies <- true;
+			l <- loop [] l;
+		end
+
+	method resolve (i : string) : resolution =
+		self#resolve_lazies;
+		let rec loop l = match l with
+			| [] ->
+				raise Not_found
+			| res :: l ->
+				begin match res.r_kind with
+				| RClassStatics c ->
+					ignore(c.cl_build());
+					begin try
+						let cf = PMap.find i c.cl_statics in
+						begin match as_importable_static c cf res.r_pos with
+						| None ->
+							loop l
+						| Some(_,res) ->
+							res
+						end;
+					with Not_found ->
+						loop l
+					end
+				| REnumStatics en ->
+					begin try
+						let ef = PMap.find i en.e_constrs in
+						if not (has_meta Meta.NoImportGlobal ef.ef_meta) then
+							enum_constructor_resolution en ef None res.r_pos
+						else
+							loop l
+					with Not_found ->
+						loop l
+					end
+				| RTypeImport(alias,_) | RClassFieldImport(alias,_,_) | RAbstractFieldImport(alias,_,_,_) | REnumConstructorImport(alias,_,_) ->
+					if alias = i then
+						res
+					else
+						loop l
+				| RLazy _ | RWildcardPackage _ ->
+					loop l
+				end
+		in
+		loop l
+
+	method expand_enum_constructors (mt : module_type) = match mt with
+		| TAbstractDecl ({a_impl = Some c} as a) when a.a_enum ->
+			Some (class_statics_resolution c null_pos)
+		| TEnumDecl en ->
+			Some (enum_statics_resolution en null_pos)
+		| TTypeDecl t ->
+			let f () =
+				begin match follow t.t_type with
+					| TEnum (e,_) -> self#expand_enum_constructors (TEnumDecl e)
+					| TAbstract (a,_) when a.a_enum -> self#expand_enum_constructors (TAbstractDecl a)
+					| _ -> None
+				end
+			in
+			resolved_lazies <- false;
+			Some (lazy_resolution f)
+		| TClassDecl _ | TAbstractDecl _ ->
+			None
+
+	method save =
+		let l' = l in
+		let resolved_lazies' = resolved_lazies in
+		(fun () ->
+			l <- l';
+			resolved_lazies <- resolved_lazies';
+		)
+
+	method get_list =
+		l
+
+	method cache_type_imports =
+		let rec loop = function
+		| [] ->
+			()
+		| res :: l ->
+			(* loop first to retain correct order *)
+			loop l;
+			match res.r_kind with
+			| RTypeImport(alias,mt) ->
+				type_import_cache <- StringMap.add alias (mt,res.r_pos) type_import_cache;
+			| _ ->
+				()
+		in
+		if not cached_type_imports then begin
+			cached_type_imports <- true;
+			type_import_cache <- StringMap.empty;
+			loop l
+		end;
+
+	method find_type_import alias =
+		self#cache_type_imports;
+		StringMap.find alias type_import_cache
+
+	method find_type_import_weirdly pack name =
+		let rec find l = match l with
+			| [] ->
+				raise Not_found
+			| {r_kind = RTypeImport(alias,mt); r_pos = p} :: l ->
+				if  t_path mt = (pack,name) then (mt,p) else find l
+			| _ :: l ->
+				find l
+		in
+		find l
+
+	method extract_type_imports =
+		ExtList.List.filter_map (fun res -> match res.r_kind with
+			| RTypeImport(_,mt) ->
+				Some (mt,res.r_pos)
+			| _ ->
+				None
+		) l
+
+	method extract_field_imports =
+		self#resolve_lazies;
+		let l = List.fold_left (fun acc res -> match res.r_kind with
+			| RClassFieldImport(alias,c,cf) ->
+				PMap.add alias ((TClassDecl c),cf.cf_name,res.r_pos) acc
+			| RClassStatics c ->
+				List.fold_left (fun acc cf ->
+					begin match as_importable_static c cf null_pos with
+					| Some (alias,res) ->
+						PMap.add alias ((TClassDecl c),cf.cf_name,res.r_pos) acc
+					| _ ->
+						acc
+					end
+				) acc c.cl_ordered_statics
+			| _ ->
+				acc
+		) PMap.empty l in
+		l
+
+	method extract_wildcard_packages =
+		ExtList.List.filter_map (fun res -> match res.r_kind with
+			| RWildcardPackage sl ->
+				Some (sl,res.r_pos)
+			| _ ->
+				None
+		) l
+end

+ 1 - 3
src/context/sourcemaps.ml

@@ -1,7 +1,5 @@
 open Extlib_leftovers
 open Globals
-open Ast
-open Lexer
 open Common
 
 (**
@@ -299,4 +297,4 @@ let set_sourcemap_pointer (builder:sourcemap_builder option) (pointer:sm_node op
 		| Some builder ->
 			match pointer with
 				| Some node -> builder#seek node
-				| None -> ()
+				| None -> ()

+ 126 - 81
src/context/typecore.ml

@@ -22,7 +22,7 @@ open Ast
 open Common
 open Type
 open Error
-open DisplayTypes
+open Resolution
 
 type type_patch = {
 	mutable tp_type : complex_type option;
@@ -60,15 +60,20 @@ type typer_pass =
 
 type typer_module = {
 	curmod : module_def;
-	mutable module_imports : (module_type * pos) list;
+	import_resolution : resolution_list;
+	mutable own_resolution : resolution_list option;
+	mutable enum_with_type : module_type option;
 	mutable module_using : (tclass * pos) list;
-	mutable module_globals : (string, (module_type * string * pos)) PMap.t;
-	mutable wildcard_packages : (string list * pos) list;
 	mutable import_statements : import list;
 }
 
+type delay = {
+	delay_pass : typer_pass;
+	delay_functions : (unit -> unit) list;
+}
+
 type typer_globals = {
-	mutable delayed : (typer_pass * (unit -> unit) list) list;
+	mutable delayed : delay list;
 	mutable debug_delayed : (typer_pass * ((unit -> unit) * string * typer) list) list;
 	doinline : bool;
 	retain_meta : bool;
@@ -76,7 +81,6 @@ type typer_globals = {
 	mutable macros : ((unit -> unit) * typer) option;
 	mutable std : module_def;
 	type_patches : (path, (string * bool, type_patch) Hashtbl.t * type_patch) Hashtbl.t;
-	mutable global_metadata : (string list * metadata_entry * (bool * bool * bool)) list;
 	mutable module_check_policies : (string list * module_check_policy list * bool) list;
 	mutable global_using : (tclass * pos) list;
 	(* Indicates that Typer.create() finished building this instance *)
@@ -86,7 +90,6 @@ type typer_globals = {
 	functional_interface_lut : (path,tclass_field) lookup;
 	(* api *)
 	do_inherit : typer -> Type.tclass -> pos -> (bool * placed_type_path) -> bool;
-	do_create : Common.context -> typer;
 	do_macro : typer -> macro_mode -> path -> string -> expr list -> pos -> expr option;
 	do_load_macro : typer -> bool -> path -> string -> pos -> ((string * bool * t) list * t * tclass * Type.tclass_field);
 	do_load_module : typer -> path -> pos -> module_def;
@@ -199,7 +202,7 @@ type dot_path_part = {
 
 exception Forbid_package of (string * path * pos) * pos list * string
 
-exception WithTypeError of error_msg * pos * int (* depth *)
+exception WithTypeError of error
 
 let memory_marker = [|Unix.time()|]
 
@@ -214,6 +217,8 @@ let analyzer_run_on_expr_ref : (Common.context -> string -> texpr -> texpr) ref
 let cast_or_unify_raise_ref : (typer -> ?uctx:unification_context option -> Type.t -> texpr -> pos -> texpr) ref = ref (fun _ ?uctx _ _ _ -> assert false)
 let type_generic_function_ref : (typer -> field_access -> (unit -> texpr) field_call_candidate -> WithType.t -> pos -> texpr) ref = ref (fun _ _ _ _ _ -> assert false)
 
+let create_context_ref : (Common.context -> ((unit -> unit) * typer) option -> typer) ref = ref (fun _ -> assert false)
+
 let pass_name = function
 	| PBuildModule -> "build-module"
 	| PBuildClass -> "build-class"
@@ -229,6 +234,24 @@ let warning ?(depth=0) ctx w msg p =
 
 let make_call ctx e el t p = (!make_call_ref) ctx e el t p
 
+let make_static_call_gen ctx c cf el map p =
+	let monos = Monomorph.spawn_constrained_monos map cf.cf_params in
+	let t = map (apply_params cf.cf_params monos cf.cf_type) in
+	match follow t with
+	| TFun(args,ret) ->
+		let ethis = Texpr.Builder.make_static_this c p in
+		let ef = mk (TField(ethis,FStatic(c,cf))) t p in
+		make_call ctx ef el ret p
+	| t ->
+		raise_typing_error (s_type (print_context()) t ^ " cannot be called") p
+
+let make_static_class_call ctx c cf el p =
+	make_static_call_gen ctx c cf el (fun t -> t) p
+
+let make_static_abstract_call ctx a tl c cf el p =
+	let map = apply_params a.a_params tl in
+	make_static_call_gen ctx c cf el map p
+
 let type_expr ?(mode=MGet) ctx e with_type = (!type_expr_ref) ~mode ctx e with_type
 
 let unify_min ctx el = (!unify_min_ref) ctx el
@@ -242,27 +265,21 @@ let spawn_monomorph' ctx p =
 let spawn_monomorph ctx p =
 	TMono (spawn_monomorph' ctx p)
 
-let make_static_this c p =
-	let ta = mk_anon ~fields:c.cl_statics (ref (Statics c)) in
-	mk (TTypeExpr (TClassDecl c)) ta p
-
-let make_static_field_access c cf t p =
-	let ethis = make_static_this c p in
-	mk (TField (ethis,(FStatic (c,cf)))) t p
-
-let make_static_call ctx c cf map args t p =
-	let monos = List.map (fun _ -> spawn_monomorph ctx p) cf.cf_params in
-	let map t = map (apply_params cf.cf_params monos t) in
-	let ef = make_static_field_access c cf (map cf.cf_type) p in
-	make_call ctx ef args (map t) p
+let raise_with_type_error ?(depth = 0) msg p =
+	raise (WithTypeError (make_error ~depth (Custom msg) p))
 
 let raise_or_display ctx l p =
 	if ctx.untyped then ()
-	else if ctx.in_call_args then raise (WithTypeError(Unify l,p,0))
-	else located_display_error ctx.com (error_msg p (Unify l))
+	else if ctx.in_call_args then raise (WithTypeError (make_error (Unify l) p))
+	else display_error_ext ctx.com (make_error (Unify l) p)
+
+let raise_or_display_error ctx err =
+	if ctx.untyped then ()
+	else if ctx.in_call_args then raise (WithTypeError err)
+	else display_error_ext ctx.com err
 
 let raise_or_display_message ctx msg p =
-	if ctx.in_call_args then raise (WithTypeError (Custom msg,p,0))
+	if ctx.in_call_args then raise_with_type_error msg p
 	else display_error ctx.com msg p
 
 let unify ctx t1 t2 p =
@@ -278,7 +295,7 @@ let unify_raise_custom uctx t1 t2 p =
 	with
 		Unify_error l ->
 			(* no untyped check *)
-			raise (Error (Unify l,p,0))
+			raise_error_msg (Unify l) p
 
 let unify_raise = unify_raise_custom default_unification_context
 
@@ -336,8 +353,11 @@ let check_module_path ctx (pack,name) p =
 	try
 		List.iter (fun part -> Path.check_package_name part) pack;
 	with Failure msg ->
-		display_error ctx.com ("\"" ^ (StringHelper.s_escape (String.concat "." pack)) ^ "\" is not a valid package name:") p;
-		display_error ctx.com msg p
+		display_error_ext ctx.com (make_error
+			~sub:[make_error (Custom msg) p]
+			(Custom ("\"" ^ (StringHelper.s_escape (String.concat "." pack)) ^ "\" is not a valid package name:"))
+			p
+		)
 
 let check_local_variable_name ctx name origin p =
 	match name with
@@ -361,32 +381,42 @@ let add_local_with_origin ctx origin n t p =
 let gen_local_prefix = "`"
 
 let gen_local ctx t p =
-	add_local ctx VGenerated "`" t p
+	add_local ctx VGenerated gen_local_prefix t p
 
-let is_gen_local v =
-	String.unsafe_get v.v_name 0 = String.unsafe_get gen_local_prefix 0
+let is_gen_local v = match v.v_kind with
+	| VGenerated ->
+		true
+	| _ ->
+		false
+
+let make_delay pass fl = {
+	delay_pass = pass;
+	delay_functions = fl;
+}
 
 let delay ctx p f =
 	let rec loop = function
-		| [] -> [p,[f]]
-		| (p2,l) :: rest ->
-			if p2 = p then
-				(p, f :: l) :: rest
-			else if p2 < p then
-				(p2,l) :: loop rest
+		| [] ->
+			[make_delay p [f]]
+		| delay :: rest ->
+			if delay.delay_pass = p then
+				(make_delay p (f :: delay.delay_functions)) :: rest
+			else if delay.delay_pass < p then
+				delay :: loop rest
 			else
-				(p,[f]) :: (p2,l) :: rest
+				(make_delay p [f]) :: delay :: rest
 	in
 	ctx.g.delayed <- loop ctx.g.delayed
 
 let delay_late ctx p f =
 	let rec loop = function
-		| [] -> [p,[f]]
-		| (p2,l) :: rest ->
-			if p2 <= p then
-				(p2,l) :: loop rest
+		| [] ->
+			[make_delay p [f]]
+		| delay :: rest ->
+			if delay.delay_pass <= p then
+				delay :: loop rest
 			else
-				(p,[f]) :: (p2,l) :: rest
+				(make_delay p [f]) :: delay :: rest
 	in
 	ctx.g.delayed <- loop ctx.g.delayed
 
@@ -398,12 +428,12 @@ let delay_if_mono ctx p t f = match follow t with
 
 let rec flush_pass ctx p (where:string) =
 	match ctx.g.delayed with
-	| (p2,l) :: rest when p2 <= p ->
-		(match l with
+	| delay :: rest when delay.delay_pass <= p ->
+		(match delay.delay_functions with
 		| [] ->
 			ctx.g.delayed <- rest;
 		| f :: l ->
-			ctx.g.delayed <- (p2,l) :: rest;
+			ctx.g.delayed <- (make_delay delay.delay_pass l) :: rest;
 			f());
 		flush_pass ctx p where
 	| _ ->
@@ -422,8 +452,8 @@ let exc_protect ?(force=true) ctx f (where:string) =
 			r := lazy_available t;
 			t
 		with
-			| Error (m,p,depth) ->
-				raise (Fatal_error ((error_msg p m),depth))
+			| Error e ->
+				raise (Fatal_error e)
 	);
 	if force then delay ctx PForce (fun () -> ignore(lazy_type r));
 	r
@@ -455,8 +485,18 @@ let is_removable_field com f =
 			| _ -> false)
 	)
 
+let is_forced_inline c cf =
+	match c with
+	| Some { cl_kind = KAbstractImpl _ } -> true
+	| Some c when has_class_flag c CExtern -> true
+	| _ when has_class_field_flag cf CfExtern -> true
+	| _ -> false
+
+let needs_inline ctx c cf =
+	cf.cf_kind = Method MethInline && ctx.allow_inline && (ctx.g.doinline || is_forced_inline c cf)
+
 (** checks if we can access to a given class field using current context *)
-let rec can_access ctx c cf stat =
+let can_access ctx c cf stat =
 	if (has_class_field_flag cf CfPublic) then
 		true
 	else if c == ctx.curclass then
@@ -592,7 +632,7 @@ let merge_core_doc ctx mt =
 
 let field_to_type_path com e =
 	let rec loop e pack name = match e with
-		| EField(e,f,_),p when Char.lowercase (String.get f 0) <> String.get f 0 -> (match name with
+		| EField(e,f,_),p when Char.lowercase_ascii (String.get f 0) <> String.get f 0 -> (match name with
 			| [] | _ :: [] ->
 				loop e pack (f :: name)
 			| _ -> (* too many name paths *)
@@ -604,7 +644,7 @@ let field_to_type_path com e =
 			let pack, name, sub = match name with
 				| [] ->
 					let fchar = String.get f 0 in
-					if Char.uppercase fchar = fchar then
+					if Char.uppercase_ascii fchar = fchar then
 						pack, f, None
 					else begin
 						display_error com "A class name must start with an uppercase letter" (snd e);
@@ -654,12 +694,12 @@ let s_field_call_candidate fcc =
 let relative_path ctx file =
 	let slashes path = String.concat "/" (ExtString.String.nsplit path "\\") in
 	let fpath = slashes (Path.get_full_path file) in
-	let fpath_lower = String.lowercase fpath in
+	let fpath_lower = String.lowercase_ascii fpath in
 	let flen = String.length fpath_lower in
 	let rec loop = function
 		| [] -> file
 		| path :: l ->
-			let spath = String.lowercase (slashes path) in
+			let spath = String.lowercase_ascii (slashes path) in
 			let slen = String.length spath in
 			if slen > 0 && slen < flen && String.sub fpath_lower 0 slen = spath then String.sub fpath slen (flen - slen) else loop l
 	in
@@ -703,14 +743,13 @@ let get_next_stored_typed_expr_id =
 	let uid = ref 0 in
 	(fun() -> incr uid; !uid)
 
-let get_stored_typed_expr com id =
-	let e = com.stored_typed_exprs#find id in
-	Texpr.duplicate_tvars e
+let make_stored_id_expr id p =
+	(EConst (Int (string_of_int id, None))), p
 
 let store_typed_expr com te p =
 	let id = get_next_stored_typed_expr_id() in
 	com.stored_typed_exprs#add id te;
-	let eid = (EConst (Int (string_of_int id, None))), p in
+	let eid = make_stored_id_expr id p in
 	id,((EMeta ((Meta.StoredTypedExpr,[],null_pos), eid)),p)
 
 let push_this ctx e = match e.eexpr with
@@ -720,29 +759,35 @@ let push_this ctx e = match e.eexpr with
 	let id,er = store_typed_expr ctx.com e e.epos in
 	er,fun () -> ctx.com.stored_typed_exprs#remove id
 
+let create_deprecation_context ctx = {
+	(DeprecationCheck.create_context ctx.com) with
+	class_meta = ctx.curclass.cl_meta;
+	field_meta = ctx.curfield.cf_meta;
+}
+
 (* -------------- debug functions to activate when debugging typer passes ------------------------------- *)
 (*/*
 
 let delay_tabs = ref ""
 
-let context_ident ctx =
-	if Common.defined ctx.com Common.Define.CoreApi then
+let context_ident com =
+	if Common.defined com Common.Define.CoreApi then
 		" core "
-	else if Common.defined ctx.com Common.Define.Macro then
+	else if Common.defined com Common.Define.Macro then
 		"macro "
 	else
 		"  out "
 
-let debug ctx str =
-	if Common.raw_defined ctx.com "cdebug" then begin
-		let s = (context_ident ctx ^ string_of_int (String.length !delay_tabs) ^ " " ^ !delay_tabs ^ str) in
-		match ctx.com.json_out with
+let debug com str =
+	if Common.raw_defined com "cdebug" then begin
+		let s = (context_ident com ^ string_of_int (String.length !delay_tabs) ^ " " ^ !delay_tabs ^ str) in
+		match com.json_out with
 		| None -> print_endline s
-		| Some _ -> DynArray.add ctx.com.pass_debug_messages s
+		| Some _ -> DynArray.add com.pass_debug_messages s
 	end
 
 let init_class_done ctx =
-	debug ctx ("init_class_done " ^ s_type_path ctx.curclass.cl_path);
+	debug ctx.com ("init_class_done " ^ s_type_path ctx.curclass.cl_path);
 	init_class_done ctx
 
 let ctx_pos ctx =
@@ -769,7 +814,7 @@ let delay ctx p f =
 				(p,[f,inf,ctx]) :: (p2,l) :: rest
 	in
 	ctx.g.debug_delayed <- loop ctx.g.debug_delayed;
-	debug ctx ("add " ^ inf)
+	debug ctx.com ("add " ^ inf)
 
 let delay_late ctx p f =
 	let inf = pass_infos ctx p in
@@ -782,7 +827,7 @@ let delay_late ctx p f =
 				(p,[f,inf,ctx]) :: (p2,l) :: rest
 	in
 	ctx.g.debug_delayed <- loop ctx.g.debug_delayed;
-	debug ctx ("add late " ^ inf)
+	debug ctx.com ("add late " ^ inf)
 
 let pending_passes ctx =
 	let rec loop acc = function
@@ -793,28 +838,28 @@ let pending_passes ctx =
 	| [] -> ""
 	| l -> " ??PENDING[" ^ String.concat ";" (List.map (fun (_,i,_) -> i) l) ^ "]"
 
-let display_error ctx.com msg p =
-	debug ctx ("ERROR " ^ msg);
-	display_error ctx.com msg p
+let display_error com ?(depth=0) msg p =
+	debug com ("ERROR " ^ msg);
+	display_error com ~depth msg p
 
-let located_display_error ctx.com msg =
-	debug ctx ("ERROR " ^ msg);
-	located_display_error ctx.com msg
+let display_error_ext com err =
+	debug com ("ERROR " ^ (error_msg err.err_message));
+	display_error_ext com err
 
 let make_pass ?inf ctx f =
 	let inf = (match inf with None -> pass_infos ctx ctx.pass | Some inf -> inf) in
 	(fun v ->
-		debug ctx ("run " ^ inf ^ pending_passes ctx);
+		debug ctx.com ("run " ^ inf ^ pending_passes ctx);
 		let old = !delay_tabs in
 		delay_tabs := !delay_tabs ^ "\t";
 		let t = (try
 			f v
 		with
-			| Fatal_error (e,p) ->
+			| Fatal_error _ as exc ->
 				delay_tabs := old;
-				raise (Fatal_error (e,p))
+				raise exc
 			| exc when not (Common.raw_defined ctx.com "stack") ->
-				debug ctx ("FATAL " ^ Printexc.to_string exc);
+				debug ctx.com ("FATAL " ^ Printexc.to_string exc);
 				delay_tabs := old;
 				raise exc
 		) in
@@ -841,11 +886,11 @@ let rec flush_pass ctx p where =
 	match ctx.g.debug_delayed with
 	| (p2,_) :: _ when p2 <= p ->
 		let old = !delay_tabs in
-		debug ctx ("flush " ^ pass_name p ^ "(" ^ where ^ ")");
+		debug ctx.com ("flush " ^ pass_name p ^ "(" ^ where ^ ")");
 		delay_tabs := !delay_tabs ^ "\t";
 		loop();
 		delay_tabs := old;
-		debug ctx "flush-done";
+		debug ctx.com "flush-done";
 	| _ ->
 		()
 
@@ -860,8 +905,8 @@ let exc_protect ?(force=true) ctx f (where:string) =
 			r := lazy_available t;
 			t
 		with
-			| Error (m,p,depth) ->
-				raise (Fatal_error ((error_msg m),p,depth))
+			| Error e ->
+				raise (Fatal_error e)
 	));
 	if force then delay ctx PForce (fun () -> ignore(lazy_type r));
 	r

+ 2 - 4
src/core/abstract.ml

@@ -1,6 +1,4 @@
-open Globals
 open Ast
-open Meta
 open TType
 open TFunctions
 open TPrinting
@@ -83,7 +81,7 @@ let rec find_multitype_params a pl =
 				| EMeta((Meta.Custom ":followWithAbstracts",_,_),e1) ->
 					loop follow_with_abstracts e1;
 				| _ ->
-					typing_error "Type parameter expected" (pos e)
+					raise_typing_error "Type parameter expected" (pos e)
 			in
 			loop (fun t -> t) e
 		) el;
@@ -124,7 +122,7 @@ and get_underlying_type ?(return_first=false) a pl =
 				if rec_stack_exists (fast_eq t) underlying_type_stack then begin
 					let pctx = print_context() in
 					let s = String.concat " -> " (List.map (fun t -> s_type pctx t) (List.rev (t :: underlying_type_stack.rec_stack))) in
-					typing_error ("Abstract chain detected: " ^ s) a.a_pos
+					raise_typing_error ("Abstract chain detected: " ^ s) a.a_pos
 				end;
 				get_underlying_type a tl
 			| _ ->

+ 5 - 5
src/core/ast.ml

@@ -300,6 +300,7 @@ and access =
 	| AExtern
 	| AAbstract
 	| AOverload
+	| AEnum
 
 and placed_access = access * pos
 
@@ -440,7 +441,7 @@ let gen_doc_text_opt = Option.map gen_doc_text
 
 let get_own_doc_opt = Option.map_default (fun d -> d.doc_own) None
 
-let rec is_postfix (e,_) op = match op with
+let is_postfix (e,_) op = match op with
 	| Increment | Decrement | Not -> true
 	| Neg | NegBits | Spread -> false
 
@@ -491,6 +492,7 @@ let s_access = function
 	| AExtern -> "extern"
 	| AAbstract -> "abstract"
 	| AOverload -> "overload"
+	| AEnum -> "enum"
 
 let s_placed_access (a,_) = s_access a
 
@@ -1205,7 +1207,7 @@ module Expr = struct
 		Buffer.contents buf
 
 	let find_ident e =
-		let rec loop e = match fst e with
+		match fst e with
 			| EConst ct ->
 				begin match ct with
 				| Ident s ->
@@ -1215,8 +1217,6 @@ module Expr = struct
 				end
 			| _ ->
 				None
-		in
-		loop e
 end
 
 let has_meta_option metas meta s =
@@ -1258,4 +1258,4 @@ let get_meta_string meta key =
 		| (k,[EConst (String(name,_)),_],_) :: _ when k = key -> Some name
 		| _ :: l -> loop l
 	in
-	loop meta
+	loop meta

+ 8 - 2
src/core/define.ml

@@ -39,6 +39,7 @@ let get_documentation user_defines d =
 		| HasParam s -> params := s :: !params
 		| Platforms fl -> pfs := fl @ !pfs
 		| Link _ -> ()
+		| Deprecated _ -> ()
 	) flags;
 	let params = (match List.rev !params with
 		| [] -> ""
@@ -117,7 +118,7 @@ let get_signature def =
 			   Note that we should removed flags like use_rtti_doc here.
 			*)
 			| "display" | "use_rtti_doc" | "macro_times" | "display_details" | "no_copt" | "display_stdin"
-			| "message_reporting" | "messages_log_file" | "messages_log_format" | "no_color"
+			| "message.reporting" | "message.log_file" | "message.log_format" | "message.no_color"
 			| "dump" | "dump_dependencies" | "dump_ignore_var_ids" -> acc
 			| _ -> (k ^ "=" ^ v) :: acc
 		) def.values [] in
@@ -126,4 +127,9 @@ let get_signature def =
 		def.defines_signature <- Some s;
 		s
 
-let is_haxe3_compat def = raw_defined def "hx3compat"
+let deprecation_lut =
+	let h = Hashtbl.create 0 in
+	List.iter (fun (name,reason) ->
+		Hashtbl.add h name reason
+	) deprecated_defines;
+	h

+ 6 - 4
src/core/displayTypes.ml

@@ -1,8 +1,6 @@
 open Globals
-open Path
 open Ast
 open Type
-open Json
 open Genjson
 
 module SymbolKind = struct
@@ -198,6 +196,7 @@ module DisplayMode = struct
 		dms_inline : bool;
 		dms_display_file_policy : display_file_policy;
 		dms_exit_during_typing : bool;
+		dms_populate_cache : bool;
 		dms_per_file : bool;
 	}
 
@@ -210,6 +209,7 @@ module DisplayMode = struct
 		dms_inline = false;
 		dms_display_file_policy = DFPOnly;
 		dms_exit_during_typing = true;
+		dms_populate_cache = false;
 		dms_per_file = false;
 	}
 
@@ -222,6 +222,7 @@ module DisplayMode = struct
 		dms_inline = true;
 		dms_display_file_policy = DFPNo;
 		dms_exit_during_typing = false;
+		dms_populate_cache = true;
 		dms_per_file = false;
 	}
 
@@ -232,6 +233,7 @@ module DisplayMode = struct
 		| DMDefault | DMDefinition | DMTypeDefinition | DMPackage | DMHover | DMSignature -> settings
 		| DMUsage _ | DMImplementation -> { settings with
 				dms_full_typing = true;
+				dms_populate_cache = !ServerConfig.populate_cache_from_display;
 				dms_force_macro_typing = true;
 				dms_display_file_policy = DFPAlso;
 				dms_exit_during_typing = false
@@ -332,7 +334,7 @@ type diagnostics_context = {
 	mutable import_positions : (pos,bool ref) PMap.t;
 	mutable dead_blocks : (Path.UniqueKey.t,(pos * expr) list) Hashtbl.t;
 	mutable unresolved_identifiers : (string * pos * (string * CompletionItem.t * int) list) list;
-	mutable diagnostics_messages : (string * pos * MessageKind.t * MessageSeverity.t * int (* depth *)) list;
+	mutable diagnostics_messages : diagnostic list;
 	mutable missing_fields : (pos,(module_type * (missing_fields_diagnostics list ref))) PMap.t;
 }
 
@@ -344,4 +346,4 @@ type display_exception_kind =
 	| DisplayPositions of pos list
 	| DisplayFields of fields_result
 	| DisplayPackage of string list
-	| DisplayNoResult
+	| DisplayNoResult

+ 51 - 35
src/core/error.ml

@@ -17,7 +17,6 @@ and error_msg =
 	| Unify of unify_error list
 	| Custom of string
 	| Unknown_ident of string
-	| Stack of (error_msg * Globals.pos) list
 	| Call_error of call_error
 	| No_constructor of module_type
 	| Abstract_class of module_type
@@ -26,8 +25,31 @@ and type_not_found_reason =
 	| Private_type
 	| Not_defined
 
-exception Fatal_error of Globals.located * int (* depth *)
-exception Error of error_msg * Globals.pos * int (* depth *)
+type error = {
+	err_message : error_msg;
+	err_pos : pos;
+	(* TODO Should probably be deprecated at some point and be derived from err_sub *)
+	err_depth : int;
+	(* Reverse list of sub errors. Use Error.recurse_error to handle an error and its sub errors with depth. *)
+	err_sub : error list;
+	err_from_macro : bool;
+}
+
+let make_error ?(depth = 0) ?(from_macro = false) ?(sub = []) msg p = {
+	err_message = msg;
+	err_pos = p;
+	err_depth = depth;
+	err_from_macro = from_macro;
+	err_sub = sub;
+}
+
+let rec recurse_error ?(depth = 0) cb err =
+	let depth = if depth > 0 then depth else err.err_depth in
+	cb depth err;
+	List.iter (recurse_error ~depth:(depth+1) cb) (List.rev err.err_sub);
+
+exception Fatal_error of error
+exception Error of error
 
 let string_source t = match follow t with
 	| TInst(c,tl) -> PMap.foldi (fun s _ acc -> s :: acc) (TClass.get_all_fields c tl) []
@@ -43,9 +65,6 @@ let short_type ctx t =
 	Should be called for each complementary error message.
 *)
 let compl_msg s = "... " ^ s
-let rec compl_located_msg = function
-	 | Message (s,p) -> Message (compl_msg s,p)
-	 | Stack stack -> Stack (List.map compl_located_msg stack)
 
 let unify_error_msg ctx err = match err with
 	| Cannot_unify (t1,t2) ->
@@ -191,7 +210,7 @@ module BetterErrors = struct
 		| TAnon a ->
 			begin
 				match !(a.a_status) with
-				| Statics c -> Printf.sprintf "{ Statics %s }" (s_type_path c.cl_path)
+				| ClassStatics c -> Printf.sprintf "{ ClassStatics %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)
 				| _ ->
@@ -256,7 +275,7 @@ module BetterErrors = struct
 				let s1,s2 = loop() in
 				Printf.sprintf "(...) -> %s" s1,Printf.sprintf "(...) -> %s" s2
 			| TypeParameter i ->
-				let rec get_params t = match t with
+				let get_params t = match t with
 					| TInst({cl_path = path},params) | TEnum({e_path = path},params) | TAbstract({a_path = path},params) | TType({t_path = path},params) ->
 						path,params
 					| _ ->
@@ -280,39 +299,36 @@ module BetterErrors = struct
 			Printf.sprintf "error: %s\nhave: %s\nwant: %s" (Buffer.contents message_buffer) slhs srhs
 end
 
-let rec error_msg p = function
-	| Module_not_found m -> located ("Type not found : " ^ s_type_path m) p
-	| Type_not_found (m,t,Private_type) -> located ("Cannot access private type " ^ t ^ " in module " ^ s_type_path m) p
-	| Type_not_found (m,t,Not_defined) -> located ("Module " ^ s_type_path m ^ " does not define type " ^ t) p
-	| Unify l -> located (BetterErrors.better_error_message l) p
-	| Unknown_ident s -> located ("Unknown identifier : " ^ s) p
-	| Custom s -> located s p
-	| Stack stack -> located_stack (List.map (fun (e,p) -> error_msg p e) stack)
-	| Call_error err -> s_call_error p err
-	| No_constructor mt -> located (s_type_path (t_infos mt).mt_path ^ " does not have a constructor") p
-	| Abstract_class mt -> located (s_type_path (t_infos mt).mt_path ^ " is abstract and cannot be constructed") p
+let rec error_msg = function
+	| Module_not_found m -> "Type not found : " ^ s_type_path m
+	| Type_not_found (m,t,Private_type) -> "Cannot access private type " ^ t ^ " in module " ^ s_type_path m
+	| Type_not_found (m,t,Not_defined) -> "Module " ^ s_type_path m ^ " does not define type " ^ t
+	| Unify l -> BetterErrors.better_error_message l
+	| Unknown_ident s -> "Unknown identifier : " ^ s
+	| Custom s -> s
+	| Call_error err -> s_call_error err
+	| No_constructor mt -> s_type_path (t_infos mt).mt_path ^ " does not have a constructor"
+	| Abstract_class mt -> s_type_path (t_infos mt).mt_path ^ " is abstract and cannot be constructed"
 
-and s_call_error p = function
+and s_call_error = function
 	| Not_enough_arguments tl ->
 		let pctx = print_context() in
-		located ("Not enough arguments, expected " ^ (String.concat ", " (List.map (fun (n,_,t) -> n ^ ":" ^ (short_type pctx t)) tl))) p
-	| Too_many_arguments -> located "Too many arguments" p
-	| Could_not_unify err -> error_msg p err
-	| Cannot_skip_non_nullable s -> located ("Cannot skip non-nullable argument " ^ s) p
+		"Not enough arguments, expected " ^ (String.concat ", " (List.map (fun (n,_,t) -> n ^ ":" ^ (short_type pctx t)) tl))
+	| Too_many_arguments -> "Too many arguments"
+	| Could_not_unify err -> error_msg err
+	| Cannot_skip_non_nullable s -> "Cannot skip non-nullable argument " ^ s
 
-let typing_error ?(depth=0) msg p = raise (Error (Custom msg,p,depth))
-let located_typing_error ?(depth=0) msg =
-	let err = match msg with
-		| Message (msg,p) -> Custom msg
-		| Stack _ -> Stack (List.map (fun (msg,p) -> (Custom msg,p)) (extract_located msg))
-	in
-	raise (Error (err,(extract_located_pos msg),depth))
+(* Global error helpers *)
+let raise_error err = raise (Error err)
+let raise_error_msg ?(depth = 0) msg p = raise_error (make_error ~depth msg p)
+let raise_msg ?(depth = 0) msg p = raise_error_msg ~depth (Custom msg) p
 
-let raise_typing_error ?(depth=0) err p = raise (Error(err,p,depth))
+let raise_typing_error ?(depth = 0) msg p = raise_msg ~depth msg p
+let raise_typing_error_ext err = raise_error err
 
 let error_require r p =
 	if r = "" then
-		typing_error "This field is not available with the current compilation flags" p
+		raise_typing_error "This field is not available with the current compilation flags" p
 	else
 	let r = if r = "sys" then
 		"a system platform (php,neko,cpp,etc.)"
@@ -323,6 +339,6 @@ let error_require r p =
 	with _ ->
 		"'" ^ r ^ "' to be enabled"
 	in
-	typing_error ("Accessing this field requires " ^ r) p
+	raise_typing_error ("Accessing this field requires " ^ r) p
 
-let invalid_assign p = typing_error "Invalid assign" p
+let invalid_assign p = raise_typing_error "Invalid assign" p

+ 68 - 29
src/core/globals.ml

@@ -5,11 +5,8 @@ type pos = {
 }
 
 type path = string list * string
-type located =
-	| Message of string * pos
-	| Stack of located list
 
-module IntMap = Ptmap
+module IntMap = Map.Make(struct type t = int let compare i1 i2 = i2 - i1 end)
 module StringMap = Map.Make(struct type t = string let compare = String.compare end)
 module Int32Map = Map.Make(struct type t = Int32.t let compare = Int32.compare end)
 
@@ -25,31 +22,50 @@ type platform =
 	| Python
 	| Hl
 	| Eval
+	| CustomTarget of string
 
-let version = 4300
+let version = 5000
 let version_major = version / 1000
 let version_minor = (version mod 1000) / 100
 let version_revision = (version mod 100)
-let version_pre = None
+let version_pre = Some "alpha.1"
 
 let null_pos = { pfile = "?"; pmin = -1; pmax = -1 }
 
-let located msg p = Message (msg,p)
-let located_stack stack = Stack stack
-
-let rec extract_located = function
-	| Message (msg,p) -> [(msg, p)]
-	| Stack stack -> List.fold_left (fun acc s -> acc @ (extract_located s)) [] stack
-
-let rec relocate msg p = match msg with
-	| Message (msg,_) -> Message (msg,p)
-	| Stack [] -> Stack []
-	| Stack (hd :: tl) -> Stack ((relocate hd p) :: tl)
-
-let rec extract_located_pos = function
-	| Message (_,p) -> p
-	| Stack [] -> null_pos
-	| Stack (hd :: _) -> extract_located_pos hd
+let no_color = false
+let c_reset = if no_color then "" else "\x1b[0m"
+let c_dim = if no_color then "" else "\x1b[2m"
+
+let loc_short (loc:Printexc.location) =
+	Printf.sprintf "%s:%d" loc.filename loc.line_number
+
+let loc_to_string (loc:Printexc.location) =
+	Printf.sprintf "%s, line %d, characters %d-%d" loc.filename loc.line_number loc.start_char loc.end_char
+
+let trace s =
+	let stack = Printexc.get_callstack 2 in
+	match Printexc.backtrace_slots stack with
+	| Some [|_; item |] ->
+		(match Printexc.Slot.location item with
+		| Some loc -> print_endline (Printf.sprintf "%s%s:%s %s" c_dim (loc_short loc) c_reset s)
+		| _ -> ())
+	| _ ->
+		()
+
+let trace_call_stack ?(n:int = 5) () =
+	assert (n >= 0);
+	let stack = Printexc.get_callstack (n+2) in
+	let len = Printexc.raw_backtrace_length stack - 1 in
+
+	let slot = Printexc.convert_raw_backtrace_slot (Printexc.get_raw_backtrace_slot stack 1) in
+	let loc = Printexc.Slot.location slot in
+	Option.may (fun loc -> print_endline (Printf.sprintf "%s%s:%s" c_dim (loc_short loc) c_reset)) loc;
+
+	for i = 2 to len do
+		let slot = Printexc.convert_raw_backtrace_slot (Printexc.get_raw_backtrace_slot stack i) in
+		let loc = Printexc.Slot.location slot in
+		Option.may (fun loc -> print_endline (Printf.sprintf "  called from %s" (loc_to_string loc))) loc;
+	done
 
 let macro_platform = ref Neko
 
@@ -57,6 +73,8 @@ let return_partial_type = ref false
 
 let is_windows = Sys.os_type = "Win32" || Sys.os_type = "Cygwin"
 
+let max_custom_target_len = 16
+
 let platforms = [
 	Js;
 	Lua;
@@ -83,6 +101,7 @@ let platform_name = function
 	| Python -> "python"
 	| Hl -> "hl"
 	| Eval -> "eval"
+	| CustomTarget c -> c
 
 let parse_platform = function
 	| "cross" -> Cross
@@ -96,7 +115,7 @@ let parse_platform = function
 	| "python" -> Python
 	| "hl" -> Hl
 	| "eval" -> Eval
-	| p -> raise (failwith ("invalid platform " ^ p))
+	| p -> CustomTarget p
 
 let platform_list_help = function
 	| [] -> ""
@@ -191,16 +210,36 @@ type compiler_message = {
 	cm_message : string;
 	cm_pos : pos;
 	cm_depth : int;
+	cm_from_macro : bool;
 	cm_kind : MessageKind.t;
 	cm_severity : MessageSeverity.t;
 }
 
-let make_compiler_message msg p depth kind sev = {
-		cm_message = msg;
-		cm_pos = p;
-		cm_depth = depth;
-		cm_kind = kind;
-		cm_severity = sev;
+let make_compiler_message ?(from_macro = false) msg p depth kind sev = {
+	cm_message = msg;
+	cm_pos = p;
+	cm_depth = depth;
+	cm_from_macro = from_macro;
+	cm_kind = kind;
+	cm_severity = sev;
+}
+
+type diagnostic = {
+	diag_message : string;
+	diag_code : string option;
+	diag_pos : pos;
+	diag_kind : MessageKind.t;
+	diag_severity : MessageSeverity.t;
+	diag_depth : int;
+}
+
+let make_diagnostic ?(depth = 0) ?(code = None) message pos kind sev = {
+	diag_message = message;
+	diag_pos = pos;
+	diag_code = code;
+	diag_kind = kind;
+	diag_severity = sev;
+	diag_depth = depth;
 }
 
 let i32_31 = Int32.of_int 31

+ 3 - 5
src/core/inheritDoc.ml

@@ -1,14 +1,12 @@
-open Globals
 open Ast
 open Type
-open Typecore
 
 let expr_to_target e =
 	let rec loop (e,p) =
 		match e with
 		| EConst (Ident s) when s <> "" -> [s]
 		| EField (e,s,_) -> s :: loop e
-		| _ -> Error.typing_error "Invalid target expression for @:inheritDoc" p
+		| _ -> Error.raise_typing_error "Invalid target expression for @:inheritDoc" p
 	in
 	match loop e with
 	| sub_name :: type_name :: pack when not (is_lower_ident type_name) ->
@@ -16,7 +14,7 @@ let expr_to_target e =
 	| type_name :: pack ->
 		(List.rev pack, type_name), None
 	| [] ->
-		Error.typing_error "Invalid target path for @:inheritDoc" (snd e)
+		Error.raise_typing_error "Invalid target path for @:inheritDoc" (snd e)
 
 let rec get_constructor c =
 	match c.cl_constructor, c.cl_super with
@@ -194,7 +192,7 @@ and get_target_doc ctx e_target =
 		with Not_found ->
 			None
 	in
-	let rec resolve_type_t t =
+	let resolve_type_t t =
 		match follow t with
 		| TInst (c, _) ->
 			build_class_doc ctx c;

+ 8 - 6
src/core/json/genjson.ml

@@ -236,7 +236,7 @@ and generate_anon_status ctx status =
 		| Closed -> "AClosed",None
 		| Const -> "AConst",None
 		| Extend tl -> "AExtend", Some (generate_types ctx tl)
-		| Statics c -> "AClassStatics",Some (class_ref ctx c)
+		| ClassStatics c -> "AClassStatics",Some (class_ref ctx c)
 		| EnumStatics en -> "AEnumStatics",Some (enum_ref ctx en)
 		| AbstractStatics a -> "AAbstractStatics", Some (abstract_ref ctx a)
 	in
@@ -707,7 +707,7 @@ let generate_module_type ctx mt =
 
 (* module *)
 
-let generate_module cc m =
+let generate_module cs cc m =
 	jobject [
 		"id",jint m.m_id;
 		"path",generate_module_path m.m_path;
@@ -718,10 +718,12 @@ let generate_module cc m =
 			| MSGood -> "Good"
 			| MSBad reason -> Printer.s_module_skip_reason reason
 			| MSUnknown -> "Unknown");
-		"dependencies",jarray (PMap.fold (fun m acc -> (jobject [
-			"path",jstring (s_type_path m.m_path);
-			"sign",jstring (Digest.to_hex m.m_extra.m_sign);
-		]) :: acc) m.m_extra.m_deps []);
+		"dependencies",jarray (PMap.fold (fun (sign,mpath) acc ->
+			(jobject [
+				"path",jstring (s_type_path mpath);
+				"sign",jstring (Digest.to_hex ((cs#get_context sign)#find_module mpath).m_extra.m_sign);
+			]) :: acc
+		) m.m_extra.m_deps []);
 		"dependents",jarray (List.map (fun m -> (jobject [
 			"path",jstring (s_type_path m.m_path);
 			"sign",jstring (Digest.to_hex m.m_extra.m_sign);

+ 6 - 0
src/core/meta.ml

@@ -120,3 +120,9 @@ let get_user_documentation_list user_metas =
 let copy_from_to m src dst =
 	try (get m src) :: dst
 	with Not_found -> dst
+
+let maybe_get_pos m ml = try
+		let (_,_,p) = get m ml in
+		Some p
+	with Not_found ->
+		None

+ 2 - 2
src/core/path.ml

@@ -223,7 +223,7 @@ end = struct
 
 	let create =
 		if Globals.is_windows then
-			(fun f -> String.lowercase (get_full_path f))
+			(fun f -> ExtString.String.lowercase (get_full_path f))
 		else
 			get_full_path
 
@@ -378,7 +378,7 @@ let full_dot_path pack mname tname =
 
 let file_extension file =
 	match List.rev (ExtString.String.nsplit file ".") with
-	| e :: _ -> String.lowercase e
+	| e :: _ -> ExtString.String.lowercase e
 	| [] -> ""
 
 module FilePath = struct

+ 12 - 3
src/core/tFunctions.ml

@@ -172,6 +172,13 @@ let module_extra file sign time kind policy =
 		m_check_policy = policy;
 	}
 
+let mk_class_field_ref (c : tclass) (cf : tclass_field) (kind : class_field_ref_kind) (is_macro : bool) = {
+	cfr_sign = c.cl_module.m_extra.m_sign;
+	cfr_path = c.cl_path;
+	cfr_field = cf.cf_name;
+	cfr_kind = kind;
+	cfr_is_macro = is_macro;
+}
 
 let mk_field name ?(public = true) ?(static = false) t p name_pos = {
 	cf_name = name;
@@ -233,8 +240,8 @@ let null_abstract = {
 }
 
 let add_dependency ?(skip_postprocess=false) m mdep =
-	if m != null_module && m != mdep then begin
-		m.m_extra.m_deps <- PMap.add mdep.m_id mdep m.m_extra.m_deps;
+	if m != null_module && (m.m_path != mdep.m_path || m.m_extra.m_sign != mdep.m_extra.m_sign) then begin
+		m.m_extra.m_deps <- PMap.add mdep.m_id (mdep.m_extra.m_sign, mdep.m_path) m.m_extra.m_deps;
 		(* In case the module is cached, we'll have to run post-processing on it again (issue #10635) *)
 		if not skip_postprocess then m.m_extra.m_processed <- 0
 	end
@@ -250,6 +257,8 @@ let t_infos t : tinfos =
 
 let t_path t = (t_infos t).mt_path
 
+let t_name t = snd (t_path t)
+
 let rec extends c csup =
 	if c == csup || List.exists (fun (i,_) -> extends i csup) c.cl_implements then
 		true
@@ -781,7 +790,7 @@ let quick_field t n =
 		| EnumStatics e ->
 			let ef = PMap.find n e.e_constrs in
 			FEnum(e,ef)
-		| Statics c ->
+		| ClassStatics c ->
 			FStatic (c,PMap.find n c.cl_statics)
 		| AbstractStatics a ->
 			begin match a.a_impl with

+ 4 - 4
src/core/tOther.ml

@@ -42,7 +42,7 @@ module TExprToExpr = struct
 				) args, (convert_type' ret))
 		| TAnon a ->
 			begin match !(a.a_status) with
-			| Statics c -> tpath ([],"Class") ([],"Class") [TPType (tpath c.cl_path c.cl_path [],null_pos)]
+			| ClassStatics c -> tpath ([],"Class") ([],"Class") [TPType (tpath c.cl_path c.cl_path [],null_pos)]
 			| EnumStatics e -> tpath ([],"Enum") ([],"Enum") [TPType (tpath e.e_path e.e_path [],null_pos)]
 			| _ ->
 				CTAnonymous (PMap.foldi (fun _ f acc ->
@@ -149,8 +149,8 @@ module TExprToExpr = struct
 			EFor (ein,convert_expr e)
 		| TIf (e,e1,e2) -> EIf (convert_expr e,convert_expr e1,eopt e2)
 		| TWhile (e1,e2,flag) -> EWhile (convert_expr e1, convert_expr e2, flag)
-		| TSwitch (e,cases,def) ->
-			let cases = List.map (fun (vl,e) ->
+		| TSwitch {switch_subject = e;switch_cases = cases;switch_default = def} ->
+			let cases = List.map (fun {case_patterns = vl;case_expr = e} ->
 				List.map convert_expr vl,None,(match e.eexpr with TBlock [] -> None | _ -> Some (convert_expr e)),e.epos
 			) cases in
 			let def = match eopt def with None -> None | Some (EBlock [],_) -> Some (None,null_pos) | Some e -> Some (Some e,pos e) in
@@ -265,7 +265,7 @@ let no_meta = []
 
 let class_module_type c =
 	let path = ([],"Class<" ^ (s_type_path c.cl_path) ^ ">") in
-	let t = mk_anon ~fields:c.cl_statics (ref (Statics c)) in
+	let t = mk_anon ~fields:c.cl_statics (ref (ClassStatics c)) in
 	{ (mk_typedef c.cl_module path c.cl_pos null_pos t) with t_private = true}
 
 let enum_module_type m path p  =

+ 34 - 96
src/core/tPrinting.ml

@@ -58,7 +58,7 @@ let rec s_type ctx t =
 		(match c.cl_kind with
 		| KExpr e -> Ast.Printer.s_expr e
 		| _ -> s_type_path c.cl_path ^ s_type_params ctx tl)
-	| TType ({ t_type = TAnon { a_status = { contents = Statics { cl_kind = KAbstractImpl a }}}}, _) ->
+	| TType ({ t_type = TAnon { a_status = { contents = ClassStatics { cl_kind = KAbstractImpl a }}}}, _) ->
 		"Abstract<" ^ (s_type_path a.a_path) ^ ">"
 	| TType (t,tl) ->
 		s_type_path t.t_path ^ s_type_params ctx tl
@@ -80,7 +80,7 @@ let rec s_type ctx t =
 	| TAnon a ->
 		begin
 			match !(a.a_status) with
-			| Statics c -> Printf.sprintf "{ Statics %s }" (s_type_path c.cl_path)
+			| ClassStatics c -> Printf.sprintf "{ ClassStatics %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)
 			| _ ->
@@ -161,7 +161,7 @@ let s_expr_kind e =
 	| TFor (_,_,_) -> "For"
 	| TIf (_,_,_) -> "If"
 	| TWhile (_,_,_) -> "While"
-	| TSwitch (_,_,_) -> "Switch"
+	| TSwitch _ -> "Switch"
 	| TTry (_,_) -> "Try"
 	| TReturn _ -> "Return"
 	| TBreak -> "Break"
@@ -188,81 +188,6 @@ let s_field_access s_type fa = match fa with
 	| FEnum (en,f) -> "enum(" ^ s_type_path en.e_path ^ "." ^ f.ef_name ^ ")"
 	| FDynamic f -> "dynamic(" ^ f ^ ")"
 
-let rec s_expr s_type e =
-	let sprintf = Printf.sprintf in
-	let slist f l = String.concat "," (List.map f l) in
-	let loop = s_expr s_type in
-	let s_var v = v.v_name ^ ":" ^ string_of_int v.v_id ^ if has_var_flag v VCaptured then "[c]" else "" in
-	let str = (match e.eexpr with
-	| TConst c ->
-		"Const " ^ s_const c
-	| TLocal v ->
-		"Local " ^ s_var v
-	| TArray (e1,e2) ->
-		sprintf "%s[%s]" (loop e1) (loop e2)
-	| TBinop (op,e1,e2) ->
-		sprintf "(%s %s %s)" (loop e1) (s_binop op) (loop e2)
-	| TEnumIndex e1 ->
-		sprintf "EnumIndex %s" (loop e1)
-	| TEnumParameter (e1,_,i) ->
-		sprintf "%s[%i]" (loop e1) i
-	| TField (e,f) ->
-		let fstr = s_field_access s_type f in
-		sprintf "%s.%s" (loop e) fstr
-	| TTypeExpr m ->
-		sprintf "TypeExpr %s" (s_type_path (t_path m))
-	| TParenthesis e ->
-		sprintf "Parenthesis %s" (loop e)
-	| TObjectDecl fl ->
-		sprintf "ObjectDecl {%s}" (slist (fun ((f,_,qs),e) -> sprintf "%s : %s" (s_object_key_name f qs) (loop e)) fl)
-	| TArrayDecl el ->
-		sprintf "ArrayDecl [%s]" (slist loop el)
-	| TCall (e,el) ->
-		sprintf "Call %s(%s)" (loop e) (slist loop el)
-	| TNew (c,pl,el) ->
-		sprintf "New %s%s(%s)" (s_type_path c.cl_path) (match pl with [] -> "" | l -> sprintf "<%s>" (slist s_type l)) (slist loop el)
-	| TUnop (op,f,e) ->
-		(match f with
-		| Prefix -> sprintf "(%s %s)" (s_unop op) (loop e)
-		| Postfix -> sprintf "(%s %s)" (loop e) (s_unop op))
-	| TFunction f ->
-		let args = slist (fun (v,o) -> sprintf "%s : %s%s" (s_var v) (s_type v.v_type) (match o with None -> "" | Some c -> " = " ^ loop c)) f.tf_args in
-		sprintf "Function(%s) : %s = %s" args (s_type f.tf_type) (loop f.tf_expr)
-	| TVar (v,eo) ->
-		sprintf "Vars %s" (sprintf "%s : %s%s" (s_var v) (s_type v.v_type) (match eo with None -> "" | Some e -> " = " ^ loop e))
-	| TBlock el ->
-		sprintf "Block {\n%s}" (String.concat "" (List.map (fun e -> sprintf "%s;\n" (loop e)) el))
-	| TFor (v,econd,e) ->
-		sprintf "For (%s : %s in %s,%s)" (s_var v) (s_type v.v_type) (loop econd) (loop e)
-	| TIf (e,e1,e2) ->
-		sprintf "If (%s,%s%s)" (loop e) (loop e1) (match e2 with None -> "" | Some e -> "," ^ loop e)
-	| TWhile (econd,e,flag) ->
-		(match flag with
-		| NormalWhile -> sprintf "While (%s,%s)" (loop econd) (loop e)
-		| DoWhile -> sprintf "DoWhile (%s,%s)" (loop e) (loop econd))
-	| TSwitch (e,cases,def) ->
-		sprintf "Switch (%s,(%s)%s)" (loop e) (slist (fun (cl,e) -> sprintf "case %s: %s" (slist loop cl) (loop e)) cases) (match def with None -> "" | Some e -> "," ^ loop e)
-	| TTry (e,cl) ->
-		sprintf "Try %s(%s) " (loop e) (slist (fun (v,e) -> sprintf "catch( %s : %s ) %s" (s_var v) (s_type v.v_type) (loop e)) cl)
-	| TReturn None ->
-		"Return"
-	| TReturn (Some e) ->
-		sprintf "Return %s" (loop e)
-	| TBreak ->
-		"Break"
-	| TContinue ->
-		"Continue"
-	| TThrow e ->
-		"Throw " ^ (loop e)
-	| TCast (e,t) ->
-		sprintf "Cast %s%s" (match t with None -> "" | Some t -> s_type_path (t_path t) ^ ": ") (loop e)
-	| TMeta ((n,el,_),e) ->
-		sprintf "@%s%s %s" (Meta.to_string n) (match el with [] -> "" | _ -> "(" ^ (String.concat ", " (List.map Ast.Printer.s_expr el)) ^ ")") (loop e)
-	| TIdent s ->
-		"Ident " ^ s
-	) in
-	sprintf "(%s : %s)" str (s_type e.etype)
-
 let rec s_expr_pretty print_var_ids tabs top_level s_type e =
 	let sprintf = Printf.sprintf in
 	let loop = s_expr_pretty print_var_ids tabs false s_type in
@@ -307,9 +232,12 @@ let rec s_expr_pretty print_var_ids tabs top_level s_type e =
 		(match flag with
 		| NormalWhile -> sprintf "while (%s) %s" (loop econd) (loop e)
 		| DoWhile -> sprintf "do (%s) while(%s)" (loop e) (loop econd))
-	| TSwitch (e,cases,def) ->
+	| TSwitch switch ->
 		let ntabs = tabs ^ "\t" in
-		let s = sprintf "switch (%s) {\n%s%s" (loop e) (slist "" (fun (cl,e) -> sprintf "%scase %s: %s;\n" ntabs (clist loop cl) (s_expr_pretty print_var_ids ntabs top_level s_type e)) cases) (match def with None -> "" | Some e -> ntabs ^ "default: " ^ (s_expr_pretty print_var_ids ntabs top_level s_type e) ^ "\n") in
+		let s = sprintf "switch (%s) {\n%s%s"
+			(loop switch.switch_subject)
+			(slist "" (fun case -> sprintf "%scase %s: %s;\n" ntabs (clist loop case.case_patterns) (s_expr_pretty print_var_ids ntabs top_level s_type case.case_expr)) switch.switch_cases)
+			(match switch.switch_default with None -> "" | Some e -> ntabs ^ "default: " ^ (s_expr_pretty print_var_ids ntabs top_level s_type e) ^ "\n") in
 		s ^ tabs ^ "}"
 	| TTry (e,cl) ->
 		sprintf "try %s%s" (loop e) (clist (fun (v,e) -> sprintf " catch (%s:%s) %s" (local v) (s_type v.v_type) (loop e)) cl)
@@ -332,6 +260,12 @@ let rec s_expr_pretty print_var_ids tabs top_level s_type e =
 	| TIdent s ->
 		s
 
+let s_flags flags all_flags =
+	let _,l = List.fold_left (fun (i,acc) name ->
+		if has_flag flags i then (i + 1,name :: acc) else (i + 1,acc)
+	) (0,[]) all_flags in
+	String.concat " " l
+
 let rec s_expr_ast print_var_ids tabs s_type e =
 	let sprintf = Printf.sprintf in
 	let loop ?(extra_tabs="") = s_expr_ast print_var_ids (tabs ^ "\t" ^ extra_tabs) s_type in
@@ -352,7 +286,12 @@ let rec s_expr_ast print_var_ids tabs s_type e =
 	let var_id v = if print_var_ids then v.v_id else 0 in
 	let const c t = tag "Const" ~t [s_const c] in
 	let local v t = sprintf "[Local %s(%i):%s%s]" v.v_name (var_id v) (s_type v.v_type) (match t with None -> "" | Some t -> ":" ^ (s_type t)) in
-	let var v sl = sprintf "[Var %s(%i):%s]%s" v.v_name (var_id v) (s_type v.v_type) (tag_args tabs sl) in
+	let var tag v sl =
+		let s_flags = match v.v_flags with
+			| 0 -> ""
+			| _ -> Printf.sprintf "(%s)" (s_flags v.v_flags flag_tvar_names)
+		in
+		sprintf "[%s %s<%i>%s:%s]%s" tag v.v_name (var_id v) s_flags (s_type v.v_type) (tag_args tabs sl) in
 	let module_type mt = sprintf "[TypeExpr %s:%s]" (s_type_path (t_path mt)) (s_type e.etype) in
 	match e.eexpr with
 	| TConst c -> const c (Some e.etype)
@@ -380,10 +319,10 @@ let rec s_expr_ast print_var_ids tabs s_type e =
 	| TNew (c,tl,el) -> tag "New" ((s_type (TInst(c,tl))) :: (List.map loop el))
 	| TFunction f ->
 		let arg (v,cto) =
-			tag "Arg" ~t:(Some v.v_type) ~extra_tabs:"\t" (match cto with None -> [local v None] | Some ct -> [local v None;loop ct])
+			var "Arg" v (match cto with None -> [] | Some e -> [loop e])
 		in
 		tag "Function" ((List.map arg f.tf_args) @ [loop f.tf_expr])
-	| TVar (v,eo) -> var v (match eo with None -> [] | Some e -> [loop e])
+	| TVar (v,eo) -> var "Var" v (match eo with None -> [] | Some e -> [loop e])
 	| TBlock el -> tag "Block" (List.map loop el)
 	| TIf (e,e1,e2) -> tag "If" (loop e :: (Printf.sprintf "[Then:%s] %s" (s_type e1.etype) (loop e1)) :: (match e2 with None -> [] | Some e -> [Printf.sprintf "[Else:%s] %s" (s_type e.etype) (loop e)]))
 	| TCast (e1,None) -> tag "Cast" [loop e1]
@@ -401,15 +340,15 @@ let rec s_expr_ast print_var_ids tabs s_type e =
 			sprintf "Catch %s%s" (local v None) (tag_args (tabs ^ "\t") [loop ~extra_tabs:"\t" e]);
 		) catches in
 		tag "Try" ((loop e1) :: sl)
-	| TSwitch (e1,cases,eo) ->
-		let sl = List.map (fun (el,e) ->
+	| TSwitch switch ->
+		let sl = List.map (fun {case_patterns = el;case_expr = e} ->
 			tag "Case" ~t:(Some e.etype) ~extra_tabs:"\t" ((List.map loop el) @ [loop ~extra_tabs:"\t" e])
-		) cases in
-		let sl = match eo with
+		) switch.switch_cases in
+		let sl = match switch.switch_default with
 			| None -> sl
 			| Some e -> sl @ [tag "Default" ~t:(Some e.etype) ~extra_tabs:"\t" [loop ~extra_tabs:"\t" e]]
 		in
-		tag "Switch" ((loop e1) :: sl)
+		tag "Switch" ((loop switch.switch_subject) :: sl)
 	| TMeta ((m,el,_),e1) ->
 		let s = Meta.to_string m in
 		let s = match el with
@@ -450,6 +389,11 @@ let s_class_kind = function
 	| KModuleFields m ->
 		Printf.sprintf "KModuleFields %s" (s_type_path m.m_path)
 
+let s_class_field_ref_kind = function
+	| CfrStatic -> "CfrStatic"
+	| CfrMember -> "CfrMember"
+	| CfrConstructor -> "CfrConstructor"
+
 module Printer = struct
 
 	let s_type t =
@@ -506,12 +450,6 @@ module Printer = struct
 	let s_type_params tl =
 		s_list ", " s_type_param tl
 
-	let s_flags flags all_flags =
-		let _,l = List.fold_left (fun (i,acc) name ->
-			if has_flag flags i then (i + 1,name :: acc) else (i + 1,acc)
-		) (0,[]) all_flags in
-		String.concat " " l
-
 	let s_tclass_field_flags flags =
 		s_flags flags flag_tclass_field_names
 
@@ -667,12 +605,12 @@ module Printer = struct
 	let s_module_def_extra tabs me =
 		s_record_fields tabs [
 			"m_file",Path.UniqueKey.lazy_path me.m_file;
-			"m_sign",me.m_sign;
+			"m_sign",(Digest.to_hex me.m_sign);
 			"m_time",string_of_float me.m_time;
 			"m_cache_state",s_module_cache_state me.m_cache_state;
 			"m_added",string_of_int me.m_added;
 			"m_checked",string_of_int me.m_checked;
-			"m_deps",s_pmap string_of_int (fun m -> snd m.m_path) me.m_deps;
+			"m_deps",s_pmap string_of_int (fun (_,m) -> snd m) me.m_deps;
 			"m_processed",string_of_int me.m_processed;
 			"m_kind",s_module_kind me.m_kind;
 			"m_binded_res",""; (* TODO *)

+ 33 - 4
src/core/tType.ml

@@ -149,7 +149,7 @@ and anon_status =
 	| Closed
 	| Const
 	| Extend of t list
-	| Statics of tclass
+	| ClassStatics of tclass
 	| EnumStatics of tenum
 	| AbstractStatics of tabstract
 
@@ -177,7 +177,7 @@ and texpr_expr =
 	| TFor of tvar * texpr * texpr
 	| TIf of texpr * texpr * texpr option
 	| TWhile of texpr * texpr * Ast.while_flag
-	| TSwitch of texpr * (texpr list * texpr) list * texpr option
+	| TSwitch of tswitch
 	| TTry of texpr * (tvar * texpr) list
 	| TReturn of texpr option
 	| TBreak
@@ -189,6 +189,18 @@ and texpr_expr =
 	| TEnumIndex of texpr
 	| TIdent of string
 
+and tswitch = {
+	switch_subject : texpr;
+	switch_cases : switch_case list;
+	switch_default: texpr option;
+	switch_exhaustive : bool;
+}
+
+and switch_case = {
+	case_patterns : texpr list;
+	case_expr : texpr;
+}
+
 and tfield_access =
 	| FInstance of tclass * tparams * tclass_field
 	| FStatic of tclass * tclass_field
@@ -378,13 +390,26 @@ and module_def_extra = {
 	mutable m_added : int;
 	mutable m_checked : int;
 	mutable m_processed : int;
-	mutable m_deps : (int,module_def) PMap.t;
+	mutable m_deps : (int,(string (* sign *) * path)) PMap.t;
 	mutable m_kind : module_kind;
 	mutable m_binded_res : (string, string) PMap.t;
-	mutable m_if_feature : (string *(tclass * tclass_field * bool)) list;
+	mutable m_if_feature : (string * class_field_ref) list;
 	mutable m_features : (string,bool) Hashtbl.t;
 }
 
+and class_field_ref_kind =
+	| CfrStatic
+	| CfrMember
+	| CfrConstructor
+
+and class_field_ref = {
+	cfr_sign : string;
+	cfr_path : path;
+	cfr_field : string;
+	cfr_kind : class_field_ref_kind;
+	cfr_is_macro : bool;
+}
+
 and module_kind =
 	| MCode
 	| MMacro
@@ -446,3 +471,7 @@ type flag_tvar =
 	| VAssigned
 	| VCaught
 	| VStatic
+
+let flag_tvar_names = [
+	"VCaptured";"VFinal";"VUsed";"VAssigned";"VCaught";"VStatic"
+]

+ 9 - 9
src/core/tUnification.ml

@@ -166,7 +166,7 @@ module Monomorph = struct
 		| CMixed l ->
 			List.iter (fun constr -> check_down_constraints constr t) l
 
-	let rec collect_up_constraints m =
+	let collect_up_constraints m =
 		let rec collect m acc =
 			List.fold_left (fun acc (t,name) ->
 				match t with
@@ -286,7 +286,7 @@ let rec follow_and_close t = match follow t with
 	| t ->
 		t
 
-let rec link e a b =
+let link e a b =
 	(* tell if setting a == b will create a type-loop *)
 	let rec loop t =
 		if t == a then
@@ -386,7 +386,7 @@ let rec shallow_eq a b =
 					loop (List.sort sort_compare fields1) (List.sort sort_compare fields2)
 				in
 				(match !(a2.a_status), !(a1.a_status) with
-				| Statics c, Statics c2 -> c == c2
+				| ClassStatics c, ClassStatics c2 -> c == c2
 				| EnumStatics e, EnumStatics e2 -> e == e2
 				| AbstractStatics a, AbstractStatics a2 -> a == a2
 				| Extend tl1, Extend tl2 -> fields_eq() && List.for_all2 shallow_eq tl1 tl2
@@ -560,7 +560,7 @@ let rec type_eq uctx a b =
 	| TAnon a1, TAnon a2 ->
 		(try
 			(match !(a2.a_status) with
-			| Statics c -> (match !(a1.a_status) with Statics c2 when c == c2 -> () | _ -> error [])
+			| ClassStatics c -> (match !(a1.a_status) with ClassStatics c2 when c == c2 -> () | _ -> error [])
 			| EnumStatics e -> (match !(a1.a_status) with EnumStatics e2 when e == e2 -> () | _ -> error [])
 			| AbstractStatics a -> (match !(a1.a_status) with AbstractStatics a2 when a == a2 -> () | _ -> error [])
 			| _ -> ()
@@ -801,7 +801,7 @@ let rec unify (uctx : unification_context) a b =
 				| _ -> ());
 			) an.a_fields;
 			(match !(an.a_status) with
-			| Statics _ | EnumStatics _ | AbstractStatics _ -> error []
+			| ClassStatics _ | EnumStatics _ | AbstractStatics _ -> error []
 			| Closed | Extend _ | Const -> ())
 		with
 			Unify_error l -> error (cannot_unify a b :: l))
@@ -809,7 +809,7 @@ let rec unify (uctx : unification_context) a b =
 		unify_anons uctx a b a1 a2
 	| TAnon an, TAbstract ({ a_path = [],"Class" },[pt]) ->
 		(match !(an.a_status) with
-		| Statics cl -> unify uctx (TInst (cl,List.map (fun _ -> mk_mono()) cl.cl_params)) pt
+		| ClassStatics cl -> unify uctx (TInst (cl,List.map (fun _ -> mk_mono()) cl.cl_params)) pt
 		| _ -> error [cannot_unify a b])
 	| TAnon an, TAbstract ({ a_path = [],"Enum" },[pt]) ->
 		(match !(an.a_status) with
@@ -867,7 +867,7 @@ let rec unify (uctx : unification_context) a b =
 		| TAnon an ->
 			(try
 				(match !(an.a_status) with
-				| Statics _ | EnumStatics _ -> error []
+				| ClassStatics _ | EnumStatics _ -> error []
 				| _ -> ());
 				PMap.iter (fun _ f ->
 					try
@@ -910,7 +910,7 @@ and unify_anons uctx a b a1 a2 =
 				in
 				unify_with_access uctx f1 f1_type f2;
 				(match !(a1.a_status) with
-				| Statics c when not (Meta.has Meta.MaybeUsed f1.cf_meta) -> f1.cf_meta <- (Meta.MaybeUsed,[],f1.cf_pos) :: f1.cf_meta
+				| ClassStatics c when not (Meta.has Meta.MaybeUsed f1.cf_meta) -> f1.cf_meta <- (Meta.MaybeUsed,[],f1.cf_pos) :: f1.cf_meta
 				| _ -> ());
 			with
 				Unify_error l -> error (invalid_field n :: l)
@@ -923,7 +923,7 @@ and unify_anons uctx a b a1 a2 =
 					error [has_no_field a n];
 		) a2.a_fields;
 		(match !(a2.a_status) with
-		| Statics c -> (match !(a1.a_status) with Statics c2 when c == c2 -> () | _ -> error [])
+		| ClassStatics c -> (match !(a1.a_status) with ClassStatics c2 when c == c2 -> () | _ -> error [])
 		| EnumStatics e -> (match !(a1.a_status) with EnumStatics e2 when e == e2 -> () | _ -> error [])
 		| AbstractStatics a -> (match !(a1.a_status) with AbstractStatics a2 when a == a2 -> () | _ -> error [])
 		| Const | Extend _ | Closed -> ())

+ 79 - 65
src/core/texpr.ml

@@ -47,10 +47,10 @@ let iter f e =
 		f e;
 		f e1;
 		(match e2 with None -> () | Some e -> f e)
-	| TSwitch (e,cases,def) ->
-		f e;
-		List.iter (fun (el,e2) -> List.iter f el; f e2) cases;
-		(match def with None -> () | Some e -> f e)
+	| TSwitch switch ->
+		f switch.switch_subject;
+		List.iter (fun case -> List.iter f case.case_patterns; f case.case_expr) switch.switch_cases;
+		(match switch.switch_default with None -> () | Some e -> f e)
 	| TTry (e,catches) ->
 		f e;
 		List.iter (fun (_,e) -> f e) catches
@@ -83,10 +83,10 @@ let check_expr predicate e =
 			predicate fu.tf_expr
 		| TIf (e,e1,e2) ->
 			predicate e || predicate e1 || (match e2 with None -> false | Some e -> predicate e)
-		| TSwitch (e,cases,def) ->
-			predicate e
-			|| List.exists (fun (el,e2) -> List.exists predicate el || predicate e2) cases
-			|| (match def with None -> false | Some e -> predicate e)
+		| TSwitch switch ->
+			predicate switch.switch_subject
+			|| List.exists (fun case -> List.exists predicate case.case_patterns || predicate case.case_expr) switch.switch_cases
+			|| (match switch.switch_default with None -> false | Some e -> predicate e)
 		| TTry (e,catches) ->
 			predicate e || List.exists (fun (_,e) -> predicate e) catches
 
@@ -142,10 +142,14 @@ let map_expr f e =
 		let ec = f ec in
 		let e1 = f e1 in
 		{ e with eexpr = TIf (ec,e1,match e2 with None -> None | Some e -> Some (f e)) }
-	| TSwitch (e1,cases,def) ->
-		let e1 = f e1 in
-		let cases = List.map (fun (el,e2) -> List.map f el, f e2) cases in
-		{ e with eexpr = TSwitch (e1, cases, match def with None -> None | Some e -> Some (f e)) }
+	| TSwitch switch ->
+		let e1 = f switch.switch_subject in
+		let cases = List.map (fun case -> {
+			case_patterns = List.map f case.case_patterns;
+			case_expr = f case.case_expr
+		}) switch.switch_cases in
+		let def = Option.map f switch.switch_default in
+		{ e with eexpr = TSwitch {switch with switch_subject = e1;switch_cases = cases;switch_default = def} }
 	| TTry (e1,catches) ->
 		let e1 = f e1 in
 		{ e with eexpr = TTry (e1, List.map (fun (v,e) -> v, f e) catches) }
@@ -228,7 +232,7 @@ let map_expr_type f ft fv e =
 	| TFunction fu ->
 		let fu = {
 			tf_expr = f fu.tf_expr;
-			tf_args = List.map (fun (v,o) -> fv v, o) fu.tf_args;
+			tf_args = List.map (fun (v,o) -> fv v, (Option.map f o)) fu.tf_args;
 			tf_type = ft fu.tf_type;
 		} in
 		{ e with eexpr = TFunction fu; etype = ft e.etype }
@@ -236,10 +240,14 @@ let map_expr_type f ft fv e =
 		let ec = f ec in
 		let e1 = f e1 in
 		{ e with eexpr = TIf (ec,e1,match e2 with None -> None | Some e -> Some (f e)); etype = ft e.etype }
-	| TSwitch (e1,cases,def) ->
-		let e1 = f e1 in
-		let cases = List.map (fun (el,e2) -> List.map f el, f e2) cases in
-		{ e with eexpr = TSwitch (e1, cases, match def with None -> None | Some e -> Some (f e)); etype = ft e.etype }
+	| TSwitch switch ->
+		let e1 = f switch.switch_subject in
+		let cases = List.map (fun case -> {
+			case_patterns = List.map f case.case_patterns;
+			case_expr = f case.case_expr
+		}) switch.switch_cases in
+		let def = Option.map f switch.switch_default in
+		{ e with eexpr = TSwitch {switch with switch_subject = e1;switch_cases = cases;switch_default = def}; etype = ft e.etype }
 	| TTry (e1,catches) ->
 		let e1 = f e1 in
 		{ e with eexpr = TTry (e1, List.map (fun (v,e) -> fv v, f e) catches); etype = ft e.etype }
@@ -284,10 +292,10 @@ let rec equal e1 e2 = match e1.eexpr,e2.eexpr with
 	| 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)
+	| TSwitch switch1,TSwitch switch2 ->
+		equal switch1.switch_subject switch2.switch_subject &&
+		safe_for_all2 (fun case1 case2 -> safe_for_all2 equal case1.case_patterns case2.case_patterns && equal case1.case_expr case2.case_expr) switch1.switch_cases switch2.switch_cases &&
+		(match switch1.switch_default,switch2.switch_default 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
@@ -299,7 +307,9 @@ let rec equal e1 e2 = match e1.eexpr,e2.eexpr with
 	| TEnumParameter(e1,ef1,i1),TEnumParameter(e2,ef2,i2) -> equal e1 e2 && ef1 == ef2 && i1 = i2
 	| _ -> false
 
-let duplicate_tvars e =
+let e_identity e = e
+
+let duplicate_tvars f_this e =
 	let vars = Hashtbl.create 0 in
 	let copy_var v =
 		let v2 = alloc_var v.v_kind v.v_name v.v_type v.v_pos in
@@ -336,6 +346,8 @@ let duplicate_tvars e =
 				{e with eexpr = TLocal v2}
 			with _ ->
 				e)
+		| TConst TThis ->
+			f_this e
 		| _ ->
 			map_expr build_expr e
 	in
@@ -434,15 +446,15 @@ let foldmap f acc e =
 		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) }
+	| TSwitch switch ->
+		let acc,e1 = f acc switch.switch_subject in
+		let acc,cases = List.fold_left (fun (acc,cases) case ->
+			let acc,el = foldmap_list f acc case.case_patterns in
+			let acc,e2 = f acc case.case_expr in
+			acc,({case_patterns = el;case_expr = e2} :: cases)
+		) (acc,[]) switch.switch_cases in
+		let acc,def = foldmap_opt f acc switch.switch_default in
+		acc,{ e with eexpr = TSwitch {switch with switch_subject = e1;switch_cases = cases;switch_default = def} }
 	| TTry (e1,catches) ->
 		let acc,e1 = f acc e1 in
 		let acc,catches = foldmap_pairs f acc catches in
@@ -461,22 +473,22 @@ let foldmap f acc e =
 (* Collection of functions that return expressions *)
 module Builder = struct
 	let make_static_this c p =
-		let ta = mk_anon ~fields:c.cl_statics (ref (Statics c)) in
+		let ta = mk_anon ~fields:c.cl_statics (ref (ClassStatics c)) in
 		mk (TTypeExpr (TClassDecl c)) ta p
 
 	let make_typeexpr mt pos =
 		let t =
 			match resolve_typedef mt with
-			| TClassDecl c -> mk_anon ~fields:c.cl_statics (ref (Statics c))
+			| TClassDecl c -> mk_anon ~fields:c.cl_statics (ref (ClassStatics c))
 			| TEnumDecl e -> mk_anon (ref (EnumStatics e))
 			| TAbstractDecl a -> mk_anon (ref (AbstractStatics a))
 			| _ -> die "" __LOC__
 		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_static_field_access c cf t p =
+		let ethis = make_static_this c p in
+		mk (TField (ethis,(FStatic (c,cf)))) t p
 
 	let make_throw e p =
 		mk (TThrow e) t_dynamic p
@@ -505,7 +517,7 @@ module Builder = struct
 		| 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
-		| _ -> typing_error "Unsupported constant" p
+		| _ -> raise_typing_error "Unsupported constant" p
 
 	let field e name t p =
 		let f =
@@ -572,7 +584,7 @@ let replace_separators s c =
 let type_constant basic c p =
 	match c with
 	| Int (s,_) ->
-		if String.length s > 10 && String.sub s 0 2 = "0x" then typing_error "Invalid hexadecimal integer" p;
+		if String.length s > 10 && String.sub s 0 2 = "0x" then raise_typing_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
@@ -580,8 +592,8 @@ let type_constant basic c 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 -> typing_error ("Invalid constant :  " ^ t) p
-	| Regexp _ -> typing_error "Invalid constant" p
+	| Ident t -> raise_typing_error ("Invalid constant :  " ^ t) p
+	| Regexp _ -> raise_typing_error "Invalid constant" p
 
 let rec type_constant_value basic (e,p) =
 	match e with
@@ -594,16 +606,16 @@ let rec type_constant_value basic (e,p) =
 	| EArrayDecl el ->
 		mk (TArrayDecl (List.map (type_constant_value basic) el)) (basic.tarray t_dynamic) p
 	| _ ->
-		typing_error "Constant value expected" p
+		raise_typing_error "Constant value expected" p
 
 let is_constant_value basic e =
-	try (ignore (type_constant_value basic e); true) with Error (Custom _,_,_) -> false
+	try (ignore (type_constant_value basic e); true) with Error {err_message = Custom _} -> false
 
 let for_remap basic v e1 e2 p =
 	let v' = alloc_var v.v_kind 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',try quick_field t1 "hasNext" with Not_found -> typing_error (s_type (print_context()) t1 ^ "has no field hasNext()") p)) (tfun [] basic.tbool) e1.epos in
+	let ehasnext = mk (TField(ev',try quick_field t1 "hasNext" with Not_found -> raise_typing_error (s_type (print_context()) t1 ^ "has no field hasNext()") p)) (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
@@ -638,7 +650,7 @@ let build_metadata api t =
 	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 typing_error ("Duplicate metadata '" ^ f ^ "'") p;
+			if Hashtbl.mem h f then raise_typing_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
@@ -732,14 +744,14 @@ let dump_with_pos tabs e =
 			add "TWhile";
 			loop e1;
 			loop e2;
-		| TSwitch(e1,cases,def) ->
+		| TSwitch switch ->
 			add "TSwitch";
-			loop e1;
-			List.iter (fun (el,e) ->
-				List.iter (loop' (tabs ^ "    ")) el;
-				loop' (tabs ^ "      ") e;
-			) cases;
-			Option.may (loop' (tabs ^ "      ")) def
+			loop switch.switch_subject;
+			List.iter (fun case ->
+				List.iter (loop' (tabs ^ "    ")) case.case_patterns;
+				loop' (tabs ^ "      ") case.case_expr;
+			) switch.switch_cases;
+			Option.may (loop' (tabs ^ "      ")) switch.switch_default
 		| TTry(e1,catches) ->
 			add "TTry";
 			loop e1;
@@ -843,13 +855,15 @@ let punion_el default_pos el =
 		else
 			punion first last
 
-let is_exhaustive e1 def =
-	let rec loop e1 = match e1.eexpr with
-		| TMeta((Meta.Exhaustive,_,_),_) -> true
-		| TMeta(_, e1) | TParenthesis e1 -> loop e1
-		| _ -> false
-	in
-	def <> None || loop e1
+let is_exhaustive switch =
+	switch.switch_exhaustive
+
+let mk_switch subject cases default exhaustive = {
+	switch_subject = subject;
+	switch_cases = cases;
+	switch_default = default;
+	switch_exhaustive = exhaustive;
+}
 
 let rec is_true_expr e1 = match e1.eexpr with
 	| TConst(TBool true) -> true
@@ -890,15 +904,15 @@ module DeadEnd = struct
 				loop cond || loop if_body && loop else_body
 			| TIf (cond, _, None) ->
 				loop cond
-			| TSwitch(e1, cases, def) ->
+			| TSwitch switch ->
 				let check_exhaustive () =
-					(is_exhaustive e1 def) && List.for_all (fun (el,e) ->
-						List.exists loop el ||
-						loop e
-					) cases &&
-					Option.map_default (loop ) true def (* true because we know it's exhaustive *)
+					(is_exhaustive switch) && List.for_all (fun case ->
+						List.exists loop case.case_patterns ||
+						loop case.case_expr
+					) switch.switch_cases &&
+					Option.map_default (loop ) true switch.switch_default (* true because we know it's exhaustive *)
 				in
-				loop e1 || check_exhaustive ()
+				loop switch.switch_subject || check_exhaustive ()
 			| TFor(_, e1, _) ->
 				loop e1
 			| TBinop(OpBoolAnd, e1, e2) ->

+ 4 - 2
src/core/timer.ml

@@ -92,6 +92,8 @@ let close = close (get_time())
 
 (* Printing *)
 
+let timer_threshold = 0.01
+
 type timer_node = {
 	name : string;
 	path : string;
@@ -168,7 +170,7 @@ let build_times_tree () =
 		) 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;
+		if node.time >= timer_threshold && l > !max_name then max_name := l;
 	in
 	loop 0 root;
 	!max_name,!max_calls,root
@@ -180,7 +182,7 @@ let report_times print =
 	let sep = String.make (max_name + max_calls + 27) '-' in
 	print sep;
 	let print_time name node =
-		if node.time > 0.0009 then
+		if node.time >= timer_threshold 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 =

+ 3 - 3
src/core/warning.ml

@@ -13,7 +13,7 @@ type warning_option = {
 
 let parse_options s ps lexbuf =
 	let fail msg p =
-		Error.typing_error msg {p with pmin = ps.pmin + p.pmin; pmax = ps.pmin + p.pmax}
+		raise_typing_error msg {p with pmin = ps.pmin + p.pmin; pmax = ps.pmin + p.pmax}
 	in
 	let parse_string s p =
 		begin try
@@ -58,7 +58,7 @@ let from_meta ml =
 			let p = snd e in
 			parse_options s {p with pmin = p.pmin + 1; pmax = p.pmax - 1} (* pmin is on the quote *)
 		| _ ->
-			Error.typing_error "String expected" (snd e)
+			raise_typing_error "String expected" (snd e)
 	in
 	let rec loop acc ml = match ml with
 		| (Meta.HaxeWarning,args,_) :: ml ->
@@ -92,4 +92,4 @@ let get_mode w (l : warning_option list list) =
 			in
 			loop (loop2 mode l2) l
 	in
-	loop WMEnable (* ? *) l
+	loop WMEnable (* ? *) l

+ 13 - 5
src/dune

@@ -2,17 +2,25 @@
 
 (env
 	(_
-		(flags (:standard -w -3 -w -23 -thread))
+		; 3 - Remove deprecation warnings
+		; 6 - Label omitted in function application
+		; 9 - Missing record field in a record pattern
+		; 23 - Useless record `with` clause (all fields already listed)
+		; 27 - Unused var (strict)
+		; 32 - Unused value declaration
+		; 36 - Unused `as super`
+		; 50 - Unexpected docstring
+		(flags (:standard -w -3 -w -6 -w -9 -w -23 -w -27 -w -32 -w -36 -w -50 -thread))
 	)
 )
 
 (library
 	(name haxe)
 	(libraries
-		extc extproc extlib_leftovers mbedtls neko objsize pcre2 swflib ttflib ziplib
+		extc extproc extlib_leftovers mbedtls neko objsize pcre2 camlp-streams swflib ttflib ziplib
 		json
-		unix str bigarray threads dynlink
-		xml-light extlib ptmap sha
+		unix ipaddr str bigarray threads dynlink
+		xml-light extlib sha
 		luv
 	)
 	(modules (:standard \ haxe))
@@ -31,4 +39,4 @@
 	(link_flags (:include ../lib.sexp))
 	; Uncomment to enable bytecode output for ocamldebug support
 	; (modes byte)
-)
+)

+ 0 - 1
src/filters/defaultArguments.ml

@@ -18,7 +18,6 @@
 *)
 open Common
 open Type
-open Codegen
 open Texpr.Builder
 
 (*

部分文件因文件數量過多而無法顯示