2
0
Эх сурвалжийг харах

Merge branch 'development' of github.com:HaxeFoundation/haxe into development

Nicolas Cannasse 6 жил өмнө
parent
commit
cefe46fac2
100 өөрчлөгдсөн 2975 нэмэгдсэн , 1519 устгасан
  1. 4 0
      .github/FUNDING.yml
  2. 1 0
      .gitignore
  3. 9 0
      .vscode/schemas/define.schema.json
  4. 9 0
      .vscode/schemas/meta.schema.json
  5. 3 7
      Makefile
  6. 7 7
      Makefile.win
  7. 1 1
      README.md
  8. 17 97
      azure-pipelines.yml
  9. 1 1
      extra/azure-pipelines/build-linux.yml
  10. 1 1
      extra/azure-pipelines/build-mac.yml
  11. 4 1
      extra/azure-pipelines/build-windows.yml
  12. 1 1
      extra/azure-pipelines/install-neko-snapshot.yaml
  13. 87 0
      extra/azure-pipelines/test-windows.yml
  14. 1 1
      extra/haxelib_src
  15. 1 1
      extra/installer.nsi
  16. 10 0
      libs/ttflib/tTFData.ml
  17. 2 2
      libs/ttflib/tTFSwfWriter.ml
  18. 1 1
      opam
  19. 144 121
      src-json/define.json
  20. 234 177
      src-json/meta.json
  21. 79 71
      src/codegen/dotnet.ml
  22. 8 8
      src/codegen/gencommon/gencommon.ml
  23. 299 238
      src/codegen/java.ml
  24. 57 28
      src/codegen/swfLoader.ml
  25. 9 29
      src/compiler/displayOutput.ml
  26. 40 46
      src/compiler/main.ml
  27. 20 4
      src/compiler/server.ml
  28. 75 22
      src/context/common.ml
  29. 78 1
      src/context/compilationServer.ml
  30. 9 3
      src/context/display/deprecationCheck.ml
  31. 3 0
      src/context/display/diagnostics.ml
  32. 7 2
      src/context/display/displayEmitter.ml
  33. 95 18
      src/context/display/displayException.ml
  34. 5 2
      src/context/display/displayFields.ml
  35. 14 2
      src/context/display/displayJson.ml
  36. 54 12
      src/context/display/displayToplevel.ml
  37. 1 4
      src/context/display/findReferences.ml
  38. 60 0
      src/context/nativeLibraries.ml
  39. 39 0
      src/context/nativeLibraryHandler.ml
  40. 9 2
      src/context/typecore.ml
  41. 12 2
      src/core/abstract.ml
  42. 9 4
      src/core/define.ml
  43. 35 9
      src/core/display/completionItem.ml
  44. 3 1
      src/core/displayTypes.ml
  45. 3 1
      src/core/error.ml
  46. 1 0
      src/core/globals.ml
  47. 6 1
      src/core/json/genjson.ml
  48. 2 1
      src/core/meta.ml
  49. 142 23
      src/core/type.ml
  50. 15 15
      src/core/withType.ml
  51. 74 22
      src/filters/filters.ml
  52. 1 0
      src/generators/genas3.ml
  53. 122 73
      src/generators/gencpp.ml
  54. 68 59
      src/generators/gencs.ml
  55. 20 12
      src/generators/genhl.ml
  56. 79 71
      src/generators/genjava.ml
  57. 105 47
      src/generators/genjvm.ml
  58. 20 1
      src/generators/genphp7.ml
  59. 1 1
      src/generators/genpy.ml
  60. 23 9
      src/generators/genswf.ml
  61. 7 2
      src/generators/genswf9.ml
  62. 19 0
      src/generators/jvm/jvmAttribute.ml
  63. 19 0
      src/generators/jvm/jvmBuilder.ml
  64. 19 0
      src/generators/jvm/jvmClass.ml
  65. 19 0
      src/generators/jvm/jvmCode.ml
  66. 19 0
      src/generators/jvm/jvmConstantPool.ml
  67. 21 2
      src/generators/jvm/jvmData.ml
  68. 19 0
      src/generators/jvm/jvmDebug.ml
  69. 21 0
      src/generators/jvm/jvmGlobals.ml
  70. 30 11
      src/generators/jvm/jvmMethod.ml
  71. 19 0
      src/generators/jvm/jvmSignature.ml
  72. 19 0
      src/generators/jvm/jvmVerificationTypeInfo.ml
  73. 29 3
      src/generators/jvm/jvmWriter.ml
  74. 30 3
      src/macro/eval/evalContext.ml
  75. 28 11
      src/macro/eval/evalDebugMisc.ml
  76. 2 3
      src/macro/eval/evalMain.ml
  77. 3 3
      src/macro/eval/evalPrototype.ml
  78. 43 14
      src/macro/eval/evalStdLib.ml
  79. 8 13
      src/macro/macroApi.ml
  80. 0 1
      src/optimization/analyzer.ml
  81. 0 2
      src/optimization/analyzerTexprTransformer.ml
  82. 28 13
      src/prebuild/main.ml
  83. 14 6
      src/syntax/grammar.mly
  84. 14 1
      src/syntax/lexer.ml
  85. 2 2
      src/syntax/parser.ml
  86. 14 8
      src/typing/calls.ml
  87. 38 14
      src/typing/fields.ml
  88. 6 1
      src/typing/forLoop.ml
  89. 2 2
      src/typing/macroContext.ml
  90. 11 14
      src/typing/matcher.ml
  91. 26 16
      src/typing/nullSafety.ml
  92. 10 11
      src/typing/typeload.ml
  93. 34 4
      src/typing/typeloadCheck.ml
  94. 10 6
      src/typing/typeloadFields.ml
  95. 1 8
      src/typing/typeloadFunction.ml
  96. 11 5
      src/typing/typeloadModule.ml
  97. 7 3
      src/typing/typeloadParse.ml
  98. 115 57
      src/typing/typer.ml
  99. 1 6
      src/typing/typerBase.ml
  100. 17 11
      src/typing/typerDisplay.ml

+ 4 - 0
.github/FUNDING.yml

@@ -0,0 +1,4 @@
+# These are supported funding model platforms
+
+open_collective: haxe
+custom: ['https://haxe.org/foundation/support-plans.html', 'https://haxe.org/foundation/donate.html']

+ 1 - 0
.gitignore

@@ -127,3 +127,4 @@ tests/benchs/dump/
 tests/display/.unittest/
 tests/display/.unittest/
 tests/unit/.unittest/
 tests/unit/.unittest/
 tests/threads/export/
 tests/threads/export/
+tests/server/test.js.map

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

@@ -48,6 +48,15 @@
 			"devcomment": {
 			"devcomment": {
 				"type": "string",
 				"type": "string",
 				"markdownDescription": "Internal comment that is not exposed."
 				"markdownDescription": "Internal comment that is not exposed."
+			},
+			"links": {
+				"type": "array",
+				"markdownDescription": "Relevant URLs.",
+				"minItems": 1,
+				"items": {
+					"type": "string",
+					"format": "uri"
+				}
 			}
 			}
 		},
 		},
 		"required": [
 		"required": [

+ 9 - 0
.vscode/schemas/meta.schema.json

@@ -70,6 +70,15 @@
 						"TAnyField"
 						"TAnyField"
 					]
 					]
 				}
 				}
+			},
+			"links": {
+				"type": "array",
+				"markdownDescription": "Relevant URLs.",
+				"minItems": 1,
+				"items": {
+					"type": "string",
+					"format": "uri"
+				}
 			}
 			}
 		},
 		},
 		"required": [
 		"required": [

+ 3 - 7
Makefile

@@ -123,7 +123,7 @@ build_dirs:
 	@mkdir -p $(BUILD_DIRECTORIES)
 	@mkdir -p $(BUILD_DIRECTORIES)
 
 
 _build/src/syntax/grammar.ml:src/syntax/grammar.mly
 _build/src/syntax/grammar.ml:src/syntax/grammar.mly
-	camlp4o -impl $< -o $@
+	camlp5o -impl $< -o $@
 
 
 _build/src/compiler/version.ml: FORCE
 _build/src/compiler/version.ml: FORCE
 ifneq ($(ADD_REVISION),0)
 ifneq ($(ADD_REVISION),0)
@@ -211,7 +211,7 @@ uninstall:
 	rm -rf $(DESTDIR)$(INSTALL_STD_DIR)
 	rm -rf $(DESTDIR)$(INSTALL_STD_DIR)
 
 
 opam_install:
 opam_install:
-	opam install $(OPAM_LIBS) camlp4 ocamlfind --yes
+	opam install $(OPAM_LIBS) camlp5 ocamlfind --yes
 
 
 # Dependencies
 # Dependencies
 
 
@@ -229,13 +229,9 @@ package_src:
 package_unix:
 package_unix:
 	mkdir -p $(PACKAGE_OUT_DIR)
 	mkdir -p $(PACKAGE_OUT_DIR)
 	rm -rf $(PACKAGE_FILE_NAME) $(PACKAGE_FILE_NAME).tar.gz
 	rm -rf $(PACKAGE_FILE_NAME) $(PACKAGE_FILE_NAME).tar.gz
-	#delete all content which was generated in _build dir except interfaces
-	find _build/ -type f ! -name '*.cmi' -delete
-	#add ocaml version to the _build dir
-	ocaml -version > _build/ocaml.version
 	# Copy the package contents to $(PACKAGE_FILE_NAME)
 	# Copy the package contents to $(PACKAGE_FILE_NAME)
 	mkdir -p $(PACKAGE_FILE_NAME)
 	mkdir -p $(PACKAGE_FILE_NAME)
-	cp -r $(HAXE_OUTPUT) $(HAXELIB_OUTPUT) std extra/LICENSE.txt extra/CONTRIB.txt extra/CHANGES.txt _build $(PACKAGE_FILE_NAME)
+	cp -r $(HAXE_OUTPUT) $(HAXELIB_OUTPUT) std extra/LICENSE.txt extra/CONTRIB.txt extra/CHANGES.txt $(PACKAGE_FILE_NAME)
 	# archive
 	# archive
 	tar -zcf $(PACKAGE_OUT_DIR)/$(PACKAGE_FILE_NAME)_bin.tar.gz $(PACKAGE_FILE_NAME)
 	tar -zcf $(PACKAGE_OUT_DIR)/$(PACKAGE_FILE_NAME)_bin.tar.gz $(PACKAGE_FILE_NAME)
 	rm -r $(PACKAGE_FILE_NAME)
 	rm -r $(PACKAGE_FILE_NAME)

+ 7 - 7
Makefile.win

@@ -6,6 +6,11 @@ HAXELIB_OUTPUT=haxelib.exe
 PREBUILD_OUTPUT=prebuild.exe
 PREBUILD_OUTPUT=prebuild.exe
 EXTENSION=.exe
 EXTENSION=.exe
 PACKAGE_SRC_EXTENSION=.zip
 PACKAGE_SRC_EXTENSION=.zip
+ARCH?=32
+
+ifeq ($(ARCH),64)
+NEKO_ARCH_STR=64
+endif
 
 
 kill:
 kill:
 	-@taskkill /F /IM haxe.exe
 	-@taskkill /F /IM haxe.exe
@@ -34,10 +39,9 @@ endif
 
 
 ifdef FILTER
 ifdef FILTER
 CC_CMD=($(COMPILER) $(ALL_CFLAGS) -c $< 2>tmp.cmi && $(FILTER)) || ($(FILTER) && exit 1)
 CC_CMD=($(COMPILER) $(ALL_CFLAGS) -c $< 2>tmp.cmi && $(FILTER)) || ($(FILTER) && exit 1)
-CC_PARSER_CMD=($(COMPILER) -pp camlp4o $(ALL_CFLAGS) -c src/syntax/parser.ml 2>tmp.cmi && $(FILTER)) || ($(FILTER) && exit 1)
 endif
 endif
 
 
-PACKAGE_FILES=$(HAXE_OUTPUT) $(HAXELIB_OUTPUT) std _build "$$(cygcheck $(CURDIR)/$(HAXE_OUTPUT) | grep zlib1.dll | sed -e 's/^\s*//')" "$$(cygcheck $(CURDIR)/$(HAXE_OUTPUT) | grep libpcre-1.dll | sed -e 's/^\s*//')"
+PACKAGE_FILES=$(HAXE_OUTPUT) $(HAXELIB_OUTPUT) std "$$(cygcheck $(CURDIR)/$(HAXE_OUTPUT) | grep zlib1.dll | sed -e 's/^\s*//')" "$$(cygcheck $(CURDIR)/$(HAXE_OUTPUT) | grep libpcre-1.dll | sed -e 's/^\s*//')"
 
 
 echo_package_files:
 echo_package_files:
 	echo $(PACKAGE_FILES)
 	echo $(PACKAGE_FILES)
@@ -45,10 +49,6 @@ echo_package_files:
 package_win:
 package_win:
 	mkdir -p out
 	mkdir -p out
 	rm -rf $(PACKAGE_FILE_NAME) $(PACKAGE_FILE_NAME).zip temp.zip
 	rm -rf $(PACKAGE_FILE_NAME) $(PACKAGE_FILE_NAME).zip temp.zip
-	#delete all content which was generated in _build dir except interfaces
-	find _build/ -type f ! -name '*.cmi' -delete
-	#add ocaml version to the _build dir
-	ocaml -version > _build/ocaml.version
 	# Copy the package contents to $(PACKAGE_FILE_NAME)
 	# Copy the package contents to $(PACKAGE_FILE_NAME)
 	# Using poor man's cp (zip then unzip), because cp in cygwin is quite broken
 	# Using poor man's cp (zip then unzip), because cp in cygwin is quite broken
 	mkdir -p $(PACKAGE_FILE_NAME)
 	mkdir -p $(PACKAGE_FILE_NAME)
@@ -71,7 +71,7 @@ package_choco:
 	rm -rf out/choco
 	rm -rf out/choco
 
 
 $(INSTALLER_TMP_DIR)/neko-win.zip: $(INSTALLER_TMP_DIR)
 $(INSTALLER_TMP_DIR)/neko-win.zip: $(INSTALLER_TMP_DIR)
-	wget -nv http://nekovm.org/media/neko-2.1.0-win.zip -O installer/neko-win.zip
+	wget -nv https://nekovm.org/media/neko-2.2.0-win$(NEKO_ARCH_STR).zip -O installer/neko-win.zip
 
 
 package_installer_win: $(INSTALLER_TMP_DIR)/neko-win.zip package_win
 package_installer_win: $(INSTALLER_TMP_DIR)/neko-win.zip package_win
 	$(eval OUTFILE := $(PACKAGE_OUT_DIR)/$(PACKAGE_FILE_NAME)_installer.zip)
 	$(eval OUTFILE := $(PACKAGE_OUT_DIR)/$(PACKAGE_FILE_NAME)_installer.zip)

+ 1 - 1
README.md

@@ -100,7 +100,7 @@ Haxe            | Neko  | SWF |  Python   | HL    | PHP   | Lua  |
 4.0.0-preview.4 |       |        |        | 1.6   |       |      |
 4.0.0-preview.4 |       |        |        | 1.6   |       |      |
 4.0.0-preview.5 |       |        |        | 1.8   |       |      |
 4.0.0-preview.5 |       |        |        | 1.8   |       |      |
 4.0.0-rc.1      |       |        |        | 1.9   |       |      |
 4.0.0-rc.1      |       |        |        | 1.9   |       |      |
-
+4.0.0-rc.3      |       |        |        | 1.10  |       |      |
 
 
 ## Contributing
 ## Contributing
 
 

+ 17 - 97
azure-pipelines.yml

@@ -64,6 +64,8 @@ stages:
             lua:
             lua:
               TEST: lua
               TEST: lua
         steps:
         steps:
+          - checkout: self
+            fetchDepth: 20
           - template: extra/azure-pipelines/install-neko-snapshot.yaml
           - template: extra/azure-pipelines/install-neko-snapshot.yaml
             parameters:
             parameters:
               platform: linux64
               platform: linux64
@@ -131,6 +133,8 @@ stages:
             lua:
             lua:
               TEST: lua
               TEST: lua
         steps:
         steps:
+          - checkout: self
+            fetchDepth: 20
           - template: extra/azure-pipelines/install-neko-snapshot.yaml
           - template: extra/azure-pipelines/install-neko-snapshot.yaml
             parameters:
             parameters:
               platform: mac
               platform: mac
@@ -161,78 +165,16 @@ stages:
             workingDirectory: $(Build.SourcesDirectory)/tests
             workingDirectory: $(Build.SourcesDirectory)/tests
             displayName: Test
             displayName: Test
 
 
-      - job: TestWin64
-        dependsOn: BuildWin64
-        pool:
-          vmImage: 'windows-2019'
-        variables:
-          HAXELIB_ROOT: C:/haxelib
-          HAXE_ARCH: 64
-        strategy:
-          matrix:
-            macro:
-              TEST: macro
-            neko:
-              TEST: neko
-            hl:
-              TEST: hl
-            cpp:
-              TEST: cpp
-              HXCPP_COMPILE_CACHE: C:/hxcache
-            java:
-              TEST: java,jvm
-            cs:
-              TEST: cs
-            js:
-              TEST: js
-            # https://github.com/microsoft/azure-pipelines-image-generation/issues/990
-            # php:
-            #   TEST: php
-            # TODO. flash has never been enabled on our AppVeyor builds.
-            # flash:
-            #   TEST: flash9,as3
-            python:
-              TEST: python
-            # TODO. Lua has never been enabled on our AppVeyor builds.
-            # lua:
-            #   TEST: lua
-        steps:
-          - template: extra/azure-pipelines/install-neko-snapshot.yaml
-            parameters:
-              platform: windows
-          - task: DownloadPipelineArtifact@0
-            inputs:
-              artifactName: 'win64Binaries'
-              targetPath: win64Binaries
-          - powershell: |
-              Set-PSDebug -Trace 1
-              7z x win64Binaries/*_bin.zip -owin64Binaries
-              $dir = Get-ChildItem win64Binaries/* -Name -Directory
-              Rename-Item win64Binaries/$dir haxe
-              $dir = '' + ( get-location ) + '\win64Binaries\haxe'
-              dir $dir
-              Set-PSDebug -Trace 0
-              Write-Host "##vso[task.prependpath]$dir"
-            displayName: Setup Haxe
-          - script: haxe -version
-            displayName: Print Haxe version
-          - task: UsePythonVersion@0
-            inputs:
-              versionSpec: '3.7'
-          - powershell: |
-              Set-PSDebug -Trace 1
-              $pypath = python -c "import sys; print(sys.executable)"
-              $py3path = $pypath.replace("python.exe","python3.exe")
-              cmd /c mklink $py3path $pypath
-              python3 -V
-            displayName: "Make Python 3 be available as python3 in the cmdline"
-          - script: |
-              mkdir "$(HAXELIB_ROOT)"
-              haxelib setup "$(HAXELIB_ROOT)"
-            displayName: Setup haxelib
-          - script: haxe RunCi.hxml
-            workingDirectory: $(Build.SourcesDirectory)/tests
-            displayName: Test
+      - template: extra/azure-pipelines/test-windows.yml
+        parameters:
+          name: TestWin64
+          arch: '64'
+
+      - template: extra/azure-pipelines/test-windows.yml
+        parameters:
+          name: TestWin32
+          arch: '32'
+
   - stage: StageDeploy
   - stage: StageDeploy
     condition: and(succeeded(), not(variables['System.PullRequest.PullRequestId']))
     condition: and(succeeded(), not(variables['System.PullRequest.PullRequestId']))
     jobs:
     jobs:
@@ -241,6 +183,8 @@ stages:
         pool:
         pool:
           vmImage: 'ubuntu-16.04'
           vmImage: 'ubuntu-16.04'
         steps:
         steps:
+          - checkout: self
+            fetchDepth: 20
           - task: DownloadPipelineArtifact@0
           - task: DownloadPipelineArtifact@0
             inputs:
             inputs:
               artifactName: 'linuxBinaries'
               artifactName: 'linuxBinaries'
@@ -317,31 +261,7 @@ stages:
               AWS_SECRET_ACCESS_KEY: $(HXBUILDS_AWS_SECRET_ACCESS_KEY)
               AWS_SECRET_ACCESS_KEY: $(HXBUILDS_AWS_SECRET_ACCESS_KEY)
             condition: and(succeeded(), eq(variables['Build.SourceBranchName'], 'development'))
             condition: and(succeeded(), eq(variables['Build.SourceBranchName'], 'development'))
             displayName: Update "latest"
             displayName: Update "latest"
-          - script: |
-              set -ex
-              haxe --run runci.Indexer $(HXBUILDS_S3ADDR)/haxe/linux64
-              aws s3 cp index.html     $(HXBUILDS_S3ADDR)/haxe/linux64/
-              haxe --run runci.Indexer $(HXBUILDS_S3ADDR)/haxe/mac
-              aws s3 cp index.html     $(HXBUILDS_S3ADDR)/haxe/mac/
-              haxe --run runci.Indexer $(HXBUILDS_S3ADDR)/haxe/windows64
-              aws s3 cp index.html     $(HXBUILDS_S3ADDR)/haxe/windows64/
-              haxe --run runci.Indexer $(HXBUILDS_S3ADDR)/haxe/windows64-installer
-              aws s3 cp index.html     $(HXBUILDS_S3ADDR)/haxe/windows64-installer/
-              haxe --run runci.Indexer $(HXBUILDS_S3ADDR)/haxe/windows64-choco
-              aws s3 cp index.html     $(HXBUILDS_S3ADDR)/haxe/windows64-choco/
-              haxe --run runci.Indexer $(HXBUILDS_S3ADDR)/haxe/windows
-              aws s3 cp index.html     $(HXBUILDS_S3ADDR)/haxe/windows/
-              haxe --run runci.Indexer $(HXBUILDS_S3ADDR)/haxe/windows-installer
-              aws s3 cp index.html     $(HXBUILDS_S3ADDR)/haxe/windows-installer/
-              haxe --run runci.Indexer $(HXBUILDS_S3ADDR)/haxe/windows-choco
-              aws s3 cp index.html     $(HXBUILDS_S3ADDR)/haxe/windows-choco/
-              haxe --run runci.Indexer $(HXBUILDS_S3ADDR)/haxe
-              aws s3 cp index.html     $(HXBUILDS_S3ADDR)/haxe/
-            workingDirectory: $(Build.SourcesDirectory)/tests
-            env:
-              AWS_ACCESS_KEY_ID: $(HXBUILDS_AWS_ACCESS_KEY_ID)
-              AWS_SECRET_ACCESS_KEY: $(HXBUILDS_AWS_SECRET_ACCESS_KEY)
-            displayName: Update indices
+
       - job: ApiHaxeOrg
       - job: ApiHaxeOrg
         condition: and(succeeded(), variables['GHP_USERNAME'], variables['GHP_EMAIL'])
         condition: and(succeeded(), variables['GHP_USERNAME'], variables['GHP_EMAIL'])
         pool:
         pool:

+ 1 - 1
extra/azure-pipelines/build-linux.yml

@@ -16,7 +16,7 @@ jobs:
           set -ex
           set -ex
           sudo add-apt-repository ppa:avsm/ppa -y # provides newer version of OCaml and OPAM
           sudo add-apt-repository ppa:avsm/ppa -y # provides newer version of OCaml and OPAM
           sudo apt-get update -qqy
           sudo apt-get update -qqy
-          sudo apt-get install -qqy ocaml-nox camlp4-extra opam libpcre3-dev zlib1g-dev libgtk2.0-dev ninja-build
+          sudo apt-get install -qqy ocaml-nox camlp5 opam libpcre3-dev zlib1g-dev libgtk2.0-dev ninja-build
         displayName: Install dependencies
         displayName: Install dependencies
       - template: install-neko-snapshot.yaml
       - template: install-neko-snapshot.yaml
         parameters:
         parameters:

+ 1 - 1
extra/azure-pipelines/build-mac.yml

@@ -14,7 +14,7 @@ jobs:
         submodules: recursive
         submodules: recursive
       - script: |
       - script: |
           set -ex
           set -ex
-          brew update
+          brew update || brew update || brew update
           brew bundle --file=tests/Brewfile --no-upgrade
           brew bundle --file=tests/Brewfile --no-upgrade
         displayName: Install dependencies
         displayName: Install dependencies
       - template: install-neko-snapshot.yaml
       - template: install-neko-snapshot.yaml

+ 4 - 1
extra/azure-pipelines/build-windows.yml

@@ -31,7 +31,10 @@ jobs:
         displayName: Install dependencies
         displayName: Install dependencies
       - template: install-neko-snapshot.yaml
       - template: install-neko-snapshot.yaml
         parameters:
         parameters:
-          platform: windows
+          ${{ if eq(parameters.arch, '64') }}:
+            platform: windows64
+          ${{ if eq(parameters.arch, '32') }}:
+            platform: windows
       - powershell: |
       - powershell: |
           Set-PSDebug -Trace 1
           Set-PSDebug -Trace 1
           curl.exe -fsSL -o cygwin-setup.exe --retry 3 $(CYGWIN_SETUP)
           curl.exe -fsSL -o cygwin-setup.exe --retry 3 $(CYGWIN_SETUP)

+ 1 - 1
extra/azure-pipelines/install-neko-snapshot.yaml

@@ -6,7 +6,7 @@ steps:
     - powershell: |
     - powershell: |
         Invoke-WebRequest https://build.haxe.org/builds/neko/${{parameters.platform}}/neko_latest.zip -OutFile $(Agent.TempDirectory)/neko_latest.zip
         Invoke-WebRequest https://build.haxe.org/builds/neko/${{parameters.platform}}/neko_latest.zip -OutFile $(Agent.TempDirectory)/neko_latest.zip
         Expand-Archive $(Agent.TempDirectory)/neko_latest.zip -DestinationPath $(Agent.TempDirectory)
         Expand-Archive $(Agent.TempDirectory)/neko_latest.zip -DestinationPath $(Agent.TempDirectory)
-        $NEKOPATH = Get-ChildItem $(Agent.TempDirectory)/neko-*-win
+        $NEKOPATH = Get-ChildItem $(Agent.TempDirectory)/neko-*-*
         Write-Host "##vso[task.prependpath]$NEKOPATH"
         Write-Host "##vso[task.prependpath]$NEKOPATH"
         Write-Host "##vso[task.setvariable variable=NEKOPATH]$NEKOPATH"
         Write-Host "##vso[task.setvariable variable=NEKOPATH]$NEKOPATH"
       displayName: Install Neko using snapshot from S3
       displayName: Install Neko using snapshot from S3

+ 87 - 0
extra/azure-pipelines/test-windows.yml

@@ -0,0 +1,87 @@
+parameters:
+  name: 'TestWindows'
+  vmImage: 'windows-2019'
+  arch: '64' # or '32'
+
+jobs:
+  - job: ${{ parameters.name }}
+    dependsOn: BuildWin${{ parameters.arch }}
+    pool:
+      vmImage: ${{ parameters.vmImage }}
+    variables:
+      HAXELIB_ROOT: C:/haxelib
+    strategy:
+      matrix:
+        # https://github.com/HaxeFoundation/haxe/issues/8600
+        ${{ if eq(parameters.arch, '64') }}:
+          macro:
+            TEST: macro
+        neko:
+          TEST: neko
+        hl:
+          TEST: hl
+        cpp:
+          TEST: cpp
+          HXCPP_COMPILE_CACHE: C:/hxcache
+        java:
+          # https://github.com/HaxeFoundation/haxe/issues/8601
+          ${{ if eq(parameters.arch, '64') }}:
+            TEST: java,jvm
+          ${{ if eq(parameters.arch, '32') }}:
+            TEST: java
+        cs:
+          TEST: cs
+        js:
+          TEST: js
+        php:
+          TEST: php
+        # TODO. flash has never been enabled on our AppVeyor builds.
+        # flash:
+        #   TEST: flash9,as3
+        python:
+          TEST: python
+        # TODO. Lua has never been enabled on our AppVeyor builds.
+        # lua:
+        #   TEST: lua
+    steps:
+      - checkout: self
+        fetchDepth: 20
+      - template: install-neko-snapshot.yaml
+        parameters:
+          ${{ if eq(parameters.arch, '64') }}:
+            platform: windows64
+          ${{ if eq(parameters.arch, '32') }}:
+            platform: windows
+      - task: DownloadPipelineArtifact@0
+        inputs:
+          artifactName: 'win${{ parameters.arch }}Binaries'
+          targetPath: win${{ parameters.arch }}Binaries
+      - powershell: |
+          Set-PSDebug -Trace 1
+          7z x win${{ parameters.arch }}Binaries/*_bin.zip -owin${{ parameters.arch }}Binaries
+          $dir = Get-ChildItem win${{ parameters.arch }}Binaries/* -Name -Directory
+          Rename-Item win${{ parameters.arch }}Binaries/$dir haxe
+          $dir = '' + ( get-location ) + '\win${{ parameters.arch }}Binaries\haxe'
+          dir $dir
+          Set-PSDebug -Trace 0
+          Write-Host "##vso[task.prependpath]$dir"
+        displayName: Setup Haxe
+      - script: haxe -version
+        displayName: Print Haxe version
+      - task: UsePythonVersion@0
+        inputs:
+          versionSpec: '3.7'
+      - powershell: |
+          Set-PSDebug -Trace 1
+          $pypath = python -c "import sys; print(sys.executable)"
+          $py3path = $pypath.replace("python.exe","python3.exe")
+          cmd /c mklink $py3path $pypath
+          python3 -V
+        displayName: "Make Python 3 be available as python3 in the cmdline"
+      - script: |
+          mkdir "$(HAXELIB_ROOT)"
+          haxelib setup "$(HAXELIB_ROOT)"
+        displayName: Setup haxelib
+      - script: haxe RunCi.hxml
+        workingDirectory: $(Build.SourcesDirectory)/tests
+        displayName: Test

+ 1 - 1
extra/haxelib_src

@@ -1 +1 @@
-Subproject commit cdfe34118bd8e993cf5480ce7a26a6bb5b96f285
+Subproject commit 8795d1120c3afb94dda229cab3a60bad42df506d

+ 1 - 1
extra/installer.nsi

@@ -20,7 +20,7 @@
 !define VERLONG "%%VERLONG%%"
 !define VERLONG "%%VERLONG%%"
 
 
 ; Define Neko info
 ; Define Neko info
-!define NEKO_VERSION "2.1.0"
+!define NEKO_VERSION "2.2.0"
 
 
 ; Installer details
 ; Installer details
 VIAddVersionKey "CompanyName" "Haxe Foundation"
 VIAddVersionKey "CompanyName" "Haxe Foundation"

+ 10 - 0
libs/ttflib/tTFData.ml

@@ -344,7 +344,17 @@ type ttf = {
 	ttf_kern : kern option;
 	ttf_kern : kern option;
 }
 }
 
 
+type ttf_font_weight =
+	| TFWRegular
+	| TFWBold
+
+type ttf_font_posture =
+	| TFPNormal
+	| TFPItalic
+
 type ttf_config = {
 type ttf_config = {
 	mutable ttfc_range_str : string;
 	mutable ttfc_range_str : string;
 	mutable ttfc_font_name : string option;
 	mutable ttfc_font_name : string option;
+	mutable ttfc_font_weight : ttf_font_weight;
+	mutable ttfc_font_posture : ttf_font_posture;
 }
 }

+ 2 - 2
libs/ttflib/tTFSwfWriter.ml

@@ -200,8 +200,8 @@ let to_swf ttf config =
 		font_is_ansi = false;
 		font_is_ansi = false;
 		font_wide_offsets = true;
 		font_wide_offsets = true;
 		font_wide_codes = true;
 		font_wide_codes = true;
-		font_is_italic = false;
-		font_is_bold = false;
+		font_is_italic = config.ttfc_font_posture = TFPItalic;
+		font_is_bold = config.ttfc_font_weight = TFWBold;
 		font_language = LCNone;
 		font_language = LCNone;
 		font_name = (match config.ttfc_font_name with Some s -> s | None -> ttf.ttf_font_name);
 		font_name = (match config.ttfc_font_name with Some s -> s | None -> ttf.ttf_font_name);
 		font_glyphs = glyfs;
 		font_glyphs = glyfs;

+ 1 - 1
opam

@@ -21,7 +21,7 @@ remove: [make "uninstall" "INSTALL_DIR=%{prefix}%"]
 depends: [
 depends: [
   "ocaml"               {>= "4.02"}
   "ocaml"               {>= "4.02"}
   "ocamlfind"           {build}
   "ocamlfind"           {build}
-  "camlp4"              {build}
+  "camlp5"              {build}
   "sedlex"              {build & <= "1.99.4"} #https://github.com/HaxeFoundation/haxe/issues/7958
   "sedlex"              {build & <= "1.99.4"} #https://github.com/HaxeFoundation/haxe/issues/7958
   "ppx_tools_versioned" {build & != "5.2.1"} #https://github.com/alainfrisch/sedlex/issues/64
   "ppx_tools_versioned" {build & != "5.2.1"} #https://github.com/alainfrisch/sedlex/issues/64
   "xml-light"           {build}
   "xml-light"           {build}

+ 144 - 121
src-json/define.json

@@ -2,148 +2,154 @@
 	{
 	{
 		"name": "AbsolutePath",
 		"name": "AbsolutePath",
 		"define": "absolute_path",
 		"define": "absolute_path",
-		"doc": "Print absolute file path in trace output"
+		"doc": "Print absolute file path in trace output."
 	},
 	},
 	{
 	{
 		"name": "AdvancedTelemetry",
 		"name": "AdvancedTelemetry",
 		"define": "advanced-telemetry",
 		"define": "advanced-telemetry",
-		"doc": "Allow the SWF to be measured with Monocle tool",
+		"doc": "Allow the SWF to be measured with Monocle tool.",
 		"platforms": ["flash"]
 		"platforms": ["flash"]
 	},
 	},
 	{
 	{
 		"name": "AnnotateSource",
 		"name": "AnnotateSource",
 		"define": "annotate_source",
 		"define": "annotate_source",
-		"doc": "Add additional comments to generated source code",
+		"doc": "Add additional comments to generated source code.",
 		"platforms": ["cpp"]
 		"platforms": ["cpp"]
 	},
 	},
 	{
 	{
 		"name": "As3",
 		"name": "As3",
 		"define": "as3",
 		"define": "as3",
-		"doc": "Defined when outputting flash9 as3 source code"
+		"doc": "Defined when outputting flash9 as3 source code."
 	},
 	},
 	{
 	{
 		"name": "CheckXmlProxy",
 		"name": "CheckXmlProxy",
 		"define": "check_xml_proxy",
 		"define": "check_xml_proxy",
-		"doc": "Check the used fields of the xml proxy"
+		"doc": "Check the used fields of the XML proxy."
 	},
 	},
 	{
 	{
 		"name": "CoreApi",
 		"name": "CoreApi",
 		"define": "core_api",
 		"define": "core_api",
-		"doc": "Defined in the core api context"
+		"doc": "Defined in the core API context."
 	},
 	},
 	{
 	{
 		"name": "CoreApiSerialize",
 		"name": "CoreApiSerialize",
 		"define": "core_api_serialize",
 		"define": "core_api_serialize",
-		"doc": "Mark some generated core api classes with the Serializable attribute on C#",
+		"doc": "Mark some generated core API classes with the `Serializable` attribute on C#.",
 		"platforms": ["cs"]
 		"platforms": ["cs"]
 	},
 	},
 	{
 	{
 		"name": "Cppia",
 		"name": "Cppia",
 		"define": "cppia",
 		"define": "cppia",
-		"doc": "Generate cpp instruction assembly"
+		"doc": "Generate cpp instruction assembly."
 	},
 	},
 	{
 	{
 		"name": "CsVer",
 		"name": "CsVer",
 		"define": "cs_ver",
 		"define": "cs_ver",
-		"doc": "The C# version to target",
+		"doc": "The C# version to target.",
 		"platforms": ["cs"]
 		"platforms": ["cs"]
 	},
 	},
 	{
 	{
 		"name": "NoCppiaAst",
 		"name": "NoCppiaAst",
 		"define": "nocppiaast",
 		"define": "nocppiaast",
-		"doc": "Use legacy cppia generation"
+		"doc": "Use legacy cppia generation."
 	},
 	},
 	{
 	{
 		"name": "Dce",
 		"name": "Dce",
 		"define": "dce",
 		"define": "dce",
-		"doc": "<mode:std|full|no> Set the dead code elimination mode (default std)"
+		"doc": "Set the dead code elimination mode. (default: std)",
+		"params": ["mode: std | full | no"],
+		"links": ["https://haxe.org/manual/cr-dce.html"]
 	},
 	},
 	{
 	{
 		"name": "DceDebug",
 		"name": "DceDebug",
 		"define": "dce_debug",
 		"define": "dce_debug",
-		"doc": "Show DCE log"
+		"doc": "Show DCE log.",
+		"links": ["https://haxe.org/manual/cr-dce.html"]
 	},
 	},
 	{
 	{
 		"name": "Debug",
 		"name": "Debug",
 		"define": "debug",
 		"define": "debug",
-		"doc": "Activated when compiling with -debug"
+		"doc": "Activated when compiling with -debug."
 	},
 	},
 	{
 	{
 		"name": "DisableUnicodeStrings",
 		"name": "DisableUnicodeStrings",
 		"define": "disable_unicode_strings",
 		"define": "disable_unicode_strings",
-		"doc": "Disable unicode support in String type on some platforms",
+		"doc": "Disable Unicode support in `String` type.",
 		"platforms": ["cpp"]
 		"platforms": ["cpp"]
 	},
 	},
 	{
 	{
 		"name": "Display",
 		"name": "Display",
 		"define": "display",
 		"define": "display",
-		"doc": "Activated during completion"
+		"doc": "Activated during completion.",
+		"links": ["https://haxe.org/manual/cr-completion.html"]
 	},
 	},
 	{
 	{
 		"name": "DisplayStdin",
 		"name": "DisplayStdin",
 		"define": "display_stdin",
 		"define": "display_stdin",
-		"doc": "Read the contents of a file specified in --display from standard input"
+		"doc": "Read the contents of a file specified in `--display` from standard input."
 	},
 	},
 	{
 	{
 		"name": "DllExport",
 		"name": "DllExport",
 		"define": "dll_export",
 		"define": "dll_export",
-		"doc": "GenCPP experimental linking",
+		"doc": "GenCPP experimental linking.",
 		"platforms": ["cpp"]
 		"platforms": ["cpp"]
 	},
 	},
 	{
 	{
 		"name": "DllImport",
 		"name": "DllImport",
 		"define": "dll_import",
 		"define": "dll_import",
-		"doc": "Handle Haxe-generated .NET dll imports",
+		"doc": "Handle Haxe-generated .NET DLL imports.",
 		"platforms": ["cs"]
 		"platforms": ["cs"]
 	},
 	},
 	{
 	{
 		"name": "DocGen",
 		"name": "DocGen",
 		"define": "doc_gen",
 		"define": "doc_gen",
-		"doc": "Do not perform any removal/change in order to correctly generate documentation"
+		"doc": "Do not perform any removal/change in order to correctly generate documentation."
 	},
 	},
 	{
 	{
 		"name": "Dump",
 		"name": "Dump",
 		"define": "dump",
 		"define": "dump",
-		"doc": "<mode:pretty|record|position|legacy> Dump typed AST in dump subdirectory using specified mode or non-prettified default"
+		"doc": "Dump typed AST in dump subdirectory using specified mode or non-prettified default.",
+		"params": ["mode: pretty | record | position | legacy"]
 	},
 	},
 	{
 	{
 		"name": "DumpDependencies",
 		"name": "DumpDependencies",
 		"define": "dump_dependencies",
 		"define": "dump_dependencies",
-		"doc": "Dump the classes dependencies in a dump subdirectory"
+		"doc": "Dump the classes dependencies in a dump subdirectory."
 	},
 	},
 	{
 	{
 		"name": "DumpIgnoreVarIds",
 		"name": "DumpIgnoreVarIds",
 		"define": "dump_ignore_var_ids",
 		"define": "dump_ignore_var_ids",
-		"doc": "Remove variable IDs from non-pretty dumps (helps with diff)"
+		"doc": "Remove variable IDs from non-pretty dumps (helps with diff)."
 	},
 	},
 	{
 	{
 		"name": "DynamicInterfaceClosures",
 		"name": "DynamicInterfaceClosures",
 		"define": "dynamic_interface_closures",
 		"define": "dynamic_interface_closures",
-		"doc": "Use slow path for interface closures to save space",
+		"doc": "Use slow path for interface closures to save space.",
 		"platforms": ["cpp"]
 		"platforms": ["cpp"]
 	},
 	},
 	{
 	{
 		"name": "EraseGenerics",
 		"name": "EraseGenerics",
 		"define": "erase_generics",
 		"define": "erase_generics",
-		"doc": "Erase generic classes on C#",
+		"doc": "Erase generic classes on C#.",
 		"platforms": ["cs"]
 		"platforms": ["cs"]
 	},
 	},
 	{
 	{
 		"name": "EvalCallStackDepth",
 		"name": "EvalCallStackDepth",
 		"define": "eval_call_stack_depth",
 		"define": "eval_call_stack_depth",
-		"doc": "Set maximum call stack depth for eval. Default: 1000.",
-		"platforms": ["eval"]
+		"doc": "Set maximum call stack depth for eval. (default: 1000)",
+		"platforms": ["eval"],
+		"params": ["depth"]
 	},
 	},
 	{
 	{
 		"name": "EvalDebugger",
 		"name": "EvalDebugger",
 		"define": "eval_debugger",
 		"define": "eval_debugger",
-		"doc": "Support debugger in macro/interp mode. Allows host:port value to open a socket. Implies eval_stack.",
+		"doc": "Support debugger in macro/interp mode. Allows `host:port` value to open a socket. Implies eval_stack.",
 		"platforms": ["eval"]
 		"platforms": ["eval"]
 	},
 	},
 	{
 	{
 		"name": "EvalStack",
 		"name": "EvalStack",
 		"define": "eval_stack",
 		"define": "eval_stack",
-		"doc": "Record stack information in macro/interp mode",
+		"doc": "Record stack information in macro/interp mode.",
 		"platforms": ["eval"]
 		"platforms": ["eval"]
 	},
 	},
 	{
 	{
@@ -155,301 +161,310 @@
 	{
 	{
 		"name": "FastCast",
 		"name": "FastCast",
 		"define": "fast_cast",
 		"define": "fast_cast",
-		"doc": "Enables an experimental casts cleanup on C# and Java",
+		"doc": "Enables an experimental casts cleanup on C# and Java.",
 		"platforms": ["cs", "java"]
 		"platforms": ["cs", "java"]
 	},
 	},
 	{
 	{
 		"name": "Fdb",
 		"name": "Fdb",
 		"define": "fdb",
 		"define": "fdb",
-		"doc": "Enable full flash debug infos for FDB interactive debugging",
+		"doc": "Enable full flash debug infos for FDB interactive debugging.",
 		"platforms": ["flash"]
 		"platforms": ["flash"]
 	},
 	},
 	{
 	{
 		"name": "FileExtension",
 		"name": "FileExtension",
 		"define": "file_extension",
 		"define": "file_extension",
-		"doc": "Output filename extension for cpp source code",
+		"doc": "Output filename extension for cpp source code.",
 		"platforms": ["cpp"]
 		"platforms": ["cpp"]
 	},
 	},
 	{
 	{
 		"name": "FlashStrict",
 		"name": "FlashStrict",
 		"define": "flash_strict",
 		"define": "flash_strict",
-		"doc": "More strict typing for flash target",
+		"doc": "More strict typing for flash target.",
 		"platforms": ["flash"]
 		"platforms": ["flash"]
 	},
 	},
 	{
 	{
 		"name": "FlashUseStage",
 		"name": "FlashUseStage",
 		"define": "flash_use_stage",
 		"define": "flash_use_stage",
-		"doc": "Keep the SWF library initial stage",
+		"doc": "Keep the SWF library initial stage.",
 		"platforms": ["flash"]
 		"platforms": ["flash"]
 	},
 	},
 	{
 	{
 		"devcomment": "force_lib_check is only here as a debug facility - compiler checking allows errors to be found more easily",
 		"devcomment": "force_lib_check is only here as a debug facility - compiler checking allows errors to be found more easily",
 		"name": "ForceLibCheck",
 		"name": "ForceLibCheck",
 		"define": "force_lib_check",
 		"define": "force_lib_check",
-		"doc": "Force the compiler to check -net-lib and -java-lib added classes (internal)",
+		"doc": "Force the compiler to check `--net-lib` and `–-java-lib` added classes (internal).",
 		"platforms": ["cs", "java"]
 		"platforms": ["cs", "java"]
 	},
 	},
 	{
 	{
 		"name": "ForceNativeProperty",
 		"name": "ForceNativeProperty",
 		"define": "force_native_property",
 		"define": "force_native_property",
-		"doc": "Tag all properties with :nativeProperty metadata for 3.1 compatibility",
+		"doc": "Tag all properties with `:nativeProperty` metadata for 3.1 compatibility.",
 		"platforms": ["cpp"]
 		"platforms": ["cpp"]
 	},
 	},
 	{
 	{
 		"name": "GencommonDebug",
 		"name": "GencommonDebug",
 		"define": "gencommon_debug",
 		"define": "gencommon_debug",
-		"doc": "GenCommon internal",
+		"doc": "GenCommon internal.",
 		"platforms": ["cs", "java"]
 		"platforms": ["cs", "java"]
 	},
 	},
 	{
 	{
 		"name": "Haxe3Compat",
 		"name": "Haxe3Compat",
 		"define": "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."
 	},
 	},
 	{
 	{
 		"name": "HaxeBoot",
 		"name": "HaxeBoot",
 		"define": "haxe_boot",
 		"define": "haxe_boot",
-		"doc": "Given the name 'haxe' to the flash boot class instead of a generated name",
+		"doc": "Give the name 'haxe' to the flash boot class instead of a generated name.",
 		"platforms": ["flash"]
 		"platforms": ["flash"]
 	},
 	},
 	{
 	{
 		"name": "HaxeVer",
 		"name": "HaxeVer",
 		"define": "haxe_ver",
 		"define": "haxe_ver",
-		"doc": "The current Haxe version value as decimal number. E.g. 4.000 for 4.0.0"
+		"doc": "The current Haxe version value as decimal number. E.g. 3.407 for 3.4.7."
 	},
 	},
 	{
 	{
 		"name": "Haxe",
 		"name": "Haxe",
 		"define": "haxe",
 		"define": "haxe",
-		"doc": "The current Haxe version value in SemVer format"
+		"doc": "The current Haxe version value in SemVer format."
 	},
 	},
 	{
 	{
 		"name": "HxcppApiLevel",
 		"name": "HxcppApiLevel",
 		"define": "hxcpp_api_level",
 		"define": "hxcpp_api_level",
-		"doc": "Provided to allow compatibility between hxcpp versions",
+		"doc": "Provided to allow compatibility between hxcpp versions.",
 		"platforms": ["cpp"]
 		"platforms": ["cpp"]
 	},
 	},
 	{
 	{
 		"name": "HxcppGcGenerational",
 		"name": "HxcppGcGenerational",
-		"define": "HXCPP_GC_GENERATIONAL",
-		"doc": "Experimental Garbage Collector",
+		"define": "hxcpp_gc_generational",
+		"doc": "Experimental Garbage Collector.",
 		"platforms": ["cpp"]
 		"platforms": ["cpp"]
 	},
 	},
 	{
 	{
 		"name": "HxcppDebugger",
 		"name": "HxcppDebugger",
-		"define": "HXCPP_DEBUGGER",
-		"doc": "Include additional information for HXCPP_DEBUGGER",
+		"define": "hxcpp_debugger",
+		"doc": "Include additional information for hxcpp_debugger.",
 		"platforms": ["cpp"]
 		"platforms": ["cpp"]
 	},
 	},
 	{
 	{
 		"name": "HxcppSmartStings",
 		"name": "HxcppSmartStings",
 		"define": "hxcpp_smart_strings",
 		"define": "hxcpp_smart_strings",
-		"doc": "Use wide strings in hxcpp (Turned on by default unless `-D disable_unicode_strings` is specified)",
+		"doc": "Use wide strings in hxcpp. (Turned on by default unless `-D disable_unicode_strings` is specified.)",
 		"platforms": ["cpp"]
 		"platforms": ["cpp"]
 	},
 	},
 	{
 	{
 		"name": "IncludePrefix",
 		"name": "IncludePrefix",
 		"define": "include_prefix",
 		"define": "include_prefix",
-		"doc": "prepend path to generated include files",
+		"doc": "Prepend path to generated include files.",
 		"platforms": ["cpp"]
 		"platforms": ["cpp"]
 	},
 	},
 	{
 	{
 		"name": "Interp",
 		"name": "Interp",
 		"define": "interp",
 		"define": "interp",
-		"doc": "The code is compiled to be run with --interp"
+		"doc": "The code is compiled to be run with `--interp`."
 	},
 	},
 	{
 	{
 		"name": "JavaVer",
 		"name": "JavaVer",
 		"define": "java_ver",
 		"define": "java_ver",
-		"doc": "<version:5-7> Sets the Java version to be targeted",
-		"platforms": ["java"]
+		"doc": "Sets the Java version to be targeted.",
+		"platforms": ["java"],
+		"params": ["version: 5-7"]
 	},
 	},
 	{
 	{
 		"name": "JsClassic",
 		"name": "JsClassic",
 		"define": "js_classic",
 		"define": "js_classic",
-		"doc": "Don't use a function wrapper and strict mode in JS output",
+		"doc": "Don't use a function wrapper and strict mode in JS output.",
 		"platforms": ["js"]
 		"platforms": ["js"]
 	},
 	},
 	{
 	{
 		"name": "JsEs",
 		"name": "JsEs",
 		"define": "js_es",
 		"define": "js_es",
-		"doc": "Generate JS compliant with given ES standard version (default 5)",
+		"doc": "Generate JS compliant with given ES standard version. (default: 5)",
 		"platforms": ["js"],
 		"platforms": ["js"],
-		"params": ["version number"]
+		"params": ["version number"],
+		"links": ["https://haxe.org/manual/target-javascript-es6.html"]
 	},
 	},
 	{
 	{
 		"name": "JsEnumsAsArrays",
 		"name": "JsEnumsAsArrays",
 		"define": "js_enums_as_arrays",
 		"define": "js_enums_as_arrays",
-		"doc": "Generate enum representation as array instead of as object",
+		"doc": "Generate enum representation as array instead of as object.",
 		"platforms": ["js"]
 		"platforms": ["js"]
 	},
 	},
 	{
 	{
 		"name": "JsUnflatten",
 		"name": "JsUnflatten",
 		"define": "js_unflatten",
 		"define": "js_unflatten",
-		"doc": "Generate nested objects for packages and types",
+		"doc": "Generate nested objects for packages and types.",
 		"platforms": ["js"]
 		"platforms": ["js"]
 	},
 	},
 	{
 	{
 		"name": "JsSourceMap",
 		"name": "JsSourceMap",
 		"define": "js_source_map",
 		"define": "js_source_map",
-		"doc": "Generate JavaScript source map even in non-debug mode",
+		"doc": "Generate JavaScript source map even in non-debug mode.",
 		"platforms": ["js"]
 		"platforms": ["js"]
 	},
 	},
 	{
 	{
 		"name": "Jvm",
 		"name": "Jvm",
 		"define": "jvm",
 		"define": "jvm",
-		"doc": "Generate jvm directly",
+		"doc": "Generate jvm directly.",
 		"platforms": ["java"]
 		"platforms": ["java"]
 	},
 	},
 	{
 	{
 		"name": "SourceMap",
 		"name": "SourceMap",
 		"define": "source_map",
 		"define": "source_map",
-		"doc": "Generate source map for compiled files (Currently supported for php only)",
+		"doc": "Generate source map for compiled files.",
 		"platforms": ["php"]
 		"platforms": ["php"]
 	},
 	},
 	{
 	{
 		"name": "KeepOldOutput",
 		"name": "KeepOldOutput",
 		"define": "keep_old_output",
 		"define": "keep_old_output",
-		"doc": "Keep old source files in the output directory",
+		"doc": "Keep old source files in the output directory.",
 		"platforms": ["cs", "java"]
 		"platforms": ["cs", "java"]
 	},
 	},
 	{
 	{
 		"name": "LoopUnrollMaxCost",
 		"name": "LoopUnrollMaxCost",
 		"define": "loop_unroll_max_cost",
 		"define": "loop_unroll_max_cost",
-		"doc": "Maximum cost (number of expressions * iterations) before loop unrolling is canceled (default 250)"
+		"doc": "Maximum cost (number of expressions * iterations) before loop unrolling is canceled. (default: 250)",
+		"params": ["cost"]
 	},
 	},
 	{
 	{
 		"name": "LuaJit",
 		"name": "LuaJit",
 		"define": "lua_jit",
 		"define": "lua_jit",
-		"doc": "Enable the jit compiler for lua (version 5.2 only)",
+		"doc": "Enable the jit compiler for lua (version 5.2 only).",
 		"platforms": ["lua"]
 		"platforms": ["lua"]
 	},
 	},
 	{
 	{
 		"name": "LuaVanilla",
 		"name": "LuaVanilla",
 		"define": "lua_vanilla",
 		"define": "lua_vanilla",
-		"doc": "Generate code lacking compiled extern lib support (e.g. utf8)",
+		"doc": "Generate code lacking compiled extern lib support (e.g. utf8).",
 		"platforms": ["lua"]
 		"platforms": ["lua"]
 	},
 	},
 	{
 	{
 		"name": "LuaVer",
 		"name": "LuaVer",
 		"define": "lua_ver",
 		"define": "lua_ver",
-		"doc": "The lua version to target",
-		"platforms": ["lua"]
+		"doc": "The lua version to target.",
+		"platforms": ["lua"],
+		"params": ["version"]
 	},
 	},
 	{
 	{
 		"name": "Macro",
 		"name": "Macro",
 		"define": "macro",
 		"define": "macro",
-		"doc": "Defined when code is compiled in the macro context"
+		"doc": "Defined when code is compiled in the macro context.",
+		"links": ["https://haxe.org/manual/macro.html"]
 	},
 	},
 	{
 	{
 		"name": "MacroTimes",
 		"name": "MacroTimes",
 		"define": "macro_times",
 		"define": "macro_times",
-		"doc": "Display per-macro timing when used with --times"
+		"doc": "Display per-macro timing when used with `--times`."
 	},
 	},
 	{
 	{
 		"name": "NetVer",
 		"name": "NetVer",
 		"define": "net_ver",
 		"define": "net_ver",
-		"doc": "<version:20-45> Sets the .NET version to be targeted",
-		"platforms": ["cs"]
+		"doc": "Sets the .NET version to be targeted.",
+		"platforms": ["cs"],
+		"params": ["version: 20-45"]
 	},
 	},
 	{
 	{
 		"name": "NetcoreVer",
 		"name": "NetcoreVer",
 		"define": "netcore_ver",
 		"define": "netcore_ver",
-		"doc": "<version:x.x.x> Sets the .NET core version to be targeted",
-		"platforms": ["cs"]
+		"doc": "Sets the .NET core version to be targeted",
+		"platforms": ["cs"],
+		"params": ["version: x.x.x"]
 	},
 	},
 	{
 	{
 		"name": "NetTarget",
 		"name": "NetTarget",
 		"define": "net_target",
 		"define": "net_target",
-		"doc": "<name> Sets the .NET target. Defaults to \"net\". netcore, xbox, micro (Micro Framework), compact (Compact Framework) are some valid values",
-		"platforms": ["cs"]
+		"doc": "Sets the .NET target. `netcore` (.NET core), `xbox`, `micro` (Micro Framework), `compact` (Compact Framework) are some valid values. (default: `net`)",
+		"platforms": ["cs"],
+		"params": ["name"]
 	},
 	},
 	{
 	{
 		"name": "NekoSource",
 		"name": "NekoSource",
 		"define": "neko_source",
 		"define": "neko_source",
-		"doc": "Output neko source instead of bytecode",
+		"doc": "Output neko source instead of bytecode.",
 		"platforms": ["neko"]
 		"platforms": ["neko"]
 	},
 	},
 	{
 	{
 		"name": "NekoV1",
 		"name": "NekoV1",
 		"define": "neko_v1",
 		"define": "neko_v1",
-		"doc": "Keep Neko 1.x compatibility",
+		"doc": "Keep Neko 1.x compatibility.",
 		"platforms": ["neko"]
 		"platforms": ["neko"]
 	},
 	},
 	{
 	{
 		"name": "NetworkSandbox",
 		"name": "NetworkSandbox",
 		"define": "network-sandbox",
 		"define": "network-sandbox",
-		"doc": "Use local network sandbox instead of local file access one",
+		"doc": "Use local network sandbox instead of local file access one.",
 		"platforms": ["flash"]
 		"platforms": ["flash"]
 	},
 	},
 	{
 	{
 		"name": "NoCompilation",
 		"name": "NoCompilation",
 		"define": "no-compilation",
 		"define": "no-compilation",
-		"doc": "Disable final compilation",
+		"doc": "Disable final compilation.",
 		"platforms": ["cs", "java", "cpp", "hl"]
 		"platforms": ["cs", "java", "cpp", "hl"]
 	},
 	},
 	{
 	{
 		"name": "NoCOpt",
 		"name": "NoCOpt",
 		"define": "no_copt",
 		"define": "no_copt",
-		"doc": "Disable completion optimization (for debug purposes)"
+		"doc": "Disable completion optimization (for debug purposes)."
 	},
 	},
 	{
 	{
 		"name": "NoDebug",
 		"name": "NoDebug",
 		"define": "no_debug",
 		"define": "no_debug",
-		"doc": "Remove all debug macros from cpp output"
+		"doc": "Remove all debug macros from cpp output."
 	},
 	},
 	{
 	{
 		"name": "NoDeprecationWarnings",
 		"name": "NoDeprecationWarnings",
 		"define": "no-deprecation-warnings",
 		"define": "no-deprecation-warnings",
-		"doc": "Do not warn if fields annotated with @:deprecated are used"
+		"doc": "Do not warn if fields annotated with `@:deprecated` are used."
 	},
 	},
 	{
 	{
 		"name": "NoFlashOverride",
 		"name": "NoFlashOverride",
 		"define": "no-flash-override",
 		"define": "no-flash-override",
-		"doc": "Change overrides on some basic classes into HX suffixed methods, flash only",
+		"doc": "Change overrides on some basic classes into HX suffixed methods",
 		"platforms": ["flash"]
 		"platforms": ["flash"]
 	},
 	},
 	{
 	{
 		"name": "NoOpt",
 		"name": "NoOpt",
 		"define": "no_opt",
 		"define": "no_opt",
-		"doc": "Disable optimizations"
+		"doc": "Disable optimizations."
 	},
 	},
 	{
 	{
 		"name": "NoInline",
 		"name": "NoInline",
 		"define": "no_inline",
 		"define": "no_inline",
-		"doc": "Disable inlining"
+		"doc": "Disable inlining.",
+		"links": ["https://haxe.org/manual/class-field-inline.html"]
 	},
 	},
 	{
 	{
 		"name": "NoRoot",
 		"name": "NoRoot",
 		"define": "no_root",
 		"define": "no_root",
-		"doc": "Generate top-level types into haxe.root namespace",
+		"doc": "Generate top-level types into the `haxe.root` namespace.",
 		"platforms": ["cs"]
 		"platforms": ["cs"]
 	},
 	},
 	{
 	{
 		"name": "NoMacroCache",
 		"name": "NoMacroCache",
 		"define": "no_macro_cache",
 		"define": "no_macro_cache",
-		"doc": "Disable macro context caching"
+		"doc": "Disable macro context caching."
 	},
 	},
 	{
 	{
 		"name": "NoSwfCompress",
 		"name": "NoSwfCompress",
 		"define": "no_swf_compress",
 		"define": "no_swf_compress",
-		"doc": "Disable SWF output compression",
+		"doc": "Disable SWF output compression.",
 		"platforms": ["flash"]
 		"platforms": ["flash"]
 	},
 	},
 	{
 	{
 		"name": "NoTraces",
 		"name": "NoTraces",
 		"define": "no_traces",
 		"define": "no_traces",
-		"doc": "Disable all trace calls"
+		"doc": "Disable all trace calls."
 	},
 	},
 	{
 	{
 		"name": "Objc",
 		"name": "Objc",
 		"define": "objc",
 		"define": "objc",
-		"doc": "Sets the hxcpp output to objective-c++ classes. Must be defined for interop",
+		"doc": "Sets the hxcpp output to Objective-C++ classes. Must be defined for interop.",
 		"platforms": ["cpp"]
 		"platforms": ["cpp"]
 	},
 	},
 	{
 	{
 		"name": "OldConstructorInline",
 		"name": "OldConstructorInline",
 		"define": "old-constructor-inline",
 		"define": "old-constructor-inline",
-		"doc": "Use old constructor inlining logic (from haxe 3.4.2) instead of the reworked version."
+		"doc": "Use old constructor inlining logic (from Haxe 3.4.2) instead of the reworked version."
 	},
 	},
 	{
 	{
 		"name": "OldErrorFormat",
 		"name": "OldErrorFormat",
@@ -460,157 +475,165 @@
 		"name": "PhpPrefix",
 		"name": "PhpPrefix",
 		"define": "php_prefix",
 		"define": "php_prefix",
 		"doc": "Root namespace for generated php classes. E.g. if compiled with`-D php-prefix=some.sub`, then all classes will be generated in `\\some\\sub` namespace.",
 		"doc": "Root namespace for generated php classes. E.g. if compiled with`-D php-prefix=some.sub`, then all classes will be generated in `\\some\\sub` namespace.",
-		"platforms": ["php"]
+		"platforms": ["php"],
+		"params": ["dot-separated namespace"]
 	},
 	},
 	{
 	{
 		"name": "PhpLib",
 		"name": "PhpLib",
 		"define": "php_lib",
 		"define": "php_lib",
 		"doc": "Select the name for the php lib folder.",
 		"doc": "Select the name for the php lib folder.",
-		"platforms": ["php"]
+		"platforms": ["php"],
+		"params": ["folder name"]
 	},
 	},
 	{
 	{
 		"name": "PhpFront",
 		"name": "PhpFront",
 		"define": "php_front",
 		"define": "php_front",
-		"doc": "Select the name for the php front file (by default: `index.php`).",
-		"platforms": ["php"]
+		"doc": "Select the name for the php front file. (default: `index.php`)",
+		"platforms": ["php"],
+		"params": ["filename"]
 	},
 	},
 	{
 	{
 		"name": "PythonVersion",
 		"name": "PythonVersion",
 		"define": "python_version",
 		"define": "python_version",
-		"doc": "The python version to target (default 3.3)",
-		"platforms": ["python"]
+		"doc": "The python version to target. (default: 3.3)",
+		"platforms": ["python"],
+		"params": ["version"]
 	},
 	},
 	{
 	{
 		"name": "RealPosition",
 		"name": "RealPosition",
 		"define": "real_position",
 		"define": "real_position",
-		"doc": "Disables Haxe source mapping when targetting C#, removes position comments in Java and Php output",
+		"doc": "Disables Haxe source mapping when targetting C#, removes position comments in Java and Php output.",
 		"platforms": ["cs", "java", "php"]
 		"platforms": ["cs", "java", "php"]
 	},
 	},
 	{
 	{
 		"name": "ReplaceFiles",
 		"name": "ReplaceFiles",
 		"define": "replace_files",
 		"define": "replace_files",
-		"doc": "GenCommon internal",
+		"doc": "GenCommon internal.",
 		"platforms": ["cs", "java"]
 		"platforms": ["cs", "java"]
 	},
 	},
 	{
 	{
 		"name": "Scriptable",
 		"name": "Scriptable",
 		"define": "scriptable",
 		"define": "scriptable",
-		"doc": "GenCPP internal",
+		"doc": "GenCPP internal.",
 		"platforms": ["cpp"]
 		"platforms": ["cpp"]
 	},
 	},
 	{
 	{
 		"name": "ShallowExpose",
 		"name": "ShallowExpose",
 		"define": "shallow-expose",
 		"define": "shallow-expose",
-		"doc": "Expose types to surrounding scope of Haxe generated closure without writing to window object",
+		"doc": "Expose types to surrounding scope of Haxe generated closure without writing to window object.",
 		"platforms": ["js"]
 		"platforms": ["js"]
 	},
 	},
 	{
 	{
 		"name": "SourceHeader",
 		"name": "SourceHeader",
 		"define": "source-header",
 		"define": "source-header",
-		"doc": "Print value as comment on top of generated files, use '' value to disable"
+		"doc": "Print value as comment on top of generated files, use '' value to disable."
 	},
 	},
 	{
 	{
 		"name": "SourceMapContent",
 		"name": "SourceMapContent",
 		"define": "source-map-content",
 		"define": "source-map-content",
-		"doc": "Include the hx sources as part of the JS source map",
+		"doc": "Include the Haxe sources as part of the JS source map.",
 		"platforms": ["js"]
 		"platforms": ["js"]
 	},
 	},
 	{
 	{
 		"name": "Static",
 		"name": "Static",
 		"define": "static",
 		"define": "static",
-		"doc": "Defined if the current target is static"
+		"doc": "Defined if the current target is static."
 	},
 	},
 	{
 	{
 		"name": "Swc",
 		"name": "Swc",
 		"define": "swc",
 		"define": "swc",
-		"doc": "Output a SWC instead of a SWF",
+		"doc": "Output a SWC instead of a SWF.",
 		"platforms": ["flash"]
 		"platforms": ["flash"]
 	},
 	},
 	{
 	{
 		"name": "SwfCompressLevel",
 		"name": "SwfCompressLevel",
 		"define": "swf_compress_level",
 		"define": "swf_compress_level",
-		"doc": "<level:1-9> Set the amount of compression for the SWF output",
-		"platforms": ["flash"]
+		"doc": "Set the amount of compression for the SWF output.",
+		"platforms": ["flash"],
+		"params": ["level: 1-9"]
 	},
 	},
 	{
 	{
 		"name": "SwfDebugPassword",
 		"name": "SwfDebugPassword",
 		"define": "swf_debug_password",
 		"define": "swf_debug_password",
-		"doc": "Set a password for debugging",
-		"platforms": ["flash"]
+		"doc": "Set a password for debugging.",
+		"platforms": ["flash"],
+		"params": ["password"]
 	},
 	},
 	{
 	{
 		"name": "SwfDirectBlit",
 		"name": "SwfDirectBlit",
 		"define": "swf_direct_blit",
 		"define": "swf_direct_blit",
-		"doc": "Use hardware acceleration to blit graphics",
+		"doc": "Use hardware acceleration to blit graphics.",
 		"platforms": ["flash"]
 		"platforms": ["flash"]
 	},
 	},
 	{
 	{
 		"name": "SwfGpu",
 		"name": "SwfGpu",
 		"define": "swf_gpu",
 		"define": "swf_gpu",
-		"doc": "Use GPU compositing features when drawing graphics",
+		"doc": "Use GPU compositing features when drawing graphics.",
 		"platforms": ["flash"]
 		"platforms": ["flash"]
 	},
 	},
 	{
 	{
 		"name": "SwfMetadata",
 		"name": "SwfMetadata",
 		"define": "swf_metadata",
 		"define": "swf_metadata",
-		"doc": "<file> Include contents of <file> as metadata in the swf",
-		"platforms": ["flash"]
+		"doc": "Include contents of the given file as metadata in the SWF.",
+		"platforms": ["flash"],
+		"params": ["file"]
 	},
 	},
 	{
 	{
 		"name": "SwfPreloaderFrame",
 		"name": "SwfPreloaderFrame",
 		"define": "swf_preloader_frame",
 		"define": "swf_preloader_frame",
-		"doc": "Insert empty first frame in swf",
+		"doc": "Insert empty first frame in SWF.",
 		"platforms": ["flash"]
 		"platforms": ["flash"]
 	},
 	},
 	{
 	{
 		"name": "SwfProtected",
 		"name": "SwfProtected",
 		"define": "swf_protected",
 		"define": "swf_protected",
-		"doc": "Compile Haxe private as protected in the SWF instead of public",
+		"doc": "Compile Haxe `private` as `protected` in the SWF instead of `public`.",
 		"platforms": ["flash"]
 		"platforms": ["flash"]
 	},
 	},
 	{
 	{
 		"name": "SwfScriptTimeout",
 		"name": "SwfScriptTimeout",
 		"define": "swf_script_timeout",
 		"define": "swf_script_timeout",
-		"doc": "Maximum ActionScript processing time before script stuck dialog box displays (in seconds)",
-		"platforms": ["flash"]
+		"doc": "Maximum ActionScript processing time before script stuck dialog box displays.",
+		"platforms": ["flash"],
+		"params": ["time in seconds"]
 	},
 	},
 	{
 	{
 		"name": "SwfUseDoAbc",
 		"name": "SwfUseDoAbc",
 		"define": "swf_use_doabc",
 		"define": "swf_use_doabc",
-		"doc": "Use DoAbc swf-tag instead of DoAbcDefine",
+		"doc": "Use `DoAbc` SWF-tag instead of `DoAbcDefine`.",
 		"platforms": ["flash"]
 		"platforms": ["flash"]
 	},
 	},
 	{
 	{
 		"name": "Sys",
 		"name": "Sys",
 		"define": "sys",
 		"define": "sys",
-		"doc": "Defined for all system platforms"
+		"doc": "Defined for all system platforms."
 	},
 	},
 	{
 	{
 		"name": "Unsafe",
 		"name": "Unsafe",
 		"define": "unsafe",
 		"define": "unsafe",
-		"doc": "Allow unsafe code when targeting C#",
+		"doc": "Allow unsafe code when targeting C#.",
 		"platforms": ["cs"]
 		"platforms": ["cs"]
 	},
 	},
 	{
 	{
 		"name": "UseNekoc",
 		"name": "UseNekoc",
 		"define": "use_nekoc",
 		"define": "use_nekoc",
-		"doc": "Use nekoc compiler instead of internal one",
+		"doc": "Use `nekoc` compiler instead of the internal one.",
 		"platforms": ["neko"]
 		"platforms": ["neko"]
 	},
 	},
 	{
 	{
 		"name": "Utf16",
 		"name": "Utf16",
 		"define": "utf16",
 		"define": "utf16",
-		"doc": "Defined for all platforms that have utf16 encoding with ucs2 api"
+		"doc": "Defined for all platforms that use UTF-16 string encoding with UCS-2 API."
 	},
 	},
 	{
 	{
 		"name": "Vcproj",
 		"name": "Vcproj",
 		"define": "vcproj",
 		"define": "vcproj",
-		"doc": "GenCPP internal",
+		"doc": "GenCPP internal.",
 		"platforms": ["cpp"]
 		"platforms": ["cpp"]
 	},
 	},
 	{
 	{
 		"name": "WarnVarShadowing",
 		"name": "WarnVarShadowing",
 		"define": "warn_var_shadowing",
 		"define": "warn_var_shadowing",
-		"doc": "Warn about shadowing variable declarations"
+		"doc": "Warn about shadowing variable declarations."
 	}
 	}
 ]
 ]

Файлын зөрүү хэтэрхий том тул дарагдсан байна
+ 234 - 177
src-json/meta.json


+ 79 - 71
src/codegen/dotnet.ml

@@ -22,6 +22,7 @@ open Globals
 open Ast
 open Ast
 open IlData
 open IlData
 open IlMeta
 open IlMeta
+open NativeLibraries
 
 
 (* see http://msdn.microsoft.com/en-us/library/2sk3x8a7(v=vs.71).aspx *)
 (* see http://msdn.microsoft.com/en-us/library/2sk3x8a7(v=vs.71).aspx *)
 let cs_binops =
 let cs_binops =
@@ -126,11 +127,11 @@ let netpath_to_hx std = function
 
 
 let lookup_ilclass std com ilpath =
 let lookup_ilclass std com ilpath =
 	let path = netpath_to_hx std ilpath in
 	let path = netpath_to_hx std ilpath in
-	List.fold_right (fun (_,_,_,get_raw_class) acc ->
+	List.fold_right (fun net_lib acc ->
 		match acc with
 		match acc with
-		| None -> get_raw_class path
+		| None -> net_lib#lookup path
 		| Some p -> acc
 		| Some p -> acc
-	) com.net_libs None
+	) com.native_libs.net_libs None
 
 
 let discard_nested = function
 let discard_nested = function
 	| (ns,_),cl -> (ns,[]),cl
 	| (ns,_),cl -> (ns,[]),cl
@@ -495,7 +496,7 @@ let convert_ilmethod ctx p m is_explicit_impl =
 			| Some ilcls when not (List.mem SInterface ilcls.cflags.tdf_semantics) ->
 			| Some ilcls when not (List.mem SInterface ilcls.cflags.tdf_semantics) ->
 				(AOverride,null_pos) :: acc
 				(AOverride,null_pos) :: acc
 			| None when ctx.ncom.verbose ->
 			| None when ctx.ncom.verbose ->
-				prerr_endline ("(net-lib) A referenced assembly for path " ^ ilpath_s path ^ " was not found");
+				print_endline ("(net-lib) A referenced assembly for path " ^ ilpath_s path ^ " was not found");
 				acc
 				acc
 			| _ -> acc
 			| _ -> acc
 	in
 	in
@@ -1109,52 +1110,57 @@ let normalize_ilcls ctx cls =
 let add_net_std com file =
 let add_net_std com file =
 	com.net_std <- file :: com.net_std
 	com.net_std <- file :: com.net_std
 
 
-let add_net_lib com file std =
-	let ilctx = ref None in
-	let netpath_to_hx = netpath_to_hx std in
-	let real_file = ref file in
-	let get_ctx () =
-		match !ilctx with
-		| Some c ->
-			c
-		| None ->
-			let file = if Sys.file_exists file then
-				file
-			else try Common.find_file com file with
-				| Not_found -> try Common.find_file com (file ^ ".dll") with
-				| Not_found ->
-					failwith (".NET lib " ^ file ^ " not found")
-			in
-			real_file := file;
-			let r = PeReader.create_r (open_in_bin file) com.defines.Define.values in
-			let ctx = PeReader.read r in
-			let clr_header = PeReader.read_clr_header ctx in
-			let cache = IlMetaReader.create_cache () in
-			let meta = IlMetaReader.read_meta_tables ctx clr_header cache in
-			close_in (r.PeReader.ch);
+class net_library com name file_path std = object(self)
+	inherit [net_lib_type,unit] native_library name file_path
+
+	val mutable ilctx = None
+	val cache = Hashtbl.create 0
+
+	method private netpath_to_hx =
+		netpath_to_hx std
+
+	method load =
+		let r = PeReader.create_r (open_in_bin file_path) com.defines.Define.values in
+		let ctx = PeReader.read r in
+		let clr_header = PeReader.read_clr_header ctx in
+		let cache = IlMetaReader.create_cache () in
+		let meta = IlMetaReader.read_meta_tables ctx clr_header cache in
+		close_in (r.PeReader.ch);
+		if PMap.mem "net_loader_debug" com.defines.Define.values then
+			print_endline ("for lib " ^ file_path);
+		let il_typedefs = Hashtbl.copy meta.il_typedefs in
+		Hashtbl.clear meta.il_typedefs;
+
+		Hashtbl.iter (fun _ td ->
+			let path = IlMetaTools.get_path (TypeDef td) in
 			if PMap.mem "net_loader_debug" com.defines.Define.values then
 			if PMap.mem "net_loader_debug" com.defines.Define.values then
-				print_endline ("for lib " ^ file);
-			let il_typedefs = Hashtbl.copy meta.il_typedefs in
-			Hashtbl.clear meta.il_typedefs;
-
-			Hashtbl.iter (fun _ td ->
-				let path = IlMetaTools.get_path (TypeDef td) in
-				if PMap.mem "net_loader_debug" com.defines.Define.values then
-					Printf.printf "found %s\n" (s_type_path (netpath_to_hx path));
-				Hashtbl.replace com.net_path_map (netpath_to_hx path) path;
-				Hashtbl.replace meta.il_typedefs path td
-			) il_typedefs;
-			let meta = { nstd = std; ncom = com; nil = meta } in
-			ilctx := Some meta;
-			meta
-	in
+				Printf.printf "found %s\n" (s_type_path (self#netpath_to_hx path));
+			Hashtbl.replace com.net_path_map (self#netpath_to_hx path) path;
+			Hashtbl.replace meta.il_typedefs path td
+		) il_typedefs;
+		let meta = { nstd = std; ncom = com; nil = meta } in
+		ilctx <- Some meta
+
+	method get_ctx = match ilctx with
+		| None ->
+			self#load;
+			self#get_ctx
+		| Some ctx ->
+			ctx
+
+	method close =
+		()
 
 
-	let cache = Hashtbl.create 0 in
-	let lookup path =
+	method list_modules =
+		Hashtbl.fold (fun path _ acc -> match path with
+			| _,_ :: _, _ -> acc
+			| _ -> self#netpath_to_hx path :: acc) (self#get_ctx).nil.il_typedefs []
+
+	method lookup path : net_lib_type =
 		try
 		try
 			Hashtbl.find cache path
 			Hashtbl.find cache path
 		with | Not_found -> try
 		with | Not_found -> try
-			let ctx = get_ctx() in
+			let ctx = self#get_ctx in
 			let ns, n, cl = hxpath_to_net ctx path in
 			let ns, n, cl = hxpath_to_net ctx path in
 			let cls = IlMetaTools.convert_class ctx.nil (ns,n,cl) in
 			let cls = IlMetaTools.convert_class ctx.nil (ns,n,cl) in
 			let cls = normalize_ilcls ctx cls in
 			let cls = normalize_ilcls ctx cls in
@@ -1163,38 +1169,31 @@ let add_net_lib com file std =
 		with | Not_found ->
 		with | Not_found ->
 			Hashtbl.add cache path None;
 			Hashtbl.add cache path None;
 			None
 			None
-	in
 
 
-	let all_files () =
-		Hashtbl.fold (fun path _ acc -> match path with
-			| _,_ :: _, _ -> acc
-			| _ -> netpath_to_hx path :: acc) (get_ctx()).nil.il_typedefs []
-	in
-
-	let build path =
-		let p = { pfile = !real_file ^ " @ " ^ s_type_path path; pmin = 0; pmax = 0; } in
+	method build (path : path) (p : pos) : Ast.package option =
+		let p = { pfile = file_path ^ " @ " ^ s_type_path path; pmin = 0; pmax = 0; } in
 		let pack = match fst path with | ["haxe";"root"] -> [] | p -> p in
 		let pack = match fst path with | ["haxe";"root"] -> [] | p -> p in
 		let cp = ref [] in
 		let cp = ref [] in
 		let rec build path = try
 		let rec build path = try
 			if PMap.mem "net_loader_debug" com.defines.Define.values then
 			if PMap.mem "net_loader_debug" com.defines.Define.values then
 				Printf.printf "looking up %s\n" (s_type_path path);
 				Printf.printf "looking up %s\n" (s_type_path path);
-			match lookup path with
+			match self#lookup path with
 			| Some({csuper = Some{snorm = LClass( (["System"],[],("Delegate"|"MulticastDelegate")),_)}} as cls)
 			| Some({csuper = Some{snorm = LClass( (["System"],[],("Delegate"|"MulticastDelegate")),_)}} as cls)
 				when List.mem SSealed cls.cflags.tdf_semantics ->
 				when List.mem SSealed cls.cflags.tdf_semantics ->
-				let ctx = get_ctx() in
+				let ctx = self#get_ctx in
 				let hxcls = convert_ilclass ctx p ~delegate:true cls in
 				let hxcls = convert_ilclass ctx p ~delegate:true cls in
 				let delegate = convert_delegate ctx p cls in
 				let delegate = convert_delegate ctx p cls in
 				cp := (hxcls,p) :: (delegate,p) :: !cp;
 				cp := (hxcls,p) :: (delegate,p) :: !cp;
 				List.iter (fun ilpath ->
 				List.iter (fun ilpath ->
-					let path = netpath_to_hx ilpath in
+					let path = netpath_to_hx std ilpath in
 					build path
 					build path
 				) cls.cnested
 				) cls.cnested
 			| Some cls ->
 			| Some cls ->
-				let ctx = get_ctx() in
+				let ctx = self#get_ctx in
 				let hxcls = convert_ilclass ctx p cls in
 				let hxcls = convert_ilclass ctx p cls in
 				cp := (hxcls,p) :: !cp;
 				cp := (hxcls,p) :: !cp;
 				List.iter (fun ilpath ->
 				List.iter (fun ilpath ->
-					let path = netpath_to_hx ilpath in
+					let path = netpath_to_hx std ilpath in
 					build path
 					build path
 				) cls.cnested
 				) cls.cnested
 			| _ -> ()
 			| _ -> ()
@@ -1204,14 +1203,26 @@ let add_net_lib com file std =
 		build path;
 		build path;
 		match !cp with
 		match !cp with
 			| [] -> None
 			| [] -> None
-			| cp -> Some (!real_file, (pack,cp))
-	in
-	let build path p =
-		build path
-	in
-	com.load_extern_type <- com.load_extern_type @ [build];
-	com.net_libs <- (file, std, all_files, lookup) :: com.net_libs
+			| cp -> Some (pack,cp)
 
 
+	method get_data = ()
+
+	initializer
+		if std then self#add_flag FlagIsStd
+end
+
+let add_net_lib com file std extern =
+	let real_file = if Sys.file_exists file then
+		file
+	else try Common.find_file com file with
+		| Not_found -> try Common.find_file com (file ^ ".dll") with
+		| Not_found ->
+			failwith (".NET lib " ^ file ^ " not found")
+	in
+	let net_lib = new net_library com file real_file std in
+	if extern then net_lib#add_flag FlagIsExtern;
+	com.native_libs.net_libs <- (net_lib :> (net_lib_type,unit) native_library) :: com.native_libs.net_libs;
+	CompilationServer.handle_native_lib com net_lib
 
 
 let before_generate com =
 let before_generate com =
 	(* netcore version *)
 	(* netcore version *)
@@ -1283,13 +1294,10 @@ let before_generate com =
 				let f = Unix.readdir f in
 				let f = Unix.readdir f in
 				let finsens = String.lowercase f in
 				let finsens = String.lowercase f in
 				if String.ends_with finsens ".dll" then
 				if String.ends_with finsens ".dll" then
-					add_net_lib com (path ^ "/" ^ f) true;
+					add_net_lib com (path ^ "/" ^ f) true false ();
 				loop()
 				loop()
 			with | End_of_file ->
 			with | End_of_file ->
 				Unix.closedir f
 				Unix.closedir f
 		in
 		in
 		loop()
 		loop()
-	) !matched;
-
-	(* now force all libraries to initialize *)
-	List.iter (function (_,_,_,lookup) -> ignore (lookup ([],""))) com.net_libs
+	) !matched

+ 8 - 8
src/codegen/gencommon/gencommon.ml

@@ -947,19 +947,19 @@ let dump_descriptor gen name path_s module_s =
 				file
 				file
 	in
 	in
 	if Common.platform gen.gcon Java then
 	if Common.platform gen.gcon Java then
-		List.iter (fun (s,std,_,_,_) ->
-			if not std then begin
-				SourceWriter.write w (path s ".jar");
+		List.iter (fun java_lib ->
+			if not (java_lib#has_flag NativeLibraries.FlagIsStd) && not (java_lib#has_flag NativeLibraries.FlagIsExtern) then begin
+				SourceWriter.write w (path java_lib#get_file_path ".jar");
 				SourceWriter.newline w;
 				SourceWriter.newline w;
 			end
 			end
-		) gen.gcon.java_libs
+		) gen.gcon.native_libs.java_libs
 	else if Common.platform gen.gcon Cs then
 	else if Common.platform gen.gcon Cs then
-		List.iter (fun (s,std,_,_) ->
-			if not std then begin
-				SourceWriter.write w (path s ".dll");
+		List.iter (fun net_lib ->
+			if not (net_lib#has_flag NativeLibraries.FlagIsStd) && not (net_lib#has_flag NativeLibraries.FlagIsExtern) then begin
+				SourceWriter.write w (path net_lib#get_name ".dll");
 				SourceWriter.newline w;
 				SourceWriter.newline w;
 			end
 			end
-		) gen.gcon.net_libs;
+		) gen.gcon.native_libs.net_libs;
 	SourceWriter.write w "end libs";
 	SourceWriter.write w "end libs";
 	SourceWriter.newline w;
 	SourceWriter.newline w;
 	let args = gen.gcon.c_args in
 	let args = gen.gcon.c_args in

+ 299 - 238
src/codegen/java.ml

@@ -18,6 +18,7 @@
 *)
 *)
 open Unix
 open Unix
 open ExtString
 open ExtString
+open NativeLibraries
 open Common
 open Common
 open Globals
 open Globals
 open Ast
 open Ast
@@ -31,6 +32,7 @@ type java_lib_ctx = {
 	jcom : Common.context;
 	jcom : Common.context;
 	(* current tparams context *)
 	(* current tparams context *)
 	mutable jtparams : jtypes list;
 	mutable jtparams : jtypes list;
+	is_std : bool;
 }
 }
 
 
 exception ConversionError of string * pos
 exception ConversionError of string * pos
@@ -73,11 +75,11 @@ let real_java_path ctx (pack,name) =
 
 
 let lookup_jclass com path =
 let lookup_jclass com path =
 	let path = jpath_to_hx path in
 	let path = jpath_to_hx path in
-	List.fold_right (fun (_,_,_,_,get_raw_class) acc ->
+	List.fold_right (fun java_lib acc ->
 		match acc with
 		match acc with
-		| None -> get_raw_class path
+		| None -> java_lib#lookup path
 		| Some p -> Some p
 		| Some p -> Some p
-	) com.java_libs None
+	) com.native_libs.java_libs None
 
 
 let mk_type_path ctx path params =
 let mk_type_path ctx path params =
 	let name, sub = try
 	let name, sub = try
@@ -217,6 +219,12 @@ let del_override field =
 let get_canonical ctx p pack name =
 let get_canonical ctx p pack name =
 	(Meta.JavaCanonical, [EConst (String (String.concat "." pack)), p; EConst (String name), p], p)
 	(Meta.JavaCanonical, [EConst (String (String.concat "." pack)), p; EConst (String name), p], p)
 
 
+let show_in_completion ctx jc =
+	if not ctx.is_std then true
+	else match fst jc.cpath with
+		| ("java" | "javax" | "org") :: _ -> true
+		| _ -> false
+
 let convert_java_enum ctx p pe =
 let convert_java_enum ctx p pe =
 	let meta = ref (get_canonical ctx p (fst pe.cpath) (snd pe.cpath) :: [Meta.Native, [EConst (String (real_java_path ctx pe.cpath) ), p], p ]) in
 	let meta = ref (get_canonical ctx p (fst pe.cpath) (snd pe.cpath) :: [Meta.Native, [EConst (String (real_java_path ctx pe.cpath) ), p], p ]) in
 	let data = ref [] in
 	let data = ref [] in
@@ -228,6 +236,8 @@ let convert_java_enum ctx p pe =
 		| _ -> ()
 		| _ -> ()
 	) pe.cfields;
 	) pe.cfields;
 
 
+	if not (show_in_completion ctx pe) then meta := (Meta.NoCompletion,[],null_pos) :: !meta;
+
 	EEnum {
 	EEnum {
 		d_name = jname_to_hx (snd pe.cpath),null_pos;
 		d_name = jname_to_hx (snd pe.cpath),null_pos;
 		d_doc = None;
 		d_doc = None;
@@ -466,6 +476,8 @@ let convert_java_enum ctx p pe =
 				) f.jf_throws
 				) f.jf_throws
 			) jc.cmethods) in
 			) jc.cmethods) in
 
 
+			if not (show_in_completion ctx jc) then meta := (Meta.NoCompletion,[],null_pos) :: !meta;
+
 			(EClass {
 			(EClass {
 				d_name = jname_to_hx (snd jc.cpath),null_pos;
 				d_name = jname_to_hx (snd jc.cpath),null_pos;
 				d_doc = None;
 				d_doc = None;
@@ -475,10 +487,11 @@ let convert_java_enum ctx p pe =
 				d_data = !fields;
 				d_data = !fields;
 			}) :: imports
 			}) :: imports
 
 
-	let create_ctx com =
+	let create_ctx com is_std =
 		{
 		{
 			jcom = com;
 			jcom = com;
 			jtparams = [];
 			jtparams = [];
+			is_std = is_std;
 		}
 		}
 
 
 	let rec has_type_param = function
 	let rec has_type_param = function
@@ -593,7 +606,7 @@ let jclass_with_params com cls params = try
 			cinterfaces = List.map (japply_params jparams) cls.cinterfaces;
 			cinterfaces = List.map (japply_params jparams) cls.cinterfaces;
 		}
 		}
 	with Invalid_argument _ ->
 	with Invalid_argument _ ->
-		if com.verbose then prerr_endline ("Differing parameters for class: " ^ s_type_path cls.cpath);
+		if com.verbose then print_endline ("Differing parameters for class: " ^ s_type_path cls.cpath);
 		cls
 		cls
 
 
 let is_object = function | TObject( (["java";"lang"], "Object"), [] ) -> true | _ -> false
 let is_object = function | TObject( (["java";"lang"], "Object"), [] ) -> true | _ -> false
@@ -647,8 +660,8 @@ let compare_type com s1 s2 =
 				let implements = List.map (japply_params jparams) c.cinterfaces in
 				let implements = List.map (japply_params jparams) c.cinterfaces in
 				loop ~first_error:first_error super s2 || List.exists (fun super -> loop ~first_error:first_error super s2) implements
 				loop ~first_error:first_error super s2 || List.exists (fun super -> loop ~first_error:first_error super s2) implements
 			with | Not_found ->
 			with | Not_found ->
-				prerr_endline ("-java-lib: The type " ^ (s_sig s1) ^ " is referred but was not found. Compilation may not occur correctly.");
-				prerr_endline "Did you forget to include a needed lib?";
+				print_endline ("-java-lib: The type " ^ (s_sig s1) ^ " is referred but was not found. Compilation may not occur correctly.");
+				print_endline "Did you forget to include a needed lib?";
 				if first_error then
 				if first_error then
 					not (loop ~first_error:false s2 s1)
 					not (loop ~first_error:false s2 s1)
 				else
 				else
@@ -681,13 +694,13 @@ let select_best com flist =
 				| -1 ->
 				| -1 ->
 					loop cur_best flist
 					loop cur_best flist
 				| -2 -> (* error - no type is compatible *)
 				| -2 -> (* error - no type is compatible *)
-					if com.verbose then prerr_endline (f.jf_name ^ ": The types " ^ (s_sig r) ^ " and " ^ (s_sig r2) ^ " are incompatible");
+					if com.verbose then print_endline (f.jf_name ^ ": The types " ^ (s_sig r) ^ " and " ^ (s_sig r2) ^ " are incompatible");
 					(* bet that the current best has "beaten" other types *)
 					(* bet that the current best has "beaten" other types *)
 					loop cur_best flist
 					loop cur_best flist
 				| _ -> assert false
 				| _ -> assert false
 			with | Exit -> (* incompatible type parameters *)
 			with | Exit -> (* incompatible type parameters *)
 				(* error mode *)
 				(* error mode *)
-				if com.verbose then prerr_endline (f.jf_name ^ ": Incompatible argument return signatures: " ^ (s_sig r) ^ " and " ^ (s_sig r2));
+				if com.verbose then print_endline (f.jf_name ^ ": Incompatible argument return signatures: " ^ (s_sig r) ^ " and " ^ (s_sig r2));
 				None)
 				None)
 			| TMethod _, _ -> (* select the method *)
 			| TMethod _, _ -> (* select the method *)
 				loop f flist
 				loop f flist
@@ -778,7 +791,7 @@ let normalize_jclass com cls =
 				List.iter (fun jf ->
 				List.iter (fun jf ->
 					if not(List.mem JStatic jf.jf_flags) && not (List.exists (fun jf2 -> jf.jf_name = jf2.jf_name && not (List.mem JStatic jf2.jf_flags) && jf.jf_signature = jf2.jf_signature) all_methods) then begin
 					if not(List.mem JStatic jf.jf_flags) && not (List.exists (fun jf2 -> jf.jf_name = jf2.jf_name && not (List.mem JStatic jf2.jf_flags) && jf.jf_signature = jf2.jf_signature) all_methods) then begin
 						let jf = if abstract && force_check then del_override jf else jf in
 						let jf = if abstract && force_check then del_override jf else jf in
-						let jf = { jf with jf_flags = JPublic :: jf.jf_flags } in (* interfaces implementations are always public *)
+						let jf = if not (List.mem JPublic jf.jf_flags) then { jf with jf_flags = JPublic :: jf.jf_flags } else jf in (* interfaces implementations are always public *)
 
 
 						added_interface_fields := jf :: !added_interface_fields;
 						added_interface_fields := jf :: !added_interface_fields;
 					end
 					end
@@ -890,101 +903,15 @@ let get_classes_zip zip =
 	) (Zip.entries zip);
 	) (Zip.entries zip);
 	!ret
 	!ret
 
 
-let add_java_lib com file std =
-	let file = if Sys.file_exists file then
-		file
-	else try Common.find_file com file with
-		| Not_found -> try Common.find_file com (file ^ ".jar") with
-		| Not_found ->
-			failwith ("Java lib " ^ file ^ " not found")
-	in
-	let hxpack_to_jpack = Hashtbl.create 16 in
-	let get_raw_class, close, list_all_files =
-		(* check if it is a directory or jar file *)
-		match (Unix.stat file).st_kind with
-		| S_DIR -> (* open classes directly from directory *)
-			let all = ref [] in
-			let rec iter_files pack dir path = try
-				let file = Unix.readdir dir in
-				let filepath = path ^ "/" ^ file in
-				(if String.ends_with file ".class" then
-					let name = String.sub file 0 (String.length file - 6) in
-					let path = jpath_to_hx (pack,name) in
-					if not (String.exists file "$") then all := path :: !all;
-					Hashtbl.add hxpack_to_jpack path (pack,name)
-				else if (Unix.stat filepath).st_kind = S_DIR && file <> "." && file <> ".." then
-					let pack = pack @ [file] in
-					iter_files (pack) (Unix.opendir filepath) filepath);
-				iter_files pack dir path
-			with | End_of_file | Unix.Unix_error _ ->
-				Unix.closedir dir
-			in
-			iter_files [] (Unix.opendir file) file;
-			let all = !all in
-
-			(fun (pack, name) ->
-				let real_path = file ^ "/" ^ (String.concat "/" pack) ^ "/" ^ (name ^ ".class") in
-				try
-					let data = Std.input_file ~bin:true real_path in
-					Some(JReader.parse_class (IO.input_string data), real_path, real_path)
-				with
-					| _ -> None), (fun () -> ()), (fun () -> all)
-		| _ -> (* open zip file *)
-			let closed = ref false in
-			let zip = ref (Zip.open_in file) in
-			let check_open () =
-				if !closed then begin
-					prerr_endline ("JAR file " ^ file ^ " already closed"); (* if this happens, find when *)
-					zip := Zip.open_in file;
-					closed := false
-				end
-			in
-			List.iter (function
-				| { Zip.is_directory = false; Zip.filename = filename } when String.ends_with filename ".class" ->
-					let pack = String.nsplit filename "/" in
-					(match List.rev pack with
-						| [] -> ()
-						| name :: pack ->
-							let name = String.sub name 0 (String.length name - 6) in
-							let pack = List.rev pack in
-							Hashtbl.add hxpack_to_jpack (jpath_to_hx (pack,name)) (pack,name))
-				| _ -> ()
-			) (Zip.entries !zip);
-			(fun (pack, name) ->
-				check_open();
-				try
-					let location = (String.concat "/" (pack @ [name]) ^ ".class") in
-					let entry = Zip.find_entry !zip location in
-					let data = Zip.read_entry !zip entry in
-					Some(JReader.parse_class (IO.input_string data), file, file ^ "@" ^ location)
-				with
-					| Not_found ->
-						None),
-			(fun () -> if not !closed then begin closed := true; Zip.close_in !zip end),
-			(fun () -> check_open(); get_classes_zip !zip)
-	in
-	let cached_types = Hashtbl.create 12 in
-	let get_raw_class path =
-		try
-			Hashtbl.find cached_types path
-		with | Not_found -> try
-			let pack, name = Hashtbl.find hxpack_to_jpack path in
-			let try_file (pack,name) =
-				match get_raw_class (pack,name) with
-				| None ->
-						Hashtbl.add cached_types path None;
-						None
-				| Some (i, p1, p2) ->
-						Hashtbl.add cached_types path (Some(i,p1,p2)); (* type loop normalization *)
-						let ret = Some (normalize_jclass com i, p1, p2) in
-						Hashtbl.replace cached_types path ret;
-						ret
-			in
-			try_file (pack,name)
-		with Not_found ->
-			None
-	in
-	let replace_canonical_name p pack name_original name_replace decl =
+class virtual java_library com name file_path = object(self)
+	inherit [java_lib_type,unit] native_library name file_path as super
+
+	val hxpack_to_jpack = Hashtbl.create 16
+
+	method convert_path (path : path) : path =
+		Hashtbl.find hxpack_to_jpack path
+
+	method private replace_canonical_name p pack name_original name_replace decl =
 		let mk_meta name = (Meta.JavaCanonical, [EConst (String (String.concat "." pack)), p; EConst(String name), p], p) in
 		let mk_meta name = (Meta.JavaCanonical, [EConst (String (String.concat "." pack)), p; EConst(String name), p], p) in
 		let add_meta name metas =
 		let add_meta name metas =
 			if Meta.has Meta.JavaCanonical metas then
 			if Meta.has Meta.JavaCanonical metas then
@@ -1006,145 +933,279 @@ let add_java_lib com file std =
 			| EAbstract a ->
 			| EAbstract a ->
 				EAbstract { a with d_meta = add_meta (fst a.d_name) a.d_meta }
 				EAbstract { a with d_meta = add_meta (fst a.d_name) a.d_meta }
 			| d -> d
 			| d -> d
-	in
-	let rec build ctx path p types =
+
+	method build path (p : pos) : Ast.package option =
+		let rec build ctx path p types =
+			try
+				if List.mem path !types then
+					None
+				else begin
+					let first = match !types with
+						| [ ["java";"lang"], "String" ] | [] -> true
+						| p :: _ ->
+							false
+					in
+					types := path :: !types;
+					match self#lookup path, path with
+					| None, ([], c) -> build ctx (["haxe";"root"], c) p types
+					| None, _ -> None
+					| Some (cls, real_path, pos_path), _ ->
+							let is_disallowed_inner = first && String.exists (snd cls.cpath) "$" in
+							let is_disallowed_inner = if is_disallowed_inner then begin
+									let outer, inner = String.split (snd cls.cpath) "$" in
+									match self#lookup (fst path, outer) with
+										| None -> false
+										| _ -> true
+								end else
+									false
+							in
+							if is_disallowed_inner then
+								None
+							else begin
+								if ctx.jcom.verbose then print_endline ("Parsed Java class " ^ (s_type_path cls.cpath));
+								let old_types = ctx.jtparams in
+								ctx.jtparams <- cls.ctypes :: ctx.jtparams;
+
+								let pos = { pfile = pos_path; pmin = 0; pmax = 0; } in
+
+								let pack = match fst path with | ["haxe";"root"] -> [] | p -> p in
+
+								let ppath = self#convert_path path in
+								let inner = List.fold_left (fun acc (path,out,_,_) ->
+									let path = jpath_to_hx path in
+									(if out <> Some ppath then
+										acc
+									else match build ctx path p types with
+										| Some(_, classes) ->
+											let base = snd ppath ^ "$" in
+											(List.map (fun (def,p) ->
+												self#replace_canonical_name p (fst ppath) base (snd ppath ^ ".") def, p) classes) @ acc
+										| _ -> acc);
+								) [] cls.cinner_types in
+
+								(* add _Statics class *)
+								let inner = try
+									if not (List.mem JInterface cls.cflags) then raise Not_found;
+									let smethods = List.filter (fun f -> List.mem JStatic f.jf_flags) cls.cmethods in
+									let sfields = List.filter (fun f -> List.mem JStatic f.jf_flags) cls.cfields in
+									if not (smethods <> [] || sfields <> []) then raise Not_found;
+									let obj = TObject( (["java";"lang"],"Object"), []) in
+									let ncls = convert_java_class ctx pos { cls with cmethods = smethods; cfields = sfields; cflags = []; csuper = obj; cinterfaces = []; cinner_types = []; ctypes = [] } in
+									match ncls with
+									| EClass c :: imports ->
+										(EClass { c with d_name = (fst c.d_name ^ "_Statics"),snd c.d_name }, pos) :: inner @ List.map (fun i -> i,pos) imports
+									| _ -> assert false
+								with | Not_found ->
+									inner
+								in
+								let inner_alias = ref SS.empty in
+								List.iter (fun x ->
+									match fst x with
+									| EClass c ->
+										inner_alias := SS.add (fst c.d_name) !inner_alias;
+									| _ -> ()
+								) inner;
+								let alias_list = ref [] in
+								List.iter (fun x ->
+									match x with
+									| (EClass c, pos) -> begin
+										let parts = String.nsplit (fst c.d_name) "_24" in
+										match parts with
+											| _ :: _ ->
+												let alias_name = String.concat "_" parts in
+												if (not (SS.mem alias_name !inner_alias)) && (not (String.exists (snd path) "_24")) then begin
+													let alias_def = ETypedef {
+														d_name = alias_name,null_pos;
+														d_doc = None;
+														d_params = c.d_params;
+														d_meta = [];
+														d_flags = [];
+														d_data = CTPath {
+															tpackage = pack;
+															tname = snd path;
+															tparams = List.map (fun tp ->
+																TPType (CTPath {
+																	tpackage = [];
+																	tname = fst tp.tp_name;
+																	tparams = [];
+																	tsub = None;
+																},null_pos)
+															) c.d_params;
+															tsub = Some(fst c.d_name);
+														},null_pos;
+													} in
+													inner_alias := SS.add alias_name !inner_alias;
+													alias_list := (alias_def, pos) :: !alias_list;
+												end
+											| _ -> ()
+									end
+									| _ -> ()
+								) inner;
+								let inner = List.concat [!alias_list ; inner] in
+								let classes = List.map (fun t -> t,pos) (convert_java_class ctx pos cls) in
+								let imports, defs = List.partition (function | (EImport(_),_) -> true | _ -> false) (classes @ inner) in
+								let ret = Some (pack, imports @ defs) in
+								ctx.jtparams <- old_types;
+								ret
+							end
+				end
+			with
+			| JReader.Error_message msg ->
+				print_endline ("Class reader failed: " ^ msg);
+				None
+			| e ->
+				if ctx.jcom.verbose then begin
+					(* print_endline (Printexc.get_backtrace ()); requires ocaml 3.11 *)
+					print_endline (Printexc.to_string e)
+				end;
+				None
+		in
+		build (create_ctx com (self#has_flag FlagIsStd)) path p (ref [["java";"lang"], "String"])
+
+	method get_data = ()
+end
+
+class java_library_jar com name file_path = object(self)
+	inherit java_library com name file_path
+
+	val zip = lazy (Zip.open_in file_path)
+	val mutable cached_files = None
+	val cached_types = Hashtbl.create 12
+	val mutable closed = false
+
+	method load =
+		List.iter (function
+			| { Zip.is_directory = false; Zip.filename = filename } when String.ends_with filename ".class" ->
+				let pack = String.nsplit filename "/" in
+				(match List.rev pack with
+					| [] -> ()
+					| name :: pack ->
+						let name = String.sub name 0 (String.length name - 6) in
+						let pack = List.rev pack in
+						Hashtbl.add hxpack_to_jpack (jpath_to_hx (pack,name)) (pack,name))
+			| _ -> ()
+		) (Zip.entries (Lazy.force zip))
+
+	method private lookup' ((pack,name) : path) : java_lib_type =
 		try
 		try
-			if List.mem path !types then
+			let zip = Lazy.force zip in
+			let location = (String.concat "/" (pack @ [name]) ^ ".class") in
+			let entry = Zip.find_entry zip location in
+			let data = Zip.read_entry zip entry in
+			Some(JReader.parse_class (IO.input_string data), file_path, file_path ^ "@" ^ location)
+		with
+			| Not_found ->
 				None
 				None
-			else begin
-				let first = match !types with
-					| [ ["java";"lang"], "String" ] | [] -> true
-					| p :: _ ->
-						false
-				in
-				types := path :: !types;
-				match get_raw_class path, path with
-				| None, ([], c) -> build ctx (["haxe";"root"], c) p types
-				| None, _ -> None
-				| Some (cls, real_path, pos_path), _ ->
-						let is_disallowed_inner = first && String.exists (snd cls.cpath) "$" in
-						let is_disallowed_inner = if is_disallowed_inner then begin
-								let outer, inner = String.split (snd cls.cpath) "$" in
-								match get_raw_class (fst path, outer) with
-									| None -> false
-									| _ -> true
-							end else
-								false
-						in
-						if is_disallowed_inner then
-							None
-						else begin
-							if com.verbose then print_endline ("Parsed Java class " ^ (s_type_path cls.cpath));
-							let old_types = ctx.jtparams in
-							ctx.jtparams <- cls.ctypes :: ctx.jtparams;
-
-							let pos = { pfile = pos_path; pmin = 0; pmax = 0; } in
-
-							let pack = match fst path with | ["haxe";"root"] -> [] | p -> p in
-
-							let ppath = Hashtbl.find hxpack_to_jpack path in
-							let inner = List.fold_left (fun acc (path,out,_,_) ->
-								let path = jpath_to_hx path in
-								(if out <> Some ppath then
-									acc
-								else match build ctx path p types with
-									| Some(_,(_, classes)) ->
-										let base = snd ppath ^ "$" in
-										(List.map (fun (def,p) ->
-											replace_canonical_name p (fst ppath) base (snd ppath ^ ".") def, p) classes) @ acc
-									| _ -> acc);
-							) [] cls.cinner_types in
-
-							(* add _Statics class *)
-							let inner = try
-								if not (List.mem JInterface cls.cflags) then raise Not_found;
-								let smethods = List.filter (fun f -> List.mem JStatic f.jf_flags) cls.cmethods in
-								let sfields = List.filter (fun f -> List.mem JStatic f.jf_flags) cls.cfields in
-								if not (smethods <> [] || sfields <> []) then raise Not_found;
-								let obj = TObject( (["java";"lang"],"Object"), []) in
-								let ncls = convert_java_class ctx pos { cls with cmethods = smethods; cfields = sfields; cflags = []; csuper = obj; cinterfaces = []; cinner_types = []; ctypes = [] } in
-								match ncls with
-								| EClass c :: imports ->
-									(EClass { c with d_name = (fst c.d_name ^ "_Statics"),snd c.d_name }, pos) :: inner @ List.map (fun i -> i,pos) imports
-								| _ -> assert false
-							with | Not_found ->
-								inner
-							in
-							let inner_alias = ref SS.empty in
-							List.iter (fun x ->
-								match fst x with
-								| EClass c ->
-									inner_alias := SS.add (fst c.d_name) !inner_alias;
-								| _ -> ()
-							) inner;
-							let alias_list = ref [] in
-							List.iter (fun x ->
-								match x with
-								| (EClass c, pos) -> begin
-									let parts = String.nsplit (fst c.d_name) "_24" in
-									match parts with
-										| _ :: _ ->
-											let alias_name = String.concat "_" parts in
-											if (not (SS.mem alias_name !inner_alias)) && (not (String.exists (snd path) "_24")) then begin
-												let alias_def = ETypedef {
-													d_name = alias_name,null_pos;
-													d_doc = None;
-													d_params = c.d_params;
-													d_meta = [];
-													d_flags = [];
-													d_data = CTPath {
-														tpackage = pack;
-														tname = snd path;
-														tparams = List.map (fun tp ->
-															TPType (CTPath {
-																tpackage = [];
-																tname = fst tp.tp_name;
-																tparams = [];
-																tsub = None;
-															},null_pos)
-														) c.d_params;
-														tsub = Some(fst c.d_name);
-													},null_pos;
-												} in
-												inner_alias := SS.add alias_name !inner_alias;
-												alias_list := (alias_def, pos) :: !alias_list;
-											end
-										| _ -> ()
-								end
-								| _ -> ()
-							) inner;
-							let inner = List.concat [!alias_list ; inner] in
-							let classes = List.map (fun t -> t,pos) (convert_java_class ctx pos cls) in
-							let imports, defs = List.partition (function | (EImport(_),_) -> true | _ -> false) (classes @ inner) in
-							let ret = Some ( real_path, (pack, imports @ defs) ) in
-							ctx.jtparams <- old_types;
-							ret
+
+	method lookup (path : path) : java_lib_type =
+		try
+			Hashtbl.find cached_types path
+		with | Not_found -> try
+			let pack, name = self#convert_path path in
+			let try_file (pack,name) =
+				match self#lookup' (pack,name) with
+				| None ->
+						Hashtbl.add cached_types path None;
+						None
+				| Some (i, p1, p2) ->
+						Hashtbl.add cached_types path (Some(i,p1,p2)); (* type loop normalization *)
+						let ret = Some (normalize_jclass com i, p1, p2) in
+						Hashtbl.replace cached_types path ret;
+						ret
+			in
+			try_file (pack,name)
+		with Not_found ->
+			None
+
+	method close =
+		if not closed then begin
+			closed <- true;
+			Zip.close_in (Lazy.force zip)
+		end
+
+	method private list_modules' : path list =
+		let ret = ref [] in
+		List.iter (function
+			| { Zip.is_directory = false; Zip.filename = f } when (String.sub (String.uncapitalize f) (String.length f - 6) 6) = ".class" && not (String.exists f "$") ->
+					(match List.rev (String.nsplit f "/") with
+					| clsname :: pack ->
+						if not (String.contains clsname '$') then begin
+							let path = jpath_to_hx (List.rev pack, String.sub clsname 0 (String.length clsname - 6)) in
+							ret := path :: !ret
 						end
 						end
-			end
+					| _ ->
+							ret := ([], jname_to_hx f) :: !ret)
+			| _ -> ()
+		) (Zip.entries (Lazy.force zip));
+		!ret
+
+	method list_modules : path list = match cached_files with
+		| None ->
+			let ret = self#list_modules' in
+			cached_files <- Some ret;
+			ret
+		| Some r ->
+			r
+end
+
+class java_library_dir com name file_path = object(self)
+	inherit java_library com name file_path
+
+	val mutable files = []
+
+	method load =
+		let all = ref [] in
+		let rec iter_files pack dir path = try
+			let file = Unix.readdir dir in
+			let filepath = path ^ "/" ^ file in
+			(if String.ends_with file ".class" then
+				let name = String.sub file 0 (String.length file - 6) in
+				let path = jpath_to_hx (pack,name) in
+				if not (String.exists file "$") then all := path :: !all;
+				Hashtbl.add hxpack_to_jpack path (pack,name)
+			else if (Unix.stat filepath).st_kind = S_DIR && file <> "." && file <> ".." then
+				let pack = pack @ [file] in
+				iter_files (pack) (Unix.opendir filepath) filepath);
+			iter_files pack dir path
+		with | End_of_file | Unix.Unix_error _ ->
+			Unix.closedir dir
+		in
+		iter_files [] (Unix.opendir file_path) file_path;
+		files <- !all
+
+	method close =
+		()
+
+	method list_modules =
+		files
+
+	method lookup (pack,name) : java_lib_type =
+		let real_path = file_path ^ "/" ^ (String.concat "/" pack) ^ "/" ^ (name ^ ".class") in
+		try
+			let data = Std.input_file ~bin:true real_path in
+			Some(JReader.parse_class (IO.input_string data), real_path, real_path)
 		with
 		with
-		| JReader.Error_message msg ->
-			prerr_endline ("Class reader failed: " ^ msg);
-			None
-		| e ->
-			if com.verbose then begin
-				(* prerr_endline (Printexc.get_backtrace ()); requires ocaml 3.11 *)
-				prerr_endline (Printexc.to_string e)
-			end;
-			None
+			| _ -> None
+end
+
+let add_java_lib com name std extern =
+	let file = if Sys.file_exists name then
+		name
+	else try Common.find_file com name with
+		| Not_found -> try Common.find_file com (name ^ ".jar") with
+		| Not_found ->
+			failwith ("Java lib " ^ name ^ " not found")
 	in
 	in
-	let build path p = build (create_ctx com) path p (ref [["java";"lang"], "String"]) in
-	let cached_files = ref None in
-	let list_all_files () = match !cached_files with
-		| None ->
-				let ret = list_all_files () in
-				cached_files := Some ret;
-				ret
-		| Some r -> r
+	let java_lib = match (Unix.stat file).st_kind with
+		| S_DIR ->
+			(new java_library_dir com name file :> java_library)
+		| _ ->
+			(new java_library_jar com name file :> java_library)
 	in
 	in
-
-	(* TODO: add_dependency m mdep *)
-	com.load_extern_type <- com.load_extern_type @ [build];
-	com.java_libs <- (file, std, close, list_all_files, get_raw_class) :: com.java_libs
+	if std then java_lib#add_flag FlagIsStd;
+	if extern then java_lib#add_flag FlagIsExtern;
+	com.native_libs.java_libs <- (java_lib :> (java_lib_type,unit) native_library) :: com.native_libs.java_libs;
+	CompilationServer.handle_native_lib com java_lib
 
 
 let before_generate con =
 let before_generate con =
 	let java_ver = try
 	let java_ver = try

+ 57 - 28
src/codegen/swfLoader.ml

@@ -22,6 +22,7 @@ open As3hl
 open Common
 open Common
 open Globals
 open Globals
 open Ast
 open Ast
+open NativeLibraries
 
 
 let lowercase_pack pack =
 let lowercase_pack pack =
 	let rec loop acc pack =
 	let rec loop acc pack =
@@ -131,10 +132,10 @@ let is_valid_path com pack name =
 	let rec loop = function
 	let rec loop = function
 		| [] ->
 		| [] ->
 			false
 			false
-		| load :: l ->
+		| (file,load) :: l ->
 			match load (pack,name) null_pos with
 			match load (pack,name) null_pos with
 			| None -> loop l
 			| None -> loop l
-			| Some (file,(_,a)) -> true
+			| Some (_,a) -> true
 	in
 	in
 	let file = Printf.sprintf "%s/%s.hx" (String.concat "/" pack) name in
 	let file = Printf.sprintf "%s/%s.hx" (String.concat "/" pack) name in
 	loop com.load_extern_type || (try ignore(Common.find_file com file); true with Not_found -> false)
 	loop com.load_extern_type || (try ignore(Common.find_file com file); true with Not_found -> false)
@@ -541,7 +542,6 @@ let remove_debug_infos as3 =
 let parse_swf com file =
 let parse_swf com file =
 	let t = Timer.timer ["read";"swf"] in
 	let t = Timer.timer ["read";"swf"] in
 	let is_swc = file_extension file = "swc" || file_extension file = "ane" in
 	let is_swc = file_extension file = "swc" || file_extension file = "ane" in
-	let file = (try Common.find_file com file with Not_found -> failwith ((if is_swc then "SWC" else "SWF") ^ " Library not found : " ^ file)) in
 	let ch = if is_swc then begin
 	let ch = if is_swc then begin
 		let zip = Zip.open_in file in
 		let zip = Zip.open_in file in
 		try
 		try
@@ -572,39 +572,68 @@ let parse_swf com file =
 	t();
 	t();
 	(h,tags)
 	(h,tags)
 
 
-let add_swf_lib com file extern =
-	let swf_data = ref None in
-	let swf_classes = ref None in
-	let getSWF = (fun() ->
-		match !swf_data with
+class swf_library com name file_path = object(self)
+	inherit [swf_lib_type,Swf.swf] native_library name file_path
+
+	val mutable swf_data = None
+	val mutable swf_classes = None
+	val haxe_classes = Hashtbl.create 0
+
+	method load =
+		ignore(self#get_swf)
+
+	method get_swf = match swf_data with
 		| None ->
 		| None ->
-			let d = parse_swf com file in
-			swf_data := Some d;
+			let d = parse_swf com file_path in
+			swf_data <- Some d;
 			d
 			d
-		| Some d -> d
-	) in
-	let extract = (fun() ->
-		match !swf_classes with
+		| Some d ->
+			d
+
+	method extract = match swf_classes with
 		| None ->
 		| None ->
-			let d = extract_data (getSWF()) in
-			swf_classes := Some d;
+			let d = extract_data self#get_swf in
+			swf_classes <- Some d;
 			d
 			d
-		| Some d -> d
-	) in
-	let build cl p =
-		match (try Some (Hashtbl.find (extract()) cl) with Not_found -> None) with
-		| None -> None
-		| Some c -> Some (file, build_class com c file)
-	in
-	com.load_extern_type <- com.load_extern_type @ [build];
-	if not extern then com.swf_libs <- (file,getSWF,extract) :: com.swf_libs
+		| Some d ->
+			d
+
+	method lookup path =
+		try Some (Hashtbl.find (self#extract) path)
+		with Not_found -> None
+
+	method list_modules =
+		Hashtbl.fold (fun path _ acc -> path :: acc) (self#extract) []
+
+	method close =
+		()
+
+	method build (path : path) (p : pos) : Ast.package option =
+		try
+			Some (Hashtbl.find haxe_classes path)
+		with Not_found -> try
+			let c = Hashtbl.find (self#extract) path in
+			let c = build_class com c file_path in
+			Hashtbl.add haxe_classes path c;
+			Some c
+		with Not_found ->
+			None
+
+	method get_data = self#get_swf
+end
+
+let add_swf_lib com file extern =
+	let real_file = (try Common.find_file com file with Not_found -> failwith (" Library not found : " ^ file)) in
+	let swf_lib = new swf_library com file real_file in
+	if not extern then com.native_libs.swf_libs <- (swf_lib :> (swf_lib_type,Swf.swf) native_library) :: com.native_libs.swf_libs;
+	CompilationServer.handle_native_lib com swf_lib
 
 
-let remove_classes toremove lib hcl =
-	let lib = lib() in
+let remove_classes toremove lib l =
 	match !toremove with
 	match !toremove with
 	| [] -> lib
 	| [] -> lib
 	| _ ->
 	| _ ->
-		let hcl = hcl() in
+		let hcl = Hashtbl.create 0 in
+		List.iter (fun path -> Hashtbl.add hcl path ()) l;
 		match List.filter (fun c -> Hashtbl.mem hcl c) (!toremove) with
 		match List.filter (fun c -> Hashtbl.mem hcl c) (!toremove) with
 		| [] -> lib
 		| [] -> lib
 		| classes ->
 		| classes ->

+ 9 - 29
src/compiler/displayOutput.ml

@@ -328,6 +328,7 @@ module Memory = struct
 				"haxelibCache",jint (mem_size cs.cache.c_haxelib);
 				"haxelibCache",jint (mem_size cs.cache.c_haxelib);
 				"parserCache",jint (mem_size cs.cache.c_files);
 				"parserCache",jint (mem_size cs.cache.c_files);
 				"moduleCache",jint (mem_size cs.cache.c_modules);
 				"moduleCache",jint (mem_size cs.cache.c_modules);
+				"nativeLibCache",jint (mem_size cs.cache.c_native_libs);
 			]
 			]
 		]
 		]
 
 
@@ -444,8 +445,8 @@ module TypePathHandler = struct
 				end;
 				end;
 			) r;
 			) r;
 		) com.class_path;
 		) com.class_path;
-		List.iter (fun (_,_,extract) ->
-			Hashtbl.iter (fun (path,name) _ ->
+		let process_lib lib =
+			List.iter (fun (path,name) ->
 				if path = p then classes := name :: !classes else
 				if path = p then classes := name :: !classes else
 				let rec loop p1 p2 =
 				let rec loop p1 p2 =
 					match p1, p2 with
 					match p1, p2 with
@@ -454,32 +455,11 @@ module TypePathHandler = struct
 					| a :: p1, b :: p2 -> if a = b then loop p1 p2
 					| a :: p1, b :: p2 -> if a = b then loop p1 p2
 				in
 				in
 				loop path p
 				loop path p
-			) (extract());
-		) com.swf_libs;
-		List.iter (fun (path,std,close,all_files,lookup) ->
-			List.iter (fun (path, name) ->
-				if path = p then classes := name :: !classes else
-				let rec loop p1 p2 =
-					match p1, p2 with
-					| [], _ -> ()
-					| x :: _, [] -> packages := x :: !packages
-					| a :: p1, b :: p2 -> if a = b then loop p1 p2
-				in
-				loop path p
-			) (all_files())
-		) com.java_libs;
-		List.iter (fun (path,std,all_files,lookup) ->
-			List.iter (fun (path, name) ->
-				if path = p then classes := name :: !classes else
-				let rec loop p1 p2 =
-					match p1, p2 with
-					| [], _ -> ()
-					| x :: _, [] -> packages := x :: !packages
-					| a :: p1, b :: p2 -> if a = b then loop p1 p2
-				in
-			loop path p
-			) (all_files())
-		) com.net_libs;
+			) lib#list_modules;
+		in
+		List.iter process_lib com.native_libs.swf_libs;
+		List.iter process_lib com.native_libs.net_libs;
+		List.iter process_lib com.native_libs.java_libs;
 		unique !packages, unique !classes
 		unique !packages, unique !classes
 
 
 	(** raise field completion listing packages and modules in a given package *)
 	(** raise field completion listing packages and modules in a given package *)
@@ -806,4 +786,4 @@ let handle_syntax_completion com kind p =
 			raise (Completion s)
 			raise (Completion s)
 		| Some(f,_,jsonrpc) ->
 		| Some(f,_,jsonrpc) ->
 			let ctx = Genjson.create_context ~jsonrpc:jsonrpc GMFull in
 			let ctx = Genjson.create_context ~jsonrpc:jsonrpc GMFull in
-			f(fields_to_json ctx l kind None)
+			f(fields_to_json ctx l kind None None)

+ 40 - 46
src/compiler/main.ml

@@ -246,7 +246,7 @@ module Initialize = struct
 			| Cs ->
 			| Cs ->
 				let old_flush = ctx.flush in
 				let old_flush = ctx.flush in
 				ctx.flush <- (fun () ->
 				ctx.flush <- (fun () ->
-					com.net_libs <- [];
+					com.native_libs.net_libs <- [];
 					old_flush()
 					old_flush()
 				);
 				);
 				Dotnet.before_generate com;
 				Dotnet.before_generate com;
@@ -254,12 +254,15 @@ module Initialize = struct
 			| Java ->
 			| Java ->
 				let old_flush = ctx.flush in
 				let old_flush = ctx.flush in
 				ctx.flush <- (fun () ->
 				ctx.flush <- (fun () ->
-					List.iter (fun (_,_,close,_,_) -> close()) com.java_libs;
-					com.java_libs <- [];
+					List.iter (fun java_lib -> java_lib#close) com.native_libs.java_libs;
+					com.native_libs.java_libs <- [];
 					old_flush()
 					old_flush()
 				);
 				);
 				Java.before_generate com;
 				Java.before_generate com;
-				if defined com Define.Jvm then add_std "jvm";
+				if defined com Define.Jvm then begin
+					add_std "jvm";
+					com.package_rules <- PMap.remove "jvm" com.package_rules;
+				end;
 				add_std "java";
 				add_std "java";
 				"java"
 				"java"
 			| Python ->
 			| Python ->
@@ -361,19 +364,19 @@ let get_std_class_paths () =
 			let lib_path = Filename.concat prefix_path "lib" in
 			let lib_path = Filename.concat prefix_path "lib" in
 			let share_path = Filename.concat prefix_path "share" in
 			let share_path = Filename.concat prefix_path "share" in
 			[
 			[
+				"";
 				Path.add_trailing_slash (Filename.concat lib_path "haxe/std");
 				Path.add_trailing_slash (Filename.concat lib_path "haxe/std");
 				Path.add_trailing_slash (Filename.concat lib_path "haxe/extraLibs");
 				Path.add_trailing_slash (Filename.concat lib_path "haxe/extraLibs");
 				Path.add_trailing_slash (Filename.concat share_path "haxe/std");
 				Path.add_trailing_slash (Filename.concat share_path "haxe/std");
 				Path.add_trailing_slash (Filename.concat share_path "haxe/extraLibs");
 				Path.add_trailing_slash (Filename.concat share_path "haxe/extraLibs");
 				Path.add_trailing_slash (Filename.concat base_path "std");
 				Path.add_trailing_slash (Filename.concat base_path "std");
-				Path.add_trailing_slash (Filename.concat base_path "extraLibs");
-				""
+				Path.add_trailing_slash (Filename.concat base_path "extraLibs")
 			]
 			]
 		else
 		else
 			[
 			[
+				"";
 				Path.add_trailing_slash (Filename.concat base_path "std");
 				Path.add_trailing_slash (Filename.concat base_path "std");
-				Path.add_trailing_slash (Filename.concat base_path "extraLibs");
-				""
+				Path.add_trailing_slash (Filename.concat base_path "extraLibs")
 			]
 			]
 
 
 let rec process_params create pl =
 let rec process_params create pl =
@@ -482,6 +485,8 @@ try
 	let pre_compilation = ref [] in
 	let pre_compilation = ref [] in
 	let interp = ref false in
 	let interp = ref false in
 	let swf_version = ref false in
 	let swf_version = ref false in
+	let native_libs = ref [] in
+	let add_native_lib file extern = native_libs := (file,extern) :: !native_libs in
 	Common.define_value com Define.HaxeVer (Printf.sprintf "%.3f" (float_of_int Globals.version /. 1000.));
 	Common.define_value com Define.HaxeVer (Printf.sprintf "%.3f" (float_of_int Globals.version /. 1000.));
 	Common.raw_define com "haxe3";
 	Common.raw_define com "haxe3";
 	Common.raw_define com "haxe4";
 	Common.raw_define com "haxe4";
@@ -515,7 +520,6 @@ try
 		| [] -> ()
 		| [] -> ()
 		| args -> (!process_ref) args
 		| args -> (!process_ref) args
 	in
 	in
-	let arg_delays = ref [] in
 	(* category, official names, deprecated names, arg spec, usage hint, doc *)
 	(* category, official names, deprecated names, arg spec, usage hint, doc *)
 	let basic_args_spec = [
 	let basic_args_spec = [
 		("Target",["--js"],["-js"],Arg.String (Initialize.set_platform com Js),"<file>","compile code to JavaScript file");
 		("Target",["--js"],["-js"],Arg.String (Initialize.set_platform com Js),"<file>","compile code to JavaScript file");
@@ -644,29 +648,20 @@ try
 			with
 			with
 				_ -> raise (Arg.Bad "Invalid SWF header format, expected width:height:fps[:color]")
 				_ -> raise (Arg.Bad "Invalid SWF header format, expected width:height:fps[:color]")
 		),"<header>","define SWF header (width:height:fps:color)");
 		),"<header>","define SWF header (width:height:fps:color)");
-		(* FIXME: replace with -D define *)
-		("Target-specific",["--swf-lib"],["-swf-lib"],Arg.String (fun file ->
+		("Target-specific",["--flash-strict"],[], define Define.FlashStrict, "","more type strict flash API");
+		("Target-specific",[],["--swf-lib";"-swf-lib"],Arg.String (fun file ->
 			process_libs(); (* linked swf order matters, and lib might reference swf as well *)
 			process_libs(); (* linked swf order matters, and lib might reference swf as well *)
-			SwfLoader.add_swf_lib com file false
+			add_native_lib file false;
 		),"<file>","add the SWF library to the compiled SWF");
 		),"<file>","add the SWF library to the compiled SWF");
 		(* FIXME: replace with -D define *)
 		(* FIXME: replace with -D define *)
-		("Target-specific",["--swf-lib-extern"],["-swf-lib-extern"],Arg.String (fun file ->
-			SwfLoader.add_swf_lib com file true
+		("Target-specific",[],["--swf-lib-extern";"-swf-lib-extern"],Arg.String (fun file ->
+			add_native_lib file true;
 		),"<file>","use the SWF library for type checking");
 		),"<file>","use the SWF library for type checking");
-		("Target-specific",["--flash-strict"],[], define Define.FlashStrict, "","more type strict flash API");
-		("Target-specific",["--java-lib"],["-java-lib"],Arg.String (fun file ->
-			let std = file = "lib/hxjava-std.jar" in
-			arg_delays := (fun () -> Java.add_java_lib com file std) :: !arg_delays;
+		("Target-specific",[],["--java-lib";"-java-lib"],Arg.String (fun file ->
+			add_native_lib file false;
 		),"<file>","add an external JAR or class directory library");
 		),"<file>","add an external JAR or class directory library");
-		("Target-specific",["--net-lib"],["-net-lib"],Arg.String (fun file ->
-			let file, is_std = match ExtString.String.nsplit file "@" with
-				| [file] ->
-					file,false
-				| [file;"std"] ->
-					file,true
-				| _ -> raise Exit
-			in
-			arg_delays := (fun () -> Dotnet.add_net_lib com file is_std) :: !arg_delays;
+		("Target-specific",[],["--net-lib";"-net-lib"],Arg.String (fun file ->
+			add_native_lib file false;
 		),"<file>[@std]","add an external .NET DLL file");
 		),"<file>[@std]","add an external .NET DLL file");
 		("Target-specific",["--net-std"],["-net-std"],Arg.String (fun file ->
 		("Target-specific",["--net-std"],["-net-std"],Arg.String (fun file ->
 			Dotnet.add_net_std com file
 			Dotnet.add_net_std com file
@@ -777,7 +772,6 @@ try
 			in
 			in
 			let args = loop [] args in
 			let args = loop [] args in
 			Arg.parse_argv ~current (Array.of_list ("" :: args)) all_args_spec args_callback "";
 			Arg.parse_argv ~current (Array.of_list ("" :: args)) all_args_spec args_callback "";
-			List.iter (fun fn -> fn()) !arg_delays
 		with
 		with
 		| Arg.Help _ ->
 		| Arg.Help _ ->
 			raise (HelpMessage (usage_string all_args usage))
 			raise (HelpMessage (usage_string all_args usage))
@@ -801,7 +795,6 @@ try
 				end;
 				end;
 			with Not_found ->
 			with Not_found ->
 				raise (Arg.Bad new_msg));
 				raise (Arg.Bad new_msg));
-		arg_delays := [];
 		if com.platform = Globals.Cpp && not (Define.defined com.defines DisableUnicodeStrings) && not (Define.defined com.defines HxcppSmartStings) then begin
 		if com.platform = Globals.Cpp && not (Define.defined com.defines DisableUnicodeStrings) && not (Define.defined com.defines HxcppSmartStings) then begin
 			Define.define com.defines HxcppSmartStings;
 			Define.define com.defines HxcppSmartStings;
 		end;
 		end;
@@ -809,17 +802,13 @@ try
 			(* TODO: this is something we're gonna remove once we have something nicer for generating flash externs *)
 			(* TODO: this is something we're gonna remove once we have something nicer for generating flash externs *)
 			force_typing := true;
 			force_typing := true;
 			pre_compilation := (fun() ->
 			pre_compilation := (fun() ->
-				List.iter (fun (_,_,extract) ->
-					Hashtbl.iter (fun n _ -> classes := n :: !classes) (extract())
-				) com.swf_libs;
-				List.iter (fun (_,std,_,all_files,_) ->
-					if not std then
-						List.iter (fun path -> if path <> (["java";"lang"],"String") then classes := path :: !classes) (all_files())
-				) com.java_libs;
-				List.iter (fun (_,std,all_files,_) ->
-					if not std then
-						List.iter (fun path -> classes := path :: !classes) (all_files())
-				) com.net_libs;
+				let process_lib lib =
+					if not (lib#has_flag NativeLibraries.FlagIsStd) then
+						List.iter (fun path -> if path <> (["java";"lang"],"String") then classes := path :: !classes) lib#list_modules
+				in
+				List.iter process_lib com.native_libs.net_libs;
+				List.iter process_lib com.native_libs.swf_libs;
+				List.iter process_lib com.native_libs.java_libs;
 			) :: !pre_compilation;
 			) :: !pre_compilation;
 			xml_out := Some "hx"
 			xml_out := Some "hx"
 		end;
 		end;
@@ -884,7 +873,12 @@ try
 		Common.log com ("Classpath: " ^ (String.concat ";" com.class_path));
 		Common.log com ("Classpath: " ^ (String.concat ";" com.class_path));
 		Common.log com ("Defines: " ^ (String.concat ";" (PMap.foldi (fun k v acc -> (match v with "1" -> k | _ -> k ^ "=" ^ v) :: acc) com.defines.Define.values [])));
 		Common.log com ("Defines: " ^ (String.concat ";" (PMap.foldi (fun k v acc -> (match v with "1" -> k | _ -> k ^ "=" ^ v) :: acc) com.defines.Define.values [])));
 		let t = Timer.timer ["typing"] in
 		let t = Timer.timer ["typing"] in
-		Typecore.type_expr_ref := (fun ctx e with_type -> Typer.type_expr ctx e with_type);
+		Typecore.type_expr_ref := (fun ?(mode=MGet) ctx e with_type -> Typer.type_expr ~mode ctx e with_type);
+		List.iter (fun f -> f ()) (List.rev 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) !native_libs in
+		(* Native lib pass 2: Initialize *)
+		List.iter (fun f -> f()) fl;
 		let tctx = Typer.create com in
 		let tctx = Typer.create com in
 		let add_signature desc =
 		let add_signature desc =
 			Option.may (fun cs -> CompilationServer.maybe_add_context_sign cs com desc) (CompilationServer.get ());
 			Option.may (fun cs -> CompilationServer.maybe_add_context_sign cs com desc) (CompilationServer.get ());
@@ -1055,17 +1049,17 @@ with
 	| DisplayException(DisplayPackage pack) ->
 	| DisplayException(DisplayPackage pack) ->
 		DisplayPosition.display_position#reset;
 		DisplayPosition.display_position#reset;
 		raise (DisplayOutput.Completion (String.concat "." pack))
 		raise (DisplayOutput.Completion (String.concat "." pack))
-	| DisplayException(DisplayFields Some(fields,cr,_)) ->
+	| DisplayException(DisplayFields Some r) ->
 		DisplayPosition.display_position#reset;
 		DisplayPosition.display_position#reset;
 		let fields = if !measure_times then begin
 		let fields = if !measure_times then begin
 			Timer.close_times();
 			Timer.close_times();
 			(List.map (fun (name,value) ->
 			(List.map (fun (name,value) ->
 				CompletionItem.make_ci_timer ("@TIME " ^ name) value
 				CompletionItem.make_ci_timer ("@TIME " ^ name) value
-			) (DisplayOutput.get_timer_fields !start_time)) @ fields
+			) (DisplayOutput.get_timer_fields !start_time)) @ r.fitems
 		end else
 		end else
-			fields
+			r.fitems
 		in
 		in
-		let s = match cr with
+		let s = match r.fkind with
 			| CRToplevel _
 			| CRToplevel _
 			| CRTypeHint
 			| CRTypeHint
 			| CRExtends
 			| CRExtends
@@ -1120,7 +1114,7 @@ with
 					| [] -> [],""
 					| [] -> [],""
 				in
 				in
 				let kind = CRField ((CompletionItem.make_ci_module path,pos,None,None)) in
 				let kind = CRField ((CompletionItem.make_ci_module path,pos,None,None)) in
-				f (DisplayException.fields_to_json ctx fields kind None);
+				f (DisplayException.fields_to_json ctx fields kind None None);
 			| _ -> raise (DisplayOutput.Completion (DisplayOutput.print_fields fields))
 			| _ -> raise (DisplayOutput.Completion (DisplayOutput.print_fields fields))
 			end
 			end
 		end
 		end

+ 20 - 4
src/compiler/server.ml

@@ -257,6 +257,8 @@ let rec wait_loop process_params verbose accept =
 	let compilation_step = ref 0 in
 	let compilation_step = ref 0 in
 	let compilation_mark = ref 0 in
 	let compilation_mark = ref 0 in
 	let mark_loop = ref 0 in
 	let mark_loop = ref 0 in
+	let removed_modules = ref [] in
+	let is_removed_module m = List.exists (fun (_,m') -> m == m') !removed_modules in
 	TypeloadModule.type_module_hook := (fun (ctx:Typecore.typer) mpath p ->
 	TypeloadModule.type_module_hook := (fun (ctx:Typecore.typer) mpath p ->
 		let t = Timer.timer ["server";"module cache"] in
 		let t = Timer.timer ["server";"module cache"] in
 		let com2 = ctx.Typecore.com in
 		let com2 = ctx.Typecore.com in
@@ -292,10 +294,10 @@ let rec wait_loop process_params verbose accept =
 						| [] ->
 						| [] ->
 							if verbose then print_endline ("No library file was found for " ^ s_type_path m.m_path); (* TODO *)
 							if verbose then print_endline ("No library file was found for " ^ s_type_path m.m_path); (* TODO *)
 							raise Not_found (* no extern registration *)
 							raise Not_found (* no extern registration *)
-						| load :: l ->
+						| (file,load) :: l ->
 							match load m.m_path p with
 							match load m.m_path p with
 							| None -> loop l
 							| None -> loop l
-							| Some (file,_) ->
+							| Some _ ->
 								if Path.unique_full_path file <> m.m_extra.m_file then begin
 								if Path.unique_full_path file <> m.m_extra.m_file then begin
 									if verbose then print_endline ("Library file was changed for " ^ s_type_path m.m_path); (* TODO *)
 									if verbose then print_endline ("Library file was changed for " ^ s_type_path m.m_path); (* TODO *)
 									raise Not_found;
 									raise Not_found;
@@ -373,6 +375,8 @@ let rec wait_loop process_params verbose accept =
 				| MCode, MMacro | MMacro, MCode ->
 				| MCode, MMacro | MMacro, MCode ->
 					(* this was just a dependency to check : do not add to the context *)
 					(* this was just a dependency to check : do not add to the context *)
 					PMap.iter (Hashtbl.replace com2.resources) m.m_extra.m_binded_res;
 					PMap.iter (Hashtbl.replace com2.resources) m.m_extra.m_binded_res;
+				| _ when is_removed_module m ->
+					()
 				| _ ->
 				| _ ->
 					ServerMessage.reusing com2 tabs m;
 					ServerMessage.reusing com2 tabs m;
 					m.m_extra.m_added <- !compilation_step;
 					m.m_extra.m_added <- !compilation_step;
@@ -422,11 +426,22 @@ let rec wait_loop process_params verbose accept =
 	while true do
 	while true do
 		let read, write, close = accept() in
 		let read, write, close = accept() in
 		let was_compilation = ref false in
 		let was_compilation = ref false in
+		let recache_removed_modules () =
+			List.iter (fun (k,m) ->
+				try
+					ignore(CompilationServer.find_module cs k);
+				with Not_found ->
+					CompilationServer.cache_module cs k m
+			) !removed_modules;
+			removed_modules := [];
+		in
 		let maybe_cache_context com =
 		let maybe_cache_context com =
 			if com.display.dms_full_typing then begin
 			if com.display.dms_full_typing then begin
 				CompilationServer.cache_context cs com;
 				CompilationServer.cache_context cs com;
 				ServerMessage.cached_modules com "" (List.length com.modules);
 				ServerMessage.cached_modules com "" (List.length com.modules);
-			end;
+				removed_modules := [];
+			end else
+				recache_removed_modules();
 		in
 		in
 		let create params =
 		let create params =
 			let ctx = create_context params in
 			let ctx = create_context params in
@@ -460,7 +475,8 @@ let rec wait_loop process_params verbose accept =
 					let fkey = (file,sign) in
 					let fkey = (file,sign) in
 					(* force parsing again : if the completion point have been changed *)
 					(* force parsing again : if the completion point have been changed *)
 					CompilationServer.remove_file cs fkey;
 					CompilationServer.remove_file cs fkey;
-					CompilationServer.taint_modules cs file;
+					removed_modules := CompilationServer.filter_modules cs file;
+					delays := recache_removed_modules :: !delays;
 				end;
 				end;
 				try
 				try
 					if (Hashtbl.find arguments sign) <> ctx.com.class_path then begin
 					if (Hashtbl.find arguments sign) <> ctx.com.class_path then begin

+ 75 - 22
src/context/common.ml

@@ -21,6 +21,7 @@ open Ast
 open Type
 open Type
 open Globals
 open Globals
 open Define
 open Define
+open NativeLibraries
 
 
 type package_rule =
 type package_rule =
 	| Forbidden
 	| Forbidden
@@ -107,6 +108,7 @@ type platform_config = {
 }
 }
 
 
 class compiler_callbacks = object(self)
 class compiler_callbacks = object(self)
+	val mutable before_typer_create = [];
 	val mutable after_init_macros = [];
 	val mutable after_init_macros = [];
 	val mutable after_typing = [];
 	val mutable after_typing = [];
 	val mutable before_save = [];
 	val mutable before_save = [];
@@ -115,6 +117,9 @@ class compiler_callbacks = object(self)
 	val mutable after_generation = [];
 	val mutable after_generation = [];
 	val mutable null_safety_report = [];
 	val mutable null_safety_report = [];
 
 
+	method add_before_typer_create (f : unit -> unit) : unit =
+		before_typer_create <- f :: before_typer_create
+
 	method add_after_init_macros (f : unit -> unit) : unit =
 	method add_after_init_macros (f : unit -> unit) : unit =
 		after_init_macros <- f :: after_init_macros
 		after_init_macros <- f :: after_init_macros
 
 
@@ -136,6 +141,7 @@ class compiler_callbacks = object(self)
 	method add_null_safety_report (f : (string*pos) list -> unit) : unit =
 	method add_null_safety_report (f : (string*pos) list -> unit) : unit =
 		null_safety_report <- f :: null_safety_report
 		null_safety_report <- f :: null_safety_report
 
 
+	method get_before_typer_create = before_typer_create
 	method get_after_init_macros = after_init_macros
 	method get_after_init_macros = after_init_macros
 	method get_after_typing = after_typing
 	method get_after_typing = after_typing
 	method get_before_save = before_save
 	method get_before_save = before_save
@@ -182,13 +188,14 @@ type context = {
 	mutable warning : string -> pos -> unit;
 	mutable warning : string -> pos -> unit;
 	mutable get_messages : unit -> compiler_message list;
 	mutable get_messages : unit -> compiler_message list;
 	mutable filter_messages : (compiler_message -> bool) -> unit;
 	mutable filter_messages : (compiler_message -> bool) -> unit;
-	mutable load_extern_type : (path -> pos -> (string * Ast.package) option) list; (* allow finding types which are not in sources *)
+	mutable load_extern_type : (string * (path -> pos -> Ast.package option)) list; (* allow finding types which are not in sources *)
 	callbacks : compiler_callbacks;
 	callbacks : compiler_callbacks;
 	defines : Define.define;
 	defines : Define.define;
 	mutable print : string -> unit;
 	mutable print : string -> unit;
 	mutable get_macros : unit -> context option;
 	mutable get_macros : unit -> context option;
 	mutable run_command : string -> int;
 	mutable run_command : string -> int;
 	file_lookup_cache : (string,string option) Hashtbl.t;
 	file_lookup_cache : (string,string option) Hashtbl.t;
+	readdir_cache : (string * string,(string array) option) Hashtbl.t;
 	parser_cache : (string,(type_def * pos) list) Hashtbl.t;
 	parser_cache : (string,(type_def * pos) list) Hashtbl.t;
 	module_to_file : (path,string) Hashtbl.t;
 	module_to_file : (path,string) Hashtbl.t;
 	cached_macros : (path * string,(((string * bool * t) list * t * tclass * Type.tclass_field) * module_def)) Hashtbl.t;
 	cached_macros : (path * string,(((string * bool * t) list * t * tclass * Type.tclass_field) * module_def)) Hashtbl.t;
@@ -204,9 +211,7 @@ type context = {
 	mutable resources : (string,string) Hashtbl.t;
 	mutable resources : (string,string) Hashtbl.t;
 	mutable neko_libs : string list;
 	mutable neko_libs : string list;
 	mutable include_files : (string * string) list;
 	mutable include_files : (string * string) list;
-	mutable swf_libs : (string * (unit -> Swf.swf) * (unit -> ((string list * string),As3hl.hl_class) Hashtbl.t)) list;
-	mutable java_libs : (string * bool * (unit -> unit) * (unit -> (path list)) * (path -> ((JData.jclass * string * string) option))) list; (* (path,std,close,all_files,lookup) *)
-	mutable net_libs : (string * bool * (unit -> path list) * (path -> IlData.ilclass option)) list; (* (path,std,all_files,lookup) *)
+	mutable native_libs : native_libraries;
 	mutable net_std : string list;
 	mutable net_std : string list;
 	net_path_map : (path,string list * string list * string) Hashtbl.t;
 	net_path_map : (path,string list * string list * string) Hashtbl.t;
 	mutable c_args : string list;
 	mutable c_args : string list;
@@ -436,10 +441,8 @@ let create version s_version args =
 		main = None;
 		main = None;
 		flash_version = 10.;
 		flash_version = 10.;
 		resources = Hashtbl.create 0;
 		resources = Hashtbl.create 0;
-		swf_libs = [];
-		java_libs = [];
-		net_libs = [];
 		net_std = [];
 		net_std = [];
+		native_libs = create_native_libs();
 		net_path_map = Hashtbl.create 0;
 		net_path_map = Hashtbl.create 0;
 		c_args = [];
 		c_args = [];
 		neko_libs = [];
 		neko_libs = [];
@@ -467,6 +470,7 @@ let create version s_version args =
 			tarray = (fun _ -> assert false);
 			tarray = (fun _ -> assert false);
 		};
 		};
 		file_lookup_cache = Hashtbl.create 0;
 		file_lookup_cache = Hashtbl.create 0;
+		readdir_cache = Hashtbl.create 0;
 		module_to_file = Hashtbl.create 0;
 		module_to_file = Hashtbl.create 0;
 		stored_typed_exprs = PMap.empty;
 		stored_typed_exprs = PMap.empty;
 		cached_macros = Hashtbl.create 0;
 		cached_macros = Hashtbl.create 0;
@@ -485,6 +489,7 @@ let clone com =
 		main_class = None;
 		main_class = None;
 		features = Hashtbl.create 0;
 		features = Hashtbl.create 0;
 		file_lookup_cache = Hashtbl.create 0;
 		file_lookup_cache = Hashtbl.create 0;
+		readdir_cache = Hashtbl.create 0;
 		parser_cache = Hashtbl.create 0;
 		parser_cache = Hashtbl.create 0;
 		module_to_file = Hashtbl.create 0;
 		module_to_file = Hashtbl.create 0;
 		callbacks = new compiler_callbacks;
 		callbacks = new compiler_callbacks;
@@ -495,7 +500,8 @@ let clone com =
 		defines = {
 		defines = {
 			values = com.defines.values;
 			values = com.defines.values;
 			defines_signature = com.defines.defines_signature;
 			defines_signature = com.defines.defines_signature;
-		}
+		};
+		native_libs = create_native_libs();
 	}
 	}
 
 
 let file_time file = Extc.filetime file
 let file_time file = Extc.filetime file
@@ -536,7 +542,7 @@ let init_platform com pf =
 	com.platform <- pf;
 	com.platform <- pf;
 	let name = platform_name pf in
 	let name = platform_name pf in
 	let forbid acc p = if p = name || PMap.mem p acc then acc else PMap.add p Forbidden acc in
 	let forbid acc p = if p = name || PMap.mem p acc then acc else PMap.add p Forbidden acc in
-	com.package_rules <- List.fold_left forbid com.package_rules (List.map platform_name platforms);
+	com.package_rules <- List.fold_left forbid com.package_rules ("jvm" :: (List.map platform_name platforms));
 	com.config <- get_config com;
 	com.config <- get_config com;
 	if com.config.pf_static then begin
 	if com.config.pf_static then begin
 		raw_define_value com.defines "target.static" "true";
 		raw_define_value com.defines "target.static" "true";
@@ -617,34 +623,81 @@ let platform ctx p = ctx.platform = p
 let platform_name_macro com =
 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 normalize_dir_separator path =
+	if is_windows then String.map (fun c -> if c = '/' then '\\' else c) path
+	else path
+
 let find_file ctx f =
 let find_file ctx f =
 	try
 	try
-		(match Hashtbl.find ctx.file_lookup_cache f with
+		match Hashtbl.find ctx.file_lookup_cache f with
 		| None -> raise Exit
 		| None -> raise Exit
-		| Some f -> f)
+		| Some f -> f
 	with Exit ->
 	with Exit ->
 		raise Not_found
 		raise Not_found
 	| Not_found ->
 	| Not_found ->
+		let remove_extension file =
+			try String.sub file 0 (String.rindex file '.')
+			with Not_found -> file
+		in
+		let extension file =
+			try
+				let dot_pos = String.rindex file '.' in
+				String.sub file dot_pos (String.length file - dot_pos)
+			with Not_found -> file
+		in
+		let f_dir = Filename.dirname f
+		and platform_ext = "." ^ (platform_name_macro ctx)
+		and is_core_api = defined ctx Define.CoreApi in
 		let rec loop had_empty = function
 		let rec loop had_empty = function
 			| [] when had_empty -> raise Not_found
 			| [] when had_empty -> raise Not_found
 			| [] -> loop true [""]
 			| [] -> loop true [""]
 			| p :: l ->
 			| p :: l ->
 				let file = p ^ f in
 				let file = p ^ f in
-				if Sys.file_exists file then begin
-					(try
-						let ext = String.rindex file '.' in
-						let file_pf = String.sub file 0 (ext + 1) ^ platform_name_macro ctx ^ String.sub file ext (String.length file - ext) in
-						if not (defined ctx Define.CoreApi) && Sys.file_exists file_pf then file_pf else file
-					with Not_found ->
-						file)
-				end else
+				let dir = Filename.dirname file in
+				if Hashtbl.mem ctx.readdir_cache (p,dir) then
 					loop (had_empty || p = "") l
 					loop (had_empty || p = "") l
+				else begin
+					let found = ref "" in
+					let dir_listing =
+						try Some (Sys.readdir dir);
+						with Sys_error _ -> None
+					in
+					Hashtbl.add ctx.readdir_cache (p,dir) dir_listing;
+					let normalized_f = normalize_dir_separator f in
+					Option.may
+						(Array.iter (fun file_name ->
+							let current_f = if f_dir = "." then file_name else f_dir ^ "/" ^ file_name in
+							let pf,current_f =
+								if is_core_api then false,current_f
+								else begin
+									let ext = extension current_f in
+									let pf_ext = extension (remove_extension current_f) in
+									if platform_ext = pf_ext then
+										true,(remove_extension (remove_extension current_f)) ^ ext
+									else
+										false,current_f
+								end
+							in
+							let is_cached = Hashtbl.mem ctx.file_lookup_cache current_f in
+							if is_core_api || pf || not is_cached then begin
+								let full_path = if dir = "." then file_name else dir ^ "/" ^ file_name in
+								if is_cached then
+									Hashtbl.remove ctx.file_lookup_cache current_f;
+								Hashtbl.add ctx.file_lookup_cache current_f (Some full_path);
+								if normalize_dir_separator current_f = normalized_f then
+									found := full_path;
+							end
+						))
+						dir_listing;
+					if !found <> "" then !found
+					else loop (had_empty || p = "") l
+				end
 		in
 		in
 		let r = (try Some (loop false ctx.class_path) with Not_found -> None) in
 		let r = (try Some (loop false ctx.class_path) with Not_found -> None) in
 		Hashtbl.add ctx.file_lookup_cache f r;
 		Hashtbl.add ctx.file_lookup_cache f r;
-		(match r with
+		match r with
 		| None -> raise Not_found
 		| None -> raise Not_found
-		| Some f -> f)
+		| Some f -> f
 
 
 (* let find_file ctx f =
 (* let find_file ctx f =
 	let timer = Timer.timer ["find_file"] in
 	let timer = Timer.timer ["find_file"] in
@@ -759,4 +812,4 @@ let dump_context com = s_record_fields "" [
 	"class_path",s_list ", " (fun s -> s) com.class_path;
 	"class_path",s_list ", " (fun s -> s) com.class_path;
 	"defines",s_pmap (fun s -> s) (fun s -> s) com.defines.values;
 	"defines",s_pmap (fun s -> s) (fun s -> s) com.defines.values;
 	"defines_signature",s_opt (fun s -> Digest.to_hex s) com.defines.defines_signature;
 	"defines_signature",s_opt (fun s -> Digest.to_hex s) com.defines.defines_signature;
-]
+]

+ 78 - 1
src/context/compilationServer.ml

@@ -16,11 +16,18 @@ type cached_directory = {
 	mutable c_mtime : float;
 	mutable c_mtime : float;
 }
 }
 
 
+type cached_native_lib = {
+	c_nl_mtime : float;
+	c_nl_files : (path,Ast.package) Hashtbl.t;
+}
+
 type cache = {
 type cache = {
 	c_haxelib : (string list, string list) Hashtbl.t;
 	c_haxelib : (string list, string list) Hashtbl.t;
 	c_files : ((string * string), cached_file) Hashtbl.t;
 	c_files : ((string * string), cached_file) Hashtbl.t;
 	c_modules : (path * string, module_def) Hashtbl.t;
 	c_modules : (path * string, module_def) Hashtbl.t;
 	c_directories : (string, cached_directory list) Hashtbl.t;
 	c_directories : (string, cached_directory list) Hashtbl.t;
+	c_removed_files : (string * string,unit) Hashtbl.t;
+	c_native_libs : (string,cached_native_lib) Hashtbl.t;
 }
 }
 
 
 type context_sign = {
 type context_sign = {
@@ -46,6 +53,8 @@ let create_cache () = {
 	c_files = Hashtbl.create 0;
 	c_files = Hashtbl.create 0;
 	c_modules = Hashtbl.create 0;
 	c_modules = Hashtbl.create 0;
 	c_directories = Hashtbl.create 0;
 	c_directories = Hashtbl.create 0;
+	c_removed_files = Hashtbl.create 0;
+	c_native_libs = Hashtbl.create 0;
 }
 }
 
 
 let create () =
 let create () =
@@ -119,6 +128,15 @@ let cache_module cs key value =
 let taint_modules cs file =
 let taint_modules cs file =
 	Hashtbl.iter (fun _ m -> if m.m_extra.m_file = file then m.m_extra.m_dirty <- Some m) cs.cache.c_modules
 	Hashtbl.iter (fun _ m -> if m.m_extra.m_file = file then m.m_extra.m_dirty <- Some m) cs.cache.c_modules
 
 
+let filter_modules cs file =
+	let removed = DynArray.create () in
+	(* TODO: Using filter_map_inplace would be better, but we can't move to OCaml 4.03 yet *)
+	Hashtbl.iter (fun k m ->
+		if m.m_extra.m_file = file then	DynArray.add removed (k,m);
+	) cs.cache.c_modules;
+	DynArray.iter (fun (k,_) -> Hashtbl.remove cs.cache.c_modules k) removed;
+	DynArray.to_list removed
+
 let iter_modules cs com f =
 let iter_modules cs com f =
 	let sign = Define.get_signature com.defines in
 	let sign = Define.get_signature com.defines in
 	Hashtbl.iter (fun (_,sign') m -> if sign = sign' then f m) cs.cache.c_modules
 	Hashtbl.iter (fun (_,sign') m -> if sign = sign' then f m) cs.cache.c_modules
@@ -136,7 +154,10 @@ let cache_file cs key time data =
 	Hashtbl.replace cs.cache.c_files key { c_time = time; c_package = fst data; c_decls = snd data; c_module_name = None }
 	Hashtbl.replace cs.cache.c_files key { c_time = time; c_package = fst data; c_decls = snd data; c_module_name = None }
 
 
 let remove_file cs key =
 let remove_file cs key =
-	Hashtbl.remove cs.cache.c_files key
+	if Hashtbl.mem cs.cache.c_files key then begin
+		Hashtbl.remove cs.cache.c_files key;
+		Hashtbl.replace cs.cache.c_removed_files key ()
+	end
 
 
 let remove_files cs file =
 let remove_files cs file =
 	List.iter (fun (sign,_) -> remove_file cs (file,sign)) cs.signs
 	List.iter (fun (sign,_) -> remove_file cs (file,sign)) cs.signs
@@ -204,6 +225,62 @@ let add_directory cs key value =
 let clear_directories cs key =
 let clear_directories cs key =
 	Hashtbl.remove cs.cache.c_directories key
 	Hashtbl.remove cs.cache.c_directories key
 
 
+(* native lib *)
+
+let add_native_lib cs key files timestamp =
+	Hashtbl.replace cs.cache.c_native_libs key { c_nl_files = files; c_nl_mtime = timestamp }
+
+let get_native_lib cs key =
+	try Some (Hashtbl.find cs.cache.c_native_libs key)
+	with Not_found -> None
+
+let handle_native_lib com lib =
+	com.native_libs.all_libs <- lib#get_file_path :: com.native_libs.all_libs;
+	com.load_extern_type <- com.load_extern_type @ [lib#get_file_path,lib#build];
+	match get() with
+	| Some cs when Define.raw_defined com.defines "haxe.cacheNativeLibs" ->
+		let init () =
+			let file = lib#get_file_path in
+			let key = file in
+			let ftime = file_time file in
+			begin match get_native_lib cs key with
+			| Some lib when ftime <= lib.c_nl_mtime ->
+				(* Cached lib is good, set up lookup into cached files. *)
+				lib.c_nl_files;
+			| _ ->
+				(* Cached lib is outdated or doesn't exist yet, read library. *)
+				lib#load;
+				(* Created lookup and eagerly read each known type. *)
+				let h = Hashtbl.create 0 in
+				List.iter (fun path ->
+					if not (Hashtbl.mem h path) then begin
+						let p = { pfile = file ^ " @ " ^ Globals.s_type_path path; pmin = 0; pmax = 0; } in
+						try begin match lib#build path p with
+						| Some r -> Hashtbl.add h path r
+						| None -> ()
+						end with _ ->
+							()
+					end
+				) lib#list_modules;
+				(* Save and set up lookup. *)
+				add_native_lib cs key h ftime;
+				h;
+			end;
+		in
+		(fun () ->
+			let lut = init() in
+			let build path p =
+				try Some (Hashtbl.find lut path)
+				with Not_found -> None
+			in
+			com.load_extern_type <- List.map (fun (name,f) ->
+				name,if name = lib#get_file_path then build else f
+			) com.load_extern_type
+		)
+	| _ ->
+		(* Offline mode, just read library as usual. *)
+		(fun () -> lib#load)
+
 (* context *)
 (* context *)
 
 
 let rec cache_context cs com =
 let rec cache_context cs com =

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

@@ -9,8 +9,10 @@ let warned_positions = Hashtbl.create 0
 
 
 let warn_deprecation com s p_usage =
 let warn_deprecation com s p_usage =
 	if not (Hashtbl.mem warned_positions p_usage) then begin
 	if not (Hashtbl.mem warned_positions p_usage) then begin
-		Hashtbl.replace warned_positions p_usage true;
-		com.warning s p_usage;
+		Hashtbl.replace warned_positions p_usage s;
+		match com.display.dms_kind with
+		| DMDiagnostics _ -> ()
+		| _ -> com.warning s p_usage;
 	end
 	end
 
 
 let print_deprecation_message com meta s p_usage =
 let print_deprecation_message com meta s p_usage =
@@ -63,7 +65,11 @@ let run_on_expr com e =
 		| TNew(c,_,el) ->
 		| TNew(c,_,el) ->
 			List.iter expr el;
 			List.iter expr el;
 			check_class com c e.epos;
 			check_class com c e.epos;
-			(match c.cl_constructor with None -> () | Some cf -> check_cf com cf e.epos)
+			begin match c.cl_constructor with
+				(* The AST doesn't carry the correct overload for TNew, so let's ignore this case... (#8557). *)
+				| Some cf when cf.cf_overloads = [] -> check_cf com cf e.epos
+				| _ -> ()
+			end
 		| TTypeExpr(mt) | TCast(_,Some mt) ->
 		| TTypeExpr(mt) | TCast(_,Some mt) ->
 			check_module_type com mt e.epos
 			check_module_type com mt e.epos
 		| TMeta((Meta.Deprecated,_,_) as meta,e1) ->
 		| TMeta((Meta.Deprecated,_,_) as meta,e1) ->

+ 3 - 0
src/context/display/diagnostics.ml

@@ -190,6 +190,9 @@ module Printer = struct
 		List.iter (fun (s,p,prange) ->
 		List.iter (fun (s,p,prange) ->
 			add DKRemovableCode p DiagnosticsSeverity.Warning (JObject ["description",JString s;"range",if prange = null_pos then JNull else Genjson.generate_pos_as_range prange])
 			add DKRemovableCode p DiagnosticsSeverity.Warning (JObject ["description",JString s;"range",if prange = null_pos then JNull else Genjson.generate_pos_as_range prange])
 		) dctx.removable_code;
 		) dctx.removable_code;
+		Hashtbl.iter (fun p s ->
+			add DKDeprecationWarning p DiagnosticsSeverity.Warning (JString s);
+		) DeprecationCheck.warned_positions;
 		let jl = Hashtbl.fold (fun file diag acc ->
 		let jl = Hashtbl.fold (fun file diag acc ->
 			let jl = Hashtbl.fold (fun _ (dk,p,sev,jargs) acc ->
 			let jl = Hashtbl.fold (fun _ (dk,p,sev,jargs) acc ->
 				(JObject [
 				(JObject [

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

@@ -15,7 +15,12 @@ open Display
 open DisplayPosition
 open DisplayPosition
 
 
 let get_expected_name with_type = match with_type with
 let get_expected_name with_type = match with_type with
-	| WithType.Value (Some s) | WithType.WithType(_,Some s) -> Some s
+	| WithType.Value (Some src) | WithType.WithType(_,Some src) ->
+		(match src with
+		| WithType.FunctionArgument name -> Some name
+		| WithType.StructureField name -> Some name
+		| WithType.ImplicitReturn -> None
+		)
 	| _ -> None
 	| _ -> None
 
 
 let sort_fields l with_type tk =
 let sort_fields l with_type tk =
@@ -25,7 +30,7 @@ let sort_fields l with_type tk =
 	in
 	in
 	let expected_name = get_expected_name with_type in
 	let expected_name = get_expected_name with_type in
 	let l = List.map (fun ci ->
 	let l = List.map (fun ci ->
-		let i = get_sort_index tk ci (Option.default Globals.null_pos p) (Option.map fst expected_name) in
+		let i = get_sort_index tk ci (Option.default Globals.null_pos p) expected_name in
 		ci,i
 		ci,i
 	) l in
 	) l in
 	let sort l =
 	let sort l =

+ 95 - 18
src/context/display/displayException.ml

@@ -11,6 +11,13 @@ type hover_result = {
 	hexpected : WithType.t option;
 	hexpected : WithType.t option;
 }
 }
 
 
+type fields_result = {
+	fitems : CompletionItem.t list;
+	fkind : CompletionResultKind.t;
+	finsert_pos : pos option;
+	fsubject : placed_name option;
+}
+
 type signature_kind =
 type signature_kind =
 	| SKCall
 	| SKCall
 	| SKArrayAccess
 	| SKArrayAccess
@@ -23,7 +30,7 @@ type kind =
 	| DisplaySignatures of (((tsignature * CompletionType.ct_function) * documentation) list * int * int * signature_kind) option
 	| DisplaySignatures of (((tsignature * CompletionType.ct_function) * documentation) list * int * int * signature_kind) option
 	| DisplayHover of hover_result option
 	| DisplayHover of hover_result option
 	| DisplayPositions of pos list
 	| DisplayPositions of pos list
-	| DisplayFields of (CompletionItem.t list * CompletionResultKind.t * pos option (* insert pos *)) option
+	| DisplayFields of fields_result option
 	| DisplayPackage of string list
 	| DisplayPackage of string list
 
 
 exception DisplayException of kind
 exception DisplayException of kind
@@ -35,17 +42,78 @@ let raise_metadata s = raise (DisplayException(Metadata s))
 let raise_signatures l isig iarg kind = raise (DisplayException(DisplaySignatures(Some(l,isig,iarg,kind))))
 let raise_signatures l isig iarg kind = raise (DisplayException(DisplaySignatures(Some(l,isig,iarg,kind))))
 let raise_hover item expected p = raise (DisplayException(DisplayHover(Some {hitem = item;hpos = p;hexpected = expected})))
 let raise_hover item expected p = raise (DisplayException(DisplayHover(Some {hitem = item;hpos = p;hexpected = expected})))
 let raise_positions pl = raise (DisplayException(DisplayPositions pl))
 let raise_positions pl = raise (DisplayException(DisplayPositions pl))
-let raise_fields ckl cr po = raise (DisplayException(DisplayFields(Some(ckl,cr,po))))
+let raise_fields ckl cr po = raise (DisplayException(DisplayFields(Some({fitems = ckl;fkind = cr;finsert_pos = po;fsubject = None}))))
+let raise_fields2 ckl cr po subject = raise (DisplayException(DisplayFields(Some({fitems = ckl;fkind = cr;finsert_pos = po;fsubject = Some subject}))))
 let raise_package sl = raise (DisplayException(DisplayPackage sl))
 let raise_package sl = raise (DisplayException(DisplayPackage sl))
 
 
 (* global state *)
 (* global state *)
 let last_completion_result = ref (Array.make 0 (CompletionItem.make (ITModule ([],"")) None))
 let last_completion_result = ref (Array.make 0 (CompletionItem.make (ITModule ([],"")) None))
+let last_completion_pos = ref None
+let max_completion_items = ref 0
 
 
-let fields_to_json ctx fields kind po =
-	let ja = List.map (CompletionItem.to_json ctx) fields in
+let filter_somehow ctx items subject kind po =
+	let ret = DynArray.create () in
+	let acc_types = DynArray.create () in
+	let subject = match subject with
+		| None -> ""
+		| Some(subject,_) -> String.lowercase subject
+	in
+	let subject_matches s =
+		let rec loop i o =
+			if i < String.length subject then begin
+				let o = String.index_from s o subject.[i] in
+				loop (i + 1) o
+			end
+		in
+		try
+			loop 0 0;
+			true
+		with Not_found ->
+			false
+	in
+	let rec loop items index =
+		match items with
+		| _ when DynArray.length ret > !max_completion_items ->
+			()
+		| item :: items ->
+			let name = String.lowercase (get_filter_name item) in
+			if subject_matches name then begin
+				(* Treat types with lowest priority. The assumption is that they are the only kind
+				   which actually causes the limit to be hit, so we show everything else and then
+				   fill in types. *)
+				match item.ci_kind with
+				| ITType _ ->
+					if DynArray.length ret + DynArray.length acc_types < !max_completion_items then
+						DynArray.add acc_types (item,index);
+				| _ ->
+					DynArray.add ret (CompletionItem.to_json ctx (Some index) item);
+			end;
+			loop items (index + 1)
+		| [] ->
+			()
+	in
+	loop items 0;
+	DynArray.iter (fun (item,index) ->
+		if DynArray.length ret < !max_completion_items then
+			DynArray.add ret (CompletionItem.to_json ctx (Some index) item);
+	) acc_types;
+	DynArray.to_list ret,DynArray.length ret = !max_completion_items
+
+let fields_to_json ctx fields kind po subject =
 	last_completion_result := Array.of_list fields;
 	last_completion_result := Array.of_list fields;
+	let needs_filtering = !max_completion_items > 0 && Array.length !last_completion_result > !max_completion_items in
+	let ja,did_filter = if needs_filtering then
+		filter_somehow ctx fields subject kind po
+	else
+		List.mapi (fun i item -> CompletionItem.to_json ctx (Some i) item) fields,false
+ 	in
+	if did_filter then begin match subject with
+		| Some(_,p) -> last_completion_pos := Some p;
+		| None -> last_completion_pos := None
+	end;
 	let fl =
 	let fl =
 		("items",jarray ja) ::
 		("items",jarray ja) ::
+		("isIncomplete",jbool did_filter) ::
 		("mode",CompletionResultKind.to_json ctx kind) ::
 		("mode",CompletionResultKind.to_json ctx kind) ::
 		(match po with None -> [] | Some p -> ["replaceRange",generate_pos_as_range (Parser.cut_pos_at_display p)]) in
 		(match po with None -> [] | Some p -> ["replaceRange",generate_pos_as_range (Parser.cut_pos_at_display p)]) in
 	jobject fl
 	jobject fl
@@ -79,33 +147,42 @@ let to_json ctx de =
 	| DisplayHover None ->
 	| DisplayHover None ->
 		jnull
 		jnull
 	| DisplayHover (Some hover) ->
 	| DisplayHover (Some hover) ->
-		let name_source_kind_to_int = function
-			| WithType.FunctionArgument -> 0
-			| WithType.StructureField -> 1
+		let named_source_kind = function
+			| WithType.FunctionArgument name -> (0, name)
+			| WithType.StructureField name -> (1, name)
+			| _ -> assert false
 		in
 		in
 		let ctx = Genjson.create_context GMFull in
 		let ctx = Genjson.create_context GMFull in
-		let generate_name (name,kind) = jobject [
-			"name",jstring name;
-			"kind",jint (name_source_kind_to_int kind);
-		] in
+		let generate_name kind =
+			let i, name = named_source_kind kind in
+			jobject [
+				"name",jstring name;
+				"kind",jint i;
+			]
+		in
 		let expected = match hover.hexpected with
 		let expected = match hover.hexpected with
-			| Some(WithType.WithType(t,name)) ->
-				jobject (("type",generate_type ctx t) :: (match name with None -> [] | Some name -> ["name",generate_name name]))
-			| Some(Value(Some name)) ->
-				jobject ["name",generate_name name]
+			| Some(WithType.WithType(t,src)) ->
+				jobject (("type",generate_type ctx t)
+				:: (match src with
+					| None -> []
+					| Some ImplicitReturn -> []
+					| Some src -> ["name",generate_name src])
+				)
+			| Some(Value(Some ((FunctionArgument name | StructureField name) as src))) ->
+				jobject ["name",generate_name src]
 			| _ -> jnull
 			| _ -> jnull
 		in
 		in
 		jobject [
 		jobject [
 			"documentation",jopt jstring (CompletionItem.get_documentation hover.hitem);
 			"documentation",jopt jstring (CompletionItem.get_documentation hover.hitem);
 			"range",generate_pos_as_range hover.hpos;
 			"range",generate_pos_as_range hover.hpos;
-			"item",CompletionItem.to_json ctx hover.hitem;
+			"item",CompletionItem.to_json ctx None hover.hitem;
 			"expected",expected;
 			"expected",expected;
 		]
 		]
 	| DisplayPositions pl ->
 	| DisplayPositions pl ->
 		jarray (List.map generate_pos_as_location pl)
 		jarray (List.map generate_pos_as_location pl)
 	| DisplayFields None ->
 	| DisplayFields None ->
 		jnull
 		jnull
-	| DisplayFields Some(fields,kind,po) ->
-		fields_to_json ctx fields kind po
+	| DisplayFields Some r ->
+		fields_to_json ctx r.fitems r.fkind r.finsert_pos r.fsubject
 	| DisplayPackage pack ->
 	| DisplayPackage pack ->
 		jarray (List.map jstring pack)
 		jarray (List.map jstring pack)

+ 5 - 2
src/context/display/displayFields.ml

@@ -50,7 +50,7 @@ let collect_static_extensions ctx items e p =
 		| (c,_) :: l ->
 		| (c,_) :: l ->
 			let rec dup t = Type.map dup t in
 			let rec dup t = Type.map dup t in
 			let acc = List.fold_left (fun acc f ->
 			let acc = List.fold_left (fun acc f ->
-				if Meta.has Meta.NoUsing f.cf_meta || Meta.has Meta.NoCompletion f.cf_meta || Meta.has Meta.Impl f.cf_meta || PMap.mem f.cf_name items then
+				if Meta.has Meta.NoUsing f.cf_meta || Meta.has Meta.NoCompletion f.cf_meta || Meta.has Meta.Impl f.cf_meta || PMap.mem f.cf_name acc then
 					acc
 					acc
 				else begin
 				else begin
 					let f = { f with cf_type = opt_type f.cf_type } in
 					let f = { f with cf_type = opt_type f.cf_type } in
@@ -171,8 +171,11 @@ let collect ctx e_ast e dk with_type p =
 					| _ -> None
 					| _ -> None
 				) el in
 				) el in
 				let forwarded_fields = loop PMap.empty (apply_params a.a_params tl a.a_this) in
 				let forwarded_fields = loop PMap.empty (apply_params a.a_params tl a.a_this) in
+				let abstract_has_own_field field_name =
+					PMap.mem field_name c.cl_fields || PMap.mem field_name c.cl_statics
+				in
 				PMap.foldi (fun name item acc ->
 				PMap.foldi (fun name item acc ->
-					if sl = [] || List.mem name sl && is_new_item acc name then
+					if (sl = [] || List.mem name sl && is_new_item acc name) && not (abstract_has_own_field name) then
 						PMap.add name item acc
 						PMap.add name item acc
 					else
 					else
 						acc
 						acc

+ 14 - 2
src/context/display/displayJson.ml

@@ -87,6 +87,7 @@ let handler =
 	let l = [
 	let l = [
 		"initialize", (fun hctx ->
 		"initialize", (fun hctx ->
 			supports_resolve := hctx.jsonrpc#get_opt_param (fun () -> hctx.jsonrpc#get_bool_param "supportsResolve") false;
 			supports_resolve := hctx.jsonrpc#get_opt_param (fun () -> hctx.jsonrpc#get_bool_param "supportsResolve") false;
+			DisplayException.max_completion_items := hctx.jsonrpc#get_opt_param (fun () -> hctx.jsonrpc#get_int_param "maxCompletionItems") 0;
 			let exclude = hctx.jsonrpc#get_opt_param (fun () -> hctx.jsonrpc#get_array_param "exclude") [] in
 			let exclude = hctx.jsonrpc#get_opt_param (fun () -> hctx.jsonrpc#get_array_param "exclude") [] in
 			DisplayToplevel.exclude := List.map (fun e -> match e with JString s -> s | _ -> assert false) exclude;
 			DisplayToplevel.exclude := List.map (fun e -> match e with JString s -> s | _ -> assert false) exclude;
 			let methods = Hashtbl.fold (fun k _ acc -> (jstring k) :: acc) h [] in
 			let methods = Hashtbl.fold (fun k _ acc -> (jstring k) :: acc) h [] in
@@ -111,7 +112,7 @@ let handler =
 			begin try
 			begin try
 				let item = (!DisplayException.last_completion_result).(i) in
 				let item = (!DisplayException.last_completion_result).(i) in
 				let ctx = Genjson.create_context GMFull in
 				let ctx = Genjson.create_context GMFull in
-				hctx.send_result (jobject ["item",CompletionItem.to_json ctx item])
+				hctx.send_result (jobject ["item",CompletionItem.to_json ctx None item])
 			with Invalid_argument _ ->
 			with Invalid_argument _ ->
 				hctx.send_error [jstring (Printf.sprintf "Invalid index: %i" i)]
 				hctx.send_error [jstring (Printf.sprintf "Invalid index: %i" i)]
 			end
 			end
@@ -179,6 +180,15 @@ let handler =
 			in
 			in
 			hctx.send_result (generate_module () m)
 			hctx.send_result (generate_module () m)
 		);
 		);
+		"server/moduleCreated", (fun hctx ->
+			let file = hctx.jsonrpc#get_string_param "file" in
+			let file = Path.unique_full_path file in
+			let cs = hctx.display#get_cs in
+			List.iter (fun (sign,_) ->
+				Hashtbl.replace cs.cache.c_removed_files (file,sign) ()
+			) (CompilationServer.get_signs cs);
+			hctx.send_result (jstring file);
+		);
 		"server/files", (fun hctx ->
 		"server/files", (fun hctx ->
 			let sign = Digest.from_hex (hctx.jsonrpc#get_string_param "signature") in
 			let sign = Digest.from_hex (hctx.jsonrpc#get_string_param "signature") in
 			let files = CompilationServer.get_files hctx.display#get_cs in
 			let files = CompilationServer.get_files hctx.display#get_cs in
@@ -196,7 +206,9 @@ let handler =
 		"server/invalidate", (fun hctx ->
 		"server/invalidate", (fun hctx ->
 			let file = hctx.jsonrpc#get_string_param "file" in
 			let file = hctx.jsonrpc#get_string_param "file" in
 			let file = Path.unique_full_path file in
 			let file = Path.unique_full_path file in
-			CompilationServer.taint_modules hctx.display#get_cs file;
+			let cs = hctx.display#get_cs in
+			CompilationServer.taint_modules cs file;
+			CompilationServer.remove_files cs file;
 			hctx.send_result jnull
 			hctx.send_result jnull
 		);
 		);
 		"server/configure", (fun hctx ->
 		"server/configure", (fun hctx ->

+ 54 - 12
src/context/display/displayToplevel.ml

@@ -84,6 +84,27 @@ let read_class_paths com timer =
 			()
 			()
 	)
 	)
 
 
+let init_or_update_server cs com timer_name =
+	if not (CompilationServer.is_initialized cs) then begin
+		CompilationServer.set_initialized cs;
+		read_class_paths com timer_name
+	end else begin
+		(* Iterate all removed files of the current context. If they aren't part of the context again,
+		   re-parse them and remove them from c_removed_files. *)
+		let sign = Define.get_signature com.defines in
+		let removed_removed_files = DynArray.create () in
+		Hashtbl.iter (fun (file,sign') () ->
+			if sign = sign' then begin
+				DynArray.add removed_removed_files (file,sign');
+				try
+					ignore(find_file cs (file,sign));
+				with Not_found ->
+					try ignore(TypeloadParse.parse_module_file com file null_pos) with _ -> ()
+			end;
+		) cs.cache.c_removed_files;
+		DynArray.iter (Hashtbl.remove cs.cache.c_removed_files) removed_removed_files;
+	end
+
 module CollectionContext = struct
 module CollectionContext = struct
 	open ImportStatus
 	open ImportStatus
 
 
@@ -175,6 +196,11 @@ let collect ctx tk with_type =
 	in
 	in
 
 
 	let process_decls pack name decls =
 	let process_decls pack name decls =
+		let added_something = ref false in
+		let add item name =
+			added_something := true;
+			add item name
+		in
 		let run () = List.iter (fun (d,p) ->
 		let run () = List.iter (fun (d,p) ->
 			begin try
 			begin try
 				let tname,is_private,meta = match d with
 				let tname,is_private,meta = match d with
@@ -197,7 +223,8 @@ let collect ctx tk with_type =
 				()
 				()
 			end
 			end
 		) decls in
 		) decls in
-		if is_pack_visible pack then run()
+		if is_pack_visible pack then run();
+		!added_something
 	in
 	in
 
 
 	(* Collection starts here *)
 	(* Collection starts here *)
@@ -362,15 +389,12 @@ let collect ctx tk with_type =
 		explore_class_paths ctx.com ["display";"toplevel"] class_paths true add_package (fun path ->
 		explore_class_paths ctx.com ["display";"toplevel"] class_paths true add_package (fun path ->
 			if not (path_exists cctx path) then begin
 			if not (path_exists cctx path) then begin
 				let _,decls = Display.parse_module ctx path Globals.null_pos in
 				let _,decls = Display.parse_module ctx path Globals.null_pos in
-				process_decls (fst path) (snd path) decls
+				ignore(process_decls (fst path) (snd path) decls)
 			end
 			end
 		)
 		)
 	| Some cs ->
 	| Some cs ->
 		(* online: iter context files *)
 		(* online: iter context files *)
-		if not (CompilationServer.is_initialized cs) then begin
-			CompilationServer.set_initialized cs;
-			read_class_paths ctx.com ["display";"toplevel"];
-		end;
+		init_or_update_server cs ctx.com ["display";"toplevel"];
 		let files = CompilationServer.get_file_list cs ctx.com in
 		let files = CompilationServer.get_file_list cs ctx.com in
 		(* Sort files by reverse distance of their package to our current package. *)
 		(* Sort files by reverse distance of their package to our current package. *)
 		let files = List.map (fun (file,cfile) ->
 		let files = List.map (fun (file,cfile) ->
@@ -378,20 +402,29 @@ let collect ctx tk with_type =
 			(file,cfile),i
 			(file,cfile),i
 		) files in
 		) files in
 		let files = List.sort (fun (_,i1) (_,i2) -> -compare i1 i2) files in
 		let files = List.sort (fun (_,i1) (_,i2) -> -compare i1 i2) files in
+		let check_package pack = match List.rev pack with
+			| [] -> ()
+			| s :: sl -> add_package (List.rev sl,s)
+		in
 		List.iter (fun ((file,cfile),_) ->
 		List.iter (fun ((file,cfile),_) ->
 			let module_name = CompilationServer.get_module_name_of_cfile file cfile in
 			let module_name = CompilationServer.get_module_name_of_cfile file cfile in
 			let dot_path = s_type_path (cfile.c_package,module_name) in
 			let dot_path = s_type_path (cfile.c_package,module_name) in
 			if (List.exists (fun e -> ExtString.String.starts_with dot_path (e ^ ".")) !exclude) then
 			if (List.exists (fun e -> ExtString.String.starts_with dot_path (e ^ ".")) !exclude) then
 				()
 				()
 			else begin
 			else begin
-				begin match List.rev cfile.c_package with
-					| [] -> ()
-					| s :: sl -> add_package (List.rev sl,s)
-				end;
 				Hashtbl.replace ctx.com.module_to_file (cfile.c_package,module_name) file;
 				Hashtbl.replace ctx.com.module_to_file (cfile.c_package,module_name) file;
-				process_decls cfile.c_package module_name cfile.c_decls
+				if process_decls cfile.c_package module_name cfile.c_decls then check_package cfile.c_package;
 			end
 			end
-		) files
+		) files;
+		List.iter (fun file ->
+			try
+				let lib = Hashtbl.find cs.cache.c_native_libs file in
+				Hashtbl.iter (fun path (pack,decls) ->
+					if process_decls pack (snd path) decls then check_package pack;
+				) lib.c_nl_files
+			with Not_found ->
+				()
+		) ctx.com.native_libs.all_libs
 	end;
 	end;
 
 
 	(* packages *)
 	(* packages *)
@@ -406,6 +439,15 @@ let collect ctx tk with_type =
 	t();
 	t();
 	l
 	l
 
 
+let collect_and_raise ctx tk with_type cr subject pinsert =
+	let fields = match !DisplayException.last_completion_pos with
+	| Some p' when (pos subject).pmin = p'.pmin ->
+		Array.to_list (!DisplayException.last_completion_result)
+	| _ ->
+		collect ctx tk with_type
+	in
+	DisplayException.raise_fields2 fields cr pinsert subject
+
 let handle_unresolved_identifier ctx i p only_types =
 let handle_unresolved_identifier ctx i p only_types =
 	let l = collect ctx (if only_types then TKType else TKExpr p) NoValue in
 	let l = collect ctx (if only_types then TKType else TKExpr p) NoValue in
 	let cl = List.map (fun it ->
 	let cl = List.map (fun it ->

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

@@ -148,10 +148,7 @@ let find_possible_references kind name (pack,decls) =
 
 
 let find_possible_references tctx cs =
 let find_possible_references tctx cs =
 	let name,pos,kind = Display.ReferencePosition.get () in
 	let name,pos,kind = Display.ReferencePosition.get () in
-	if not (CompilationServer.is_initialized cs) then begin
-		CompilationServer.set_initialized cs;
-		DisplayToplevel.read_class_paths tctx.com ["display";"references"];
-	end;
+	DisplayToplevel.init_or_update_server cs tctx.com ["display";"references"];
 	let files = CompilationServer.get_file_list cs tctx.com in
 	let files = CompilationServer.get_file_list cs tctx.com in
 	let t = Timer.timer ["display";"references";"candidates"] in
 	let t = Timer.timer ["display";"references";"candidates"] in
 	List.iter (fun (file,cfile) ->
 	List.iter (fun (file,cfile) ->

+ 60 - 0
src/context/nativeLibraries.ml

@@ -0,0 +1,60 @@
+(*
+	The Haxe Compiler
+	Copyright (C) 2005-2019  Haxe Foundation
+
+	This program is free software; you can redistribute it and/or
+	modify it under the terms of the GNU General Public License
+	as published by the Free Software Foundation; either version 2
+	of the License, or (at your option) any later version.
+
+	This program is distributed in the hope that it will be useful,
+	but WITHOUT ANY WARRANTY; without even the implied warranty of
+	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+	GNU General Public License for more details.
+
+	You should have received a copy of the GNU General Public License
+	along with this program; if not, write to the Free Software
+	Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *)
+
+open Globals
+open ExtString
+
+type native_lib_flags =
+	| FlagIsStd
+	| FlagIsExtern
+
+class virtual ['a,'data] native_library (name : string) (file_path : string) = object(self)
+	val mutable flags : native_lib_flags list = []
+
+	method add_flag flag = flags <- flag :: flags
+	method has_flag flag = List.mem flag flags
+
+	method get_name = name
+	method get_file_path = file_path
+
+	method virtual build : path -> pos -> Ast.package option
+	method virtual close : unit
+	method virtual list_modules : path list
+	method virtual load : unit
+	method virtual lookup : path -> 'a
+	method virtual get_data : 'data
+end
+
+type java_lib_type = (JData.jclass * string * string) option
+type net_lib_type = IlData.ilclass option
+type swf_lib_type = As3hl.hl_class option
+
+type native_libraries = {
+	mutable java_libs : (java_lib_type,unit) native_library list;
+	mutable net_libs : (net_lib_type,unit) native_library list;
+	mutable swf_libs : (swf_lib_type,Swf.swf) native_library list;
+	mutable all_libs : string list;
+}
+
+let create_native_libs () = {
+	java_libs = [];
+	net_libs = [];
+	swf_libs = [];
+	all_libs = [];
+}

+ 39 - 0
src/context/nativeLibraryHandler.ml

@@ -0,0 +1,39 @@
+(*
+	The Haxe Compiler
+	Copyright (C) 2005-2019  Haxe Foundation
+
+	This program is free software; you can redistribute it and/or
+	modify it under the terms of the GNU General Public License
+	as published by the Free Software Foundation; either version 2
+	of the License, or (at your option) any later version.
+
+	This program is distributed in the hope that it will be useful,
+	but WITHOUT ANY WARRANTY; without even the implied warranty of
+	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+	GNU General Public License for more details.
+
+	You should have received a copy of the GNU General Public License
+	along with this program; if not, write to the Free Software
+	Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *)
+
+open Globals
+open Common
+
+let add_native_lib com file is_extern = match com.platform with
+	| Globals.Flash ->
+		SwfLoader.add_swf_lib com file is_extern
+	| Globals.Java ->
+		let std = file = "lib/hxjava-std.jar" in
+		Java.add_java_lib com file std is_extern
+	| Globals.Cs ->
+		let file, is_std = match ExtString.String.nsplit file "@" with
+			| [file] ->
+				file,false
+			| [file;"std"] ->
+				file,true
+			| _ -> failwith ("unsupported file@`std` format: " ^ file)
+		in
+		Dotnet.add_net_lib com file is_std is_extern
+	| pf ->
+		failwith (Printf.sprintf "Target %s does not support native libraries (trying to load %s)" (platform_name pf) file);

+ 9 - 2
src/context/typecore.ml

@@ -44,6 +44,11 @@ type macro_mode =
 	| MMacroType
 	| MMacroType
 	| MDisplay
 	| MDisplay
 
 
+type access_mode =
+	| MGet
+	| MSet
+	| MCall
+
 type typer_pass =
 type typer_pass =
 	| PBuildModule			(* build the module structure and setup module type parameters *)
 	| PBuildModule			(* build the module structure and setup module type parameters *)
 	| PBuildClass			(* build the class structure *)
 	| PBuildClass			(* build the class structure *)
@@ -133,9 +138,10 @@ exception Forbid_package of (string * path * pos) * pos list * string
 exception WithTypeError of error_msg * pos
 exception WithTypeError of error_msg * pos
 
 
 let make_call_ref : (typer -> texpr -> texpr list -> t -> ?force_inline:bool -> pos -> texpr) ref = ref (fun _ _ _ _ ?force_inline:bool _ -> assert false)
 let make_call_ref : (typer -> texpr -> texpr list -> t -> ?force_inline:bool -> pos -> texpr) ref = ref (fun _ _ _ _ ?force_inline:bool _ -> assert false)
-let type_expr_ref : (typer -> expr -> WithType.t -> texpr) ref = ref (fun _ _ _ -> assert false)
+let type_expr_ref : (?mode:access_mode -> typer -> expr -> WithType.t -> texpr) ref = ref (fun ?(mode=MGet) _ _ _ -> assert false)
 let type_block_ref : (typer -> expr list -> WithType.t -> pos -> texpr) ref = ref (fun _ _ _ _ -> assert false)
 let type_block_ref : (typer -> expr list -> WithType.t -> pos -> texpr) ref = ref (fun _ _ _ _ -> assert false)
 let unify_min_ref : (typer -> texpr list -> t) ref = ref (fun _ _ -> assert false)
 let unify_min_ref : (typer -> texpr list -> t) ref = ref (fun _ _ -> assert false)
+let unify_min_for_type_source_ref : (typer -> texpr list -> WithType.with_type_source option -> t) ref = ref (fun _ _ _ -> assert false)
 let analyzer_run_on_expr_ref : (Common.context -> texpr -> texpr) ref = ref (fun _ _ -> assert false)
 let analyzer_run_on_expr_ref : (Common.context -> texpr -> texpr) ref = ref (fun _ _ -> assert false)
 
 
 let pass_name = function
 let pass_name = function
@@ -153,9 +159,10 @@ let display_error ctx msg p = match ctx.com.display.DisplayMode.dms_error_policy
 
 
 let make_call ctx e el t p = (!make_call_ref) ctx e el t p
 let make_call ctx e el t p = (!make_call_ref) ctx e el t p
 
 
-let type_expr ctx e with_type = (!type_expr_ref) ctx e with_type
+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
 let unify_min ctx el = (!unify_min_ref) ctx el
+let unify_min_for_type_source ctx el src = (!unify_min_for_type_source_ref) ctx el src
 
 
 let make_static_this c p =
 let make_static_this c p =
 	let ta = TAnon { a_fields = c.cl_statics; a_status = ref (Statics c) } in
 	let ta = TAnon { a_fields = c.cl_statics; a_status = ref (Statics c) } in

+ 12 - 2
src/core/abstract.ml

@@ -49,7 +49,7 @@ let find_from ab pl a b =
 
 
 let underlying_type_stack = new_rec_stack()
 let underlying_type_stack = new_rec_stack()
 
 
-let rec get_underlying_type a pl =
+let rec get_underlying_type ?(return_first=false) a pl =
 	let maybe_recurse t =
 	let maybe_recurse t =
 		let rec loop t = match t with
 		let rec loop t = match t with
 			| TMono r ->
 			| TMono r ->
@@ -68,7 +68,13 @@ let rec get_underlying_type a pl =
 					let s = String.concat " -> " (List.map (fun t -> s_type pctx t) (List.rev (t :: underlying_type_stack.rec_stack))) in
 					let s = String.concat " -> " (List.map (fun t -> s_type pctx t) (List.rev (t :: underlying_type_stack.rec_stack))) in
 					error ("Abstract chain detected: " ^ s) a.a_pos
 					error ("Abstract chain detected: " ^ s) a.a_pos
 				end;
 				end;
-				get_underlying_type a tl
+				(*
+					Even if only the first underlying type was requested
+					keep traversing to detect mutually recursive abstracts
+				*)
+				let result = get_underlying_type a tl in
+				if return_first then t
+				else result
 			| _ ->
 			| _ ->
 				t
 				t
 		in
 		in
@@ -76,6 +82,10 @@ let rec get_underlying_type a pl =
 	in
 	in
 	try
 	try
 		if not (Meta.has Meta.MultiType a.a_meta) then raise Not_found;
 		if not (Meta.has Meta.MultiType a.a_meta) then raise Not_found;
+		(* TODO:
+			Look into replacing `mk_mono` & `find_to` with `build_abstract a` & `TAbstract(a, pl)`.
+			`find_to` is probably needed for `@:multiType`
+		*)
 		let m = mk_mono() in
 		let m = mk_mono() in
 		let _ = find_to a pl m in
 		let _ = find_to a pl m in
 		maybe_recurse (follow m)
 		maybe_recurse (follow m)

+ 9 - 4
src/core/define.ml

@@ -12,14 +12,19 @@ let get_documentation_list() =
 		let d = Obj.magic i in
 		let d = Obj.magic i in
 		if d <> Last then begin
 		if d <> Last then begin
 			let t, (doc,flags) = infos d in
 			let t, (doc,flags) = infos d in
-			let pfs = ref [] in
+			let params = ref [] and pfs = ref [] in
 			List.iter (function
 			List.iter (function
-			| HasParam s -> () (* TODO *)
-			| Platforms pl -> pfs := pl @ !pfs;
+				| HasParam s -> params := s :: !params
+				| Platforms fl -> pfs := fl @ !pfs
+				| Link _ -> ()
 			) flags;
 			) flags;
+			let params = (match List.rev !params with
+				| [] -> ""
+				| l -> "<" ^ String.concat ">, <" l ^ "> "
+			) in
 			let pfs = platform_list_help (List.rev !pfs) in
 			let pfs = platform_list_help (List.rev !pfs) in
 			if String.length t > !m then m := String.length t;
 			if String.length t > !m then m := String.length t;
-			((String.concat "-" (ExtString.String.nsplit t "_")),doc ^ pfs) :: (loop (i + 1))
+			((String.concat "-" (ExtString.String.nsplit t "_")),params ^ doc ^ pfs) :: (loop (i + 1))
 		end else
 		end else
 			[]
 			[]
 	in
 	in

+ 35 - 9
src/core/display/completionItem.ml

@@ -567,13 +567,28 @@ let get_name item = match item.ci_kind with
 
 
 let get_type item = item.ci_type
 let get_type item = item.ci_type
 
 
+let get_filter_name item = match item.ci_kind with
+	| ITLocal v -> v.v_name
+	| ITClassField(cf) | ITEnumAbstractField(_,cf) -> cf.field.cf_name
+	| ITEnumField ef -> ef.efield.ef_name
+	| ITType(cm,_) -> s_type_path (cm.pack,cm.name)
+	| ITPackage(path,_) -> s_type_path path
+	| ITModule path -> s_type_path path
+	| ITLiteral s -> s
+	| ITTimer(s,_) -> s
+	| ITMetadata meta -> Meta.to_string meta
+	| ITKeyword kwd -> s_keyword kwd
+	| ITAnonymous _ -> ""
+	| ITExpression _ -> ""
+	| ITTypeParameter c -> snd c.cl_path
+
 let get_documentation item = match item.ci_kind with
 let get_documentation item = match item.ci_kind with
 	| ITClassField cf | ITEnumAbstractField(_,cf) -> cf.field.cf_doc
 	| ITClassField cf | ITEnumAbstractField(_,cf) -> cf.field.cf_doc
 	| ITEnumField ef -> ef.efield.ef_doc
 	| ITEnumField ef -> ef.efield.ef_doc
 	| ITType(mt,_) -> mt.doc
 	| ITType(mt,_) -> mt.doc
 	| _ -> None
 	| _ -> None
 
 
-let to_json ctx item =
+let to_json ctx index item =
 	let open ClassFieldOrigin in
 	let open ClassFieldOrigin in
 	let kind,data = match item.ci_kind with
 	let kind,data = match item.ci_kind with
 		| ITLocal v -> "Local",generate_tvar ctx v
 		| ITLocal v -> "Local",generate_tvar ctx v
@@ -653,14 +668,15 @@ let to_json ctx item =
 				| TTypeParameter -> "TTypeParameter"
 				| TTypeParameter -> "TTypeParameter"
 				| TVariable -> "TVariable"
 				| TVariable -> "TVariable"
 			in
 			in
-			let rec loop internal params platforms targets l = match l with
-				| HasParam s :: l -> loop internal (s :: params) platforms targets l
-				| Platforms pls :: l -> loop internal params ((List.map platform_name pls) @ platforms) targets l
-				| UsedOn usages :: l -> loop internal params platforms ((List.map usage_to_string usages) @ targets) l
-				| UsedInternally :: l -> loop true params platforms targets l
-				| [] -> internal,params,platforms,targets
+			let rec loop internal params platforms targets links l = match l with
+				| HasParam s :: l -> loop internal (s :: params) platforms targets links l
+				| Platforms pls :: l -> loop internal params ((List.map platform_name pls) @ platforms) targets links l
+				| UsedOn usages :: l -> loop internal params platforms ((List.map usage_to_string usages) @ targets) links l
+				| UsedInternally :: l -> loop true params platforms targets links l
+				| Link url :: l -> loop internal params platforms targets (url :: links) l
+				| [] -> internal,params,platforms,targets,links
 			in
 			in
-			let internal,params,platforms,targets = loop false [] [] [] params in
+			let internal,params,platforms,targets,links = loop false [] [] [] [] params in
 			"Metadata",jobject [
 			"Metadata",jobject [
 				"name",jstring name;
 				"name",jstring name;
 				"doc",jstring doc;
 				"doc",jstring doc;
@@ -668,6 +684,7 @@ let to_json ctx item =
 				"platforms",jlist jstring platforms;
 				"platforms",jlist jstring platforms;
 				"targets",jlist jstring targets;
 				"targets",jlist jstring targets;
 				"internal",jbool internal;
 				"internal",jbool internal;
+				"links",jlist jstring links;
 			]
 			]
 		| ITKeyword kwd ->"Keyword",jobject [
 		| ITKeyword kwd ->"Keyword",jobject [
 			"name",jstring (s_keyword kwd)
 			"name",jstring (s_keyword kwd)
@@ -685,8 +702,17 @@ let to_json ctx item =
 			| _ -> assert false
 			| _ -> assert false
 			end
 			end
 	in
 	in
+	let jindex = match index with
+		| None -> []
+		| Some index -> ["index",jint index]
+	in
 	jobject (
 	jobject (
 		("kind",jstring kind) ::
 		("kind",jstring kind) ::
 		("args",data) ::
 		("args",data) ::
-		(match item.ci_type with None -> [] | Some t -> ["type",CompletionType.to_json ctx (snd t)])
+		(match item.ci_type with
+			| None ->
+				jindex
+			| Some t ->
+				("type",CompletionType.to_json ctx (snd t)) :: jindex
+		)
 	)
 	)

+ 3 - 1
src/core/displayTypes.ml

@@ -70,6 +70,7 @@ module DiagnosticsKind = struct
 		| DKCompilerError
 		| DKCompilerError
 		| DKRemovableCode
 		| DKRemovableCode
 		| DKParserError
 		| DKParserError
+		| DKDeprecationWarning
 
 
 	let to_int = function
 	let to_int = function
 		| DKUnusedImport -> 0
 		| DKUnusedImport -> 0
@@ -77,6 +78,7 @@ module DiagnosticsKind = struct
 		| DKCompilerError -> 2
 		| DKCompilerError -> 2
 		| DKRemovableCode -> 3
 		| DKRemovableCode -> 3
 		| DKParserError -> 4
 		| DKParserError -> 4
+		| DKDeprecationWarning -> 5
 end
 end
 
 
 module CompletionResultKind = struct
 module CompletionResultKind = struct
@@ -123,7 +125,7 @@ module CompletionResultKind = struct
 							None
 							None
 				in
 				in
 				let fields =
 				let fields =
-					("item",CompletionItem.to_json ctx item) ::
+					("item",CompletionItem.to_json ctx None item) ::
 					("range",generate_pos_as_range p) ::
 					("range",generate_pos_as_range p) ::
 					("iterator", match iterator with
 					("iterator", match iterator with
 						| None -> jnull
 						| None -> jnull

+ 3 - 1
src/core/error.ml

@@ -289,4 +289,6 @@ let error_require r p =
 	with _ ->
 	with _ ->
 		"'" ^ r ^ "' to be enabled"
 		"'" ^ r ^ "' to be enabled"
 	in
 	in
-	error ("Accessing this field requires " ^ r) p
+	error ("Accessing this field requires " ^ r) p
+
+let invalid_assign p = error "Invalid assign" p

+ 1 - 0
src/core/globals.ml

@@ -8,6 +8,7 @@ type path = string list * string
 
 
 module IntMap = Ptmap
 module IntMap = Ptmap
 module StringMap = Map.Make(struct type t = string let compare = String.compare 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)
 
 
 type platform =
 type platform =
 	| Cross
 	| Cross

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

@@ -519,7 +519,12 @@ and generate_class_field' ctx cfs cf =
 						None
 						None
 			in
 			in
 			begin match value with
 			begin match value with
-				| None -> jnull
+				| None ->
+					if Meta.has (Meta.Custom ":testHack") cf.cf_meta then begin match cf.cf_expr with
+						| Some e -> jobject ["testHack",jstring (s_expr_pretty false "" false (s_type (print_context())) e)] (* TODO: haha *)
+						| None -> jnull
+					end else
+						jnull
 				| Some e -> jobject ["string",jstring (Ast.Printer.s_expr e)]
 				| Some e -> jobject ["string",jstring (Ast.Printer.s_expr e)]
 			end
 			end
 		| GMMinimum ->
 		| GMMinimum ->

+ 2 - 1
src/core/meta.ml

@@ -41,10 +41,11 @@ let get_documentation d =
 			| Platforms fl -> pfs := fl @ !pfs
 			| Platforms fl -> pfs := fl @ !pfs
 			| UsedOn ul -> used := ul @ !used
 			| UsedOn ul -> used := ul @ !used
 			| UsedInternally -> assert false
 			| UsedInternally -> assert false
+			| Link _ -> ()
 		) flags;
 		) flags;
 		let params = (match List.rev !params with
 		let params = (match List.rev !params with
 			| [] -> ""
 			| [] -> ""
-			| l -> "(" ^ String.concat "," l ^ ")"
+			| l -> "(<" ^ String.concat ">, <" l ^ ">) "
 		) in
 		) in
 		let pfs = platform_list_help (List.rev !pfs) in
 		let pfs = platform_list_help (List.rev !pfs) in
 		let str = "@" ^ t in
 		let str = "@" ^ t in

+ 142 - 23
src/core/type.ml

@@ -634,7 +634,7 @@ let map loop t =
 	| TDynamic t2 ->
 	| TDynamic t2 ->
 		if t == t2 then	t else TDynamic (loop t2)
 		if t == t2 then	t else TDynamic (loop t2)
 
 
-let dup t =
+let duplicate t =
 	let monos = ref [] in
 	let monos = ref [] in
 	let rec loop t =
 	let rec loop t =
 		match t with
 		match t with
@@ -650,8 +650,10 @@ let dup t =
 	in
 	in
 	loop t
 	loop t
 
 
+exception ApplyParamsRecursion
+
 (* substitute parameters with other types *)
 (* substitute parameters with other types *)
-let apply_params cparams params t =
+let apply_params ?stack cparams params t =
 	match cparams with
 	match cparams with
 	| [] -> t
 	| [] -> t
 	| _ ->
 	| _ ->
@@ -679,7 +681,52 @@ let apply_params cparams params t =
 		| TType (t2,tl) ->
 		| TType (t2,tl) ->
 			(match tl with
 			(match tl with
 			| [] -> t
 			| [] -> t
-			| _ -> TType (t2,List.map loop tl))
+			| _ ->
+				let new_applied_params = List.map loop tl in
+				(match stack with
+				| None -> ()
+				| Some stack ->
+					List.iter (fun (subject, old_applied_params) ->
+						(*
+							E.g.:
+							```
+							typedef Rec<T> = { function method():Rec<Array<T>> }
+							```
+							We need to make sure that we are not applying the result of previous
+							application to the same place, which would mean the result of current
+							application would go into `apply_params` again and then again and so on.
+
+							Argument `stack` holds all previous results of `apply_params` to typedefs in current
+							unification process.
+
+							Imagine we are trying to unify `Rec<Int>` with something.
+
+							Once `apply_params Array<T> Int Rec<Array<T>>` is called for the first time the result
+							will be `Rec< Array<Int> >`. Store `Array<Int>` into `stack`
+
+							Then the next params application looks like this:
+								`apply_params Array<T> Array<Int> Rec<Array<T>>`
+							Notice the second argument is actually the result of a previous `apply_params` call.
+							And the result of the current call is `Rec< Array<Array<Int>> >`.
+
+							The third call would be:
+								`apply_params Array<T> Array<Array<Int>> Rec<Array<T>>`
+							and so on.
+
+							To stop infinite params application we need to check that we are trying to apply params
+							produced by the previous `apply_params Array<Int> _ Rec<Array<T>>` to the same `Rec<Array<T>>`
+						*)
+						if
+							subject == t (* Check the place that we're applying to is the same `Rec<Array<T>>` *)
+							&& old_applied_params == params (* Check that params we're applying are the same params
+																produced by the previous call to
+																`apply_params Array<T> _ Rec<Array<T>>` *)
+						then
+							raise ApplyParamsRecursion
+					) !stack;
+					stack := (t, new_applied_params) :: !stack;
+				);
+				TType (t2,new_applied_params))
 		| TAbstract (a,tl) ->
 		| TAbstract (a,tl) ->
 			(match tl with
 			(match tl with
 			| [] -> t
 			| [] -> t
@@ -731,6 +778,21 @@ let apply_params cparams params t =
 let monomorphs eparams t =
 let monomorphs eparams t =
 	apply_params eparams (List.map (fun _ -> mk_mono()) eparams) t
 	apply_params eparams (List.map (fun _ -> mk_mono()) eparams) t
 
 
+let apply_params_stack = ref []
+
+let try_apply_params_rec cparams params t success =
+	let old_stack = !apply_params_stack in
+	try
+		let result = success (apply_params ~stack:apply_params_stack cparams params t) in
+		apply_params_stack := old_stack;
+		result
+	with
+		| ApplyParamsRecursion ->
+			apply_params_stack := old_stack;
+		| err ->
+			apply_params_stack := old_stack;
+			raise err
+
 let rec follow t =
 let rec follow t =
 	match t with
 	match t with
 	| TMono r ->
 	| TMono r ->
@@ -1662,47 +1724,94 @@ let rec link e a b =
 		true
 		true
 	end
 	end
 
 
+let would_produce_recursive_anon field_acceptor field_donor =
+	try
+		(match !(field_acceptor.a_status) with
+		| Opened ->
+			PMap.iter (fun n field ->
+				match follow field.cf_type with
+				| TAnon a when field_acceptor == a -> raise Exit
+				| _ -> ()
+			) field_donor.a_fields;
+		| _ -> ());
+		false
+	with Exit -> true
+
 let link_dynamic a b = match follow a,follow b with
 let link_dynamic a b = match follow a,follow b with
 	| TMono r,TDynamic _ -> r := Some b
 	| TMono r,TDynamic _ -> r := Some b
 	| TDynamic _,TMono r -> r := Some a
 	| TDynamic _,TMono r -> r := Some a
 	| _ -> ()
 	| _ -> ()
 
 
-let rec fast_eq a b =
+let fast_eq_check type_param_check a b =
 	if a == b then
 	if a == b then
 		true
 		true
 	else match a , b with
 	else match a , b with
 	| TFun (l1,r1) , TFun (l2,r2) when List.length l1 = List.length l2 ->
 	| TFun (l1,r1) , TFun (l2,r2) when List.length l1 = List.length l2 ->
-		List.for_all2 (fun (_,_,t1) (_,_,t2) -> fast_eq t1 t2) l1 l2 && fast_eq r1 r2
+		List.for_all2 (fun (_,_,t1) (_,_,t2) -> type_param_check t1 t2) l1 l2 && type_param_check r1 r2
 	| TType (t1,l1), TType (t2,l2) ->
 	| TType (t1,l1), TType (t2,l2) ->
-		t1 == t2 && List.for_all2 fast_eq l1 l2
+		t1 == t2 && List.for_all2 type_param_check l1 l2
 	| TEnum (e1,l1), TEnum (e2,l2) ->
 	| TEnum (e1,l1), TEnum (e2,l2) ->
-		e1 == e2 && List.for_all2 fast_eq l1 l2
+		e1 == e2 && List.for_all2 type_param_check l1 l2
 	| TInst (c1,l1), TInst (c2,l2) ->
 	| TInst (c1,l1), TInst (c2,l2) ->
-		c1 == c2 && List.for_all2 fast_eq l1 l2
+		c1 == c2 && List.for_all2 type_param_check l1 l2
 	| TAbstract (a1,l1), TAbstract (a2,l2) ->
 	| TAbstract (a1,l1), TAbstract (a2,l2) ->
-		a1 == a2 && List.for_all2 fast_eq l1 l2
+		a1 == a2 && List.for_all2 type_param_check l1 l2
 	| _ , _ ->
 	| _ , _ ->
 		false
 		false
 
 
+let rec fast_eq a b = fast_eq_check fast_eq a b
+
 let rec fast_eq_mono ml a b =
 let rec fast_eq_mono ml a b =
-	if a == b then
+	if fast_eq_check (fast_eq_mono ml) a b then
 		true
 		true
 	else match a , b with
 	else match a , b with
-	| TFun (l1,r1) , TFun (l2,r2) when List.length l1 = List.length l2 ->
-		List.for_all2 (fun (_,_,t1) (_,_,t2) -> fast_eq_mono ml t1 t2) l1 l2 && fast_eq_mono ml r1 r2
-	| TType (t1,l1), TType (t2,l2) ->
-		t1 == t2 && List.for_all2 (fast_eq_mono ml) l1 l2
-	| TEnum (e1,l1), TEnum (e2,l2) ->
-		e1 == e2 && List.for_all2 (fast_eq_mono ml) l1 l2
-	| TInst (c1,l1), TInst (c2,l2) ->
-		c1 == c2 && List.for_all2 (fast_eq_mono ml) l1 l2
-	| TAbstract (a1,l1), TAbstract (a2,l2) ->
-		a1 == a2 && List.for_all2 (fast_eq_mono ml) l1 l2
 	| TMono _, _ ->
 	| TMono _, _ ->
 		List.memq a ml
 		List.memq a ml
 	| _ , _ ->
 	| _ , _ ->
 		false
 		false
 
 
+let rec fast_eq_anon ?(mono_equals_dynamic=false) a b =
+	if fast_eq_check (fast_eq_anon ~mono_equals_dynamic) a b then
+		true
+	else match a , b with
+	(*
+		`mono_equals_dynamic` is here because of https://github.com/HaxeFoundation/haxe/issues/8588#issuecomment-520138371
+		Generally unbound monomorphs should not be considered equal to anything,
+		because it's unknown, which types they would be bound to.
+	*)
+	| t, TMono { contents = None } when t == t_dynamic -> mono_equals_dynamic
+	| TMono { contents = None }, t when t == t_dynamic -> mono_equals_dynamic
+	| TMono { contents = Some t1 }, TMono { contents = Some t2 } ->
+		fast_eq_anon t1 t2
+	| TAnon a1, TAnon a2 ->
+		let fields_eq() =
+			let rec loop fields1 fields2 =
+				match fields1, fields2 with
+				| [], [] -> true
+				| _, [] | [], _ -> false
+				| f1 :: rest1, f2 :: rest2 ->
+					f1.cf_name = f2.cf_name
+					&& (try fast_eq_anon f1.cf_type f2.cf_type with Not_found -> false)
+					&& loop rest1 rest2
+			in
+			let fields1 = PMap.fold (fun field fields -> field :: fields) a1.a_fields []
+			and fields2 = PMap.fold (fun field fields -> field :: fields) a2.a_fields []
+			and sort_compare f1 f2 = compare f1.cf_name f2.cf_name in
+			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
+		| EnumStatics e, EnumStatics e2 -> e == e2
+		| AbstractStatics a, AbstractStatics a2 -> a == a2
+		| Extend tl1, Extend tl2 -> fields_eq() && List.for_all2 fast_eq_anon tl1 tl2
+		| Closed, Closed -> fields_eq()
+		| Opened, Opened -> fields_eq()
+		| Const, Const -> fields_eq()
+		| _ -> false
+		)
+	| _ , _ ->
+		false
+
 (* perform unification with subtyping.
 (* perform unification with subtyping.
    the first type is always the most down in the class hierarchy
    the first type is always the most down in the class hierarchy
    it's also the one that is pointed by the position.
    it's also the one that is pointed by the position.
@@ -1902,6 +2011,7 @@ let rec type_eq param a b =
 			| AbstractStatics a -> (match !(a1.a_status) with AbstractStatics a2 when a == a2 -> () | _ -> error [])
 			| AbstractStatics a -> (match !(a1.a_status) with AbstractStatics a2 when a == a2 -> () | _ -> error [])
 			| _ -> ()
 			| _ -> ()
 			);
 			);
+			if would_produce_recursive_anon a1 a2 || would_produce_recursive_anon a2 a1 then error [cannot_unify a b];
 			PMap.iter (fun n f1 ->
 			PMap.iter (fun n f1 ->
 				try
 				try
 					let f2 = PMap.find n a2.a_fields in
 					let f2 = PMap.find n a2.a_fields in
@@ -1988,12 +2098,12 @@ let rec unify a b =
 	| TType (t,tl) , _ ->
 	| TType (t,tl) , _ ->
 		rec_stack unify_stack (a,b)
 		rec_stack unify_stack (a,b)
 			(fun(a2,b2) -> fast_eq a a2 && fast_eq b b2)
 			(fun(a2,b2) -> fast_eq a a2 && fast_eq b b2)
-			(fun() -> unify (apply_params t.t_params tl t.t_type) b)
+			(fun() -> try_apply_params_rec t.t_params tl t.t_type (fun a -> unify a b))
 			(fun l -> error (cannot_unify a b :: l))
 			(fun l -> error (cannot_unify a b :: l))
 	| _ , TType (t,tl) ->
 	| _ , TType (t,tl) ->
 		rec_stack unify_stack (a,b)
 		rec_stack unify_stack (a,b)
 			(fun(a2,b2) -> fast_eq a a2 && fast_eq b b2)
 			(fun(a2,b2) -> fast_eq a a2 && fast_eq b b2)
-			(fun() -> unify a (apply_params t.t_params tl t.t_type))
+			(fun() -> try_apply_params_rec t.t_params tl t.t_type (unify a))
 			(fun l -> error (cannot_unify a b :: l))
 			(fun l -> error (cannot_unify a b :: l))
 	| TEnum (ea,tl1) , TEnum (eb,tl2) ->
 	| TEnum (ea,tl1) , TEnum (eb,tl2) ->
 		if ea != eb then error [cannot_unify a b];
 		if ea != eb then error [cannot_unify a b];
@@ -2240,6 +2350,7 @@ and unify_abstracts a b a1 tl1 a2 tl2 =
 			error [cannot_unify a b]
 			error [cannot_unify a b]
 
 
 and unify_anons a b a1 a2 =
 and unify_anons a b a1 a2 =
+	if would_produce_recursive_anon a1 a2 then error [cannot_unify a b];
 	(try
 	(try
 		PMap.iter (fun n f2 ->
 		PMap.iter (fun n f2 ->
 		try
 		try
@@ -2251,7 +2362,11 @@ and unify_anons a b a1 a2 =
 				| _ -> error [invalid_kind n f1.cf_kind f2.cf_kind]);
 				| _ -> error [invalid_kind n f1.cf_kind f2.cf_kind]);
 			if (has_class_field_flag f2 CfPublic) && not (has_class_field_flag f1 CfPublic) then error [invalid_visibility n];
 			if (has_class_field_flag f2 CfPublic) && not (has_class_field_flag f1 CfPublic) then error [invalid_visibility n];
 			try
 			try
-				unify_with_access f1 (field_type f1) f2;
+				let f1_type =
+					if fast_eq f1.cf_type f2.cf_type then f1.cf_type
+					else field_type f1
+				in
+				unify_with_access f1 f1_type f2;
 				(match !(a1.a_status) with
 				(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
 				| Statics c when not (Meta.has Meta.MaybeUsed f1.cf_meta) -> f1.cf_meta <- (Meta.MaybeUsed,[],f1.cf_pos) :: f1.cf_meta
 				| _ -> ());
 				| _ -> ());
@@ -2824,6 +2939,10 @@ module TExprToExpr = struct
 end
 end
 
 
 module ExtType = struct
 module ExtType = struct
+	let is_mono = function
+		| TMono { contents = None } -> true
+		| _ -> false
+
 	let is_void = function
 	let is_void = function
 		| TAbstract({a_path=[],"Void"},_) -> true
 		| TAbstract({a_path=[],"Void"},_) -> true
 		| _ -> false
 		| _ -> false

+ 15 - 15
src/core/withType.ml

@@ -1,31 +1,31 @@
 open Type
 open Type
 
 
-type expected_name_source =
-	| FunctionArgument
-	| StructureField
-
-type expected_name = string * expected_name_source
+type with_type_source =
+	| FunctionArgument of string
+	| StructureField of string
+	| ImplicitReturn
 
 
 type t =
 type t =
 	| NoValue
 	| NoValue
-	| Value of expected_name option
-	| WithType of Type.t * expected_name option
+	| Value of with_type_source option
+	| WithType of Type.t * with_type_source option
 
 
 let with_type t = WithType(t,None)
 let with_type t = WithType(t,None)
-let with_argument t name = WithType(t,Some(name,FunctionArgument))
-let with_structure_field t name = WithType(t,Some(name,StructureField))
+let of_implicit_return t = WithType(t,Some ImplicitReturn)
+let with_argument t name = WithType(t,Some(FunctionArgument name))
+let with_structure_field t name = WithType(t,Some(StructureField name))
 let value = Value None
 let value = Value None
-let named_argument name = Value (Some(name,FunctionArgument))
-let named_structure_field name = Value (Some(name,StructureField))
+let named_argument name = Value (Some(FunctionArgument name))
+let named_structure_field name = Value (Some(StructureField name))
 let no_value = NoValue
 let no_value = NoValue
 
 
 let to_string = function
 let to_string = function
 	| NoValue -> "NoValue"
 	| NoValue -> "NoValue"
-	| Value None -> "Value"
-	| Value (Some(s,_)) -> "Value " ^ s
+	| Value (None | Some ImplicitReturn) -> "Value"
+	| Value (Some(FunctionArgument s | StructureField s)) -> "Value " ^ s
 	| WithType(t,s) ->
 	| WithType(t,s) ->
 		let name = match s with
 		let name = match s with
-			| None -> "None"
-			| Some(s,_) -> s
+			| Some(FunctionArgument s | StructureField s) -> s
+			| _ -> "None"
 		in
 		in
 		Printf.sprintf "WithType(%s, %s)" (s_type (print_context()) t) name
 		Printf.sprintf "WithType(%s, %s)" (s_type (print_context()) t) name

+ 74 - 22
src/filters/filters.ml

@@ -25,23 +25,7 @@ open Error
 open Globals
 open Globals
 open FiltersCommon
 open FiltersCommon
 
 
-(** retrieve string from @:native metadata or raise Not_found *)
-let get_native_name meta =
-	let rec get_native meta = match meta with
-		| [] -> raise Not_found
-		| (Meta.Native,[v],p as meta) :: _ ->
-			meta
-		| _ :: meta ->
-			get_native meta
-	in
-	let (_,e,mp) = get_native meta in
-	match e with
-	| [Ast.EConst (Ast.String name),p] ->
-		name,p
-	| [] ->
-		raise Not_found
-	| _ ->
-		error "String expected" mp
+let get_native_name = TypeloadCheck.get_native_name
 
 
 (* PASS 1 begin *)
 (* PASS 1 begin *)
 
 
@@ -365,12 +349,57 @@ let check_unification ctx e t =
 	end;
 	end;
 	e
 	e
 
 
+let rec fix_return_dynamic_from_void_function ctx return_is_void e =
+	match e.eexpr with
+	| TFunction fn ->
+		let is_void = ExtType.is_void (follow fn.tf_type) in
+		let body = fix_return_dynamic_from_void_function ctx is_void fn.tf_expr in
+		{ e with eexpr = TFunction { fn with tf_expr = body } }
+	| TReturn (Some return_expr) when return_is_void && t_dynamic == follow return_expr.etype ->
+		let return_pos = { e.epos with pmax = return_expr.epos.pmin - 1 } in
+		let exprs = [
+			fix_return_dynamic_from_void_function ctx return_is_void return_expr;
+			{ e with eexpr = TReturn None; epos = return_pos };
+		] in
+		{ e with
+			eexpr = TMeta (
+				(Meta.MergeBlock, [], null_pos),
+				mk (TBlock exprs) e.etype e.epos
+			);
+		}
+	| _ -> Type.map_expr (fix_return_dynamic_from_void_function ctx return_is_void) e
+
+let check_abstract_as_value e =
+	let rec loop e =
+		match e.eexpr with
+		| TField ({ eexpr = TTypeExpr _ }, _) -> ()
+		| TTypeExpr(TClassDecl {cl_kind = KAbstractImpl a}) when not (Meta.has Meta.RuntimeValue a.a_meta) ->
+			error "Cannot use abstract as value" e.epos
+		| _ -> Type.iter loop e
+	in
+	loop e;
+	e
+
 (* PASS 1 end *)
 (* PASS 1 end *)
 
 
 (* Saves a class state so it can be restored later, e.g. after DCE or native path rewrite *)
 (* Saves a class state so it can be restored later, e.g. after DCE or native path rewrite *)
 let save_class_state ctx t = match t with
 let save_class_state ctx t = match t with
 	| TClassDecl c ->
 	| TClassDecl c ->
+		let vars = ref [] in
+		let rec save_vars e =
+			let add v = vars := (v, v.v_type) :: !vars in
+			match e.eexpr with
+				| TFunction fn ->
+					List.iter (fun (v, _) -> add v) fn.tf_args;
+					save_vars fn.tf_expr
+				| TVar (v, e) ->
+					add v;
+					Option.may save_vars e
+				| _ ->
+					iter save_vars e
+		in
 		let mk_field_restore f =
 		let mk_field_restore f =
+			Option.may save_vars f.cf_expr;
 			let rec mk_overload_restore f =
 			let rec mk_overload_restore f =
 				f.cf_name,f.cf_kind,f.cf_expr,f.cf_type,f.cf_meta,f.cf_params
 				f.cf_name,f.cf_kind,f.cf_expr,f.cf_type,f.cf_meta,f.cf_params
 			in
 			in
@@ -395,6 +424,7 @@ let save_class_state ctx t = match t with
 		let ofr = List.map (mk_field_restore) c.cl_ordered_fields in
 		let ofr = List.map (mk_field_restore) c.cl_ordered_fields in
 		let osr = List.map (mk_field_restore) c.cl_ordered_statics in
 		let osr = List.map (mk_field_restore) c.cl_ordered_statics in
 		let init = c.cl_init in
 		let init = c.cl_init in
+		Option.may save_vars init;
 		c.cl_restore <- (fun() ->
 		c.cl_restore <- (fun() ->
 			c.cl_super <- sup;
 			c.cl_super <- sup;
 			c.cl_implements <- impl;
 			c.cl_implements <- impl;
@@ -409,6 +439,7 @@ let save_class_state ctx t = match t with
 			c.cl_constructor <- Option.map restore_field csr;
 			c.cl_constructor <- Option.map restore_field csr;
 			c.cl_overrides <- over;
 			c.cl_overrides <- over;
 			c.cl_descendants <- [];
 			c.cl_descendants <- [];
+			List.iter (fun (v, t) -> v.v_type <- t) !vars;
 		)
 		)
 	| _ ->
 	| _ ->
 		()
 		()
@@ -780,14 +811,28 @@ end
 let run com tctx main =
 let run com tctx main =
 	let detail_times = Common.raw_defined com "filter-times" in
 	let detail_times = Common.raw_defined com "filter-times" in
 	let new_types = List.filter (fun t ->
 	let new_types = List.filter (fun t ->
-		(match t with
+		let cached = is_cached t in
+		begin match t with
 			| TClassDecl cls ->
 			| TClassDecl cls ->
 				List.iter (fun (iface,_) -> add_descendant iface cls) cls.cl_implements;
 				List.iter (fun (iface,_) -> add_descendant iface cls) cls.cl_implements;
-				(match cls.cl_super with
+				begin match cls.cl_super with
 					| Some (csup,_) -> add_descendant csup cls
 					| Some (csup,_) -> add_descendant csup cls
-					| None -> ())
-			| _ -> ());
-		not (is_cached t)
+					| None -> ()
+				end;
+				(* Save cf_expr_unoptimized early: We want to inline with the original expression
+				   on the next compilation. *)
+				if not cached then begin
+					let field cf = match cf.cf_expr with
+						| Some {eexpr = TFunction tf} -> cf.cf_expr_unoptimized <- Some tf
+						| _ -> ()
+					in
+					List.iter field cls.cl_ordered_fields;
+					List.iter field cls.cl_ordered_statics;
+					Option.may field cls.cl_constructor;
+				end;
+			| _ -> ()
+		end;
+		not cached
 	) com.types in
 	) com.types in
 	NullSafety.run com new_types;
 	NullSafety.run com new_types;
 	(* PASS 1: general expression filters *)
 	(* PASS 1: general expression filters *)
@@ -795,7 +840,14 @@ let run com tctx main =
 		(* ForRemap.apply tctx; *)
 		(* ForRemap.apply tctx; *)
 		VarLazifier.apply com;
 		VarLazifier.apply com;
 		AbstractCast.handle_abstract_casts tctx;
 		AbstractCast.handle_abstract_casts tctx;
+	] in
+	let t = filter_timer detail_times ["expr 0"] in
+	List.iter (run_expression_filters tctx filters) new_types;
+	t();
+	let filters = [
+		fix_return_dynamic_from_void_function tctx true;
 		check_local_vars_init;
 		check_local_vars_init;
+		check_abstract_as_value;
 		if Common.defined com Define.OldConstructorInline then Optimizer.inline_constructors tctx else InlineConstructors.inline_constructors tctx;
 		if Common.defined com Define.OldConstructorInline then Optimizer.inline_constructors tctx else InlineConstructors.inline_constructors tctx;
 		Optimizer.reduce_expression tctx;
 		Optimizer.reduce_expression tctx;
 		CapturedVars.captured_vars com;
 		CapturedVars.captured_vars com;

+ 1 - 0
src/generators/genas3.ml

@@ -264,6 +264,7 @@ let rec type_str ctx t p =
 		| [], "Int" -> "int"
 		| [], "Int" -> "int"
 		| [], "Float" -> "Number"
 		| [], "Float" -> "Number"
 		| [], "Bool" -> "Boolean"
 		| [], "Bool" -> "Boolean"
+		| ["flash"], "AnyType" -> "*"
 		| _ -> s_path ctx true a.a_path p)
 		| _ -> s_path ctx true a.a_path p)
 	| TEnum (e,_) ->
 	| TEnum (e,_) ->
 		if e.e_extern then "Object" else s_path ctx true e.e_path p
 		if e.e_extern then "Object" else s_path ctx true e.e_path p

+ 122 - 73
src/generators/gencpp.ml

@@ -1728,43 +1728,48 @@ let cpp_is_dynamic_type = function
 ;;
 ;;
 
 
 
 
-let rec cpp_type_of ctx haxe_type =
-   (match haxe_type with
-   | TMono r -> (match !r with None -> TCppDynamic | Some t -> cpp_type_of ctx t)
+let rec cpp_type_of stack ctx haxe_type =
+   if List.exists (fast_eq haxe_type) stack then
+      TCppDynamic
+   else begin
+      let stack = haxe_type :: stack in
+      (match haxe_type with
+      | TMono r -> (match !r with None -> TCppDynamic | Some t -> cpp_type_of stack ctx t)
 
 
-   | TEnum (enum,params) ->  TCppEnum(enum)
+      | TEnum (enum,params) ->  TCppEnum(enum)
 
 
-   | TInst ({ cl_path=([],"Array"); cl_kind = KTypeParameter _},_)
-      -> TCppObject
+      | TInst ({ cl_path=([],"Array"); cl_kind = KTypeParameter _},_)
+         -> TCppObject
 
 
-   | TInst ({ cl_kind = KTypeParameter _},_)
-      -> TCppDynamic
+      | TInst ({ cl_kind = KTypeParameter _},_)
+         -> TCppDynamic
 
 
-   | TInst (klass,params) ->
-      cpp_instance_type ctx klass params
+      | TInst (klass,params) ->
+         cpp_instance_type stack ctx klass params
 
 
-   | TAbstract (abs,pl) when not (Meta.has Meta.CoreType abs.a_meta) ->
-       cpp_type_from_path ctx abs.a_path pl (fun () ->
-            cpp_type_of ctx (Abstract.get_underlying_type abs pl) )
+      | TAbstract (abs,pl) when not (Meta.has Meta.CoreType abs.a_meta) ->
+         cpp_type_from_path stack ctx abs.a_path pl (fun () ->
+               cpp_type_of stack ctx (Abstract.get_underlying_type abs pl) )
 
 
-   | TAbstract (a,params) ->
-       cpp_type_from_path ctx a.a_path params (fun () ->
-            if is_scalar_abstract a then begin
-               let native =  get_meta_string a.a_meta Meta.Native in
-               TCppScalar(if native="" then join_class_path a.a_path "::" else native)
-            end else
-               TCppDynamic)
+      | TAbstract (a,params) ->
+         cpp_type_from_path stack ctx a.a_path params (fun () ->
+               if is_scalar_abstract a then begin
+                  let native =  get_meta_string a.a_meta Meta.Native in
+                  TCppScalar(if native="" then join_class_path a.a_path "::" else native)
+               end else
+                  TCppDynamic)
 
 
-   | TType (type_def,params) ->
-       cpp_type_from_path ctx type_def.t_path params (fun () ->
-          cpp_type_of ctx (apply_params type_def.t_params params type_def.t_type) )
+      | TType (type_def,params) ->
+         cpp_type_from_path stack ctx type_def.t_path params (fun () ->
+            cpp_type_of stack ctx (apply_params type_def.t_params params type_def.t_type) )
 
 
-   | TFun _ -> TCppObject
-   | TAnon _ -> TCppObject
-   | TDynamic _ -> TCppDynamic
-   | TLazy func -> cpp_type_of ctx (lazy_type func)
-   )
-   and  cpp_type_from_path ctx path params default =
+      | TFun _ -> TCppObject
+      | TAnon _ -> TCppObject
+      | TDynamic _ -> TCppDynamic
+      | TLazy func -> cpp_type_of stack ctx (lazy_type func)
+      )
+   end
+   and  cpp_type_from_path stack ctx path params default =
       match path,params with
       match path,params with
       | ([],"Void"),_ -> TCppVoid
       | ([],"Void"),_ -> TCppVoid
       | ([],"void"),_ -> TCppVoid (* for old code with @:void *)
       | ([],"void"),_ -> TCppVoid (* for old code with @:void *)
@@ -1795,25 +1800,25 @@ let rec cpp_type_of ctx haxe_type =
 
 
       (* Things with type parameters hxcpp knows about ... *)
       (* Things with type parameters hxcpp knows about ... *)
       | (["cpp"],"FastIterator"), [p] ->
       | (["cpp"],"FastIterator"), [p] ->
-            TCppFastIterator(cpp_type_of ctx p)
+            TCppFastIterator(cpp_type_of stack ctx p)
       | (["cpp"],"Pointer"), [p] ->
       | (["cpp"],"Pointer"), [p] ->
-            TCppPointer("Pointer", cpp_type_of ctx p)
+            TCppPointer("Pointer", cpp_type_of stack ctx p)
       | (["cpp"],"ConstPointer"), [p] ->
       | (["cpp"],"ConstPointer"), [p] ->
-            TCppPointer("ConstPointer", cpp_type_of ctx p)
+            TCppPointer("ConstPointer", cpp_type_of stack ctx p)
       | (["cpp"],"RawPointer"), [p] ->
       | (["cpp"],"RawPointer"), [p] ->
-            TCppRawPointer("", cpp_type_of ctx p)
+            TCppRawPointer("", cpp_type_of stack ctx p)
       | (["cpp"],"RawConstPointer"), [p] ->
       | (["cpp"],"RawConstPointer"), [p] ->
-            TCppRawPointer("const ", cpp_type_of ctx p)
+            TCppRawPointer("const ", cpp_type_of stack ctx p)
       | (["cpp"],"Function"), [function_type; abi] ->
       | (["cpp"],"Function"), [function_type; abi] ->
-            cpp_function_type_of ctx function_type abi;
+            cpp_function_type_of stack ctx function_type abi;
       | (["cpp"],"Callable"), [function_type]
       | (["cpp"],"Callable"), [function_type]
       | (["cpp"],"CallableData"), [function_type] ->
       | (["cpp"],"CallableData"), [function_type] ->
-            cpp_function_type_of_string ctx function_type "";
+            cpp_function_type_of_string stack ctx function_type "";
       | (("cpp"::["objc"]),"ObjcBlock"), [function_type] ->
       | (("cpp"::["objc"]),"ObjcBlock"), [function_type] ->
-            let args,ret = (cpp_function_type_of_args_ret ctx function_type) in
+            let args,ret = (cpp_function_type_of_args_ret stack ctx function_type) in
             TCppObjCBlock(args,ret)
             TCppObjCBlock(args,ret)
       | (["haxe";"extern"], "Rest"),[rest] ->
       | (["haxe";"extern"], "Rest"),[rest] ->
-            TCppRest(cpp_type_of ctx rest)
+            TCppRest(cpp_type_of stack ctx rest)
       | (("cpp"::["objc"]),"Protocol"), [interface_type] ->
       | (("cpp"::["objc"]),"Protocol"), [interface_type] ->
             (match follow interface_type with
             (match follow interface_type with
             | TInst (klass,[]) when klass.cl_interface ->
             | TInst (klass,[]) when klass.cl_interface ->
@@ -1823,16 +1828,16 @@ let rec cpp_type_of ctx haxe_type =
                    assert false;
                    assert false;
             )
             )
       | (["cpp"],"Reference"), [param] ->
       | (["cpp"],"Reference"), [param] ->
-            TCppReference(cpp_type_of ctx param)
+            TCppReference(cpp_type_of stack ctx param)
       | (["cpp"],"Struct"), [param] ->
       | (["cpp"],"Struct"), [param] ->
-            TCppStruct(cpp_type_of ctx param)
+            TCppStruct(cpp_type_of stack ctx param)
       | (["cpp"],"Star"), [param] ->
       | (["cpp"],"Star"), [param] ->
-            TCppStar(cpp_type_of_pointer ctx param,false)
+            TCppStar(cpp_type_of_pointer stack ctx param,false)
       | (["cpp"],"ConstStar"), [param] ->
       | (["cpp"],"ConstStar"), [param] ->
-            TCppStar(cpp_type_of_pointer ctx param,true)
+            TCppStar(cpp_type_of_pointer stack ctx param,true)
 
 
       | ([],"Array"), [p] ->
       | ([],"Array"), [p] ->
-         let arrayOf = cpp_type_of ctx p in
+         let arrayOf = cpp_type_of stack ctx p in
          (match arrayOf with
          (match arrayOf with
             | TCppVoid (* ? *)
             | TCppVoid (* ? *)
             | TCppDynamic ->
             | TCppDynamic ->
@@ -1857,55 +1862,55 @@ let rec cpp_type_of ctx haxe_type =
          )
          )
 
 
       | ([],"Null"), [p] ->
       | ([],"Null"), [p] ->
-            cpp_type_of_null ctx p
+            cpp_type_of_null stack ctx p
 
 
       | _ -> default ()
       | _ -> default ()
 
 
-   and cpp_type_of_null ctx p =
-     let baseType = cpp_type_of ctx p in
+   and cpp_type_of_null stack ctx p =
+     let baseType = cpp_type_of stack ctx p in
      if (type_has_meta_key p Meta.NotNull) || (is_cpp_scalar baseType) then
      if (type_has_meta_key p Meta.NotNull) || (is_cpp_scalar baseType) then
         TCppObject
         TCppObject
      else
      else
         baseType
         baseType
-   and cpp_type_of_pointer ctx p =
+   and cpp_type_of_pointer stack ctx p =
      match p with
      match p with
-     | TAbstract ({ a_path = ([],"Null") },[t]) -> cpp_type_of ctx t
-     | x ->  cpp_type_of ctx x
+     | TAbstract ({ a_path = ([],"Null") },[t]) -> cpp_type_of stack ctx t
+     | x ->  cpp_type_of stack ctx x
    (* Optional types are Dynamic if they norally could not be null *)
    (* Optional types are Dynamic if they norally could not be null *)
-   and cpp_fun_arg_type_of ctx tvar opt =
+   and cpp_fun_arg_type_of stack ctx tvar opt =
       match opt with
       match opt with
-      | Some _ -> cpp_type_of_null ctx tvar.t_type
-      | _ -> cpp_type_of ctx tvar.t_type
+      | Some _ -> cpp_type_of_null stack ctx tvar.t_type
+      | _ -> cpp_type_of stack ctx tvar.t_type
 
 
-   and cpp_tfun_arg_type_of ctx opt t =
-      if opt then cpp_type_of_null ctx t else cpp_type_of ctx t
+   and cpp_tfun_arg_type_of stack ctx opt t =
+      if opt then cpp_type_of_null stack ctx t else cpp_type_of stack ctx t
 
 
-   and cpp_function_type_of ctx function_type abi =
+   and cpp_function_type_of stack ctx function_type abi =
       let abi = (match follow abi with
       let abi = (match follow abi with
                  | TInst (klass1,_) -> get_meta_string klass1.cl_meta Meta.Abi
                  | TInst (klass1,_) -> get_meta_string klass1.cl_meta Meta.Abi
                  | _ -> assert false )
                  | _ -> assert false )
       in
       in
-      cpp_function_type_of_string ctx function_type abi
-   and cpp_function_type_of_string ctx function_type abi_string =
-      let args,ret = cpp_function_type_of_args_ret ctx function_type in
+      cpp_function_type_of_string stack ctx function_type abi
+   and cpp_function_type_of_string stack ctx function_type abi_string =
+      let args,ret = cpp_function_type_of_args_ret stack ctx function_type in
       TCppFunction(args, ret, abi_string)
       TCppFunction(args, ret, abi_string)
 
 
-   and cpp_function_type_of_args_ret ctx function_type =
+   and cpp_function_type_of_args_ret stack ctx function_type =
       match follow function_type with
       match follow function_type with
       | TFun(args,ret) ->
       | TFun(args,ret) ->
           (* Optional types are Dynamic if they norally could not be null *)
           (* Optional types are Dynamic if they norally could not be null *)
           let  cpp_arg_type_of = fun(_,optional,haxe_type) ->
           let  cpp_arg_type_of = fun(_,optional,haxe_type) ->
              if optional then
              if optional then
-                cpp_type_of_null ctx haxe_type
+                cpp_type_of_null stack ctx haxe_type
              else
              else
-                cpp_type_of ctx haxe_type
+                cpp_type_of stack ctx haxe_type
           in
           in
-          List.map cpp_arg_type_of args, cpp_type_of ctx ret
+          List.map cpp_arg_type_of args, cpp_type_of stack ctx ret
       | _ ->  (* ? *)
       | _ ->  (* ? *)
           [TCppVoid], TCppVoid
           [TCppVoid], TCppVoid
 
 
-   and cpp_instance_type ctx klass params =
-      cpp_type_from_path ctx klass.cl_path params (fun () ->
+   and cpp_instance_type stack ctx klass params =
+      cpp_type_from_path stack ctx klass.cl_path params (fun () ->
          if is_objc_class klass then
          if is_objc_class klass then
             TCppObjC(klass)
             TCppObjC(klass)
          else if klass.cl_interface && is_native_gen_class klass then
          else if klass.cl_interface && is_native_gen_class klass then
@@ -1917,6 +1922,17 @@ let rec cpp_type_of ctx haxe_type =
          else
          else
             TCppInst(klass)
             TCppInst(klass)
        )
        )
+
+let cpp_type_of ctx = cpp_type_of [] ctx
+and cpp_type_from_path ctx = cpp_type_from_path [] ctx
+and cpp_type_of_null ctx = cpp_type_of_null [] ctx
+and cpp_type_of_pointer ctx = cpp_type_of_pointer [] ctx
+and cpp_fun_arg_type_of ctx = cpp_fun_arg_type_of [] ctx
+and cpp_tfun_arg_type_of ctx = cpp_tfun_arg_type_of [] ctx
+and cpp_function_type_of ctx = cpp_function_type_of [] ctx
+and cpp_function_type_of_string ctx = cpp_function_type_of_string [] ctx
+and cpp_function_type_of_args_ret ctx = cpp_function_type_of_args_ret [] ctx
+and cpp_instance_type ctx = cpp_instance_type [] ctx
 ;;
 ;;
 
 
 
 
@@ -4267,8 +4283,39 @@ let is_override class_def field =
    List.exists (fun f -> f.cf_name = field) class_def.cl_overrides
    List.exists (fun f -> f.cf_name = field) class_def.cl_overrides
 ;;
 ;;
 
 
+(*
+   Functions are added in reverse order (oldest on right), then list is reversed because this is easier in ocaml
+   The order is important because cppia looks up functions by index
+*)
+
+
+let current_virtual_functions_rev clazz base_functions =
+   List.fold_left (fun result elem -> match follow elem.cf_type, elem.cf_kind  with
+      | _, Method MethDynamic -> result
+      | TFun (args,return_type), Method _  ->
+          if (is_override clazz elem.cf_name ) then
+             List.map (fun (e,a,r) ->  if e.cf_name<>elem.cf_name then (e,a,r) else  (elem,args,return_type) ) result
+          else
+             (elem,args,return_type) :: result
+      | _,_ -> result
+    ) base_functions clazz.cl_ordered_fields
+;;
+
+let all_virtual_functions clazz =
+  let rec all_virtual_functions_rec clazz =
+   current_virtual_functions_rev clazz (match clazz.cl_super with
+       | Some def -> all_virtual_functions_rec (fst def)
+       | _ -> []
+     )
+   in
+   List.rev (all_virtual_functions_rec clazz)
+;;
+
+
+
+(*
 let current_virtual_functions clazz parents override_types =
 let current_virtual_functions clazz parents override_types =
-  List.rev (List.fold_left (fun result elem -> match follow elem.cf_type, elem.cf_kind  with
+  List.fold_left (fun result elem -> match follow elem.cf_type, elem.cf_kind  with
     | _, Method MethDynamic -> result
     | _, Method MethDynamic -> result
     | TFun (args,return_type), Method _ ->
     | TFun (args,return_type), Method _ ->
         if override_types then
         if override_types then
@@ -4277,17 +4324,18 @@ let current_virtual_functions clazz parents override_types =
            result
            result
         else
         else
            (elem,args,return_type) :: result
            (elem,args,return_type) :: result
-    | _,_ -> result ) parents clazz.cl_ordered_fields)
+    | _,_ -> result ) parents (List.rev clazz.cl_ordered_fields)
 ;;
 ;;
 
 
 let all_virtual_functions clazz override_types =
 let all_virtual_functions clazz override_types =
    let rec all_virtual_functions clazz =
    let rec all_virtual_functions clazz =
       current_virtual_functions clazz (match clazz.cl_super with
       current_virtual_functions clazz (match clazz.cl_super with
          | Some def -> all_virtual_functions (fst def)
          | Some def -> all_virtual_functions (fst def)
-         | _ -> [] ) override_types
+         | _ -> [] ) false
    in
    in
    all_virtual_functions clazz
    all_virtual_functions clazz
 ;;
 ;;
+*)
 
 
 
 
 let rec unreflective_type t =
 let rec unreflective_type t =
@@ -4778,7 +4826,7 @@ let find_referenced_types_flags ctx obj field_name super_deps constructor_deps h
             List.filter (fun f -> f.cf_name=field_name) fields_and_constructor in
             List.filter (fun f -> f.cf_name=field_name) fields_and_constructor in
       List.iter visit_field fields_and_constructor;
       List.iter visit_field fields_and_constructor;
       if (include_super_args) then
       if (include_super_args) then
-         List.iter visit_field (List.map (fun (a,_,_) -> a ) (all_virtual_functions class_def false));
+         List.iter visit_field (List.map (fun (a,_,_) -> a ) (all_virtual_functions class_def ));
 
 
       (* Add super & interfaces *)
       (* Add super & interfaces *)
       if is_native_gen_class class_def then
       if is_native_gen_class class_def then
@@ -5626,7 +5674,7 @@ let generate_class_files baseCtx super_deps constructor_deps class_def inScripta
    in
    in
 
 
    let not_toString = fun (field,args,_) -> field.cf_name<>"toString" || class_def.cl_interface in
    let not_toString = fun (field,args,_) -> field.cf_name<>"toString" || class_def.cl_interface in
-   let functions = List.filter not_toString (all_virtual_functions class_def true) in
+   let functions = List.filter not_toString (all_virtual_functions class_def) in
 
 
    (* Constructor definition *)
    (* Constructor definition *)
    let cargs = (constructor_arg_var_list class_def baseCtx) in
    let cargs = (constructor_arg_var_list class_def baseCtx) in
@@ -5642,14 +5690,15 @@ let generate_class_files baseCtx super_deps constructor_deps class_def inScripta
 
 
    let outputConstructor ctx out isHeader =
    let outputConstructor ctx out isHeader =
       let classScope = if isHeader then "" else class_name ^ "::" in
       let classScope = if isHeader then "" else class_name ^ "::" in
-      out (ptr_name ^ " " ^ classScope ^ "__new(" ^constructor_type_args ^") {\n");
+      let staticHead = if isHeader then "inline static " else "" in
+      out (staticHead ^ ptr_name ^ " " ^ classScope ^ "__new(" ^constructor_type_args ^") {\n");
       out ("\t" ^ ptr_name ^ " __this = new " ^ class_name ^ "();\n");
       out ("\t" ^ ptr_name ^ " __this = new " ^ class_name ^ "();\n");
          out ("\t__this->__construct(" ^ constructor_args ^ ");\n");
          out ("\t__this->__construct(" ^ constructor_args ^ ");\n");
       out ("\treturn __this;\n");
       out ("\treturn __this;\n");
       out ("}\n\n");
       out ("}\n\n");
 
 
       if can_quick_alloc then begin
       if can_quick_alloc then begin
-         out ((if isHeader then "static " else "") ^ ptr_name ^ " " ^ classScope ^ "__alloc(hx::Ctx *_hx_ctx" ^
+         out (staticHead ^ ptr_name ^ " " ^ classScope ^ "__alloc(hx::Ctx *_hx_ctx" ^
             (if constructor_type_args="" then "" else "," ^constructor_type_args)  ^") {\n");
             (if constructor_type_args="" then "" else "," ^constructor_type_args)  ^") {\n");
          out ("\t" ^ class_name ^ " *__this = (" ^ class_name ^ "*)(hx::Ctx::alloc(_hx_ctx, sizeof(" ^ class_name ^ "), " ^ isContainer ^", " ^ gcName ^ "));\n");
          out ("\t" ^ class_name ^ " *__this = (" ^ class_name ^ "*)(hx::Ctx::alloc(_hx_ctx, sizeof(" ^ class_name ^ "), " ^ isContainer ^", " ^ gcName ^ "));\n");
          out ("\t*(void **)__this = " ^ class_name ^ "::_hx_vtable;\n");
          out ("\t*(void **)__this = " ^ class_name ^ "::_hx_vtable;\n");
@@ -6261,9 +6310,9 @@ let generate_class_files baseCtx super_deps constructor_deps class_def inScripta
       in
       in
 
 
       let new_sctipt_functions = if newInteface then
       let new_sctipt_functions = if newInteface then
-            all_virtual_functions class_def false
+            all_virtual_functions class_def
          else
          else
-            current_virtual_functions class_def [] false
+            List.rev (current_virtual_functions_rev class_def [])
       in
       in
       let sctipt_name = class_name ^ "__scriptable" in
       let sctipt_name = class_name ^ "__scriptable" in
 
 

+ 68 - 59
src/generators/gencs.ml

@@ -918,60 +918,65 @@ let generate con =
 		) tl
 		) tl
 		in
 		in
 
 
-		let rec real_type t =
+		let rec real_type stack t =
 			let t = gen.gfollow#run_f t in
 			let t = gen.gfollow#run_f t in
-			let ret = match t with
-				| TAbstract({ a_path = ([], "Null") }, [t]) ->
-					(*
-						Null<> handling is a little tricky.
-						It will only change to haxe.lang.Null<> when the actual type is non-nullable or a type parameter
-						It works on cases such as Hash<T> returning Null<T> since cast_detect will invoke real_type at the original type,
-						Null<T>, which will then return the type haxe.lang.Null<>
-					*)
-					if erase_generics then
-						if is_cs_basic_type t then
-							t_dynamic
+			if List.exists (fast_eq t) stack then
+				t_dynamic
+			else begin
+				let stack = t :: stack in
+				let ret = match t with
+					| TAbstract({ a_path = ([], "Null") }, [t]) ->
+						(*
+							Null<> handling is a little tricky.
+							It will only change to haxe.lang.Null<> when the actual type is non-nullable or a type parameter
+							It works on cases such as Hash<T> returning Null<T> since cast_detect will invoke real_type at the original type,
+							Null<T>, which will then return the type haxe.lang.Null<>
+						*)
+						if erase_generics then
+							if is_cs_basic_type t then
+								t_dynamic
+							else
+								real_type stack t
 						else
 						else
-							real_type t
-					else
-						(match real_type t with
-							| TInst( { cl_kind = KTypeParameter _ }, _ ) -> TInst(null_t, [t])
-							| t when is_cs_basic_type t -> TInst(null_t, [t])
-							| _ -> real_type t)
-				| TAbstract (a, pl) when not (Meta.has Meta.CoreType a.a_meta) ->
-					real_type (Abstract.get_underlying_type a pl)
-				| TAbstract ({ a_path = (["cs";"_Flags"], "EnumUnderlying") }, [t]) ->
-					real_type t
-				| TInst( { cl_path = (["cs";"system"], "String") }, [] ) ->
-					gen.gcon.basic.tstring;
-				| TInst( { cl_path = (["haxe"], "Int32") }, [] ) -> gen.gcon.basic.tint
-				| TInst( { cl_path = (["haxe"], "Int64") }, [] ) -> ti64
-				| TAbstract( { a_path = [],"Class" }, _ )
-				| TAbstract( { a_path = [],"Enum" }, _ )
-				| TAbstract( { a_path = ["haxe";"extern"],"Rest" }, _ )
-				| TInst( { cl_path = ([], "Class") }, _ )
-				| TInst( { cl_path = ([], "Enum") }, _ ) -> TInst(ttype,[])
-				| TInst( ({ cl_kind = KTypeParameter _ } as cl), _ ) when erase_generics && not (Meta.has Meta.NativeGeneric cl.cl_meta) ->
-					t_dynamic
-				| TInst({ cl_kind = KExpr _ }, _) -> t_dynamic
-				| TEnum(_, [])
-				| TInst(_, []) -> t
-				| TInst(cl, params) when
-					has_tdyn params &&
-					Hashtbl.mem ifaces cl.cl_path ->
-						TInst(Hashtbl.find ifaces cl.cl_path, [])
-				| TEnum(e, params) ->
-					TEnum(e, List.map (fun _ -> t_dynamic) params)
-				| TInst(cl, params) when Meta.has Meta.Enum cl.cl_meta ->
-					TInst(cl, List.map (fun _ -> t_dynamic) params)
-				| TInst(cl, params) -> TInst(cl, change_param_type (TClassDecl cl) params)
-				| TAbstract _
-				| TType _ -> t
-				| TAnon (anon) when (match !(anon.a_status) with | Statics _ | EnumStatics _ | AbstractStatics _ -> true | _ -> false) -> t
-				| TFun _ -> TInst(fn_cl,[])
-				| _ -> t_dynamic
-			in
-			ret
+							(match real_type stack t with
+								| TInst( { cl_kind = KTypeParameter _ }, _ ) -> TInst(null_t, [t])
+								| t when is_cs_basic_type t -> TInst(null_t, [t])
+								| _ -> real_type stack t)
+					| TAbstract (a, pl) when not (Meta.has Meta.CoreType a.a_meta) ->
+						real_type stack (Abstract.get_underlying_type a pl)
+					| TAbstract ({ a_path = (["cs";"_Flags"], "EnumUnderlying") }, [t]) ->
+						real_type stack t
+					| TInst( { cl_path = (["cs";"system"], "String") }, [] ) ->
+						gen.gcon.basic.tstring;
+					| TInst( { cl_path = (["haxe"], "Int32") }, [] ) -> gen.gcon.basic.tint
+					| TInst( { cl_path = (["haxe"], "Int64") }, [] ) -> ti64
+					| TAbstract( { a_path = [],"Class" }, _ )
+					| TAbstract( { a_path = [],"Enum" }, _ )
+					| TAbstract( { a_path = ["haxe";"extern"],"Rest" }, _ )
+					| TInst( { cl_path = ([], "Class") }, _ )
+					| TInst( { cl_path = ([], "Enum") }, _ ) -> TInst(ttype,[])
+					| TInst( ({ cl_kind = KTypeParameter _ } as cl), _ ) when erase_generics && not (Meta.has Meta.NativeGeneric cl.cl_meta) ->
+						t_dynamic
+					| TInst({ cl_kind = KExpr _ }, _) -> t_dynamic
+					| TEnum(_, [])
+					| TInst(_, []) -> t
+					| TInst(cl, params) when
+						has_tdyn params &&
+						Hashtbl.mem ifaces cl.cl_path ->
+							TInst(Hashtbl.find ifaces cl.cl_path, [])
+					| TEnum(e, params) ->
+						TEnum(e, List.map (fun _ -> t_dynamic) params)
+					| TInst(cl, params) when Meta.has Meta.Enum cl.cl_meta ->
+						TInst(cl, List.map (fun _ -> t_dynamic) params)
+					| TInst(cl, params) -> TInst(cl, change_param_type stack (TClassDecl cl) params)
+					| TAbstract _
+					| TType _ -> t
+					| TAnon (anon) when (match !(anon.a_status) with | Statics _ | EnumStatics _ | AbstractStatics _ -> true | _ -> false) -> t
+					| TFun _ -> TInst(fn_cl,[])
+					| _ -> t_dynamic
+				in
+				ret
+			end
 		and
 		and
 
 
 		(*
 		(*
@@ -982,7 +987,7 @@ let generate con =
 			To avoid confusion between Generic<Dynamic> (which has a different meaning in hxcs AST),
 			To avoid confusion between Generic<Dynamic> (which has a different meaning in hxcs AST),
 			all those references are using dynamic_anon, which means Generic<{}>
 			all those references are using dynamic_anon, which means Generic<{}>
 		*)
 		*)
-		change_param_type md tl =
+		change_param_type stack md tl =
 			let types = match md with
 			let types = match md with
 				| TClassDecl c -> c.cl_params
 				| TClassDecl c -> c.cl_params
 				| TEnumDecl e -> []
 				| TEnumDecl e -> []
@@ -991,7 +996,7 @@ let generate con =
 			in
 			in
 			let is_hxgeneric = if types = [] then is_hxgen md else (RealTypeParams.is_hxgeneric md) in
 			let is_hxgeneric = if types = [] then is_hxgen md else (RealTypeParams.is_hxgeneric md) in
 			let ret t =
 			let ret t =
-				let t_changed = real_type t in
+				let t_changed = real_type stack t in
 				match is_hxgeneric, t_changed with
 				match is_hxgeneric, t_changed with
 				| false, _ -> t
 				| false, _ -> t
 				(*
 				(*
@@ -1014,6 +1019,9 @@ let generate con =
 				List.map ret tl
 				List.map ret tl
 		in
 		in
 
 
+		let real_type = real_type []
+		and change_param_type = change_param_type [] in
+
 		let is_dynamic t = match real_type t with
 		let is_dynamic t = match real_type t with
 			| TMono _ | TDynamic _
 			| TMono _ | TDynamic _
 			| TInst({ cl_kind = KTypeParameter _ }, _) -> true
 			| TInst({ cl_kind = KTypeParameter _ }, _) -> true
@@ -3339,15 +3347,16 @@ let generate con =
 		let hashes = Hashtbl.fold (fun i s acc -> incr nhash; (normalize_i i,s) :: acc) rcf_ctx.rcf_hash_fields [] in
 		let hashes = Hashtbl.fold (fun i s acc -> incr nhash; (normalize_i i,s) :: acc) rcf_ctx.rcf_hash_fields [] in
 		let hashes = List.sort (fun (i,s) (i2,s2) -> compare i i2) hashes in
 		let hashes = List.sort (fun (i,s) (i2,s2) -> compare i i2) hashes in
 
 
-		let haxe_libs = List.filter (function (_,_,_,lookup) -> is_some (lookup (["haxe";"lang"], "DceNo"))) gen.gcon.net_libs in
+		let haxe_libs = List.filter (function net_lib -> is_some (net_lib#lookup (["haxe";"lang"], "DceNo"))) gen.gcon.native_libs.net_libs in
 		(try
 		(try
 			(* first let's see if we're adding a -net-lib that has already a haxe.lang.FieldLookup *)
 			(* first let's see if we're adding a -net-lib that has already a haxe.lang.FieldLookup *)
-			let name,_,_,_ = List.find (function (_,_,_,lookup) -> is_some (lookup (["haxe";"lang"], "FieldLookup"))) gen.gcon.net_libs in
+			let net_lib = List.find (function net_lib -> is_some (net_lib#lookup (["haxe";"lang"], "FieldLookup"))) gen.gcon.native_libs.net_libs in
+			let name = net_lib#get_name in
 			if not (Common.defined gen.gcon Define.DllImport) then begin
 			if not (Common.defined gen.gcon Define.DllImport) then begin
 				gen.gcon.warning ("The -net-lib with path " ^ name ^ " contains a Haxe-generated assembly. Please define `-D dll_import` to handle Haxe-generated dll import correctly") null_pos;
 				gen.gcon.warning ("The -net-lib with path " ^ name ^ " contains a Haxe-generated assembly. Please define `-D dll_import` to handle Haxe-generated dll import correctly") null_pos;
 				raise Not_found
 				raise Not_found
 			end;
 			end;
-			if not (List.exists (function (n,_,_,_) -> n = name) haxe_libs) then
+			if not (List.exists (function net_lib -> net_lib#get_name = name) haxe_libs) then
 				gen.gcon.warning ("The -net-lib with path " ^ name ^ " contains a Haxe-generated assembly, however it wasn't compiled with `-dce no`. Recompilation with `-dce no` is recommended") null_pos;
 				gen.gcon.warning ("The -net-lib with path " ^ name ^ " contains a Haxe-generated assembly, however it wasn't compiled with `-dce no`. Recompilation with `-dce no` is recommended") null_pos;
 			(* it has; in this case, we need to add the used fields on each __init__ *)
 			(* it has; in this case, we need to add the used fields on each __init__ *)
 			flookup_cl.cl_extern <- true;
 			flookup_cl.cl_extern <- true;
@@ -3399,8 +3408,8 @@ let generate con =
 						| (p,_) -> p
 						| (p,_) -> p
 					in
 					in
 					let path = (pack, snd c.cl_path ^ extra) in
 					let path = (pack, snd c.cl_path ^ extra) in
-					ignore (List.find (function (_,_,_,lookup) ->
-						is_some (lookup path)) haxe_libs);
+					ignore (List.find (function net_lib ->
+						is_some (net_lib#lookup path)) haxe_libs);
 					c.cl_extern <- true;
 					c.cl_extern <- true;
 				with | Not_found -> ())
 				with | Not_found -> ())
 				| _ -> ()) gen.gtypes
 				| _ -> ()) gen.gtypes

+ 20 - 12
src/generators/genhl.ml

@@ -352,6 +352,18 @@ let fake_tnull =
 		a_params = ["T",t_dynamic];
 		a_params = ["T",t_dynamic];
 	}
 	}
 
 
+let get_rec_cache ctx t none_callback not_found_callback =
+	try
+		match !(List.assq t ctx.rec_cache) with
+		| None -> none_callback()
+		| Some t -> t
+	with Not_found ->
+		let tref = ref None in
+		ctx.rec_cache <- (t,tref) :: ctx.rec_cache;
+		let t = not_found_callback tref in
+		ctx.rec_cache <- List.tl ctx.rec_cache;
+		t
+
 let rec to_type ?tref ctx t =
 let rec to_type ?tref ctx t =
 	match t with
 	match t with
 	| TMono r ->
 	| TMono r ->
@@ -359,17 +371,11 @@ let rec to_type ?tref ctx t =
 		| None -> HDyn
 		| None -> HDyn
 		| Some t -> to_type ?tref ctx t)
 		| Some t -> to_type ?tref ctx t)
 	| TType (td,tl) ->
 	| TType (td,tl) ->
-		let t = (try
-			match !(List.assq t ctx.rec_cache) with
-			| None -> abort "Unsupported recursive type" td.t_pos
-			| Some t -> t
-		with Not_found ->
-			let tref = ref None in
-			ctx.rec_cache <- (t,tref) :: ctx.rec_cache;
-			let t = to_type ~tref ctx (apply_params td.t_params tl td.t_type) in
-			ctx.rec_cache <- List.tl ctx.rec_cache;
-			t
-		) in
+		let t =
+			get_rec_cache ctx t
+				(fun() -> abort "Unsupported recursive type" td.t_pos)
+				(fun tref -> to_type ~tref ctx (apply_params td.t_params tl td.t_type))
+		in
 		(match td.t_path with
 		(match td.t_path with
 		| ["haxe";"macro"], name -> Hashtbl.replace ctx.macro_typedefs name t; t
 		| ["haxe";"macro"], name -> Hashtbl.replace ctx.macro_typedefs name t; t
 		| _ -> t)
 		| _ -> t)
@@ -454,7 +460,9 @@ let rec to_type ?tref ctx t =
 			| ["haxe";"macro"], "Position" -> HAbstract ("macro_pos", alloc_string ctx "macro_pos")
 			| ["haxe";"macro"], "Position" -> HAbstract ("macro_pos", alloc_string ctx "macro_pos")
 			| _ -> failwith ("Unknown core type " ^ s_type_path a.a_path))
 			| _ -> failwith ("Unknown core type " ^ s_type_path a.a_path))
 		else
 		else
-			to_type ?tref ctx (Abstract.get_underlying_type a pl)
+			get_rec_cache ctx t
+				(fun() -> HDyn)
+				(fun tref -> to_type ~tref ctx (Abstract.get_underlying_type a pl))
 
 
 and resolve_class ctx c pl statics =
 and resolve_class ctx c pl statics =
 	let not_supported() =
 	let not_supported() =

+ 79 - 71
src/generators/genjava.ml

@@ -962,12 +962,12 @@ let rec get_fun_modifiers meta access modifiers =
 
 
 let generate con =
 let generate con =
 	let exists = ref false in
 	let exists = ref false in
-	con.java_libs <- List.map (fun (file,std,close,la,gr) ->
-		if String.ends_with file "hxjava-std.jar" then begin
+	List.iter (fun java_lib ->
+		if String.ends_with java_lib#get_file_path "hxjava-std.jar" then begin
 			exists := true;
 			exists := true;
-			(file,true,close,la,gr)
-		end else
-			(file,std,close,la,gr)) con.java_libs;
+			java_lib#add_flag NativeLibraries.FlagIsStd;
+		end;
+	) con.native_libs.java_libs;
 	if not !exists then
 	if not !exists then
 		failwith "Your version of hxjava is outdated. Please update it by running: `haxelib update hxjava`";
 		failwith "Your version of hxjava is outdated. Please update it by running: `haxelib update hxjava`";
 	let gen = new_ctx con in
 	let gen = new_ctx con in
@@ -1215,68 +1215,72 @@ let generate con =
 		| _ -> false
 		| _ -> false
 	in
 	in
 
 
-	let rec t_s pos t =
-		match real_type t with
-			(* basic types *)
-			| TAbstract ({ a_path = ([], "Bool") },[]) -> "boolean"
-			| TAbstract ({ a_path = ([], "Void") },[]) ->
-					path_s_import pos (["java";"lang"], "Object") []
-			| TAbstract ({ a_path = ([],"Float") },[]) -> "double"
-			| TAbstract ({ a_path = ([],"Int") },[]) -> "int"
-			| TType ({ t_path = ["java"], "Int64" },[])
-			| TAbstract ({ a_path = ["java"], "Int64" },[]) -> "long"
-			| TType ({ t_path = ["java"],"Int8" },[])
-			| TAbstract ({ a_path = ["java"],"Int8" },[]) -> "byte"
-			| TType ({ t_path = ["java"],"Int16" },[])
-			| TAbstract ({ a_path = ["java"],"Int16" },[]) -> "short"
-			| TType ({ t_path = ["java"],"Char16" },[])
-			| TAbstract ({ a_path = ["java"],"Char16" },[]) -> "char"
-			| TType ({ t_path = [],"Single" },[])
-			| TAbstract ({ a_path = [],"Single" },[]) -> "float"
-			| TInst ({ cl_path = ["haxe"],"Int32" },[])
-			| TAbstract ({ a_path = ["haxe"],"Int32" },[]) -> "int"
-			| TInst ({ cl_path = ["haxe"],"Int64" },[])
-			| TAbstract ({ a_path = ["haxe"],"Int64" },[]) -> "long"
-			| TInst({ cl_path = (["java"], "NativeArray") }, [param]) ->
-				let rec check_t_s t =
-					match real_type t with
-						| TInst({ cl_path = (["java"], "NativeArray") }, [param]) ->
-							(check_t_s param) ^ "[]"
-						| _ -> t_s pos (run_follow gen t)
-				in
-				(check_t_s param) ^ "[]"
-
-			(* end of basic types *)
-			| TInst ({ cl_kind = KTypeParameter _; cl_path=p }, []) -> snd p
-			| TAbstract ({ a_path = [], "Dynamic" },[]) ->
-					path_s_import pos (["java";"lang"], "Object") []
-			| TMono r -> (match !r with | None -> "java.lang.Object" | Some t -> t_s pos (run_follow gen t))
-			| TInst ({ cl_path = [], "String" }, []) ->
-					path_s_import pos (["java";"lang"], "String") []
-			| TAbstract ({ a_path = [], "Class" }, [p]) | TAbstract ({ a_path = [], "Enum" }, [p])
-			| TInst ({ cl_path = [], "Class" }, [p]) | TInst ({ cl_path = [], "Enum" }, [p]) ->
-					path_param_s pos (TClassDecl cl_cl) (["java";"lang"], "Class") [p] []
-			| TAbstract ({ a_path = [], "Class" }, _) | TAbstract ({ a_path = [], "Enum" }, _)
-			| TInst ({ cl_path = [], "Class" }, _) | TInst ({ cl_path = [], "Enum" }, _) ->
-					path_s_import pos (["java";"lang"], "Class") []
-			| TEnum ({e_path = p; e_meta = meta}, _) ->
-					path_s_import pos p meta
-			| TInst (({cl_path = p; cl_meta = meta} as cl), _) when Meta.has Meta.Enum cl.cl_meta ->
-					path_s_import pos p meta
-			| TInst (({cl_path = p; cl_meta = meta} as cl), params) -> (path_param_s pos (TClassDecl cl) p params meta)
-			| TType (({t_path = p; t_meta = meta} as t), params) -> (path_param_s pos (TTypeDecl t) p params meta)
-			| TAnon (anon) ->
-				(match !(anon.a_status) with
-					| Statics _ | EnumStatics _ | AbstractStatics _ ->
-							path_s_import pos (["java";"lang"], "Class") []
-					| _ ->
-							path_s_import pos (["java";"lang"], "Object") [])
-				| TDynamic _ ->
+	let rec t_s stack pos t =
+		if List.exists (fast_eq t) stack then
+			path_s_import pos (["java";"lang"], "Object") []
+		else begin
+			let stack = t :: stack in
+			match real_type t with
+				(* basic types *)
+				| TAbstract ({ a_path = ([], "Bool") },[]) -> "boolean"
+				| TAbstract ({ a_path = ([], "Void") },[]) ->
 						path_s_import pos (["java";"lang"], "Object") []
 						path_s_import pos (["java";"lang"], "Object") []
-			(* No Lazy type nor Function type made. That's because function types will be at this point be converted into other types *)
-			| _ -> if !strict_mode then begin trace ("[ !TypeError " ^ (Type.s_type (Type.print_context()) t) ^ " ]"); assert false end else "[ !TypeError " ^ (Type.s_type (Type.print_context()) t) ^ " ]"
+				| TAbstract ({ a_path = ([],"Float") },[]) -> "double"
+				| TAbstract ({ a_path = ([],"Int") },[]) -> "int"
+				| TType ({ t_path = ["java"], "Int64" },[])
+				| TAbstract ({ a_path = ["java"], "Int64" },[]) -> "long"
+				| TType ({ t_path = ["java"],"Int8" },[])
+				| TAbstract ({ a_path = ["java"],"Int8" },[]) -> "byte"
+				| TType ({ t_path = ["java"],"Int16" },[])
+				| TAbstract ({ a_path = ["java"],"Int16" },[]) -> "short"
+				| TType ({ t_path = ["java"],"Char16" },[])
+				| TAbstract ({ a_path = ["java"],"Char16" },[]) -> "char"
+				| TType ({ t_path = [],"Single" },[])
+				| TAbstract ({ a_path = [],"Single" },[]) -> "float"
+				| TInst ({ cl_path = ["haxe"],"Int32" },[])
+				| TAbstract ({ a_path = ["haxe"],"Int32" },[]) -> "int"
+				| TInst ({ cl_path = ["haxe"],"Int64" },[])
+				| TAbstract ({ a_path = ["haxe"],"Int64" },[]) -> "long"
+				| TInst({ cl_path = (["java"], "NativeArray") }, [param]) ->
+					let rec check_t_s t =
+						match real_type t with
+							| TInst({ cl_path = (["java"], "NativeArray") }, [param]) ->
+								(check_t_s param) ^ "[]"
+							| _ -> t_s stack pos (run_follow gen t)
+					in
+					(check_t_s param) ^ "[]"
 
 
-	and param_t_s pos t =
+				(* end of basic types *)
+				| TInst ({ cl_kind = KTypeParameter _; cl_path=p }, []) -> snd p
+				| TAbstract ({ a_path = [], "Dynamic" },[]) ->
+						path_s_import pos (["java";"lang"], "Object") []
+				| TMono r -> (match !r with | None -> "java.lang.Object" | Some t -> t_s stack pos (run_follow gen t))
+				| TInst ({ cl_path = [], "String" }, []) ->
+						path_s_import pos (["java";"lang"], "String") []
+				| TAbstract ({ a_path = [], "Class" }, [p]) | TAbstract ({ a_path = [], "Enum" }, [p])
+				| TInst ({ cl_path = [], "Class" }, [p]) | TInst ({ cl_path = [], "Enum" }, [p]) ->
+						path_param_s stack pos (TClassDecl cl_cl) (["java";"lang"], "Class") [p] []
+				| TAbstract ({ a_path = [], "Class" }, _) | TAbstract ({ a_path = [], "Enum" }, _)
+				| TInst ({ cl_path = [], "Class" }, _) | TInst ({ cl_path = [], "Enum" }, _) ->
+						path_s_import pos (["java";"lang"], "Class") []
+				| TEnum ({e_path = p; e_meta = meta}, _) ->
+						path_s_import pos p meta
+				| TInst (({cl_path = p; cl_meta = meta} as cl), _) when Meta.has Meta.Enum cl.cl_meta ->
+						path_s_import pos p meta
+				| TInst (({cl_path = p; cl_meta = meta} as cl), params) -> (path_param_s stack pos (TClassDecl cl) p params meta)
+				| TType (({t_path = p; t_meta = meta} as t), params) -> (path_param_s stack pos (TTypeDecl t) p params meta)
+				| TAnon (anon) ->
+					(match !(anon.a_status) with
+						| Statics _ | EnumStatics _ | AbstractStatics _ ->
+								path_s_import pos (["java";"lang"], "Class") []
+						| _ ->
+								path_s_import pos (["java";"lang"], "Object") [])
+					| TDynamic _ ->
+							path_s_import pos (["java";"lang"], "Object") []
+				(* No Lazy type nor Function type made. That's because function types will be at this point be converted into other types *)
+				| _ -> if !strict_mode then begin trace ("[ !TypeError " ^ (Type.s_type (Type.print_context()) t) ^ " ]"); assert false end else "[ !TypeError " ^ (Type.s_type (Type.print_context()) t) ^ " ]"
+		end
+	and param_t_s stack pos t =
 		match run_follow gen t with
 		match run_follow gen t with
 			| TAbstract ({ a_path = ([], "Bool") },[]) ->
 			| TAbstract ({ a_path = ([], "Bool") },[]) ->
 					path_s_import pos (["java";"lang"], "Boolean") []
 					path_s_import pos (["java";"lang"], "Boolean") []
@@ -1306,18 +1310,22 @@ let generate con =
 			| TAbstract ({ a_path = [],"Single" },[]) ->
 			| TAbstract ({ a_path = [],"Single" },[]) ->
 					path_s_import pos (["java";"lang"], "Float") []
 					path_s_import pos (["java";"lang"], "Float") []
 			| TDynamic _ -> "?"
 			| TDynamic _ -> "?"
-			| TInst (cl, params) -> t_s pos (TInst(cl, change_param_type (TClassDecl cl) params))
-			| TType (cl, params) -> t_s pos (TType(cl, change_param_type (TTypeDecl cl) params))
-			| TEnum (e, params) -> t_s pos (TEnum(e, change_param_type (TEnumDecl e) params))
-			| _ -> t_s pos t
+			| TInst (cl, params) -> t_s stack pos (TInst(cl, change_param_type (TClassDecl cl) params))
+			| TType (cl, params) -> t_s stack pos (TType(cl, change_param_type (TTypeDecl cl) params))
+			| TEnum (e, params) -> t_s stack pos (TEnum(e, change_param_type (TEnumDecl e) params))
+			| _ -> t_s stack pos t
 
 
-	and path_param_s pos md path params meta =
+	and path_param_s stack pos md path params meta =
 			match params with
 			match params with
 				| [] -> path_s_import pos path meta
 				| [] -> path_s_import pos path meta
 				| _ when has_tdynamic (change_param_type md params) -> path_s_import pos path meta
 				| _ when has_tdynamic (change_param_type md params) -> path_s_import pos path meta
-				| _ -> sprintf "%s<%s>" (path_s_import pos path meta) (String.concat ", " (List.map (fun t -> param_t_s pos t) (change_param_type md params)))
+				| _ -> sprintf "%s<%s>" (path_s_import pos path meta) (String.concat ", " (List.map (fun t -> param_t_s stack pos t) (change_param_type md params)))
 	in
 	in
 
 
+	let t_s = t_s []
+	and param_t_s = param_t_s []
+	and path_param_s = path_param_s [] in
+
 	let rett_s pos t =
 	let rett_s pos t =
 		match t with
 		match t with
 			| TAbstract ({ a_path = ([], "Void") },[]) -> "void"
 			| TAbstract ({ a_path = ([], "Void") },[]) -> "void"

+ 105 - 47
src/generators/genjvm.ml

@@ -1,3 +1,22 @@
+(*
+	The Haxe Compiler
+	Copyright (C) 2005-2019  Haxe Foundation
+
+	This program is free software; you can redistribute it and/or
+	modify it under the terms of the GNU General Public License
+	as published by the Free Software Foundation; either version 2
+	of the License, or (at your option) any later version.
+
+	This program is distributed in the hope that it will be useful,
+	but WITHOUT ANY WARRANTY; without even the implied warranty of
+	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+	GNU General Public License for more details.
+
+	You should have received a copy of the GNU General Public License
+	along with this program; if not, write to the Free Software
+	Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *)
+
 open Globals
 open Globals
 open Ast
 open Ast
 open Common
 open Common
@@ -12,6 +31,9 @@ open JvmSignature
 open JvmMethod
 open JvmMethod
 open JvmBuilder
 open JvmBuilder
 
 
+(* Note: This module is the bridge between Haxe structures and JVM structures. No module in generators/jvm should reference any
+   Haxe-specific type. *)
+
 (* hacks *)
 (* hacks *)
 
 
 let rec pow a b = match b with
 let rec pow a b = match b with
@@ -119,7 +141,7 @@ type field_generation_info = {
 	mutable has_this_before_super : bool;
 	mutable has_this_before_super : bool;
 	(* This is an ordered list of fields that are targets of super() calls which is determined during
 	(* This is an ordered list of fields that are targets of super() calls which is determined during
 	   pre-processing. The generator can pop from this list assuming that it processes the expression
 	   pre-processing. The generator can pop from this list assuming that it processes the expression
-	   in the same order (which is should). *)
+	   in the same order (which it should). *)
 	mutable super_call_fields : (tclass * tclass_field) list;
 	mutable super_call_fields : (tclass * tclass_field) list;
 }
 }
 
 
@@ -207,10 +229,10 @@ let rec jsignature_of_type stack t =
 		| Some t -> jsignature_of_type t
 		| Some t -> jsignature_of_type t
 		| None -> object_sig
 		| None -> object_sig
 		end
 		end
-	| TInst({cl_path = ([],"String")},[]) -> string_sig
-	| TInst({cl_path = ([],"Array")},[t]) ->
+	| TInst({cl_path = (["haxe";"root"],"String")},[]) -> string_sig
+	| TInst({cl_path = (["haxe";"root"],"Array")},[t]) ->
 		let t = get_boxed_type (jsignature_of_type t) in
 		let t = get_boxed_type (jsignature_of_type t) in
-		TObject(([],"Array"),[TType(WNone,t)])
+		TObject((["haxe";"root"],"Array"),[TType(WNone,t)])
 	| TInst({cl_path = (["java"],"NativeArray")},[t]) ->
 	| TInst({cl_path = (["java"],"NativeArray")},[t]) ->
 		TArray(jsignature_of_type t,None)
 		TArray(jsignature_of_type t,None)
 	| TInst({cl_kind = KTypeParameter [t]},_) -> jsignature_of_type t
 	| TInst({cl_kind = KTypeParameter [t]},_) -> jsignature_of_type t
@@ -687,7 +709,7 @@ class texpr_to_jvm gctx (jc : JvmClass.builder) (jm : JvmMethod.builder) (return
 			| _ ->
 			| _ ->
 				default();
 				default();
 			end
 			end
-		| FDynamic s | FInstance(_,_,{cf_name = s}) | FEnum(_,{ef_name = s}) | FClosure(Some({cl_interface = true},_),{cf_name = s}) ->
+		| FDynamic s | FInstance(_,_,{cf_name = s}) | FEnum(_,{ef_name = s}) | FClosure(Some({cl_interface = true},_),{cf_name = s}) | FClosure(None,{cf_name = s}) ->
 			self#texpr rvalue_any e1;
 			self#texpr rvalue_any e1;
 			jm#string s;
 			jm#string s;
 			jm#invokestatic haxe_jvm_path "readField" (method_sig [object_sig;string_sig] (Some object_sig));
 			jm#invokestatic haxe_jvm_path "readField" (method_sig [object_sig;string_sig] (Some object_sig));
@@ -697,8 +719,6 @@ class texpr_to_jvm gctx (jc : JvmClass.builder) (jm : JvmMethod.builder) (return
 			jm#read_closure false c.cl_path cf.cf_name jsig;
 			jm#read_closure false c.cl_path cf.cf_name jsig;
 			self#texpr rvalue_any e1;
 			self#texpr rvalue_any e1;
 			jm#invokevirtual method_handle_path "bindTo" (method_sig [object_sig] (Some method_handle_sig));
 			jm#invokevirtual method_handle_path "bindTo" (method_sig [object_sig] (Some method_handle_sig));
-		| _ ->
-			assert false
 
 
 	method read_write ret ak e (f : unit -> unit) =
 	method read_write ret ak e (f : unit -> unit) =
 		let apply dup =
 		let apply dup =
@@ -741,7 +761,7 @@ class texpr_to_jvm gctx (jc : JvmClass.builder) (jm : JvmMethod.builder) (return
 			jm#invokestatic haxe_jvm_path "writeField" (method_sig [object_sig;string_sig;object_sig] None)
 			jm#invokestatic haxe_jvm_path "writeField" (method_sig [object_sig;string_sig;object_sig] None)
 		| TArray(e1,e2) ->
 		| TArray(e1,e2) ->
 			begin match follow e1.etype with
 			begin match follow e1.etype with
-				| TInst({cl_path = ([],"Array")} as c,[t]) ->
+				| TInst({cl_path = (["haxe";"root"],"Array")} as c,[t]) ->
 					let t = self#mknull t in
 					let t = self#mknull t in
 					self#texpr rvalue_any e1;
 					self#texpr rvalue_any e1;
 					if ak <> AKNone then code#dup;
 					if ak <> AKNone then code#dup;
@@ -1030,14 +1050,30 @@ class texpr_to_jvm gctx (jc : JvmClass.builder) (jm : JvmMethod.builder) (return
 						jm#get_code#bconst (op = CmpNe)
 						jm#get_code#bconst (op = CmpNe)
 					)
 					)
 					(fun () ->
 					(fun () ->
-						jm#cast ~not_null:true sig2;
-						self#texpr rvalue_any e2;
+						(match (get_unboxed_type sig1), sig2 with
+						| (TFloat | TDouble as unboxed_sig1), TInt ->
+							jm#cast ~not_null:true unboxed_sig1;
+							self#texpr rvalue_any e2;
+							jm#cast ~not_null:true unboxed_sig1
+						| _ ->
+							jm#cast ~not_null:true sig2;
+							self#texpr rvalue_any e2
+						);
 						self#boolop (self#do_compare op)
 						self#boolop (self#do_compare op)
 					);
 					);
 				CmpNormal(CmpEq,TBool)
 				CmpNormal(CmpEq,TBool)
 			| true,false ->
 			| true,false ->
 				self#texpr rvalue_any e1;
 				self#texpr rvalue_any e1;
-				self#texpr rvalue_any e2;
+				let cast =
+					match sig1, (get_unboxed_type sig2) with
+					| TInt, (TFloat | TDouble as unboxed_sig2) ->
+						jm#cast ~not_null:true unboxed_sig2;
+						self#texpr rvalue_any e2;
+						(fun() -> jm#cast ~not_null:true unboxed_sig2)
+					| _ ->
+						self#texpr rvalue_any e2;
+						(fun() -> jm#cast ~not_null:true sig1)
+				in
 				jm#get_code#dup;
 				jm#get_code#dup;
 				jm#if_then_else
 				jm#if_then_else
 					(self#if_not_null sig2)
 					(self#if_not_null sig2)
@@ -1047,7 +1083,7 @@ class texpr_to_jvm gctx (jc : JvmClass.builder) (jm : JvmMethod.builder) (return
 						jm#get_code#bconst (op = CmpNe);
 						jm#get_code#bconst (op = CmpNe);
 					)
 					)
 					(fun () ->
 					(fun () ->
-						jm#cast ~not_null:true sig1;
+						cast();
 						self#boolop (self#do_compare op)
 						self#boolop (self#do_compare op)
 					);
 					);
 				CmpNormal(CmpEq,TBool)
 				CmpNormal(CmpEq,TBool)
@@ -1961,9 +1997,9 @@ class texpr_to_jvm gctx (jc : JvmClass.builder) (jm : JvmMethod.builder) (return
 			List.iter (self#texpr ret) el
 			List.iter (self#texpr ret) el
 		| TArrayDecl el ->
 		| TArrayDecl el ->
 			begin match follow e.etype with
 			begin match follow e.etype with
-			| TInst({cl_path = ([],"Array")},[t]) ->
+			| TInst({cl_path = (["haxe";"root"],"Array")},[t]) ->
 				self#new_native_array (jsignature_of_type (self#mknull t)) el;
 				self#new_native_array (jsignature_of_type (self#mknull t)) el;
-				jm#invokestatic ([],"Array") "ofNative" (method_sig [array_sig object_sig] (Some (object_path_sig ([],"Array"))));
+				jm#invokestatic (["haxe";"root"],"Array") "ofNative" (method_sig [array_sig object_sig] (Some (object_path_sig (["haxe";"root"],"Array"))));
 				self#cast e.etype
 				self#cast e.etype
 			| _ ->
 			| _ ->
 				assert false
 				assert false
@@ -1974,7 +2010,7 @@ class texpr_to_jvm gctx (jc : JvmClass.builder) (jm : JvmMethod.builder) (return
 			self#texpr ret e2;
 			self#texpr ret e2;
 		| TArray(e1,e2) ->
 		| TArray(e1,e2) ->
 			begin match follow e1.etype with
 			begin match follow e1.etype with
-			| TInst({cl_path = ([],"Array")} as c,[t]) ->
+			| TInst({cl_path = (["haxe";"root"],"Array")} as c,[t]) ->
 				self#texpr rvalue_any e1;
 				self#texpr rvalue_any e1;
 				self#texpr (rvalue_sig TInt) e2;
 				self#texpr (rvalue_sig TInt) e2;
 				jm#cast TInt;
 				jm#cast TInt;
@@ -2253,12 +2289,12 @@ class tclass_to_jvm gctx c = object(self)
 			in
 			in
 			if !has_type_param then Some t else None
 			if !has_type_param then Some t else None
 		in
 		in
-		let make_bridge cf cf_impl t =
+		let make_bridge cf_impl t =
 			let jsig = jsignature_of_type t in
 			let jsig = jsignature_of_type t in
-			if not (jc#has_method cf.cf_name jsig) then begin
+			if not (jc#has_method cf_impl.cf_name jsig) then begin
 				begin match follow t with
 				begin match follow t with
 				| TFun(tl,tr) ->
 				| TFun(tl,tr) ->
-					let jm = jc#spawn_method cf.cf_name jsig [MPublic;MSynthetic;MBridge] in
+					let jm = jc#spawn_method cf_impl.cf_name jsig [MPublic;MSynthetic;MBridge] in
 					jm#load_this;
 					jm#load_this;
 					let jsig_impl = jsignature_of_type cf_impl.cf_type in
 					let jsig_impl = jsignature_of_type cf_impl.cf_type in
 					let jsigs,_ = match jsig_impl with TMethod(jsigs,jsig) -> jsigs,jsig | _ -> assert false in
 					let jsigs,_ = match jsig_impl with TMethod(jsigs,jsig) -> jsigs,jsig | _ -> assert false in
@@ -2267,7 +2303,7 @@ class tclass_to_jvm gctx c = object(self)
 						load();
 						load();
 						jm#cast jsig;
 						jm#cast jsig;
 					) tl jsigs;
 					) tl jsigs;
-					jm#invokevirtual c.cl_path cf.cf_name jsig_impl;
+					jm#invokevirtual c.cl_path cf_impl.cf_name jsig_impl;
 					if not (ExtType.is_void (follow tr)) then jm#cast (jsignature_of_type tr);
 					if not (ExtType.is_void (follow tr)) then jm#cast (jsignature_of_type tr);
 					jm#return;
 					jm#return;
 				| _ ->
 				| _ ->
@@ -2275,27 +2311,35 @@ class tclass_to_jvm gctx c = object(self)
 				end
 				end
 			end
 			end
 		in
 		in
-		let check cf cf_impl map_type =
-			match cf.cf_kind with
-			| Method (MethNormal | MethInline) ->
-				begin match map_type_params cf.cf_type with
-				| Some t -> make_bridge cf cf_impl t
-				| None -> ()
-				end
-			| _ ->
-				()
+		let check is_interface cf cf_impl =
+			match map_type_params cf.cf_type with
+			| Some t ->
+				make_bridge cf_impl t
+			| None ->
+				(* If we implement an interface with variance, we need a bridge method too (#8528). *)
+				if is_interface && not (type_iseq cf.cf_type cf_impl.cf_type) then make_bridge cf_impl cf.cf_type
 		in
 		in
-		let check cf cf_impl map_type =
-			check cf cf_impl map_type;
-			List.iter (fun cf -> check cf cf_impl map_type) cf.cf_overloads
+		let check is_interface cf cf_impl =
+			check is_interface cf cf_impl;
+			(* TODO: I think this is incorrect... have to investigate though *)
+			(* List.iter (fun cf -> check is_interface cf cf_impl) cf.cf_overloads *)
 		in
 		in
 		let rec loop map_type c_int =
 		let rec loop map_type c_int =
 			List.iter (fun (c_int,tl) ->
 			List.iter (fun (c_int,tl) ->
 				let map_type t = apply_params c_int.cl_params tl (map_type t) in
 				let map_type t = apply_params c_int.cl_params tl (map_type t) in
 				List.iter (fun cf ->
 				List.iter (fun cf ->
-					match raw_class_field (fun cf -> map_type cf.cf_type) c (List.map snd c.cl_params) cf.cf_name with
-					| Some(c',_),_,cf_impl when c' == c -> check cf cf_impl map_type
-					| _ -> ()
+					match cf.cf_kind,raw_class_field (fun cf -> map_type cf.cf_type) c (List.map snd c.cl_params) cf.cf_name with
+					| (Method (MethNormal | MethInline)),(Some(c',_),_,cf_impl) when c' == c ->
+						let tl = match follow (map_type cf.cf_type) with
+							| TFun(tl,_) -> tl
+							| _ -> assert false
+						in
+						begin match find_overload_rec' false map_type c cf.cf_name (List.map (fun (_,_,t) -> Texpr.Builder.make_null t null_pos) tl) with
+							| Some(_,cf_impl) -> check true cf cf_impl
+							| None -> ()
+						end;
+					| _ ->
+						()
 				) c_int.cl_ordered_fields;
 				) c_int.cl_ordered_fields;
 				loop map_type c_int
 				loop map_type c_int
 			) c_int.cl_implements
 			) c_int.cl_implements
@@ -2306,9 +2350,9 @@ class tclass_to_jvm gctx c = object(self)
 			()
 			()
 		| fields,Some(c_sup,tl) ->
 		| fields,Some(c_sup,tl) ->
 			List.iter (fun cf_impl ->
 			List.iter (fun cf_impl ->
-				match raw_class_field (fun cf -> apply_params c_sup.cl_params tl cf.cf_type) c_sup tl cf_impl.cf_name with
-				| Some(c,tl),_,cf -> check cf cf_impl (apply_params c.cl_params tl)
-				| _ -> assert false
+				match cf_impl.cf_kind,raw_class_field (fun cf -> apply_params c_sup.cl_params tl cf.cf_type) c_sup tl cf_impl.cf_name with
+				| (Method (MethNormal | MethInline)),(Some(c,tl),_,cf) -> check false cf cf_impl
+				| _ -> ()
 			) fields
 			) fields
 		| _ ->
 		| _ ->
 			assert false
 			assert false
@@ -2502,9 +2546,9 @@ class tclass_to_jvm gctx c = object(self)
 			let jsig = method_sig [array_sig string_sig] None in
 			let jsig = method_sig [array_sig string_sig] None in
 			let jm = jc#spawn_method "main" jsig [MPublic;MStatic] in
 			let jm = jc#spawn_method "main" jsig [MPublic;MStatic] in
 			let _,load,_ = jm#add_local "args" (TArray(string_sig,None)) VarArgument in
 			let _,load,_ = jm#add_local "args" (TArray(string_sig,None)) VarArgument in
-			if has_feature gctx.com "Sys.args" then begin
+			if has_feature gctx.com "haxe.root.Sys.args" then begin
 				load();
 				load();
-				jm#putstatic ([],"Sys") "_args" (TArray(string_sig,None))
+				jm#putstatic (["haxe";"root"],"Sys") "_args" (TArray(string_sig,None))
 			end;
 			end;
 			jm#invokestatic (["haxe"; "java"], "Init") "init" (method_sig [] None);
 			jm#invokestatic (["haxe"; "java"], "Init") "init" (method_sig [] None);
 			jm#invokestatic jc#get_this_path "main" (method_sig [] None);
 			jm#invokestatic jc#get_this_path "main" (method_sig [] None);
@@ -2931,9 +2975,17 @@ module Preprocessor = struct
 			in
 			in
 			List.iter field (cf :: cf.cf_overloads)
 			List.iter field (cf :: cf.cf_overloads)
 
 
+	let make_root path =
+		["haxe";"root"],snd path
+
 	let preprocess gctx =
 	let preprocess gctx =
-		List.iter (function
-			| TClassDecl c when debug_path c.cl_path && not c.cl_interface -> preprocess_class gctx c
+		List.iter (fun mt ->
+			match mt with
+			| TClassDecl c ->
+				if fst c.cl_path = [] then c.cl_path <- make_root c.cl_path;
+				if debug_path c.cl_path && not c.cl_interface then preprocess_class gctx c
+			| TEnumDecl en ->
+				if fst en.e_path = [] then en.e_path <- make_root en.e_path;
 			| _ -> ()
 			| _ -> ()
 		) gctx.com.types
 		) gctx.com.types
 end
 end
@@ -2946,7 +2998,13 @@ let file_name_and_extension file =
 let generate com =
 let generate com =
 	mkdir_from_path com.file;
 	mkdir_from_path com.file;
 	let jar_name,manifest_suffix = match com.main_class with
 	let jar_name,manifest_suffix = match com.main_class with
-		| Some path -> snd path,"\nMain-Class: " ^ (s_type_path path)
+		| Some path ->
+			let pack = match fst path with
+				| [] -> ["haxe";"root"]
+				| pack -> pack
+			in
+			let name = snd path in
+			name,"\nMain-Class: " ^ (s_type_path (pack,name))
 		| None -> "jar",""
 		| None -> "jar",""
 	in
 	in
 	let jar_name = if com.debug then jar_name ^ "-Debug" else jar_name in
 	let jar_name = if com.debug then jar_name ^ "-Debug" else jar_name in
@@ -2968,13 +3026,13 @@ let generate com =
 		}
 		}
 	} in
 	} in
 	Std.finally (Timer.timer ["generate";"java";"preprocess"]) Preprocessor.preprocess gctx;
 	Std.finally (Timer.timer ["generate";"java";"preprocess"]) Preprocessor.preprocess gctx;
-	let class_paths = ExtList.List.filter_map (fun (file,std,_,_,_) ->
-		if std then None
+	let class_paths = ExtList.List.filter_map (fun java_lib ->
+		if java_lib#has_flag NativeLibraries.FlagIsStd then None
 		else begin
 		else begin
 			let dir = Printf.sprintf "%slib/" jar_dir in
 			let dir = Printf.sprintf "%slib/" jar_dir in
 			Path.mkdir_from_path dir;
 			Path.mkdir_from_path dir;
-			let name = file_name_and_extension file in
-			let ch_in = open_in_bin file in
+			let name = file_name_and_extension java_lib#get_file_path in
+			let ch_in = open_in_bin java_lib#get_file_path in
 			let ch_out = open_out_bin (Printf.sprintf "%s%s" dir name) in
 			let ch_out = open_out_bin (Printf.sprintf "%s%s" dir name) in
 			let b = IO.read_all (IO.input_channel ch_in) in
 			let b = IO.read_all (IO.input_channel ch_in) in
 			output_string ch_out b;
 			output_string ch_out b;
@@ -2982,7 +3040,7 @@ let generate com =
 			close_out ch_out;
 			close_out ch_out;
 			Some (Printf.sprintf "lib/%s" name)
 			Some (Printf.sprintf "lib/%s" name)
 		end
 		end
-	) com.java_libs in
+	) com.native_libs.java_libs in
 	let manifest_content =
 	let manifest_content =
 		"Manifest-Version: 1.0\n" ^
 		"Manifest-Version: 1.0\n" ^
 		(match class_paths with [] -> "" | _ -> "Class-Path: " ^ (String.concat " " class_paths ^ "\n")) ^
 		(match class_paths with [] -> "" | _ -> "Class-Path: " ^ (String.concat " " class_paths ^ "\n")) ^

+ 20 - 1
src/generators/genphp7.ml

@@ -310,6 +310,11 @@ let is_string_type t = match follow t with TInst ({ cl_path = ([], "String") },
 *)
 *)
 let is_string expr = is_string_type expr.etype
 let is_string expr = is_string_type expr.etype
 
 
+(**
+	Check if specified type is Array
+*)
+let is_array_type t = match follow t with TInst ({ cl_path = ([], "Array") }, _) -> true | _ -> false
+
 (**
 (**
 	Check if specified type represents a function
 	Check if specified type represents a function
 *)
 *)
@@ -1606,6 +1611,8 @@ class code_writer (ctx:php_generator_context) hx_type_path php_name =
 					vars#used var.v_name;
 					vars#used var.v_name;
 					self#write ("$" ^ var.v_name)
 					self#write ("$" ^ var.v_name)
 				| TArray (target, index) -> self#write_expr_array_access target index
 				| TArray (target, index) -> self#write_expr_array_access target index
+				| TBinop (OpAssign, { eexpr = TArray (target, index) }, value) when is_array_type target.etype ->
+					self#write_expr_set_array_item target index value
 				| TBinop (operation, expr1, expr2) when needs_dereferencing (is_assignment_binop operation) expr1 ->
 				| TBinop (operation, expr1, expr2) when needs_dereferencing (is_assignment_binop operation) expr1 ->
 					self#write_expr { expr with eexpr = TBinop (operation, self#dereference expr1, expr2) }
 					self#write_expr { expr with eexpr = TBinop (operation, self#dereference expr1, expr2) }
 				| TBinop (operation, expr1, expr2) -> self#write_expr_binop operation expr1 expr2
 				| TBinop (operation, expr1, expr2) -> self#write_expr_binop operation expr1 expr2
@@ -1720,6 +1727,14 @@ class code_writer (ctx:php_generator_context) hx_type_path php_name =
 					List.iter write_field fields;
 					List.iter write_field fields;
 					self#indent_less;
 					self#indent_less;
 					self#write_with_indentation "]"
 					self#write_with_indentation "]"
+		(**
+			Writes `target[index] = value` assuming `target` is of `Array` type
+		*)
+		method write_expr_set_array_item target index value =
+			self#write_expr target;
+			self#write "->offsetSet(";
+			write_args self#write self#write_expr [index; value];
+			self#write ")"
 		(**
 		(**
 			Writes TArray to output buffer
 			Writes TArray to output buffer
 		*)
 		*)
@@ -2082,7 +2097,11 @@ class code_writer (ctx:php_generator_context) hx_type_path php_name =
 				self#write ")"
 				self#write ")"
 			in
 			in
 			let write_for_concat expr =
 			let write_for_concat expr =
-				if ((is_constant expr) && not (is_constant_null expr)) || (is_concatenation expr) then
+				if ((is_constant expr) && not (is_constant_null expr))
+					|| (is_concatenation expr)
+					|| is_php_global expr
+					|| is_php_class_const expr
+				then
 					self#write_expr expr
 					self#write_expr expr
 				else begin
 				else begin
 					self#write "(";
 					self#write "(";

+ 1 - 1
src/generators/genpy.ml

@@ -1145,7 +1145,7 @@ module Printer = struct
 						| None -> ""
 						| None -> ""
 						| Some ct ->
 						| Some ct ->
 							had_value := true;
 							had_value := true;
-							Printf.sprintf " = %s" (print_expr pctx ct)
+							" = None"
 		) args in
 		) args in
 		String.concat "," sl
 		String.concat "," sl
 
 

+ 23 - 9
src/generators/genswf.ml

@@ -24,6 +24,7 @@ open Type
 open Common
 open Common
 open Ast
 open Ast
 open Globals
 open Globals
+open NativeLibraries
 
 
 let tag ?(ext=false) d = {
 let tag ?(ext=false) d = {
 	tid = 0;
 	tid = 0;
@@ -276,12 +277,14 @@ let build_swf9 com file swc =
 					let ttf = try TTFParser.parse ch with e -> abort ("Error while parsing font " ^ file ^ " : " ^ Printexc.to_string e) p in
 					let ttf = try TTFParser.parse ch with e -> abort ("Error while parsing font " ^ file ^ " : " ^ Printexc.to_string e) p in
 					close_in ch;
 					close_in ch;
 					let get_string e = match fst e with
 					let get_string e = match fst e with
-						| EConst (String s) -> Some s
+						| EConst (String s) -> s
 						| _ -> raise Not_found
 						| _ -> raise Not_found
 					in
 					in
 					let ttf_config = {
 					let ttf_config = {
 						ttfc_range_str = "";
 						ttfc_range_str = "";
 						ttfc_font_name = None;
 						ttfc_font_name = None;
+						ttfc_font_weight = TFWRegular;
+						ttfc_font_posture = TFPNormal;
 					} in
 					} in
 					begin match args with
 					begin match args with
 						| (EConst (String str),_) :: _ -> ttf_config.ttfc_range_str <- str;
 						| (EConst (String str),_) :: _ -> ttf_config.ttfc_range_str <- str;
@@ -291,8 +294,19 @@ let build_swf9 com file swc =
 						| _ :: [e] ->
 						| _ :: [e] ->
 							begin match fst e with
 							begin match fst e with
 								| EObjectDecl fl ->
 								| EObjectDecl fl ->
-									begin try ttf_config.ttfc_font_name <- get_string (Expr.field_assoc "fontName" fl)
-									with Not_found -> () end
+									(try ttf_config.ttfc_font_name <- Some(get_string (Expr.field_assoc "fontName" fl)) with Not_found -> ());
+									(try ttf_config.ttfc_font_weight <- (
+										match get_string (Expr.field_assoc "fontWeight" fl) with
+										| "regular" -> TFWRegular
+										| "bold" -> TFWBold
+										| _ -> abort "Invalid fontWeight value. Must be `regular` or `bold`." p
+									) with Not_found -> ());
+									(try ttf_config.ttfc_font_posture <- (
+										match get_string (Expr.field_assoc "fontStyle" fl) with
+										| "normal" -> TFPNormal
+										| "italic" -> TFPItalic
+										| _ -> abort "Invalid fontStyle value. Must be `normal` or `italic`." p
+									) with Not_found -> ());
 								| _ ->
 								| _ ->
 									()
 									()
 							end
 							end
@@ -557,8 +571,8 @@ let generate swf_header com =
 	(* list exports *)
 	(* list exports *)
 	let exports = Hashtbl.create 0 in
 	let exports = Hashtbl.create 0 in
 	let toremove = ref [] in
 	let toremove = ref [] in
-	List.iter (fun (file,lib,_) ->
-		let _, tags = lib() in
+	List.iter (fun swf_lib ->
+		let _, tags = swf_lib#get_data in
 		List.iter (fun t ->
 		List.iter (fun t ->
 			match t.tdata with
 			match t.tdata with
 			| TExport l -> List.iter (fun e -> Hashtbl.add exports e.exp_name ()) l
 			| TExport l -> List.iter (fun e -> Hashtbl.add exports e.exp_name ()) l
@@ -584,7 +598,7 @@ let generate swf_header com =
 				) el
 				) el
 			| _ -> ()
 			| _ -> ()
 		) tags;
 		) tags;
-	) com.swf_libs;
+	) com.native_libs.swf_libs;
 	(* build haxe swf *)
 	(* build haxe swf *)
 	let tags = build_swf9 com file swc in
 	let tags = build_swf9 com file swc in
 	let header, bg = (match swf_header with None -> default_header com | Some h -> convert_header com h) in
 	let header, bg = (match swf_header with None -> default_header com | Some h -> convert_header com h) in
@@ -625,11 +639,11 @@ let generate swf_header com =
 	let swf = header, fattr @ meta_data @ bg :: scene :: debug @ swf_script_limits @ tags @ [tag TShowFrame] in
 	let swf = header, fattr @ meta_data @ bg :: scene :: debug @ swf_script_limits @ tags @ [tag TShowFrame] in
 	(* merge swf libraries *)
 	(* merge swf libraries *)
 	let priority = ref (swf_header = None) in
 	let priority = ref (swf_header = None) in
-	let swf = List.fold_left (fun swf (file,lib,cl) ->
-		let swf = merge com file !priority swf (SwfLoader.remove_classes toremove lib cl) in
+	let swf = List.fold_left (fun swf swf_lib ->
+		let swf = merge com file !priority swf (SwfLoader.remove_classes toremove swf_lib#get_data swf_lib#list_modules) in
 		priority := false;
 		priority := false;
 		swf
 		swf
-	) swf com.swf_libs in
+	) swf com.native_libs.swf_libs in
 	let swf = match swf with
 	let swf = match swf with
 	| header,tags when Common.defined com Define.SwfPreloaderFrame ->
 	| header,tags when Common.defined com Define.SwfPreloaderFrame ->
 		let rec loop l =
 		let rec loop l =

+ 7 - 2
src/generators/genswf9.ml

@@ -200,7 +200,6 @@ let rec follow_basic t =
 		| TAbstract ({ a_path = ([],"Bool") },[])
 		| TAbstract ({ a_path = ([],"Bool") },[])
 		| TInst ({ cl_path = (["haxe"],"Int32") },[]) -> t
 		| TInst ({ cl_path = (["haxe"],"Int32") },[]) -> t
 		| t -> t)
 		| t -> t)
-	| TType ({ t_path = ["flash";"utils"],"Object" },[])
 	| TType ({ t_path = ["flash";"utils"],"Function" },[])
 	| TType ({ t_path = ["flash";"utils"],"Function" },[])
 	| TType ({ t_path = [],"UInt" },[]) ->
 	| TType ({ t_path = [],"UInt" },[]) ->
 		t
 		t
@@ -231,6 +230,8 @@ let rec type_id ctx t =
 			type_path ctx c.cl_path)
 			type_path ctx c.cl_path)
 	| TAbstract ({ a_path = [],"Null"},_) ->
 	| TAbstract ({ a_path = [],"Null"},_) ->
 		HMPath ([],"Object")
 		HMPath ([],"Object")
+	| TAbstract ({ a_path = ["flash"],"AnyType"},_) ->
+		HMAny
 	| TAbstract (a,_) when Meta.has Meta.CoreType a.a_meta ->
 	| TAbstract (a,_) when Meta.has Meta.CoreType a.a_meta ->
 		type_path ctx a.a_path
 		type_path ctx a.a_path
 	| TFun _ | TType ({ t_path = ["flash";"utils"],"Function" },[]) ->
 	| TFun _ | TType ({ t_path = ["flash";"utils"],"Function" },[]) ->
@@ -264,6 +265,8 @@ let classify ctx t =
 		KBool
 		KBool
 	| TAbstract ({ a_path = [],"Void" },_) | TEnum ({ e_path = [],"Void" },_) ->
 	| TAbstract ({ a_path = [],"Void" },_) | TEnum ({ e_path = [],"Void" },_) ->
 		KDynamic
 		KDynamic
+	| TAbstract ({ a_path = ["flash"],"AnyType" },_) ->
+		KDynamic
 	| TEnum ({ e_path = ["flash"],"XmlType"; e_extern = true },_) ->
 	| TEnum ({ e_path = ["flash"],"XmlType"; e_extern = true },_) ->
 		KType (HMPath ([],"String"))
 		KType (HMPath ([],"String"))
 	| TEnum (e,_) ->
 	| TEnum (e,_) ->
@@ -276,7 +279,7 @@ let classify ctx t =
 		(match !(a.a_status) with
 		(match !(a.a_status) with
 		| Statics _ -> KNone
 		| Statics _ -> KNone
 		| _ -> KDynamic)
 		| _ -> KDynamic)
-	| TType ({ t_path = ["flash";"utils"],"Object" },[]) ->
+	| TAbstract ({ a_path = ["flash";"utils"],"Object" },[]) ->
 		KType (HMPath ([],"Object"))
 		KType (HMPath ([],"Object"))
 	| TInst _ | TAbstract _ ->
 	| TInst _ | TAbstract _ ->
 		KType (type_id ctx t)
 		KType (type_id ctx t)
@@ -1034,6 +1037,8 @@ let rec gen_type ctx t =
 		write ctx (HGetLex t);
 		write ctx (HGetLex t);
 		List.iter (gen_type ctx) tl;
 		List.iter (gen_type ctx) tl;
 		write ctx (HApplyType (List.length tl));
 		write ctx (HApplyType (List.length tl));
+	| HMAny ->
+		write ctx (HNull)
 	| _ ->
 	| _ ->
 		write ctx (HGetLex t)
 		write ctx (HGetLex t)
 
 

+ 19 - 0
src/generators/jvm/jvmAttribute.ml

@@ -1,3 +1,22 @@
+(*
+	The Haxe Compiler
+	Copyright (C) 2005-2019  Haxe Foundation
+
+	This program is free software; you can redistribute it and/or
+	modify it under the terms of the GNU General Public License
+	as published by the Free Software Foundation; either version 2
+	of the License, or (at your option) any later version.
+
+	This program is distributed in the hope that it will be useful,
+	but WITHOUT ANY WARRANTY; without even the implied warranty of
+	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+	GNU General Public License for more details.
+
+	You should have received a copy of the GNU General Public License
+	along with this program; if not, write to the Free Software
+	Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *)
+
 open JvmGlobals
 open JvmGlobals
 open JvmData
 open JvmData
 open JvmVerificationTypeInfo
 open JvmVerificationTypeInfo

+ 19 - 0
src/generators/jvm/jvmBuilder.ml

@@ -1,3 +1,22 @@
+(*
+	The Haxe Compiler
+	Copyright (C) 2005-2019  Haxe Foundation
+
+	This program is free software; you can redistribute it and/or
+	modify it under the terms of the GNU General Public License
+	as published by the Free Software Foundation; either version 2
+	of the License, or (at your option) any later version.
+
+	This program is distributed in the hope that it will be useful,
+	but WITHOUT ANY WARRANTY; without even the implied warranty of
+	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+	GNU General Public License for more details.
+
+	You should have received a copy of the GNU General Public License
+	along with this program; if not, write to the Free Software
+	Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *)
+
 open JvmGlobals
 open JvmGlobals
 open JvmData
 open JvmData
 open JvmSignature
 open JvmSignature

+ 19 - 0
src/generators/jvm/jvmClass.ml

@@ -1,3 +1,22 @@
+(*
+	The Haxe Compiler
+	Copyright (C) 2005-2019  Haxe Foundation
+
+	This program is free software; you can redistribute it and/or
+	modify it under the terms of the GNU General Public License
+	as published by the Free Software Foundation; either version 2
+	of the License, or (at your option) any later version.
+
+	This program is distributed in the hope that it will be useful,
+	but WITHOUT ANY WARRANTY; without even the implied warranty of
+	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+	GNU General Public License for more details.
+
+	You should have received a copy of the GNU General Public License
+	along with this program; if not, write to the Free Software
+	Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *)
+
 open JvmGlobals
 open JvmGlobals
 open JvmData
 open JvmData
 open JvmSignature
 open JvmSignature

+ 19 - 0
src/generators/jvm/jvmCode.ml

@@ -1,3 +1,22 @@
+(*
+	The Haxe Compiler
+	Copyright (C) 2005-2019  Haxe Foundation
+
+	This program is free software; you can redistribute it and/or
+	modify it under the terms of the GNU General Public License
+	as published by the Free Software Foundation; either version 2
+	of the License, or (at your option) any later version.
+
+	This program is distributed in the hope that it will be useful,
+	but WITHOUT ANY WARRANTY; without even the implied warranty of
+	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+	GNU General Public License for more details.
+
+	You should have received a copy of the GNU General Public License
+	along with this program; if not, write to the Free Software
+	Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *)
+
 open JvmGlobals
 open JvmGlobals
 open JvmData
 open JvmData
 open JvmSignature
 open JvmSignature

+ 19 - 0
src/generators/jvm/jvmConstantPool.ml

@@ -1,3 +1,22 @@
+(*
+	The Haxe Compiler
+	Copyright (C) 2005-2019  Haxe Foundation
+
+	This program is free software; you can redistribute it and/or
+	modify it under the terms of the GNU General Public License
+	as published by the Free Software Foundation; either version 2
+	of the License, or (at your option) any later version.
+
+	This program is distributed in the hope that it will be useful,
+	but WITHOUT ANY WARRANTY; without even the implied warranty of
+	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+	GNU General Public License for more details.
+
+	You should have received a copy of the GNU General Public License
+	along with this program; if not, write to the Free Software
+	Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *)
+
 open IO
 open IO
 open IO.BigEndian
 open IO.BigEndian
 open JvmGlobals
 open JvmGlobals

+ 21 - 2
src/generators/jvm/jvmData.ml

@@ -1,3 +1,22 @@
+(*
+	The Haxe Compiler
+	Copyright (C) 2005-2019  Haxe Foundation
+
+	This program is free software; you can redistribute it and/or
+	modify it under the terms of the GNU General Public License
+	as published by the Free Software Foundation; either version 2
+	of the License, or (at your option) any later version.
+
+	This program is distributed in the hope that it will be useful,
+	but WITHOUT ANY WARRANTY; without even the implied warranty of
+	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+	GNU General Public License for more details.
+
+	You should have received a copy of the GNU General Public License
+	along with this program; if not, write to the Free Software
+	Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *)
+
 open JvmGlobals
 open JvmGlobals
 
 
 (* Low-level data that is written out. *)
 (* Low-level data that is written out. *)
@@ -266,8 +285,8 @@ and jopcode =
 	(* other *)
 	(* other *)
 	| OpAthrow
 	| OpAthrow
 	| OpIinc of jbyte * jbyte
 	| OpIinc of jbyte * jbyte
-	| OpLookupswitch of int (* num pad bytes *) * jbranchoffset ref (* default *) * (int * jbranchoffset ref) array
-	| OpTableswitch of int (* num pad bytes *) * jbranchoffset ref (* default *) * int (* low *) * int (* high *) * jbranchoffset ref array
+	| OpLookupswitch of int (* num pad bytes *) * jbranchoffset ref (* default *) * (Int32.t * jbranchoffset ref) array
+	| OpTableswitch of int (* num pad bytes *) * jbranchoffset ref (* default *) * Int32.t (* low *) * Int32.t (* high *) * jbranchoffset ref array
 	| OpMonitorenter
 	| OpMonitorenter
 	| OpMonitorexit
 	| OpMonitorexit
 	| OpRet of jbyte
 	| OpRet of jbyte

+ 19 - 0
src/generators/jvm/jvmDebug.ml

@@ -1,3 +1,22 @@
+(*
+	The Haxe Compiler
+	Copyright (C) 2005-2019  Haxe Foundation
+
+	This program is free software; you can redistribute it and/or
+	modify it under the terms of the GNU General Public License
+	as published by the Free Software Foundation; either version 2
+	of the License, or (at your option) any later version.
+
+	This program is distributed in the hope that it will be useful,
+	but WITHOUT ANY WARRANTY; without even the implied warranty of
+	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+	GNU General Public License for more details.
+
+	You should have received a copy of the GNU General Public License
+	along with this program; if not, write to the Free Software
+	Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *)
+
 open JvmGlobals
 open JvmGlobals
 open JvmData
 open JvmData
 
 

+ 21 - 0
src/generators/jvm/jvmGlobals.ml

@@ -1,3 +1,22 @@
+(*
+	The Haxe Compiler
+	Copyright (C) 2005-2019  Haxe Foundation
+
+	This program is free software; you can redistribute it and/or
+	modify it under the terms of the GNU General Public License
+	as published by the Free Software Foundation; either version 2
+	of the License, or (at your option) any later version.
+
+	This program is distributed in the hope that it will be useful,
+	but WITHOUT ANY WARRANTY; without even the implied warranty of
+	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+	GNU General Public License for more details.
+
+	You should have received a copy of the GNU General Public License
+	along with this program; if not, write to the Free Software
+	Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *)
+
 type jvm_constant_pool_index = int
 type jvm_constant_pool_index = int
 
 
 (* Constants *)
 (* Constants *)
@@ -30,6 +49,8 @@ type numeric_range =
 	| Int16Range
 	| Int16Range
 	| Int32Range
 	| Int32Range
 
 
+let i320xFF = Int32.of_int 0xFF
+
 let get_numeric_range i =
 let get_numeric_range i =
 	if i >= -128 && i <= 127 then Int8Range
 	if i >= -128 && i <= 127 then Int8Range
 	else if i >= -32768 && i <= 32767 then Int16Range
 	else if i >= -32768 && i <= 32767 then Int16Range

+ 30 - 11
src/generators/jvm/jvmMethod.ml

@@ -1,3 +1,22 @@
+(*
+	The Haxe Compiler
+	Copyright (C) 2005-2019  Haxe Foundation
+
+	This program is free software; you can redistribute it and/or
+	modify it under the terms of the GNU General Public License
+	as published by the Free Software Foundation; either version 2
+	of the License, or (at your option) any later version.
+
+	This program is distributed in the hope that it will be useful,
+	but WITHOUT ANY WARRANTY; without even the implied warranty of
+	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+	GNU General Public License for more details.
+
+	You should have received a copy of the GNU General Public License
+	along with this program; if not, write to the Free Software
+	Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *)
+
 open Globals
 open Globals
 open JvmGlobals
 open JvmGlobals
 open JvmData
 open JvmData
@@ -542,28 +561,28 @@ class builder jc name jsig = object(self)
 				def,cases
 				def,cases
 		in
 		in
 		let flat_cases = DynArray.create () in
 		let flat_cases = DynArray.create () in
-		let case_lut = ref IntMap.empty in
+		let case_lut = ref Int32Map.empty in
 		let fp = code#get_fp in
 		let fp = code#get_fp in
-		let imin = ref max_int in
-		let imax = ref min_int in
+		let imin = ref Int32.min_int in
+		let imax = ref Int32.max_int in
 		let cases = List.map (fun (il,f) ->
 		let cases = List.map (fun (il,f) ->
 			let rl = List.map (fun i32 ->
 			let rl = List.map (fun i32 ->
 				let r = ref fp in
 				let r = ref fp in
-				let i = Int32.to_int i32 in
-				if i < !imin then imin := i;
-				if i > !imax then imax := i;
-				DynArray.add flat_cases (i,r);
-				case_lut := IntMap.add i r !case_lut;
+				if i32 < !imin then imin := i32;
+				if i32 > !imax then imax := i32;
+				DynArray.add flat_cases (i32,r);
+				case_lut := Int32Map.add i32 r !case_lut;
 				r
 				r
 			) il in
 			) il in
 			(rl,f)
 			(rl,f)
 		) cases in
 		) cases in
 		let offset_def = ref fp in
 		let offset_def = ref fp in
 		(* No idea what's a good heuristic here... *)
 		(* No idea what's a good heuristic here... *)
-		let use_tableswitch = (!imax - !imin) < (DynArray.length flat_cases + 10) in
+		let diff = Int32.sub !imax !imin in
+		let use_tableswitch = diff < (Int32.of_int (DynArray.length flat_cases + 10)) && diff >= Int32.zero (* #8388 *) in
 		if use_tableswitch then begin
 		if use_tableswitch then begin
-			let offsets = Array.init (!imax - !imin + 1) (fun i ->
-				try IntMap.find (i + !imin) !case_lut
+			let offsets = Array.init (Int32.to_int (Int32.sub !imax !imin) + 1) (fun i ->
+				try Int32Map.find (Int32.add (Int32.of_int i) !imin) !case_lut
 				with Not_found -> offset_def
 				with Not_found -> offset_def
 			) in
 			) in
 			code#tableswitch offset_def !imin !imax offsets
 			code#tableswitch offset_def !imin !imax offsets

+ 19 - 0
src/generators/jvm/jvmSignature.ml

@@ -1,3 +1,22 @@
+(*
+	The Haxe Compiler
+	Copyright (C) 2005-2019  Haxe Foundation
+
+	This program is free software; you can redistribute it and/or
+	modify it under the terms of the GNU General Public License
+	as published by the Free Software Foundation; either version 2
+	of the License, or (at your option) any later version.
+
+	This program is distributed in the hope that it will be useful,
+	but WITHOUT ANY WARRANTY; without even the implied warranty of
+	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+	GNU General Public License for more details.
+
+	You should have received a copy of the GNU General Public License
+	along with this program; if not, write to the Free Software
+	Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *)
+
 open JvmGlobals
 open JvmGlobals
 
 
 type jpath = (string list) * string
 type jpath = (string list) * string

+ 19 - 0
src/generators/jvm/jvmVerificationTypeInfo.ml

@@ -1,3 +1,22 @@
+(*
+	The Haxe Compiler
+	Copyright (C) 2005-2019  Haxe Foundation
+
+	This program is free software; you can redistribute it and/or
+	modify it under the terms of the GNU General Public License
+	as published by the Free Software Foundation; either version 2
+	of the License, or (at your option) any later version.
+
+	This program is distributed in the hope that it will be useful,
+	but WITHOUT ANY WARRANTY; without even the implied warranty of
+	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+	GNU General Public License for more details.
+
+	You should have received a copy of the GNU General Public License
+	along with this program; if not, write to the Free Software
+	Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *)
+
 open JvmGlobals
 open JvmGlobals
 open JvmSignature
 open JvmSignature
 
 

+ 29 - 3
src/generators/jvm/jvmWriter.ml

@@ -1,3 +1,22 @@
+(*
+	The Haxe Compiler
+	Copyright (C) 2005-2019  Haxe Foundation
+
+	This program is free software; you can redistribute it and/or
+	modify it under the terms of the GNU General Public License
+	as published by the Free Software Foundation; either version 2
+	of the License, or (at your option) any later version.
+
+	This program is distributed in the hope that it will be useful,
+	but WITHOUT ANY WARRANTY; without even the implied warranty of
+	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+	GNU General Public License for more details.
+
+	You should have received a copy of the GNU General Public License
+	along with this program; if not, write to the Free Software
+	Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *)
+
 open JvmGlobals
 open JvmGlobals
 open JvmData
 open JvmData
 
 
@@ -48,6 +67,7 @@ let write_exception ch jvme =
 
 
 let write_opcode ch code =
 let write_opcode ch code =
   let w = write_byte ch in
   let w = write_byte ch in
+  let wr i32 = write_byte ch (Int32.to_int i32) in
   (* TODO: probably don't need these *)
   (* TODO: probably don't need these *)
   let bp i =
   let bp i =
     w ((i lsr 8) land 0xFF);
     w ((i lsr 8) land 0xFF);
@@ -59,6 +79,12 @@ let write_opcode ch code =
     w ((i lsr 8) land 0xFF);
     w ((i lsr 8) land 0xFF);
     w (i land 0xFF);
     w (i land 0xFF);
   in
   in
+  let b4r i32 =
+    wr (Int32.logand (Int32.shift_right_logical i32 24) i320xFF);
+    wr (Int32.logand (Int32.shift_right_logical i32 16) i320xFF);
+    wr (Int32.logand (Int32.shift_right_logical i32 8) i320xFF);
+    wr (Int32.logand i32 i320xFF);
+  in
   let rec loop code = match code with
   let rec loop code = match code with
     (* double *)
     (* double *)
     | OpD2f -> w 0x90
     | OpD2f -> w 0x90
@@ -280,15 +306,15 @@ let write_opcode ch code =
 		b4 !def;
 		b4 !def;
 		b4 (Array.length pairs);
 		b4 (Array.length pairs);
 		Array.iter (fun (i,offset) ->
 		Array.iter (fun (i,offset) ->
-			b4 i;
+			b4r i;
 			b4 !offset
 			b4 !offset
 		) pairs;
 		) pairs;
     | OpTableswitch(pad,def,low,high,offsets) ->
     | OpTableswitch(pad,def,low,high,offsets) ->
 		w 0xaa;
 		w 0xaa;
 		if pad > 0 then for i = 0 to pad -1 do w 0 done;
 		if pad > 0 then for i = 0 to pad -1 do w 0 done;
 		b4 !def;
 		b4 !def;
-		b4 low;
-		b4 high;
+		b4r low;
+		b4r high;
 		Array.iter (fun offset ->
 		Array.iter (fun offset ->
 			b4 !offset
 			b4 !offset
 		) offsets;
 		) offsets;

+ 30 - 3
src/macro/eval/evalContext.ml

@@ -203,6 +203,34 @@ class eval_debug_context = object(self)
 
 
 end
 end
 
 
+class static_prototypes = object(self)
+	val mutable prototypes : vprototype IntMap.t = IntMap.empty
+	val mutable inits : (bool ref * vprototype * (vprototype -> unit) list) IntMap.t = IntMap.empty
+
+	method add proto =
+		prototypes <- IntMap.add proto.ppath proto prototypes
+
+	method remove path =
+		inits <- IntMap.remove path inits;
+		prototypes <- IntMap.remove path prototypes
+
+	method set_needs_reset =
+		IntMap.iter (fun path (needs_reset, _, _) -> needs_reset := true) inits
+
+	method add_init proto delays =
+		inits <- IntMap.add proto.ppath (ref false, proto, delays) inits
+
+	method get path =
+		(try
+			let (needs_reset, proto, delays) = IntMap.find path inits in
+			if !needs_reset then begin
+				needs_reset := false;
+				List.iter (fun f -> f proto) delays
+			end
+		with Not_found -> ());
+		IntMap.find path prototypes
+end
+
 type exception_mode =
 type exception_mode =
 	| CatchAll
 	| CatchAll
 	| CatchUncaught
 	| CatchUncaught
@@ -251,10 +279,9 @@ and context = {
 	mutable string_prototype : vprototype;
 	mutable string_prototype : vprototype;
 	mutable vector_prototype : vprototype;
 	mutable vector_prototype : vprototype;
 	mutable instance_prototypes : vprototype IntMap.t;
 	mutable instance_prototypes : vprototype IntMap.t;
-	mutable static_prototypes : vprototype IntMap.t;
+	mutable static_prototypes : static_prototypes;
 	mutable constructors : value Lazy.t IntMap.t;
 	mutable constructors : value Lazy.t IntMap.t;
 	get_object_prototype : 'a . context -> (int * 'a) list -> vprototype * (int * 'a) list;
 	get_object_prototype : 'a . context -> (int * 'a) list -> vprototype * (int * 'a) list;
-	mutable static_inits : (vprototype * (vprototype -> unit) list) IntMap.t;
 	(* eval *)
 	(* eval *)
 	toplevel : value;
 	toplevel : value;
 	eval : eval;
 	eval : eval;
@@ -440,7 +467,7 @@ let pop_environment ctx env =
 (* Prototypes *)
 (* Prototypes *)
 
 
 let get_static_prototype_raise ctx path =
 let get_static_prototype_raise ctx path =
-	IntMap.find path ctx.static_prototypes
+	ctx.static_prototypes#get path
 
 
 let get_static_prototype ctx path p =
 let get_static_prototype ctx path p =
 	try get_static_prototype_raise ctx path
 	try get_static_prototype_raise ctx path

+ 28 - 11
src/macro/eval/evalDebugMisc.ml

@@ -164,7 +164,7 @@ let resolve_ident ctx env s =
 		end
 		end
 	with Not_found -> try
 	with Not_found -> try
 		(* 4. Type *)
 		(* 4. Type *)
-		VPrototype (IntMap.find key ctx.static_prototypes)
+		VPrototype (get_static_prototype_raise ctx key)
 	with Not_found -> try
 	with Not_found -> try
 		(* 5. Toplevel *)
 		(* 5. Toplevel *)
 		EvalField.field_raise ctx.toplevel key
 		EvalField.field_raise ctx.toplevel key
@@ -224,17 +224,25 @@ let rec expr_to_value ctx env e =
 			end
 			end
 		| EField(e1,s) ->
 		| EField(e1,s) ->
 			let v1 = loop e1 in
 			let v1 = loop e1 in
-			let s = hash s in
+			let s' = hash s in
 			begin match v1 with
 			begin match v1 with
 			| VEnumValue ve ->
 			| VEnumValue ve ->
 				begin try
 				begin try
-					let i = find_enum_field_by_name ve s in
+					let i = find_enum_field_by_name ve s' in
 					ve.eargs.(i)
 					ve.eargs.(i)
 				with Not_found ->
 				with Not_found ->
 					vnull
 					vnull
 				end
 				end
 			| _ ->
 			| _ ->
-				let v = EvalField.field v1 s in
+				let v = try
+					EvalField.field_raise v1 s'
+				with Not_found -> try
+					(* Maybe we have a getter? (#8599) *)
+					let vf = EvalField.field v1 (hash ("get_" ^ s)) in
+					safe_call env.env_eval (EvalPrinting.call_value_on v1 vf) []
+				with _ ->
+					vnull
+				in
 				v
 				v
 			end
 			end
 		| EArrayDecl el ->
 		| EArrayDecl el ->
@@ -248,7 +256,6 @@ let rec expr_to_value ctx env e =
 			| OpAssign ->
 			| OpAssign ->
 				let v2 = loop e2 in
 				let v2 = loop e2 in
 				write_expr ctx env e1 v2;
 				write_expr ctx env e1 v2;
-				v2
 			| OpAssignOp op ->
 			| OpAssignOp op ->
 				raise Exit (* Nobody does that, right? *)
 				raise Exit (* Nobody does that, right? *)
 			| OpBoolAnd ->
 			| OpBoolAnd ->
@@ -360,23 +367,32 @@ let rec expr_to_value ctx env e =
 and write_expr ctx env expr value =
 and write_expr ctx env expr value =
 	begin match fst expr with
 	begin match fst expr with
 		| EField(e1,s) ->
 		| EField(e1,s) ->
-			let s = hash s in
+			let s' = hash s in
 			let v1 = expr_to_value ctx env e1 in
 			let v1 = expr_to_value ctx env e1 in
 			begin match v1 with
 			begin match v1 with
 			| VEnumValue ve ->
 			| VEnumValue ve ->
 				begin try
 				begin try
-					let i = find_enum_field_by_name ve s in
-					ve.eargs.(i) <- value
+					let i = find_enum_field_by_name ve s' in
+					ve.eargs.(i) <- value;
+					value
 				with Not_found ->
 				with Not_found ->
-					()
+					value
 				end
 				end
 			| _ ->
 			| _ ->
-				set_field v1 s value;
+				try
+					set_field v1 s' value;
+					value;
+				with Not_found -> try
+					let vf = EvalField.field v1 (hash ("set_" ^ s)) in
+					safe_call env.env_eval (EvalPrinting.call_value_on v1 vf) [value]
+				with _ ->
+					value
 			end
 			end
 		| EConst (Ident s) ->
 		| EConst (Ident s) ->
 			begin try
 			begin try
 				let slot = get_var_slot_by_name env false env.env_debug.scopes s in
 				let slot = get_var_slot_by_name env false env.env_debug.scopes s in
 				env.env_locals.(slot) <- value;
 				env.env_locals.(slot) <- value;
+				value
 			with Not_found ->
 			with Not_found ->
 				raise Exit
 				raise Exit
 			end
 			end
@@ -389,7 +405,8 @@ and write_expr ctx env expr value =
 				| VVector vv -> Array.set vv idx value
 				| VVector vv -> Array.set vv idx value
 				| VEnumValue ev -> Array.set ev.eargs idx value
 				| VEnumValue ev -> Array.set ev.eargs idx value
 				| _ -> raise Exit
 				| _ -> raise Exit
-			end
+			end;
+			value
 		| _ ->
 		| _ ->
 			raise Exit
 			raise Exit
 	end
 	end

+ 2 - 3
src/macro/eval/evalMain.ml

@@ -120,11 +120,10 @@ let create com api is_macro =
 		string_prototype = fake_proto key_String;
 		string_prototype = fake_proto key_String;
 		array_prototype = fake_proto key_Array;
 		array_prototype = fake_proto key_Array;
 		vector_prototype = fake_proto key_eval_Vector;
 		vector_prototype = fake_proto key_eval_Vector;
-		static_prototypes = IntMap.empty;
+		static_prototypes = new static_prototypes;
 		instance_prototypes = IntMap.empty;
 		instance_prototypes = IntMap.empty;
 		constructors = IntMap.empty;
 		constructors = IntMap.empty;
 		get_object_prototype = get_object_prototype;
 		get_object_prototype = get_object_prototype;
-		static_inits = IntMap.empty;
 		(* eval *)
 		(* eval *)
 		toplevel = 	vobject {
 		toplevel = 	vobject {
 			ofields = [||];
 			ofields = [||];
@@ -375,7 +374,7 @@ let setup get_api =
 
 
 let do_reuse ctx api =
 let do_reuse ctx api =
 	ctx.curapi <- api;
 	ctx.curapi <- api;
-	IntMap.iter (fun _ (proto,delays) -> List.iter (fun f -> f proto) delays) ctx.static_inits
+	ctx.static_prototypes#set_needs_reset
 
 
 let set_error ctx b =
 let set_error ctx b =
 	(* TODO: Have to reset this somewhere if running compilation server. But where... *)
 	(* TODO: Have to reset this somewhere if running compilation server. But where... *)

+ 3 - 3
src/macro/eval/evalPrototype.ml

@@ -159,7 +159,7 @@ module PrototypeBuilder = struct
 		proto.pvalue <- vprototype proto;
 		proto.pvalue <- vprototype proto;
 		(* Register the prototype. *)
 		(* Register the prototype. *)
 		if pctx.is_static then
 		if pctx.is_static then
-			ctx.static_prototypes <- IntMap.add pctx.key proto ctx.static_prototypes
+			ctx.static_prototypes#add proto
 		else begin
 		else begin
 			ctx.instance_prototypes <- IntMap.add pctx.key proto ctx.instance_prototypes;
 			ctx.instance_prototypes <- IntMap.add pctx.key proto ctx.instance_prototypes;
 			if pctx.key = key_String then ctx.string_prototype <- proto
 			if pctx.key = key_String then ctx.string_prototype <- proto
@@ -307,7 +307,7 @@ let add_types ctx types ready =
 			false
 			false
 		with Not_found ->
 		with Not_found ->
 			ctx.instance_prototypes <- IntMap.remove key ctx.instance_prototypes;
 			ctx.instance_prototypes <- IntMap.remove key ctx.instance_prototypes;
-			ctx.static_prototypes <- IntMap.remove key ctx.static_prototypes;
+			ctx.static_prototypes#remove key;
 			ctx.constructors <- IntMap.remove key ctx.constructors;
 			ctx.constructors <- IntMap.remove key ctx.constructors;
 			ready mt;
 			ready mt;
 			ctx.type_cache <- IntMap.add key mt ctx.type_cache;
 			ctx.type_cache <- IntMap.add key mt ctx.type_cache;
@@ -355,7 +355,7 @@ let add_types ctx types ready =
 		| _ ->
 		| _ ->
 			DynArray.add fl_static_init (proto,delays);
 			DynArray.add fl_static_init (proto,delays);
 			let non_persistent_delays = ExtList.List.filter_map (fun (persistent,f) -> if not persistent then Some f else None) delays in
 			let non_persistent_delays = ExtList.List.filter_map (fun (persistent,f) -> if not persistent then Some f else None) delays in
-			ctx.static_inits <- IntMap.add proto.ppath (proto,non_persistent_delays) ctx.static_inits;
+			ctx.static_prototypes#add_init proto non_persistent_delays;
 	) fl_static;
 	) fl_static;
 	(* 4. Initialize static fields. *)
 	(* 4. Initialize static fields. *)
 	DynArray.iter (fun (proto,delays) -> List.iter (fun (_,f) -> f proto) delays) fl_static_init;
 	DynArray.iter (fun (proto,delays) -> List.iter (fun (_,f) -> f proto) delays) fl_static_init;

+ 43 - 14
src/macro/eval/evalStdLib.ml

@@ -674,6 +674,8 @@ module StdCrc32 = struct
 end
 end
 
 
 module StdDate = struct
 module StdDate = struct
+	open Unix
+
 	let encode_date d = encode_instance key_Date ~kind:(IDate d)
 	let encode_date d = encode_instance key_Date ~kind:(IDate d)
 
 
 	let this vthis = match vthis with
 	let this vthis = match vthis with
@@ -688,29 +690,33 @@ module StdDate = struct
 		| 19 ->
 		| 19 ->
 			let r = Str.regexp "^\\([0-9][0-9][0-9][0-9]\\)-\\([0-9][0-9]\\)-\\([0-9][0-9]\\) \\([0-9][0-9]\\):\\([0-9][0-9]\\):\\([0-9][0-9]\\)$" in
 			let r = Str.regexp "^\\([0-9][0-9][0-9][0-9]\\)-\\([0-9][0-9]\\)-\\([0-9][0-9]\\) \\([0-9][0-9]\\):\\([0-9][0-9]\\):\\([0-9][0-9]\\)$" in
 			if not (Str.string_match r s 0) then exc_string ("Invalid date format : " ^ s);
 			if not (Str.string_match r s 0) then exc_string ("Invalid date format : " ^ s);
-			let t = catch_unix_error Unix.localtime (Unix.time()) in
-			let t = { t with
+			let t = {
 				tm_year = int_of_string (Str.matched_group 1 s) - 1900;
 				tm_year = int_of_string (Str.matched_group 1 s) - 1900;
 				tm_mon = int_of_string (Str.matched_group 2 s) - 1;
 				tm_mon = int_of_string (Str.matched_group 2 s) - 1;
 				tm_mday = int_of_string (Str.matched_group 3 s);
 				tm_mday = int_of_string (Str.matched_group 3 s);
 				tm_hour = int_of_string (Str.matched_group 4 s);
 				tm_hour = int_of_string (Str.matched_group 4 s);
 				tm_min = int_of_string (Str.matched_group 5 s);
 				tm_min = int_of_string (Str.matched_group 5 s);
 				tm_sec = int_of_string (Str.matched_group 6 s);
 				tm_sec = int_of_string (Str.matched_group 6 s);
+				tm_wday = 0;
+				tm_yday = 0;
+				tm_isdst = false;
 			} in
 			} in
-			encode_date (fst (catch_unix_error Unix.mktime t))
+			encode_date (fst (catch_unix_error mktime t))
 		| 10 ->
 		| 10 ->
 			let r = Str.regexp "^\\([0-9][0-9][0-9][0-9]\\)-\\([0-9][0-9]\\)-\\([0-9][0-9]\\)$" in
 			let r = Str.regexp "^\\([0-9][0-9][0-9][0-9]\\)-\\([0-9][0-9]\\)-\\([0-9][0-9]\\)$" in
 			if not (Str.string_match r s 0) then exc_string ("Invalid date format : " ^ s);
 			if not (Str.string_match r s 0) then exc_string ("Invalid date format : " ^ s);
-			let t = catch_unix_error Unix.localtime (Unix.time()) in
-			let t = { t with
+			let t = {
 				tm_year = int_of_string (Str.matched_group 1 s) - 1900;
 				tm_year = int_of_string (Str.matched_group 1 s) - 1900;
 				tm_mon = int_of_string (Str.matched_group 2 s) - 1;
 				tm_mon = int_of_string (Str.matched_group 2 s) - 1;
 				tm_mday = int_of_string (Str.matched_group 3 s);
 				tm_mday = int_of_string (Str.matched_group 3 s);
 				tm_hour = 0;
 				tm_hour = 0;
 				tm_min = 0;
 				tm_min = 0;
 				tm_sec = 0;
 				tm_sec = 0;
+				tm_wday = 0;
+				tm_yday = 0;
+				tm_isdst = false;
 			} in
 			} in
-			encode_date (fst (catch_unix_error Unix.mktime t))
+			encode_date (fst (catch_unix_error mktime t))
 		| 8 ->
 		| 8 ->
 			let r = Str.regexp "^\\([0-9][0-9]\\):\\([0-9][0-9]\\):\\([0-9][0-9]\\)$" in
 			let r = Str.regexp "^\\([0-9][0-9]\\):\\([0-9][0-9]\\):\\([0-9][0-9]\\)$" in
 			if not (Str.string_match r s 0) then exc_string ("Invalid date format : " ^ s);
 			if not (Str.string_match r s 0) then exc_string ("Invalid date format : " ^ s);
@@ -723,15 +729,29 @@ module StdDate = struct
 			exc_string ("Invalid date format : " ^ s)
 			exc_string ("Invalid date format : " ^ s)
 	)
 	)
 
 
-	let getDate = vifun0 (fun vthis -> vint (catch_unix_error Unix.localtime (this vthis)).tm_mday)
-	let getDay = vifun0 (fun vthis -> vint (catch_unix_error Unix.localtime (this vthis)).tm_wday)
-	let getFullYear = vifun0 (fun vthis -> vint (((catch_unix_error Unix.localtime (this vthis)).tm_year) + 1900))
-	let getHours = vifun0 (fun vthis -> vint (catch_unix_error Unix.localtime (this vthis)).tm_hour)
-	let getMinutes = vifun0 (fun vthis -> vint (catch_unix_error Unix.localtime (this vthis)).tm_min)
-	let getMonth = vifun0 (fun vthis -> vint (catch_unix_error Unix.localtime (this vthis)).tm_mon)
-	let getSeconds = vifun0 (fun vthis -> vint (catch_unix_error Unix.localtime (this vthis)).tm_sec)
+	let getDate = vifun0 (fun vthis -> vint (catch_unix_error localtime (this vthis)).tm_mday)
+	let getDay = vifun0 (fun vthis -> vint (catch_unix_error localtime (this vthis)).tm_wday)
+	let getFullYear = vifun0 (fun vthis -> vint (((catch_unix_error localtime (this vthis)).tm_year) + 1900))
+	let getHours = vifun0 (fun vthis -> vint (catch_unix_error localtime (this vthis)).tm_hour)
+	let getMinutes = vifun0 (fun vthis -> vint (catch_unix_error localtime (this vthis)).tm_min)
+	let getMonth = vifun0 (fun vthis -> vint (catch_unix_error localtime (this vthis)).tm_mon)
+	let getSeconds = vifun0 (fun vthis -> vint (catch_unix_error localtime (this vthis)).tm_sec)
+	let getUTCDate = vifun0 (fun vthis -> vint (catch_unix_error gmtime (this vthis)).tm_mday)
+	let getUTCDay = vifun0 (fun vthis -> vint (catch_unix_error gmtime (this vthis)).tm_wday)
+	let getUTCFullYear = vifun0 (fun vthis -> vint (((catch_unix_error gmtime (this vthis)).tm_year) + 1900))
+	let getUTCHours = vifun0 (fun vthis -> vint (catch_unix_error gmtime (this vthis)).tm_hour)
+	let getUTCMinutes = vifun0 (fun vthis -> vint (catch_unix_error gmtime (this vthis)).tm_min)
+	let getUTCMonth = vifun0 (fun vthis -> vint (catch_unix_error gmtime (this vthis)).tm_mon)
+	let getUTCSeconds = vifun0 (fun vthis -> vint (catch_unix_error gmtime (this vthis)).tm_sec)
 	let getTime = vifun0 (fun vthis -> vfloat ((this vthis) *. 1000.))
 	let getTime = vifun0 (fun vthis -> vfloat ((this vthis) *. 1000.))
-	let now = vfun0 (fun () -> encode_date (catch_unix_error Unix.time()))
+	let getTimezoneOffset = vifun0 (fun vthis ->
+		let tmLocal = catch_unix_error localtime (this vthis) in
+		let tmUTC = catch_unix_error gmtime (this vthis) in
+		let tsLocal = fst (catch_unix_error mktime tmLocal) in
+		let tsUTC = fst (catch_unix_error mktime tmUTC) in
+		vint (int_of_float ((tsUTC -. tsLocal) /. 60.))
+	)
+	let now = vfun0 (fun () -> encode_date (catch_unix_error time()))
 	let toString = vifun0 (fun vthis -> vstring (s_date (this vthis)))
 	let toString = vifun0 (fun vthis -> vstring (s_date (this vthis)))
 end
 end
 
 
@@ -1169,6 +1189,7 @@ module StdFileSystem = struct
 
 
 	let patch_path s =
 	let patch_path s =
 		if String.length s > 1 && String.length s <= 3 && s.[1] = ':' then Path.add_trailing_slash s
 		if String.length s > 1 && String.length s <= 3 && s.[1] = ':' then Path.add_trailing_slash s
+		else if s = "/" then "/"
 		else remove_trailing_slash s
 		else remove_trailing_slash s
 
 
 	let createDirectory = vfun1 (fun path ->
 	let createDirectory = vfun1 (fun path ->
@@ -3312,7 +3333,15 @@ let init_standard_library builtins =
 		"getMinutes",StdDate.getMinutes;
 		"getMinutes",StdDate.getMinutes;
 		"getMonth",StdDate.getMonth;
 		"getMonth",StdDate.getMonth;
 		"getSeconds",StdDate.getSeconds;
 		"getSeconds",StdDate.getSeconds;
+		"getUTCDate",StdDate.getUTCDate;
+		"getUTCDay",StdDate.getUTCDay;
+		"getUTCFullYear",StdDate.getUTCFullYear;
+		"getUTCHours",StdDate.getUTCHours;
+		"getUTCMinutes",StdDate.getUTCMinutes;
+		"getUTCMonth",StdDate.getUTCMonth;
+		"getUTCSeconds",StdDate.getUTCSeconds;
 		"getTime",StdDate.getTime;
 		"getTime",StdDate.getTime;
+		"getTimezoneOffset",StdDate.getTimezoneOffset;
 		"toString",StdDate.toString;
 		"toString",StdDate.toString;
 	];
 	];
 	init_fields builtins (["sys";"thread"],"Deque") [] [
 	init_fields builtins (["sys";"thread"],"Deque") [] [

+ 8 - 13
src/macro/macroApi.ml

@@ -1682,6 +1682,12 @@ let macro_api ccom get_api =
 			);
 			);
 			vnull
 			vnull
 		);
 		);
+		"flush_disk_cache", vfun0 (fun () ->
+			let com = (get_api()).get_com() in
+			Hashtbl.clear com.file_lookup_cache;
+			Hashtbl.clear com.readdir_cache;
+			vnull
+		);
 		"get_pos_infos", vfun1 (fun p ->
 		"get_pos_infos", vfun1 (fun p ->
 			let p = decode_pos p in
 			let p = decode_pos p in
 			encode_obj ["min",vint p.Globals.pmin;"max",vint p.Globals.pmax;"file",encode_string p.Globals.pfile]
 			encode_obj ["min",vint p.Globals.pmin;"max",vint p.Globals.pmax;"file",encode_string p.Globals.pfile]
@@ -1793,24 +1799,13 @@ let macro_api ccom get_api =
 			| None ->
 			| None ->
 				());
 				());
 			Hashtbl.clear com.file_lookup_cache;
 			Hashtbl.clear com.file_lookup_cache;
+			Hashtbl.clear com.readdir_cache;
 			vnull
 			vnull
 		);
 		);
 		"add_native_lib", vfun1 (fun file ->
 		"add_native_lib", vfun1 (fun file ->
 			let file = decode_string file in
 			let file = decode_string file in
 			let com = ccom() in
 			let com = ccom() in
-			(match com.platform with
-			| Globals.Flash -> SwfLoader.add_swf_lib com file false
-			| Globals.Java -> Java.add_java_lib com file false
-			| Globals.Cs ->
-				let file, is_std = match ExtString.String.nsplit file "@" with
-					| [file] ->
-						file,false
-					| [file;"std"] ->
-						file,true
-					| _ -> failwith ("unsupported file@`std` format: " ^ file)
-				in
-				Dotnet.add_net_lib com file is_std
-			| _ -> failwith "Unsupported platform");
+			NativeLibraryHandler.add_native_lib com file false ();
 			vnull
 			vnull
 		);
 		);
 		"add_native_arg", vfun1 (fun arg ->
 		"add_native_arg", vfun1 (fun arg ->

+ 0 - 1
src/optimization/analyzer.ml

@@ -1030,7 +1030,6 @@ module Run = struct
 	let run_on_field ctx config c cf = match cf.cf_expr with
 	let run_on_field ctx config c cf = match cf.cf_expr with
 		| Some e when not (is_ignored cf.cf_meta) && not (Typecore.is_removable_field ctx cf) ->
 		| Some e when not (is_ignored cf.cf_meta) && not (Typecore.is_removable_field ctx cf) ->
 			let config = update_config_from_meta ctx.Typecore.com config cf.cf_meta in
 			let config = update_config_from_meta ctx.Typecore.com config cf.cf_meta in
-			(match e.eexpr with TFunction tf -> cf.cf_expr_unoptimized <- Some tf | _ -> ());
 			let actx = create_analyzer_context ctx.Typecore.com config e in
 			let actx = create_analyzer_context ctx.Typecore.com config e in
 			let debug() =
 			let debug() =
 				print_endline (Printf.sprintf "While analyzing %s.%s" (s_type_path c.cl_path) cf.cf_name);
 				print_endline (Printf.sprintf "While analyzing %s.%s" (s_type_path c.cl_path) cf.cf_name);

+ 0 - 2
src/optimization/analyzerTexprTransformer.ml

@@ -173,8 +173,6 @@ let rec func ctx bb tf t p =
 			close_node g bb;
 			close_node g bb;
 			add_cfg_edge bb_func_end bb_next CFGGoto;
 			add_cfg_edge bb_func_end bb_next CFGGoto;
 			bb_next,ec
 			bb_next,ec
-		(*| TTypeExpr(TClassDecl {cl_kind = KAbstractImpl a}) when not (Meta.has Meta.RuntimeValue a.a_meta) ->
-			error "Cannot use abstract as value" e.epos*)
 		| TConst _ | TTypeExpr _ ->
 		| TConst _ | TTypeExpr _ ->
 			bb,e
 			bb,e
 		| TThrow _ | TReturn _ | TBreak | TContinue ->
 		| TThrow _ | TReturn _ | TBreak | TContinue ->

+ 28 - 13
src/prebuild/main.ml

@@ -50,6 +50,13 @@ let as_bool = function
 	| JBool b -> Some b
 	| JBool b -> Some b
 	| _ -> None
 	| _ -> None
 
 
+let as_links = function
+	| JArray s -> Some (List.map (function
+			| JString s -> s
+			| _ -> raise (Prebuild_error "link should be a string")
+		) s)
+	| _ -> None
+
 let get_optional_field name map default fields =
 let get_optional_field name map default fields =
 	try
 	try
 		let field = List.find (fun (n, _) -> n = name) fields in
 		let field = List.find (fun (n, _) -> n = name) fields in
@@ -71,11 +78,12 @@ let parse_define json =
 		| JObject fl -> fl
 		| JObject fl -> fl
 		| _ -> raise (Prebuild_error "not an object")
 		| _ -> raise (Prebuild_error "not an object")
 	in
 	in
-	(*name*) get_field "name" as_string fields,
-	(*define*) get_field "define" 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
+	(* name *) get_field "name" as_string fields,
+	(* define *) get_field "define" 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,
+	(* links *) get_optional_field "links" as_links [] fields
 
 
 let parse_meta json =
 let parse_meta json =
 	let fields = match json with
 	let fields = match json with
@@ -88,7 +96,8 @@ let parse_meta json =
 	(* params *) get_optional_field "params" as_params [] fields,
 	(* params *) get_optional_field "params" as_params [] fields,
 	(* platforms *) get_optional_field "platforms" as_platforms [] fields,
 	(* platforms *) get_optional_field "platforms" as_platforms [] fields,
 	(* targets *) get_optional_field "targets" as_targets [] fields,
 	(* targets *) get_optional_field "targets" as_targets [] fields,
-	(* internal *) get_optional_field "internal" as_bool false fields
+	(* internal *) get_optional_field "internal" as_bool false fields,
+	(* links *) get_optional_field "links" as_links [] fields
 
 
 let parse_file_array path map =
 let parse_file_array path map =
 	let file = open_in path in
 	let file = open_in path in
@@ -106,27 +115,30 @@ let gen_platforms = function
 
 
 let gen_params = List.map (function param -> "HasParam \"" ^ param ^ "\"" )
 let gen_params = List.map (function param -> "HasParam \"" ^ param ^ "\"" )
 
 
+let gen_links = List.map (function link -> "Link \"" ^ link ^ "\"" )
+
 let gen_define_type defines =
 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_define_info defines =
 let gen_define_info defines =
 	let define_str = List.map (function
 	let define_str = List.map (function
-		(name, define, doc, params, platforms) ->
+		(name, define, doc, params, platforms, links) ->
 			let platforms_str = gen_platforms platforms in
 			let platforms_str = gen_platforms platforms in
 			let params_str = gen_params params in
 			let params_str = gen_params params in
-			"\t| " ^ name ^ " -> \"" ^ define ^ "\",(" ^ (Printf.sprintf "%S" doc) ^ ",[" ^ (String.concat "; " (platforms_str @ params_str)) ^ "])"
+			let links_str = gen_links links in
+			"\t| " ^ name ^ " -> \"" ^ define ^ "\",(" ^ (Printf.sprintf "%S" doc) ^ ",[" ^ (String.concat "; " (platforms_str @ params_str @ links_str)) ^ "])"
 	) defines in
 	) defines in
 	String.concat "\n" define_str
 	String.concat "\n" define_str
 
 
 let gen_meta_type metas =
 let gen_meta_type metas =
 	String.concat "\n" (List.map (function
 	String.concat "\n" (List.map (function
-		| ("InlineConstructorArgument", _, _, _, _, _, _) -> "\t| InlineConstructorArgument of int * int"
-		| (name, _, _, _, _, _, _) -> "\t| " ^ name
+		| ("InlineConstructorArgument", _, _, _, _, _, _, _) -> "\t| InlineConstructorArgument of int * int"
+		| (name, _, _, _, _, _, _, _) -> "\t| " ^ name
 	) metas)
 	) metas)
 
 
 let gen_meta_info metas =
 let gen_meta_info metas =
 	let meta_str = List.map (function
 	let meta_str = List.map (function
-		(name, metadata, doc, params, platforms, targets, internal) ->
+		(name, metadata, doc, params, platforms, targets, internal, links) ->
 			let platforms_str = gen_platforms platforms in
 			let platforms_str = gen_platforms platforms in
 			let params_str = gen_params params in
 			let params_str = gen_params params in
 			let targets_str = (match targets with
 			let targets_str = (match targets with
@@ -134,12 +146,13 @@ let gen_meta_info metas =
 				| targets -> ["UsedOn [" ^ (String.concat ";" targets) ^ "]"]
 				| targets -> ["UsedOn [" ^ (String.concat ";" targets) ^ "]"]
 			) in
 			) in
 			let internal_str = if internal then ["UsedInternally"] else [] in
 			let internal_str = if internal then ["UsedInternally"] else [] in
+			let links_str = gen_links links in
 			let name = (match name with
 			let name = (match name with
 				(* this is a hacky, I know *)
 				(* this is a hacky, I know *)
 				| "InlineConstructorArgument" -> "InlineConstructorArgument _"
 				| "InlineConstructorArgument" -> "InlineConstructorArgument _"
 				| _ -> name
 				| _ -> name
 			) in
 			) in
-			"\t| " ^ name ^ " -> \"" ^ metadata ^ "\",(" ^ (Printf.sprintf "%S" doc) ^ ",[" ^ (String.concat "; " (platforms_str @ params_str @ targets_str @ internal_str)) ^ "])"
+			"\t| " ^ name ^ " -> \"" ^ metadata ^ "\",(" ^ (Printf.sprintf "%S" doc) ^ ",[" ^ (String.concat "; " (platforms_str @ params_str @ targets_str @ internal_str @ links_str)) ^ "])"
 	) metas in
 	) metas in
 	String.concat "\n" meta_str
 	String.concat "\n" meta_str
 
 
@@ -153,6 +166,7 @@ open Globals
 type define_parameter =
 type define_parameter =
 	| HasParam of string
 	| HasParam of string
 	| Platforms of platform list
 	| Platforms of platform list
+	| Link of string
 
 
 "
 "
 
 
@@ -176,6 +190,7 @@ type meta_parameter =
 	| Platforms of platform list
 	| Platforms of platform list
 	| UsedOn of meta_usage list
 	| UsedOn of meta_usage list
 	| UsedInternally
 	| UsedInternally
+	| Link of string
 
 
 "
 "
 
 

+ 14 - 6
src/syntax/grammar.mly

@@ -1108,7 +1108,9 @@ and arrow_expr = parser
 
 
 and arrow_function p1 al er s =
 and arrow_function p1 al er s =
 	let make e =
 	let make e =
-		EFunction(None, { f_params = []; f_type = None; f_args = al; f_expr = Some (EReturn(Some e), (snd e));  }), punion p1 (pos e)
+		let p = pos e in
+		let return = (EMeta((Meta.ImplicitReturn, [], null_pos), (EReturn(Some e), p)), p) in
+		EFunction(None, { f_params = []; f_type = None; f_args = al; f_expr = Some return;  }), punion p1 p
 	in
 	in
 	List.iter (fun (_,_,ml,_,_) ->	match ml with
 	List.iter (fun (_,_,ml,_,_) ->	match ml with
 		| (_,_,p) :: _ -> syntax_error (Custom "Metadata on arrow function arguments is not allowed") ~pos:(Some p) s ()
 		| (_,_,p) :: _ -> syntax_error (Custom "Metadata on arrow function arguments is not allowed") ~pos:(Some p) s ()
@@ -1260,11 +1262,17 @@ and expr = parser
 		let e2 = (match s with parser
 		let e2 = (match s with parser
 			| [< '(Kwd Else,_); e2 = secure_expr; s >] -> Some e2
 			| [< '(Kwd Else,_); e2 = secure_expr; s >] -> Some e2
 			| [< >] ->
 			| [< >] ->
-				match Stream.npeek 2 s with
-				| [(Semicolon,_); (Kwd Else,_)] ->
-					Stream.junk s;
-					Stream.junk s;
-					Some (secure_expr s)
+				(* We check this in two steps to avoid the lexer missing tokens (#8565). *)
+				match Stream.npeek 1 s with
+				| [(Semicolon,_)] ->
+					begin match Stream.npeek 2 s with
+					| [(Semicolon,_);(Kwd Else,_)] ->
+						Stream.junk s;
+						Stream.junk s;
+						Some (secure_expr s)
+					| _ ->
+						None
+					end
 				| _ ->
 				| _ ->
 					None
 					None
 		) in
 		) in

+ 14 - 1
src/syntax/lexer.ml

@@ -198,7 +198,20 @@ let resolve_pos file =
 			| '\r' ->
 			| '\r' ->
 				ignore(input_char ch);
 				ignore(input_char ch);
 				inc 2
 				inc 2
-			| _ -> fun () -> 1
+			| c -> (fun () ->
+				let rec skip n =
+					if n > 0 then begin
+						ignore(input_char ch);
+						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
+			)
 		in
 		in
 		loop (p + i())
 		loop (p + i())
 	in
 	in

+ 2 - 2
src/syntax/parser.ml

@@ -118,11 +118,11 @@ let last_pos s = pos (last_token s)
 
 
 let next_token s = match Stream.peek s with
 let next_token s = match Stream.peek s with
 	| Some (Eof,p) ->
 	| Some (Eof,p) ->
-		(Eof,{p with pmax = max_int})
+		(Eof,p)
 	| Some tk -> tk
 	| Some tk -> tk
 	| None ->
 	| None ->
 		let last_pos = pos (last_token s) in
 		let last_pos = pos (last_token s) in
-		(Eof,{last_pos with pmax = max_int})
+		(Eof,last_pos)
 
 
 let next_pos s = pos (next_token s)
 let next_pos s = pos (next_token s)
 
 

+ 14 - 8
src/typing/calls.ml

@@ -60,7 +60,8 @@ let make_call ctx e params t ?(force_inline=false) p =
 		(match cl, ctx.curclass.cl_kind, params with
 		(match cl, ctx.curclass.cl_kind, params with
 			| Some c, KAbstractImpl _, { eexpr = TLocal { v_meta = v_meta } } :: _ when c == ctx.curclass ->
 			| Some c, KAbstractImpl _, { eexpr = TLocal { v_meta = v_meta } } :: _ when c == ctx.curclass ->
 				if
 				if
-					has_meta Meta.This v_meta
+					f.cf_name <> "_new"
+					&& has_meta Meta.This v_meta
 					&& not (assign_to_this_is_allowed ctx)
 					&& not (assign_to_this_is_allowed ctx)
 					&& has_class_field_flag f CfModifiesThis
 					&& has_class_field_flag f CfModifiesThis
 				then
 				then
@@ -537,11 +538,14 @@ let rec acc_get ctx g p =
 	| AKMacro _ ->
 	| AKMacro _ ->
 		assert false
 		assert false
 
 
-let rec build_call ctx acc el (with_type:WithType.t) p =
+let rec build_call ?(mode=MGet) ctx acc el (with_type:WithType.t) p =
+	let check_assign () = if mode = MSet then invalid_assign p in
 	match acc with
 	match acc with
 	| AKInline (ethis,f,fmode,t) when Meta.has Meta.Generic f.cf_meta ->
 	| AKInline (ethis,f,fmode,t) when Meta.has Meta.Generic f.cf_meta ->
+		check_assign();
 		type_generic_function ctx (ethis,fmode) el with_type p
 		type_generic_function ctx (ethis,fmode) el with_type p
 	| AKInline (ethis,f,fmode,t) ->
 	| AKInline (ethis,f,fmode,t) ->
+		check_assign();
 		(match follow t with
 		(match follow t with
 			| TFun (args,r) ->
 			| TFun (args,r) ->
 				let _,_,mk_call = unify_field_call ctx fmode el args r p true in
 				let _,_,mk_call = unify_field_call ctx fmode el args r p true in
@@ -550,6 +554,7 @@ let rec build_call ctx acc el (with_type:WithType.t) p =
 				error (s_type (print_context()) t ^ " cannot be called") p
 				error (s_type (print_context()) t ^ " cannot be called") p
 		)
 		)
 	| AKUsing (et,cl,ef,eparam,forced_inline (* TOOD? *)) when Meta.has Meta.Generic ef.cf_meta ->
 	| AKUsing (et,cl,ef,eparam,forced_inline (* TOOD? *)) when Meta.has Meta.Generic ef.cf_meta ->
+		check_assign();
 		(match et.eexpr with
 		(match et.eexpr with
 		| TField(ec,fa) ->
 		| TField(ec,fa) ->
 			type_generic_function ctx (ec,fa) el ~using_param:(Some eparam) with_type p
 			type_generic_function ctx (ec,fa) el ~using_param:(Some eparam) with_type p
@@ -559,10 +564,11 @@ let rec build_call ctx acc el (with_type:WithType.t) p =
 		| Method MethMacro ->
 		| Method MethMacro ->
 			let ethis = type_module_type ctx (TClassDecl cl) None p in
 			let ethis = type_module_type ctx (TClassDecl cl) None p in
 			let eparam,f = push_this ctx eparam in
 			let eparam,f = push_this ctx eparam in
-			let e = build_call ctx (AKMacro (ethis,ef)) (eparam :: el) with_type p in
+			let e = build_call ~mode ctx (AKMacro (ethis,ef)) (eparam :: el) with_type p in
 			f();
 			f();
 			e
 			e
 		| _ ->
 		| _ ->
+			check_assign();
 			let t = follow (field_type ctx cl [] ef p) in
 			let t = follow (field_type ctx cl [] ef p) in
 			(* for abstracts we have to apply their parameters to the static function *)
 			(* for abstracts we have to apply their parameters to the static function *)
 			let t,tthis = match follow eparam.etype with
 			let t,tthis = match follow eparam.etype with
@@ -589,11 +595,11 @@ let rec build_call ctx acc el (with_type:WithType.t) p =
 		let f = (match ethis.eexpr with
 		let f = (match ethis.eexpr with
 		| TTypeExpr (TClassDecl c) ->
 		| TTypeExpr (TClassDecl c) ->
 			(match ctx.g.do_macro ctx MExpr c.cl_path cf.cf_name el p with
 			(match ctx.g.do_macro ctx MExpr c.cl_path cf.cf_name el p with
-			| None -> (fun() -> type_expr ctx (EConst (Ident "null"),p) WithType.value)
+			| None -> (fun() -> type_expr ~mode ctx (EConst (Ident "null"),p) WithType.value)
 			| Some (EMeta((Meta.MergeBlock,_,_),(EBlock el,_)),_) -> (fun () -> let e = (!type_block_ref) ctx el with_type p in mk (TMeta((Meta.MergeBlock,[],p), e)) e.etype e.epos)
 			| Some (EMeta((Meta.MergeBlock,_,_),(EBlock el,_)),_) -> (fun () -> let e = (!type_block_ref) ctx el with_type p in mk (TMeta((Meta.MergeBlock,[],p), e)) e.etype e.epos)
-			| Some e -> (fun() -> type_expr ctx e with_type))
+			| Some e -> (fun() -> type_expr ~mode ctx e with_type))
 		| _ ->
 		| _ ->
-			(* member-macro call : since we will make a static call, let's found the actual class and not its subclass *)
+			(* member-macro call : since we will make a static call, let's find the actual class and not its subclass *)
 			(match follow ethis.etype with
 			(match follow ethis.etype with
 			| TInst (c,_) ->
 			| TInst (c,_) ->
 				let rec loop c =
 				let rec loop c =
@@ -601,8 +607,8 @@ let rec build_call ctx acc el (with_type:WithType.t) p =
 						let eparam,f = push_this ctx ethis in
 						let eparam,f = push_this ctx ethis in
 						ethis_f := f;
 						ethis_f := f;
 						let e = match ctx.g.do_macro ctx MExpr c.cl_path cf.cf_name (eparam :: el) p with
 						let e = match ctx.g.do_macro ctx MExpr c.cl_path cf.cf_name (eparam :: el) p with
-							| None -> (fun() -> type_expr ctx (EConst (Ident "null"),p) WithType.value)
-							| Some e -> (fun() -> type_expr ctx e WithType.value)
+							| None -> (fun() -> type_expr ~mode ctx (EConst (Ident "null"),p) WithType.value)
+							| Some e -> (fun() -> type_expr ~mode ctx e WithType.value)
 						in
 						in
 						e
 						e
 					else
 					else

+ 38 - 14
src/typing/fields.ml

@@ -136,7 +136,29 @@ let check_constructor_access ctx c f p =
 	if (Meta.has Meta.CompilerGenerated f.cf_meta) then display_error ctx (error_msg (No_constructor (TClassDecl c))) p;
 	if (Meta.has Meta.CompilerGenerated f.cf_meta) then display_error ctx (error_msg (No_constructor (TClassDecl c))) p;
 	if not (can_access ctx c f true || is_parent c ctx.curclass) && not ctx.untyped then display_error ctx (Printf.sprintf "Cannot access private constructor of %s" (s_class_path c)) p
 	if not (can_access ctx c f true || is_parent c ctx.curclass) && not ctx.untyped then display_error ctx (Printf.sprintf "Cannot access private constructor of %s" (s_class_path c)) p
 
 
+let check_no_closure_meta ctx fa mode p =
+	if mode <> MCall && not (DisplayPosition.display_position#enclosed_in p) then begin
+		let check_field f cl_meta =
+			match f.cf_kind with
+			| Method _ ->
+				if
+					Meta.has Meta.NoClosure cl_meta
+					|| Meta.has Meta.NoClosure f.cf_meta
+				then
+					error ("Method " ^ f.cf_name ^ " cannot be used as a value") p
+			| _ -> ()
+		in
+		match fa with
+		| FStatic (c, ({ cf_kind = Method _} as f)) -> check_field f c.cl_meta
+		| FInstance (c, _, ({ cf_kind = Method _} as f)) -> check_field f c.cl_meta
+		| FClosure (Some (c, _), ({ cf_kind = Method _} as f)) -> check_field f c.cl_meta
+		| FClosure (None, ({ cf_kind = Method _} as f)) -> check_field f []
+		| FAnon ({ cf_kind = Method _} as f) -> check_field f []
+		| _ -> ()
+	end
+
 let field_access ctx mode f fmode t e p =
 let field_access ctx mode f fmode t e p =
+	check_no_closure_meta ctx fmode mode p;
 	let bypass_accessor = if ctx.bypass_accessor > 0 then (ctx.bypass_accessor <- ctx.bypass_accessor - 1; true) else false in
 	let bypass_accessor = if ctx.bypass_accessor > 0 then (ctx.bypass_accessor <- ctx.bypass_accessor - 1; true) else false in
 	let fnormal() = AKExpr (mk (TField (e,fmode)) t p) in
 	let fnormal() = AKExpr (mk (TField (e,fmode)) t p) in
 	let normal() =
 	let normal() =
@@ -330,6 +352,7 @@ let rec using_field ctx mode e i p =
 
 
 (* Resolves field [i] on typed expression [e] using the given [mode]. *)
 (* Resolves field [i] on typed expression [e] using the given [mode]. *)
 let rec type_field cfg ctx e i p mode =
 let rec type_field cfg ctx e i p mode =
+	let pfield = if (e.epos = p) then p else {p with pmin = p.pmax - (String.length i)} in
 	let no_field() =
 	let no_field() =
 		if TypeFieldConfig.do_resume cfg then raise Not_found;
 		if TypeFieldConfig.do_resume cfg then raise Not_found;
 		let t = match follow e.etype with
 		let t = match follow e.etype with
@@ -348,9 +371,9 @@ let rec type_field cfg ctx e i p mode =
 			match t with
 			match t with
 			| TAbstract(a,_) when has_special_field a ->
 			| TAbstract(a,_) when has_special_field a ->
 				(* the abstract field is not part of the field list, which is only true when it has no expression (issue #2344) *)
 				(* the abstract field is not part of the field list, which is only true when it has no expression (issue #2344) *)
-				display_error ctx ("Field " ^ i ^ " cannot be called directly because it has no expression") p;
+				display_error ctx ("Field " ^ i ^ " cannot be called directly because it has no expression") pfield;
 			| _ ->
 			| _ ->
-				display_error ctx (StringError.string_error i (string_source t) (s_type (print_context()) t ^ " has no field " ^ i)) p;
+				display_error ctx (StringError.string_error i (string_source t) (s_type (print_context()) t ^ " has no field " ^ i)) pfield;
 		end;
 		end;
 		AKExpr (mk (TField (e,FDynamic i)) (mk_mono()) p)
 		AKExpr (mk (TField (e,FDynamic i)) (mk_mono()) p)
 	in
 	in
@@ -402,7 +425,7 @@ let rec type_field cfg ctx e i p mode =
 				| MCall,Var {v_read = AccCall } ->
 				| MCall,Var {v_read = AccCall } ->
 					()
 					()
 				| MCall, Var _ ->
 				| MCall, Var _ ->
-					display_error ctx "Cannot access superclass variable for calling: needs to be a proper method" p
+					display_error ctx "Cannot access superclass variable for calling: needs to be a proper method" pfield
 				| MCall, _ ->
 				| MCall, _ ->
 					()
 					()
 				| MGet,Var _
 				| MGet,Var _
@@ -411,8 +434,8 @@ let rec type_field cfg ctx e i p mode =
 				| _, Method _ ->
 				| _, Method _ ->
 					display_error ctx "Cannot create closure on super method" p
 					display_error ctx "Cannot create closure on super method" p
 				| _ ->
 				| _ ->
-					display_error ctx "Normal variables cannot be accessed with 'super', use 'this' instead" p);
-			if not (can_access ctx c f false) && not ctx.untyped then display_error ctx ("Cannot access private field " ^ i) p;
+					display_error ctx "Normal variables cannot be accessed with 'super', use 'this' instead" pfield);
+			if not (can_access ctx c f false) && not ctx.untyped then display_error ctx ("Cannot access private field " ^ i) pfield;
 			field_access ctx mode f (match c2 with None -> FAnon f | Some (c,tl) -> FInstance (c,tl,f)) (apply_params c.cl_params params t) e p
 			field_access ctx mode f (match c2 with None -> FAnon f | Some (c,tl) -> FInstance (c,tl,f)) (apply_params c.cl_params params t) e p
 		with Not_found -> try
 		with Not_found -> try
 			begin match e.eexpr with
 			begin match e.eexpr with
@@ -442,7 +465,7 @@ let rec type_field cfg ctx e i p mode =
 					raise Not_found
 					raise Not_found
 			end
 			end
 		with Not_found ->
 		with Not_found ->
-			if PMap.mem i c.cl_statics then error ("Cannot access static field " ^ i ^ " from a class instance") p;
+			if PMap.mem i c.cl_statics then error ("Cannot access static field " ^ i ^ " from a class instance") pfield;
 			no_field())
 			no_field())
 	| TDynamic t ->
 	| TDynamic t ->
 		(try
 		(try
@@ -452,12 +475,12 @@ let rec type_field cfg ctx e i p mode =
 	| TAnon a ->
 	| TAnon a ->
 		(try
 		(try
 			let f = PMap.find i a.a_fields in
 			let f = PMap.find i a.a_fields in
-			if Meta.has Meta.Impl f.cf_meta && not (Meta.has Meta.Enum f.cf_meta) then display_error ctx "Cannot access non-static abstract field statically" p;
+			if Meta.has Meta.Impl f.cf_meta && not (Meta.has Meta.Enum f.cf_meta) then display_error ctx "Cannot access non-static abstract field statically" pfield;
 			if not (has_class_field_flag f CfPublic) && not ctx.untyped then begin
 			if not (has_class_field_flag f CfPublic) && not ctx.untyped then begin
 				match !(a.a_status) with
 				match !(a.a_status) with
 				| Closed | Extend _ -> () (* always allow anon private fields access *)
 				| Closed | Extend _ -> () (* always allow anon private fields access *)
 				| Statics c when can_access ctx c f true -> ()
 				| Statics c when can_access ctx c f true -> ()
-				| _ -> display_error ctx ("Cannot access private field " ^ i) p
+				| _ -> display_error ctx ("Cannot access private field " ^ i) pfield
 			end;
 			end;
 			let fmode, ft = (match !(a.a_status) with
 			let fmode, ft = (match !(a.a_status) with
 				| Statics c -> FStatic (c,f), field_type ctx c [] f p
 				| Statics c -> FStatic (c,f), field_type ctx c [] f p
@@ -510,7 +533,7 @@ let rec type_field cfg ctx e i p mode =
 		(try
 		(try
 			let c = (match a.a_impl with None -> raise Not_found | Some c -> c) in
 			let c = (match a.a_impl with None -> raise Not_found | Some c -> c) in
 			let f = PMap.find i c.cl_statics in
 			let f = PMap.find i c.cl_statics in
-			if not (can_access ctx c f true) && not ctx.untyped then display_error ctx ("Cannot access private field " ^ i) p;
+			if not (can_access ctx c f true) && not ctx.untyped then display_error ctx ("Cannot access private field " ^ i) pfield;
 			let field_type f =
 			let field_type f =
 				if not (Meta.has Meta.Impl f.cf_meta) then begin
 				if not (Meta.has Meta.Impl f.cf_meta) then begin
 					static_abstract_access_through_instance := true;
 					static_abstract_access_through_instance := true;
@@ -538,7 +561,7 @@ let rec type_field cfg ctx e i p mode =
 				AKNo f.cf_name
 				AKNo f.cf_name
 			| (MGet | MCall), _ ->
 			| (MGet | MCall), _ ->
 				let rec loop cfl = match cfl with
 				let rec loop cfl = match cfl with
-					| [] -> error (Printf.sprintf "Field %s cannot be called on %s" f.cf_name (s_type (print_context()) e.etype)) p
+					| [] -> error (Printf.sprintf "Field %s cannot be called on %s" f.cf_name (s_type (print_context()) e.etype)) pfield
 					| cf :: cfl ->
 					| cf :: cfl ->
 						match follow (apply_params a.a_params pl (monomorphs cf.cf_params cf.cf_type)) with
 						match follow (apply_params a.a_params pl (monomorphs cf.cf_params cf.cf_type)) with
 							| TFun((_,_,t1) :: _,_) when type_iseq t1 (Abstract.get_underlying_type a pl) ->
 							| TFun((_,_,t1) :: _,_) when type_iseq t1 (Abstract.get_underlying_type a pl) ->
@@ -553,7 +576,7 @@ let rec type_field cfg ctx e i p mode =
 				let t = field_type f in
 				let t = field_type f in
 				begin match follow t with
 				begin match follow t with
 					| TFun((_,_,t1) :: _,_) -> ()
 					| TFun((_,_,t1) :: _,_) -> ()
-					| _ -> error ("Invalid call to static function " ^ i ^ " through abstract instance") p
+					| _ -> error ("Invalid call to static function " ^ i ^ " through abstract instance") pfield
 				end;
 				end;
 				let ef = field_expr f t in
 				let ef = field_expr f t in
 				AKUsing (ef,c,f,e,false)
 				AKUsing (ef,c,f,e,false)
@@ -561,7 +584,8 @@ let rec type_field cfg ctx e i p mode =
 				error "This operation is unsupported" p)
 				error "This operation is unsupported" p)
 		with Not_found -> try
 		with Not_found -> try
 			if does_forward a false then
 			if does_forward a false then
-				type_field (TypeFieldConfig.with_resume cfg) ctx {e with etype = apply_params a.a_params pl a.a_this} i p mode
+				let underlying_type = Abstract.get_underlying_type ~return_first:true a pl in
+				type_field (TypeFieldConfig.with_resume cfg) ctx {e with etype = underlying_type} i p mode
 			else
 			else
 				raise Not_found
 				raise Not_found
 		with Not_found -> try
 		with Not_found -> try
@@ -591,9 +615,9 @@ let rec type_field cfg ctx e i p mode =
 			if not (TypeFieldConfig.allow_resolve cfg) then raise Not_found;
 			if not (TypeFieldConfig.allow_resolve cfg) then raise Not_found;
 			get_resolve (mode = MSet)
 			get_resolve (mode = MSet)
 		with Not_found ->
 		with Not_found ->
-			if !static_abstract_access_through_instance then error ("Invalid call to static function " ^ i ^ " through abstract instance") p
+			if !static_abstract_access_through_instance then error ("Invalid call to static function " ^ i ^ " through abstract instance") pfield
 			else no_field())
 			else no_field())
 	| _ ->
 	| _ ->
 		try using_field ctx mode e i p with Not_found -> no_field()
 		try using_field ctx mode e i p with Not_found -> no_field()
 
 
-let type_field_default_cfg = type_field TypeFieldConfig.default
+let type_field_default_cfg = type_field TypeFieldConfig.default

+ 6 - 1
src/typing/forLoop.ml

@@ -440,7 +440,12 @@ let type_for_loop ctx handle_display it e2 p =
 			end
 			end
 		| EDisplay(e1,dk) -> loop (Some dk) e1
 		| EDisplay(e1,dk) -> loop (Some dk) e1
 		| EBinop(OpArrow,ei1,(EBinop(OpIn,ei2,e2),_)) -> IKKeyValue(loop_ident None ei1,loop_ident None ei2),e2
 		| EBinop(OpArrow,ei1,(EBinop(OpIn,ei2,e2),_)) -> IKKeyValue(loop_ident None ei1,loop_ident None ei2),e2
-		| _ -> error "For expression should be 'v in expr'" (snd it)
+		| _ ->
+			begin match dko with
+			| Some dk -> ignore(handle_display ctx e1 dk WithType.value);
+			| None -> ()
+			end;
+			error "For expression should be 'v in expr'" (snd it)
 	in
 	in
 	let ik,e1 = loop None it in
 	let ik,e1 = loop None it in
 	let e1 = type_expr ctx e1 WithType.value in
 	let e1 = type_expr ctx e1 WithType.value in

+ 2 - 2
src/typing/macroContext.ml

@@ -197,13 +197,13 @@ let make_macro_api ctx p =
 			)
 			)
 		);
 		);
 		MacroApi.on_type_not_found = (fun f ->
 		MacroApi.on_type_not_found = (fun f ->
-			ctx.com.load_extern_type <- ctx.com.load_extern_type @ [fun path p ->
+			ctx.com.load_extern_type <- ctx.com.load_extern_type @ ["onTypeNotFound",fun path p ->
 				let td = f (s_type_path path) in
 				let td = f (s_type_path path) in
 				if td = Interp.vnull then
 				if td = Interp.vnull then
 					None
 					None
 				else
 				else
 					let (pack,name),tdef,p = Interp.decode_type_def td in
 					let (pack,name),tdef,p = Interp.decode_type_def td in
-					Some (name,(pack,[tdef,p]))
+					Some (pack,[tdef,p])
 			];
 			];
 		);
 		);
 		MacroApi.parse_string = parse_expr_string;
 		MacroApi.parse_string = parse_expr_string;

+ 11 - 14
src/typing/matcher.ml

@@ -39,7 +39,7 @@ let make_offset_list left right middle other =
 	(ExtList.List.make left other) @ [middle] @ (ExtList.List.make right other)
 	(ExtList.List.make left other) @ [middle] @ (ExtList.List.make right other)
 
 
 let type_field_access ctx ?(resume=false) e name =
 let type_field_access ctx ?(resume=false) e name =
-	Calls.acc_get ctx (Fields.type_field (Fields.TypeFieldConfig.create resume) ctx e name e.epos TyperBase.MGet) e.epos
+	Calls.acc_get ctx (Fields.type_field (Fields.TypeFieldConfig.create resume) ctx e name e.epos MGet) e.epos
 
 
 let unapply_type_parameters params monos =
 let unapply_type_parameters params monos =
 	List.iter2 (fun (_,t1) t2 -> match t2,follow t2 with TMono m1,TMono m2 when m1 == m2 -> Type.unify t1 t2 | _ -> ()) params monos
 	List.iter2 (fun (_,t1) t2 -> match t2,follow t2 with TMono m1,TMono m2 when m1 == m2 -> Type.unify t1 t2 | _ -> ()) params monos
@@ -238,15 +238,7 @@ module Pattern = struct
 					PatConstructor(con_type_expr mt e.epos,[])
 					PatConstructor(con_type_expr mt e.epos,[])
 				| _ ->
 				| _ ->
 					let pat = check_expr e in
 					let pat = check_expr e in
-					begin try
-						Type.unify e.etype t
-					with (Unify_error l) ->
-						(* Hack: Allow matching the underlying type against its abstract. *)
-						begin match follow e.etype with
-							| TAbstract(a,tl) when not (Meta.has Meta.CoreType a.a_meta) && type_iseq t (Abstract.get_underlying_type a tl) -> ()
-							| _ -> raise_or_display ctx l p
-						end
-					end;
+					unify ctx e.etype t p;
 					pat
 					pat
 		in
 		in
 		let handle_ident s p =
 		let handle_ident s p =
@@ -1549,9 +1541,13 @@ module Match = struct
 			| None -> cases
 			| None -> cases
 			| Some (eo,p) -> cases @ [[EConst (Ident "_"),p],None,eo,p]
 			| Some (eo,p) -> cases @ [[EConst (Ident "_"),p],None,eo,p]
 		in
 		in
-		let tmono,with_type = match with_type with
-			| WithType.WithType(t,_) -> (match follow t with TMono _ -> Some t,WithType.value | _ -> None,with_type)
-			| _ -> None,with_type
+		let tmono,with_type,allow_min_void = match with_type with
+			| WithType.WithType(t,src) ->
+				(match follow t, src with
+				| TMono _, Some ImplicitReturn -> Some t, WithType.Value src, true
+				| TMono _, _ -> Some t,WithType.value,false
+				| _ -> None,with_type,false)
+			| _ -> None,with_type,false
 		in
 		in
 		let cases = List.map (fun (el,eg,eo,p) ->
 		let cases = List.map (fun (el,eg,eo,p) ->
 			let p = match eo with Some e when p = null_pos -> pos e | _ -> p in
 			let p = match eo with Some e when p = null_pos -> pos e | _ -> p in
@@ -1580,7 +1576,8 @@ module Match = struct
 								(* If we have no block we have to use the `case pattern` position because that's all we have. *)
 								(* If we have no block we have to use the `case pattern` position because that's all we have. *)
 								mk (TBlock []) ctx.t.tvoid case.Case.case_pos
 								mk (TBlock []) ctx.t.tvoid case.Case.case_pos
 						) cases in
 						) cases in
-						unify_min ctx el
+						if allow_min_void then unify_min_for_type_source ctx el (Some WithType.ImplicitReturn)
+						else unify_min ctx el
 					end
 					end
 				| WithType.WithType(t,_) -> t
 				| WithType.WithType(t,_) -> t
 		in
 		in

+ 26 - 16
src/typing/nullSafety.ml

@@ -947,22 +947,32 @@ class expr_checker mode immediate_execution report =
 			E.g.: `Array<Null<String>>` vs `Array<String>` returns `true`, but also adds a compilation error.
 			E.g.: `Array<Null<String>>` vs `Array<String>` returns `true`, but also adds a compilation error.
 		*)
 		*)
 		method can_pass_expr expr to_type p =
 		method can_pass_expr expr to_type p =
-			if self#is_nullable_expr expr && not (is_nullable_type to_type) then
-				false
-			else begin
-				let expr_type = unfold_null expr.etype in
-				try
-					new unificator#unify expr_type to_type;
-					true
-				with
-					| Safety_error err ->
-						self#error ("Cannot unify " ^ (str_type expr_type) ^ " with " ^ (str_type to_type)) [p; expr.epos];
-						(* returning `true` because error is already logged in the line above *)
-						true
-					| e ->
-						fail ~msg:"Null safety unification failure" expr.epos __POS__
-				(* can_pass_type expr.etype to_type *)
-			end
+			match expr.eexpr, to_type with
+				| TObjectDecl fields, TAnon to_type ->
+					List.for_all
+						(fun ((name, _, _), field_expr) ->
+							try
+								let field_to_type = PMap.find name to_type.a_fields in
+								self#can_pass_expr field_expr field_to_type.cf_type p
+							with Not_found -> false)
+						fields
+				| _, _ ->
+					if self#is_nullable_expr expr && not (is_nullable_type to_type) then
+						false
+					else begin
+						let expr_type = unfold_null expr.etype in
+						try
+							new unificator#unify expr_type to_type;
+							true
+						with
+							| Safety_error err ->
+								self#error ("Cannot unify " ^ (str_type expr_type) ^ " with " ^ (str_type to_type)) [p; expr.epos];
+								(* returning `true` because error is already logged in the line above *)
+								true
+							| e ->
+								fail ~msg:"Null safety unification failure" expr.epos __POS__
+						(* can_pass_type expr.etype to_type *)
+					end
 		(**
 		(**
 			Should be called for the root expressions of a method or for then initialization expressions of fields.
 			Should be called for the root expressions of a method or for then initialization expressions of fields.
 		*)
 		*)

+ 10 - 11
src/typing/typeload.ml

@@ -254,7 +254,7 @@ let rec load_instance' ctx (t,p) allow_no_params =
 							| _,[EConst(String s),_],_ -> s
 							| _,[EConst(String s),_],_ -> s
 							| _ -> "This typedef is deprecated in favor of " ^ (s_type (print_context()) td.t_type)
 							| _ -> "This typedef is deprecated in favor of " ^ (s_type (print_context()) td.t_type)
 						in
 						in
-						ctx.com.warning msg p
+						DeprecationCheck.warn_deprecation ctx.com msg p
 					with Not_found ->
 					with Not_found ->
 						()
 						()
 					end;
 					end;
@@ -355,7 +355,7 @@ and load_instance ctx ?(allow_display=false) (t,pn) allow_no_params =
 		t
 		t
 	with Error (Module_not_found path,_) when (ctx.com.display.dms_kind = DMDefault) && DisplayPosition.display_position#enclosed_in pn ->
 	with Error (Module_not_found path,_) when (ctx.com.display.dms_kind = DMDefault) && DisplayPosition.display_position#enclosed_in pn ->
 		let s = s_type_path path in
 		let s = s_type_path path in
-		raise_fields (DisplayToplevel.collect ctx TKType NoValue) CRTypeHint (Some {pn with pmin = pn.pmax - String.length s;});
+		DisplayToplevel.collect_and_raise ctx TKType NoValue CRTypeHint (s,pn) (Some {pn with pmin = pn.pmax - String.length s;})
 
 
 (*
 (*
 	build an instance from a complex type
 	build an instance from a complex type
@@ -370,12 +370,12 @@ and load_complex_type' ctx allow_display (t,p) =
 		let tl = List.map (fun (t,pn) ->
 		let tl = List.map (fun (t,pn) ->
 			try
 			try
 				load_complex_type ctx allow_display (t,pn)
 				load_complex_type ctx allow_display (t,pn)
-			with DisplayException(DisplayFields Some(l,CRTypeHint,p)) ->
+			with DisplayException(DisplayFields Some({fkind = CRTypeHint} as r)) ->
 				let l = List.filter (fun item -> match item.ci_kind with
 				let l = List.filter (fun item -> match item.ci_kind with
 					| ITType({kind = Struct},_) -> true
 					| ITType({kind = Struct},_) -> true
 					| _ -> false
 					| _ -> false
-				) l in
-				raise_fields l (CRStructExtension true) p
+				) r.fitems in
+				raise_fields l (CRStructExtension true) r.finsert_pos
 		) tl in
 		) tl in
 		let tr = ref None in
 		let tr = ref None in
 		let t = TMono tr in
 		let t = TMono tr in
@@ -412,12 +412,12 @@ and load_complex_type' ctx allow_display (t,p) =
 			let il = List.map (fun (t,pn) ->
 			let il = List.map (fun (t,pn) ->
 				try
 				try
 					load_instance ctx ~allow_display (t,pn) false
 					load_instance ctx ~allow_display (t,pn) false
-				with DisplayException(DisplayFields Some(l,CRTypeHint,p)) ->
+				with DisplayException(DisplayFields Some({fkind = CRTypeHint} as r)) ->
 					let l = List.filter (fun item -> match item.ci_kind with
 					let l = List.filter (fun item -> match item.ci_kind with
 						| ITType({kind = Struct},_) -> true
 						| ITType({kind = Struct},_) -> true
 						| _ -> false
 						| _ -> false
-					) l in
-					raise_fields l (CRStructExtension false) p
+					) r.fitems in
+					raise_fields l (CRStructExtension false) r.finsert_pos
 			) tl in
 			) tl in
 			let tr = ref None in
 			let tr = ref None in
 			let t = TMono tr in
 			let t = TMono tr in
@@ -845,9 +845,8 @@ let handle_path_display ctx path p =
 		DisplayEmitter.display_field ctx origin CFSStatic cf p
 		DisplayEmitter.display_field ctx origin CFSStatic cf p
 	in
 	in
 	match ImportHandling.convert_import_to_something_usable DisplayPosition.display_position#get path,ctx.com.display.dms_kind with
 	match ImportHandling.convert_import_to_something_usable DisplayPosition.display_position#get path,ctx.com.display.dms_kind with
-		| (IDKPackage [_],p),DMDefault ->
-			let fields = DisplayToplevel.collect ctx TKType WithType.no_value in
-			raise_fields fields CRImport (Some p)
+		| (IDKPackage [s],p),DMDefault ->
+			DisplayToplevel.collect_and_raise ctx TKType WithType.no_value CRImport (s,p) (Some p)
 		| (IDKPackage sl,p),DMDefault ->
 		| (IDKPackage sl,p),DMDefault ->
 			let sl = match List.rev sl with
 			let sl = match List.rev sl with
 				| s :: sl -> List.rev sl
 				| s :: sl -> List.rev sl

+ 34 - 4
src/typing/typeloadCheck.ml

@@ -130,6 +130,35 @@ let copy_meta meta_src meta_target sl =
 	) meta_src;
 	) meta_src;
 	!meta
 	!meta
 
 
+(** retrieve string from @:native metadata or raise Not_found *)
+let get_native_name meta =
+	let rec get_native meta = match meta with
+		| [] -> raise Not_found
+		| (Meta.Native,[v],p as meta) :: _ ->
+			meta
+		| _ :: meta ->
+			get_native meta
+	in
+	let (_,e,mp) = get_native meta in
+	match e with
+	| [Ast.EConst (Ast.String name),p] ->
+		name,p
+	| [] ->
+		raise Not_found
+	| _ ->
+		error "String expected" mp
+
+let check_native_name_override ctx child base =
+	let error() =
+		display_error ctx ("Field " ^ child.cf_name ^ " has different @:native value than in superclass") child.cf_pos;
+		display_error ctx ("Base field is defined here") base.cf_pos
+	in
+	try
+		let native_name = fst (get_native_name child.cf_meta) in
+		try if fst (get_native_name base.cf_meta) <> native_name then error()
+		with Not_found -> error()
+	with Not_found -> ()
+
 let check_overriding ctx c f =
 let check_overriding ctx c f =
 	match c.cl_super with
 	match c.cl_super with
 	| None ->
 	| None ->
@@ -142,6 +171,7 @@ let check_overriding ctx c f =
 			(if is_overload && not (Meta.has Meta.Overload f.cf_meta) then
 			(if is_overload && not (Meta.has Meta.Overload f.cf_meta) then
 				display_error ctx ("Missing @:overload declaration for field " ^ i) p);
 				display_error ctx ("Missing @:overload declaration for field " ^ i) p);
 			let t, f2 = get_super_field csup i in
 			let t, f2 = get_super_field csup i in
+			check_native_name_override ctx f f2;
 			(* allow to define fields that are not defined for this platform version in superclass *)
 			(* allow to define fields that are not defined for this platform version in superclass *)
 			(match f2.cf_kind with
 			(match f2.cf_kind with
 			| Var { v_read = AccRequire _ } -> raise Not_found;
 			| Var { v_read = AccRequire _ } -> raise Not_found;
@@ -471,9 +501,9 @@ module Inheritance = struct
 			try
 			try
 				let t = try
 				let t = try
 					Typeload.load_instance ~allow_display:true ctx (ct,p) false
 					Typeload.load_instance ~allow_display:true ctx (ct,p) false
-				with DisplayException(DisplayFields Some(l,CRTypeHint,p)) ->
+				with DisplayException(DisplayFields Some({fkind = CRTypeHint} as r)) ->
 					(* We don't allow `implements` on interfaces. Just raise fields completion with no fields. *)
 					(* We don't allow `implements` on interfaces. Just raise fields completion with no fields. *)
-					if not is_extends && c.cl_interface then raise_fields [] CRImplements p;
+					if not is_extends && c.cl_interface then raise_fields [] CRImplements r.finsert_pos;
 					let l = List.filter (fun item -> match item.ci_kind with
 					let l = List.filter (fun item -> match item.ci_kind with
 						| ITType({kind = Interface} as cm,_) -> (not is_extends || c.cl_interface) && CompletionModuleType.get_path cm <> c.cl_path
 						| ITType({kind = Interface} as cm,_) -> (not is_extends || c.cl_interface) && CompletionModuleType.get_path cm <> c.cl_path
 						| ITType({kind = Class} as cm,_) ->
 						| ITType({kind = Class} as cm,_) ->
@@ -481,8 +511,8 @@ module Inheritance = struct
 							(not cm.is_final || Meta.has Meta.Hack c.cl_meta) &&
 							(not cm.is_final || Meta.has Meta.Hack c.cl_meta) &&
 							(not (is_basic_class_path (cm.pack,cm.name)) || (c.cl_extern && cm.is_extern))
 							(not (is_basic_class_path (cm.pack,cm.name)) || (c.cl_extern && cm.is_extern))
 						| _ -> false
 						| _ -> false
-					) l in
-					raise_fields l (if is_extends then CRExtends else CRImplements) p
+					) r.fitems in
+					raise_fields l (if is_extends then CRExtends else CRImplements) r.finsert_pos
 				in
 				in
 				Some (check_herit t is_extends p)
 				Some (check_herit t is_extends p)
 			with Error(Module_not_found(([],name)),p) when ctx.com.display.dms_kind <> DMNone ->
 			with Error(Module_not_found(([],name)),p) when ctx.com.display.dms_kind <> DMNone ->

+ 10 - 6
src/typing/typeloadFields.ml

@@ -217,6 +217,10 @@ let transform_abstract_field com this_t a_t a f =
 			if fu.f_expr <> None then error "MultiType constructors cannot have a body" f.cff_pos;
 			if fu.f_expr <> None then error "MultiType constructors cannot have a body" f.cff_pos;
 			f.cff_access <- (AExtern,null_pos) :: f.cff_access;
 			f.cff_access <- (AExtern,null_pos) :: f.cff_access;
 		end;
 		end;
+		(try
+			let _, p = List.find (fun (acc, _) -> acc = AMacro) f.cff_access in
+			error "Macro abstract constructors are not supported" p
+		with Not_found -> ());
 		(* We don't want the generated expression positions to shadow the real code. *)
 		(* We don't want the generated expression positions to shadow the real code. *)
 		let p = { p with pmax = p.pmin } in
 		let p = { p with pmax = p.pmin } in
 		let fu = {
 		let fu = {
@@ -856,7 +860,8 @@ let check_abstract (ctx,cctx,fctx) c cf fd t ret p =
 			let ta = TAbstract(a, List.map (fun _ -> mk_mono()) a.a_params) in
 			let ta = TAbstract(a, List.map (fun _ -> mk_mono()) a.a_params) in
 			let tthis = if fctx.is_abstract_member || Meta.has Meta.To cf.cf_meta then monomorphs a.a_params a.a_this else a.a_this in
 			let tthis = if fctx.is_abstract_member || Meta.has Meta.To cf.cf_meta then monomorphs a.a_params a.a_this else a.a_this in
 			let allows_no_expr = ref (Meta.has Meta.CoreType a.a_meta) in
 			let allows_no_expr = ref (Meta.has Meta.CoreType a.a_meta) in
-			let rec loop ml = match ml with
+			let rec loop ml =
+				(match ml with
 				| (Meta.From,_,_) :: _ ->
 				| (Meta.From,_,_) :: _ ->
 					let r = exc_protect ctx (fun r ->
 					let r = exc_protect ctx (fun r ->
 						r := lazy_processing (fun () -> t);
 						r := lazy_processing (fun () -> t);
@@ -935,7 +940,6 @@ let check_abstract (ctx,cctx,fctx) c cf fd t ret p =
 						| _ ->
 						| _ ->
 							display_error ctx ("First argument of implementation function must be " ^ (s_type (print_context()) tthis)) cf.cf_pos
 							display_error ctx ("First argument of implementation function must be " ^ (s_type (print_context()) tthis)) cf.cf_pos
 					end;
 					end;
-					loop ml
 				| ((Meta.Resolve,_,_) | (Meta.Op,[EField _,_],_)) :: _ ->
 				| ((Meta.Resolve,_,_) | (Meta.Op,[EField _,_],_)) :: _ ->
 					let targ = if fctx.is_abstract_member then tthis else ta in
 					let targ = if fctx.is_abstract_member then tthis else ta in
 					let check_fun t1 t2 =
 					let check_fun t1 t2 =
@@ -956,10 +960,10 @@ let check_abstract (ctx,cctx,fctx) c cf fd t ret p =
 						| _ ->
 						| _ ->
 							error ("Field type of resolve must be " ^ (s_type (print_context()) targ) ^ " -> String -> T") cf.cf_pos
 							error ("Field type of resolve must be " ^ (s_type (print_context()) targ) ^ " -> String -> T") cf.cf_pos
 					end;
 					end;
-				| _ :: ml ->
-					loop ml
-				| [] ->
-					()
+				| _ -> ());
+				match ml with
+				| _ :: ml -> loop ml
+				| [] -> ()
 			in
 			in
 			loop cf.cf_meta;
 			loop cf.cf_meta;
 			let check_bind () =
 			let check_bind () =

+ 1 - 8
src/typing/typeloadFunction.ml

@@ -128,14 +128,7 @@ let type_function ctx args ret fmode f do_display p =
 		if is_display_debug then print_endline ("before processing:\n" ^ (Expr.dump_with_pos e));
 		if is_display_debug then print_endline ("before processing:\n" ^ (Expr.dump_with_pos e));
 		let e = if !Parser.had_resume then e else Display.ExprPreprocessing.process_expr ctx.com e in
 		let e = if !Parser.had_resume then e else Display.ExprPreprocessing.process_expr ctx.com e in
 		if is_display_debug then print_endline ("after processing:\n" ^ (Expr.dump_with_pos e));
 		if is_display_debug then print_endline ("after processing:\n" ^ (Expr.dump_with_pos e));
-		try
-			if Common.defined ctx.com Define.NoCOpt || not !Parser.had_resume then raise Exit;
-			let e = Optimizer.optimize_completion_expr e f.f_args in
-			if is_display_debug then print_endline ("after optimizing:\n" ^ (Expr.dump_with_pos e));
-			type_expr ctx e NoValue
-		with
-		| Parser.TypePath (_,None,_,_) | Exit ->
-			type_expr ctx e NoValue
+		type_expr ctx e NoValue
 	end in
 	end in
 	let e = match e.eexpr with
 	let e = match e.eexpr with
 		| TMeta((Meta.MergeBlock,_,_), ({eexpr = TBlock el} as e1)) -> e1
 		| TMeta((Meta.MergeBlock,_,_), ({eexpr = TBlock el} as e1)) -> e1

+ 11 - 5
src/typing/typeloadModule.ml

@@ -771,10 +771,16 @@ let init_module_type ctx context_init do_init (decl,p) =
 				if Meta.has Meta.CoreType a.a_meta then error "@:coreType abstracts cannot have an underlying type" p;
 				if Meta.has Meta.CoreType a.a_meta then error "@:coreType abstracts cannot have an underlying type" p;
 				let at = load_complex_type ctx true t in
 				let at = load_complex_type ctx true t in
 				delay ctx PForce (fun () ->
 				delay ctx PForce (fun () ->
-					begin match follow at with
-						| TAbstract(a2,_) when a == a2 -> error "Abstract underlying type cannot be recursive" a.a_pos
+					let rec loop stack t =
+						match follow t with
+						| TAbstract(a,_) when not (Meta.has Meta.CoreType a.a_meta) ->
+							if List.memq a stack then
+								error "Abstract underlying type cannot be recursive" a.a_pos
+							else
+								loop (a :: stack) a.a_this
 						| _ -> ()
 						| _ -> ()
-					end;
+					in
+					loop [] at
 				);
 				);
 				a.a_this <- at;
 				a.a_this <- at;
 				is_type := true;
 				is_type := true;
@@ -958,10 +964,10 @@ let load_module ctx m p =
 				let rec loop = function
 				let rec loop = function
 					| [] ->
 					| [] ->
 						raise (Error (Module_not_found m,p))
 						raise (Error (Module_not_found m,p))
-					| load :: l ->
+					| (file,load) :: l ->
 						match load m p with
 						match load m p with
 						| None -> loop l
 						| None -> loop l
-						| Some (file,(_,a)) -> file, a
+						| Some (_,a) -> file, a
 				in
 				in
 				is_extern := true;
 				is_extern := true;
 				loop ctx.com.load_extern_type
 				loop ctx.com.load_extern_type

+ 7 - 3
src/typing/typeloadParse.ml

@@ -144,9 +144,7 @@ let resolve_module_file com m remap p =
 	let timer = Timer.timer ["typing";"resolve_module_file"] in
 	let timer = Timer.timer ["typing";"resolve_module_file"] in
 	Std.finally timer (resolve_module_file com m remap) p *)
 	Std.finally timer (resolve_module_file com m remap) p *)
 
 
-let parse_module' com m p =
-	let remap = ref (fst m) in
-	let file = resolve_module_file com m remap p in
+let parse_module_file com file p =
 	let handle_parser_error msg p =
 	let handle_parser_error msg p =
 		let msg = Parser.error_msg msg in
 		let msg = Parser.error_msg msg in
 		match com.display.dms_error_policy with
 		match com.display.dms_error_policy with
@@ -166,6 +164,12 @@ let parse_module' com m p =
 			handle_parser_error msg p;
 			handle_parser_error msg p;
 			data
 			data
 	in
 	in
+	pack,decls
+
+let parse_module' com m p =
+	let remap = ref (fst m) in
+	let file = resolve_module_file com m remap p in
+	let pack,decls = parse_module_file com file p in
 	file,remap,pack,decls
 	file,remap,pack,decls
 
 
 let parse_module ctx m p =
 let parse_module ctx m p =

+ 115 - 57
src/typing/typer.ml

@@ -42,7 +42,7 @@ let check_assign ctx e =
 	| TConst TThis | TTypeExpr _ when ctx.untyped ->
 	| TConst TThis | TTypeExpr _ when ctx.untyped ->
 		()
 		()
 	| _ ->
 	| _ ->
-		error "Invalid assign" e.epos
+		invalid_assign e.epos
 
 
 type type_class =
 type type_class =
 	| KInt
 	| KInt
@@ -51,7 +51,8 @@ type type_class =
 	| KUnk
 	| KUnk
 	| KDyn
 	| KDyn
 	| KOther
 	| KOther
-	| KParam of t
+	| KNumParam of t
+	| KStrParam of t
 	| KAbstract of tabstract * t list
 	| KAbstract of tabstract * t list
 
 
 let rec classify t =
 let rec classify t =
@@ -60,8 +61,10 @@ let rec classify t =
 	| TAbstract({a_impl = Some _} as a,tl) -> KAbstract (a,tl)
 	| TAbstract({a_impl = Some _} as a,tl) -> KAbstract (a,tl)
 	| TAbstract ({ a_path = [],"Int" },[]) -> KInt
 	| TAbstract ({ a_path = [],"Int" },[]) -> KInt
 	| TAbstract ({ a_path = [],"Float" },[]) -> KFloat
 	| TAbstract ({ a_path = [],"Float" },[]) -> KFloat
-	| TAbstract (a,[]) when List.exists (fun t -> match classify t with KInt | KFloat -> true | _ -> false) a.a_to -> KParam t
-	| TInst ({ cl_kind = KTypeParameter ctl },_) when List.exists (fun t -> match classify t with KInt | KFloat -> true | _ -> false) ctl -> KParam t
+	| TAbstract (a,[]) when List.exists (fun t -> match classify t with KInt | KFloat -> true | _ -> false) a.a_to -> KNumParam t
+	| TInst ({ cl_kind = KTypeParameter ctl },_) when List.exists (fun t -> match classify t with KInt | KFloat -> true | _ -> false) ctl -> KNumParam t
+	| TAbstract (a,[]) when List.exists (fun t -> match classify t with KString -> true | _ -> false) a.a_to -> KStrParam t
+	| TInst ({ cl_kind = KTypeParameter ctl },_) when List.exists (fun t -> match classify t with KString -> true | _ -> false) ctl -> KStrParam t
 	| TMono r when !r = None -> KUnk
 	| TMono r when !r = None -> KUnk
 	| TDynamic _ -> KDyn
 	| TDynamic _ -> KDyn
 	| _ -> KOther
 	| _ -> KOther
@@ -107,7 +110,7 @@ let maybe_type_against_enum ctx f with_type iscall p =
 				| TAbstract (a,pl) when not (Meta.has Meta.CoreType a.a_meta) ->
 				| TAbstract (a,pl) when not (Meta.has Meta.CoreType a.a_meta) ->
 					begin match get_abstract_froms a pl with
 					begin match get_abstract_froms a pl with
 						| [t2] ->
 						| [t2] ->
-							if (List.exists (fast_eq t) stack) then raise Exit;
+							if (List.exists (fast_eq_anon ~mono_equals_dynamic:true t) stack) then raise Exit;
 							loop (t :: stack) t2
 							loop (t :: stack) t2
 						| _ -> raise Exit
 						| _ -> raise Exit
 					end
 					end
@@ -283,6 +286,13 @@ let unify_min ctx el =
 		if not ctx.untyped then display_error ctx (error_msg (Unify l)) p;
 		if not ctx.untyped then display_error ctx (error_msg (Unify l)) p;
 		(List.hd el).etype
 		(List.hd el).etype
 
 
+let unify_min_for_type_source ctx el src =
+	match src with
+	| Some WithType.ImplicitReturn when List.exists (fun e -> ExtType.is_void (follow e.etype)) el ->
+		ctx.com.basic.tvoid
+	| _ ->
+		unify_min ctx el
+
 let rec type_ident_raise ctx i p mode =
 let rec type_ident_raise ctx i p mode =
 	match i with
 	match i with
 	| "true" ->
 	| "true" ->
@@ -695,7 +705,7 @@ and type_binop2 ?(abstract_overload_only=false) ctx op (e1 : texpr) (e2 : Ast.ex
 			| KAbstract ({a_impl = Some c},_) when PMap.mem "toString" c.cl_statics ->
 			| KAbstract ({a_impl = Some c},_) when PMap.mem "toString" c.cl_statics ->
 				call_to_string ctx e
 				call_to_string ctx e
 			| KInt | KFloat | KString -> e
 			| KInt | KFloat | KString -> e
-			| KUnk | KDyn | KParam _ | KOther ->
+			| KUnk | KDyn | KNumParam _ | KStrParam _ | KOther ->
 				let std = type_type ctx ([],"Std") e.epos in
 				let std = type_type ctx ([],"Std") e.epos in
 				let acc = acc_get ctx (type_field_default_cfg ctx std "string" e.epos MCall) e.epos in
 				let acc = acc_get ctx (type_field_default_cfg ctx std "string" e.epos MCall) e.epos in
 				ignore(follow acc.etype);
 				ignore(follow acc.etype);
@@ -749,18 +759,21 @@ and type_binop2 ?(abstract_overload_only=false) ctx op (e1 : texpr) (e2 : Ast.ex
 			let ok1 = unify_int ctx e1 KUnk in
 			let ok1 = unify_int ctx e1 KUnk in
 			let ok2 = unify_int ctx e2 KUnk in
 			let ok2 = unify_int ctx e2 KUnk in
 			if ok1 && ok2 then tint else tfloat
 			if ok1 && ok2 then tint else tfloat
-		| KParam t1, KParam t2 when Type.type_iseq t1 t2 ->
+		| KNumParam t1, KNumParam t2 when Type.type_iseq t1 t2 ->
 			t1
 			t1
-		| KParam t, KInt | KInt, KParam t ->
+		| KNumParam t, KInt | KInt, KNumParam t ->
 			t
 			t
-		| KParam _, KFloat | KFloat, KParam _ | KParam _, KParam _ ->
+		| KNumParam _, KFloat | KFloat, KNumParam _ | KNumParam _, KNumParam _ ->
 			tfloat
 			tfloat
-		| KParam t, KUnk ->
+		| KNumParam t, KUnk ->
 			unify ctx e2.etype tfloat e2.epos;
 			unify ctx e2.etype tfloat e2.epos;
 			tfloat
 			tfloat
-		| KUnk, KParam t ->
+		| KUnk, KNumParam t ->
 			unify ctx e1.etype tfloat e1.epos;
 			unify ctx e1.etype tfloat e1.epos;
 			tfloat
 			tfloat
+		| KStrParam _, _
+		| _, KStrParam _ ->
+			tstring
 		| KAbstract _,KFloat ->
 		| KAbstract _,KFloat ->
 			unify ctx e1.etype tfloat e1.epos;
 			unify ctx e1.etype tfloat e1.epos;
 			tfloat
 			tfloat
@@ -775,8 +788,8 @@ and type_binop2 ?(abstract_overload_only=false) ctx op (e1 : texpr) (e2 : Ast.ex
 			ctx.t.tint
 			ctx.t.tint
 		| KAbstract _,_
 		| KAbstract _,_
 		| _,KAbstract _
 		| _,KAbstract _
-		| KParam _, _
-		| _, KParam _
+		| KNumParam _, _
+		| _, KNumParam _
 		| KOther, _
 		| KOther, _
 		| _ , KOther ->
 		| _ , KOther ->
 			let pr = print_context() in
 			let pr = print_context() in
@@ -800,13 +813,13 @@ and type_binop2 ?(abstract_overload_only=false) ctx op (e1 : texpr) (e2 : Ast.ex
 		(match classify e1.etype, classify e2.etype with
 		(match classify e1.etype, classify e2.etype with
 		| KFloat, KFloat ->
 		| KFloat, KFloat ->
 			result := tfloat
 			result := tfloat
-		| KParam t1, KParam t2 when Type.type_iseq t1 t2 ->
+		| KNumParam t1, KNumParam t2 when Type.type_iseq t1 t2 ->
 			if op <> OpDiv then result := t1
 			if op <> OpDiv then result := t1
-		| KParam _, KParam _ ->
+		| KNumParam _, KNumParam _ ->
 			result := tfloat
 			result := tfloat
-		| KParam t, KInt | KInt, KParam t ->
+		| KNumParam t, KInt | KInt, KNumParam t ->
 			if op <> OpDiv then result := t
 			if op <> OpDiv then result := t
-		| KParam _, KFloat | KFloat, KParam _ ->
+		| KNumParam _, KFloat | KFloat, KNumParam _ ->
 			result := tfloat
 			result := tfloat
 		| KFloat, k ->
 		| KFloat, k ->
 			ignore(unify_int ctx e2 k);
 			ignore(unify_int ctx e2 k);
@@ -853,8 +866,10 @@ and type_binop2 ?(abstract_overload_only=false) ctx op (e1 : texpr) (e2 : Ast.ex
 		| KDyn , KInt | KDyn , KFloat | KDyn , KString -> ()
 		| KDyn , KInt | KDyn , KFloat | KDyn , KString -> ()
 		| KInt , KDyn | KFloat , KDyn | KString , KDyn -> ()
 		| KInt , KDyn | KFloat , KDyn | KString , KDyn -> ()
 		| KDyn , KDyn -> ()
 		| KDyn , KDyn -> ()
-		| KParam _ , x when x <> KString && x <> KOther -> ()
-		| x , KParam _ when x <> KString && x <> KOther -> ()
+		| KNumParam _ , (KInt | KFloat | KNumParam _ | KDyn | KUnk ) -> ()
+		| (KInt | KFloat | KDyn | KUnk ), KNumParam _ -> ()
+		| KStrParam _ , (KString | KStrParam _ | KUnk | KDyn) -> ()
+		| (KString | KUnk | KDyn) , KStrParam _ -> ()
 		| KAbstract _,_
 		| KAbstract _,_
 		| _,KAbstract _
 		| _,KAbstract _
 		| KDyn , KUnk
 		| KDyn , KUnk
@@ -863,8 +878,10 @@ and type_binop2 ?(abstract_overload_only=false) ctx op (e1 : texpr) (e2 : Ast.ex
 		| KString , KFloat
 		| KString , KFloat
 		| KInt , KString
 		| KInt , KString
 		| KFloat , KString
 		| KFloat , KString
-		| KParam _ , _
-		| _ , KParam _
+		| KNumParam _ , _
+		| _ , KNumParam _
+		| KStrParam _ , _
+		| _ , KStrParam _
 		| KOther , _
 		| KOther , _
 		| _ , KOther ->
 		| _ , KOther ->
 			let pr = print_context() in
 			let pr = print_context() in
@@ -1031,7 +1048,7 @@ and type_unop ctx op flag e p =
 				if set then check_assign ctx e;
 				if set then check_assign ctx e;
 				(match classify e.etype with
 				(match classify e.etype with
 				| KFloat -> ctx.t.tfloat
 				| KFloat -> ctx.t.tfloat
-				| KParam t ->
+				| KNumParam t ->
 					unify ctx e.etype ctx.t.tfloat e.epos;
 					unify ctx e.etype ctx.t.tfloat e.epos;
 					t
 					t
 				| k ->
 				| k ->
@@ -1345,10 +1362,11 @@ and handle_efield ctx e p mode =
 								raise (Error (Module_not_found (List.rev !path,name),p))
 								raise (Error (Module_not_found (List.rev !path,name),p))
 							with
 							with
 								Not_found ->
 								Not_found ->
+									let sl = List.map (fun (n,_,_) -> n) (List.rev acc) in
 									(* if there was no module name part, last guess is that we're trying to get package completion *)
 									(* if there was no module name part, last guess is that we're trying to get package completion *)
 									if ctx.in_display then begin
 									if ctx.in_display then begin
-										if ctx.com.json_out = None then raise (Parser.TypePath (List.map (fun (n,_,_) -> n) (List.rev acc),None,false,p))
-										else raise_fields (DisplayToplevel.collect ctx TKType WithType.no_value) CRTypeHint (Some p0);
+										if ctx.com.json_out = None then raise (Parser.TypePath (sl,None,false,p))
+										else DisplayToplevel.collect_and_raise ctx TKType WithType.no_value (CRToplevel None) (String.concat "." sl,p0) (Some p0)
 									end;
 									end;
 									raise e)
 									raise e)
 		in
 		in
@@ -1431,7 +1449,7 @@ and type_access ctx e p mode =
 		let resume_typing = type_expr ~mode in
 		let resume_typing = type_expr ~mode in
 		AKExpr (TyperDisplay.handle_edisplay ~resume_typing ctx e dk WithType.value)
 		AKExpr (TyperDisplay.handle_edisplay ~resume_typing ctx e dk WithType.value)
 	| _ ->
 	| _ ->
-		AKExpr (type_expr ctx (e,p) WithType.value)
+		AKExpr (type_expr ~mode ctx (e,p) WithType.value)
 
 
 and type_array_access ctx e1 e2 p mode =
 and type_array_access ctx e1 e2 p mode =
 	let e1 = type_expr ctx e1 WithType.value in
 	let e1 = type_expr ctx e1 WithType.value in
@@ -1603,8 +1621,12 @@ and type_object_decl ctx fl with_type p =
 		let rec loop seen t =
 		let rec loop seen t =
 			match follow t with
 			match follow t with
 			| TAnon a -> ODKWithStructure a
 			| TAnon a -> ODKWithStructure a
-			| TAbstract (a,pl) as t when not (Meta.has Meta.CoreType a.a_meta) && not (List.exists (fun t' -> fast_eq t t') seen) ->
-				(match List.fold_left (fun acc t' -> match loop (t :: seen) t' with ODKPlain -> acc | t -> t :: acc) [] (get_abstract_froms a pl) with
+			| TAbstract (a,pl) as t
+				when not (Meta.has Meta.CoreType a.a_meta)
+					&& not (List.exists (fun t' -> fast_eq_anon ~mono_equals_dynamic:true t t') seen) ->
+				let froms = get_abstract_froms a pl
+				and fold = fun acc t' -> match loop (t :: seen) t' with ODKPlain -> acc | t -> t :: acc in
+				(match List.fold_left fold [] froms with
 				| [t] -> t
 				| [t] -> t
 				| _ -> ODKPlain)
 				| _ -> ODKPlain)
 			| TDynamic t when (follow t != t_dynamic) ->
 			| TDynamic t when (follow t != t_dynamic) ->
@@ -1890,7 +1912,8 @@ and type_try ctx e1 catches with_type p =
 	let e1,catches,t = match with_type with
 	let e1,catches,t = match with_type with
 		| WithType.NoValue -> e1,catches,ctx.t.tvoid
 		| WithType.NoValue -> e1,catches,ctx.t.tvoid
 		| WithType.Value _ -> e1,catches,unify_min ctx el
 		| WithType.Value _ -> e1,catches,unify_min ctx el
-		| WithType.WithType(t,_) when (match follow t with TMono _ -> true | _ -> false) -> e1,catches,unify_min ctx el
+		| WithType.WithType(t,src) when (match follow t with TMono _ -> true | t -> ExtType.is_void t) ->
+			e1,catches,unify_min_for_type_source ctx el src
 		| WithType.WithType(t,_) ->
 		| WithType.WithType(t,_) ->
 			let e1 = AbstractCast.cast_or_unify ctx t e1 e1.epos in
 			let e1 = AbstractCast.cast_or_unify ctx t e1 e1.epos in
 			let catches = List.map (fun (v,e) ->
 			let catches = List.map (fun (v,e) ->
@@ -2038,7 +2061,7 @@ and type_local_function ctx name inline f with_type p =
 		tf_expr = e;
 		tf_expr = e;
 	} in
 	} in
 	let e = mk (TFunction tf) ft p in
 	let e = mk (TFunction tf) ft p in
-	(match v with
+	match v with
 	| None -> e
 	| None -> e
 	| Some v ->
 	| Some v ->
 		Typeload.generate_value_meta ctx.com None (fun m -> v.v_meta <- m :: v.v_meta) f.f_args;
 		Typeload.generate_value_meta ctx.com None (fun m -> v.v_meta <- m :: v.v_meta) f.f_args;
@@ -2050,23 +2073,29 @@ and type_local_function ctx name inline f with_type p =
 			| LocalUsage.Use _ | LocalUsage.Assign _ | LocalUsage.Declare _ -> ()
 			| LocalUsage.Use _ | LocalUsage.Assign _ | LocalUsage.Declare _ -> ()
 		in
 		in
 		let is_rec = (try local_usage loop e; false with Exit -> true) in
 		let is_rec = (try local_usage loop e; false with Exit -> true) in
-		let decl = (if is_rec then begin
-			if inline then display_error ctx "Inline function cannot be recursive" e.epos;
-			let el =
+		let exprs =
+			if with_type <> WithType.NoValue && not inline then [mk (TLocal v) v.v_type p]
+			else []
+		in
+		let exprs =
+			if is_rec then begin
+				if inline then display_error ctx "Inline function cannot be recursive" e.epos;
 				(mk (TVar (v,Some (mk (TConst TNull) ft p))) ctx.t.tvoid p) ::
 				(mk (TVar (v,Some (mk (TConst TNull) ft p))) ctx.t.tvoid p) ::
 				(mk (TBinop (OpAssign,mk (TLocal v) ft p,e)) ft p) ::
 				(mk (TBinop (OpAssign,mk (TLocal v) ft p,e)) ft p) ::
-				(if with_type = WithType.NoValue then [] else [mk (TLocal v) ft p])
-			in
-			let e = mk (TBlock el) ft p in
-			{e with eexpr = TMeta((Meta.MergeBlock,[],null_pos),e)}
-		end else if inline && not ctx.com.display.dms_display then
-			mk (TBlock []) ctx.t.tvoid p (* do not add variable since it will be inlined *)
-		else
-			mk (TVar (v,Some e)) ctx.t.tvoid p
-		) in
-		if with_type <> WithType.NoValue && not inline then mk (TBlock [decl;mk (TLocal v) v.v_type p]) v.v_type p else decl)
+				exprs
+			end else if inline && not ctx.com.display.dms_display then
+				(mk (TBlock []) ctx.t.tvoid p) :: exprs (* do not add variable since it will be inlined *)
+			else
+				(mk (TVar (v,Some e)) ctx.t.tvoid p) :: exprs
+		in
+		match exprs with
+		| [e] -> e
+		| _ ->
+			let block = mk (TBlock exprs) v.v_type p in
+			mk (TMeta ((Meta.MergeBlock, [], null_pos), block)) v.v_type p
 
 
 and type_array_decl ctx el with_type p =
 and type_array_decl ctx el with_type p =
+	let allow_array_dynamic = ref false in
 	let tp = (match with_type with
 	let tp = (match with_type with
 	| WithType.WithType(t,_) ->
 	| WithType.WithType(t,_) ->
 		let rec loop seen t =
 		let rec loop seen t =
@@ -2074,16 +2103,18 @@ and type_array_decl ctx el with_type p =
 			| TInst ({ cl_path = [],"Array" },[tp]) ->
 			| TInst ({ cl_path = [],"Array" },[tp]) ->
 				(match follow tp with
 				(match follow tp with
 				| TMono _ -> None
 				| TMono _ -> None
-				| _ -> Some tp)
+				| _ as t ->
+					if t == t_dynamic then allow_array_dynamic := true;
+					Some tp)
 			| TAnon _ ->
 			| TAnon _ ->
 				(try
 				(try
 					Some (get_iterable_param t)
 					Some (get_iterable_param t)
 				with Not_found ->
 				with Not_found ->
 					None)
 					None)
-			| TAbstract (a,pl) as t when not (List.exists (fun t' -> fast_eq t (follow t')) seen) ->
+			| TAbstract (a,pl) as t when not (List.exists (fun t' -> fast_eq_anon ~mono_equals_dynamic:true t (follow t')) seen) ->
 				let types =
 				let types =
 					List.fold_left
 					List.fold_left
-						(fun acc t -> match loop (t :: seen) t with
+						(fun acc t' -> match loop (t :: seen) t' with
 							| None -> acc
 							| None -> acc
 							| Some t -> t :: acc
 							| Some t -> t :: acc
 						)
 						)
@@ -2094,7 +2125,12 @@ and type_array_decl ctx el with_type p =
 				| [t] -> Some t
 				| [t] -> Some t
 				| _ -> None)
 				| _ -> None)
 			| t ->
 			| t ->
-				if t == t_dynamic then Some t else None)
+				if t == t_dynamic then begin
+					allow_array_dynamic := true;
+					Some t
+				end else
+					None
+			)
 		in
 		in
 		loop [] t
 		loop [] t
 	| _ ->
 	| _ ->
@@ -2106,7 +2142,9 @@ and type_array_decl ctx el with_type p =
 		let t = try
 		let t = try
 			unify_min_raise ctx.com.basic el
 			unify_min_raise ctx.com.basic el
 		with Error (Unify l,p) ->
 		with Error (Unify l,p) ->
-			if ctx.untyped || ctx.com.display.dms_error_policy = EPIgnore then t_dynamic else begin
+			if !allow_array_dynamic || ctx.untyped || ctx.com.display.dms_error_policy = EPIgnore then
+				t_dynamic
+			else begin
 				display_error ctx "Arrays of mixed types are only allowed if the type is forced to Array<Dynamic>" p;
 				display_error ctx "Arrays of mixed types are only allowed if the type is forced to Array<Dynamic>" p;
 				raise (Error (Unify l, p))
 				raise (Error (Unify l, p))
 			end
 			end
@@ -2151,19 +2189,24 @@ and type_array_comprehension ctx e with_type p =
 		mk (TLocal v) v.v_type p;
 		mk (TLocal v) v.v_type p;
 	]) v.v_type p
 	]) v.v_type p
 
 
-and type_return ctx e with_type p =
+and type_return ?(implicit=false) ctx e with_type p =
 	match e with
 	match e with
 	| None ->
 	| None ->
 		let v = ctx.t.tvoid in
 		let v = ctx.t.tvoid in
 		unify ctx v ctx.ret p;
 		unify ctx v ctx.ret p;
 		let expect_void = match with_type with
 		let expect_void = match with_type with
 			| WithType.WithType(t,_) -> ExtType.is_void (follow t)
 			| WithType.WithType(t,_) -> ExtType.is_void (follow t)
+			| WithType.Value (Some ImplicitReturn) -> true
 			| _ -> false
 			| _ -> false
 		in
 		in
 		mk (TReturn None) (if expect_void then v else t_dynamic) p
 		mk (TReturn None) (if expect_void then v else t_dynamic) p
 	| Some e ->
 	| Some e ->
 		try
 		try
-			let e = type_expr ctx e (WithType.with_type ctx.ret) in
+			let with_expected_type =
+				if implicit then WithType.of_implicit_return ctx.ret
+				else WithType.with_type ctx.ret
+			in
+			let e = type_expr ctx e with_expected_type in
 			let e = AbstractCast.cast_or_unify ctx ctx.ret e p in
 			let e = AbstractCast.cast_or_unify ctx ctx.ret e p in
 			begin match follow e.etype with
 			begin match follow e.etype with
 			| TAbstract({a_path=[],"Void"},_) ->
 			| TAbstract({a_path=[],"Void"},_) ->
@@ -2225,7 +2268,8 @@ and type_if ctx e e1 e2 with_type p =
 		let e1,e2,t = match with_type with
 		let e1,e2,t = match with_type with
 			| WithType.NoValue -> e1,e2,ctx.t.tvoid
 			| WithType.NoValue -> e1,e2,ctx.t.tvoid
 			| WithType.Value _ -> e1,e2,unify_min ctx [e1; e2]
 			| WithType.Value _ -> e1,e2,unify_min ctx [e1; e2]
-			| WithType.WithType(t,_) when (match follow t with TMono _ -> true | _ -> false) -> e1,e2,unify_min ctx [e1; e2]
+			| WithType.WithType(t,src) when (match follow t with TMono _ -> true | t -> ExtType.is_void t) ->
+				e1,e2,unify_min_for_type_source ctx [e1; e2] src
 			| WithType.WithType(t,_) ->
 			| WithType.WithType(t,_) ->
 				let e1 = AbstractCast.cast_or_unify ctx t e1 e1.epos in
 				let e1 = AbstractCast.cast_or_unify ctx t e1 e1.epos in
 				let e2 = AbstractCast.cast_or_unify ctx t e2 e2.epos in
 				let e2 = AbstractCast.cast_or_unify ctx t e2 e2.epos in
@@ -2233,11 +2277,11 @@ and type_if ctx e e1 e2 with_type p =
 		in
 		in
 		mk (TIf (e,e1,Some e2)) t p)
 		mk (TIf (e,e1,Some e2)) t p)
 
 
-and type_meta ctx m e1 with_type p =
+and type_meta ?(mode=MGet) ctx m e1 with_type p =
 	if ctx.is_display_file then DisplayEmitter.check_display_metadata ctx [m];
 	if ctx.is_display_file then DisplayEmitter.check_display_metadata ctx [m];
 	let old = ctx.meta in
 	let old = ctx.meta in
 	ctx.meta <- m :: ctx.meta;
 	ctx.meta <- m :: ctx.meta;
-	let e () = type_expr ctx e1 with_type in
+	let e () = type_expr ~mode ctx e1 with_type in
 	let e = match m with
 	let e = match m with
 		| (Meta.ToString,_,_) ->
 		| (Meta.ToString,_,_) ->
 			let e = e() in
 			let e = e() in
@@ -2296,6 +2340,11 @@ and type_meta ctx m e1 with_type p =
 				display_error ctx "Call or function expected after inline keyword" p;
 				display_error ctx "Call or function expected after inline keyword" p;
 				e();
 				e();
 			end
 			end
+		| (Meta.ImplicitReturn,_,_) ->
+			begin match e1 with
+			| (EReturn e, p) -> type_return ~implicit:true ctx e with_type p
+			| _ -> e()
+			end
 		| _ -> e()
 		| _ -> e()
 	in
 	in
 	ctx.meta <- old;
 	ctx.meta <- old;
@@ -2319,10 +2368,10 @@ and type_call_target ctx e with_type inline p =
 		| _ ->
 		| _ ->
 			e
 			e
 
 
-and type_call ctx e el (with_type:WithType.t) inline p =
+and type_call ?(mode=MGet) ctx e el (with_type:WithType.t) inline p =
 	let def () =
 	let def () =
 		let e = type_call_target ctx e with_type inline p in
 		let e = type_call_target ctx e with_type inline p in
-		build_call ctx e el with_type p
+		build_call ~mode ctx e el with_type p
 	in
 	in
 	match e, el with
 	match e, el with
 	| (EConst (Ident "trace"),p) , e :: el ->
 	| (EConst (Ident "trace"),p) , e :: el ->
@@ -2423,7 +2472,15 @@ and type_expr ?(mode=MGet) ctx (e,p) (with_type:WithType.t) =
 		Texpr.type_constant ctx.com.basic c p
 		Texpr.type_constant ctx.com.basic c p
 	| EBinop (op,e1,e2) ->
 	| EBinop (op,e1,e2) ->
 		type_binop ctx op e1 e2 false with_type p
 		type_binop ctx op e1 e2 false with_type p
-	| EBlock [] when with_type <> WithType.NoValue ->
+	| EBlock [] when (match with_type with
+			| NoValue -> false
+			(*
+				If expected type is unknown then treat `(...) -> {}` as an empty function
+				(just like `function(...) {}`) instead of returning an object.
+			*)
+			| WithType (t, Some ImplicitReturn) -> not (ExtType.is_mono (follow t))
+			| _ -> true
+		) ->
 		type_expr ctx (EObjectDecl [],p) with_type
 		type_expr ctx (EObjectDecl [],p) with_type
 	| EBlock l ->
 	| EBlock l ->
 		let locals = save_locals ctx in
 		let locals = save_locals ctx in
@@ -2496,7 +2553,7 @@ and type_expr ?(mode=MGet) ctx (e,p) (with_type:WithType.t) =
 		let e = type_expr ctx e WithType.value in
 		let e = type_expr ctx e WithType.value in
 		mk (TThrow e) (mk_mono()) p
 		mk (TThrow e) (mk_mono()) p
 	| ECall (e,el) ->
 	| ECall (e,el) ->
-		type_call ctx e el with_type false p
+		type_call ~mode ctx e el with_type false p
 	| ENew (t,el) ->
 	| ENew (t,el) ->
 		type_new ctx t el with_type false p
 		type_new ctx t el with_type false p
 	| EUnop (op,flag,e) ->
 	| EUnop (op,flag,e) ->
@@ -2529,7 +2586,7 @@ and type_expr ?(mode=MGet) ctx (e,p) (with_type:WithType.t) =
 		let e = AbstractCast.cast_or_unify ctx t e p in
 		let e = AbstractCast.cast_or_unify ctx t e p in
 		if e.etype == t then e else mk (TCast (e,None)) t p
 		if e.etype == t then e else mk (TCast (e,None)) t p
 	| EMeta (m,e1) ->
 	| EMeta (m,e1) ->
-		type_meta ctx m e1 with_type p
+		type_meta ~mode ctx m e1 with_type p
 
 
 (* ---------------------------------------------------------------------- *)
 (* ---------------------------------------------------------------------- *)
 (* TYPER INITIALIZATION *)
 (* TYPER INITIALIZATION *)
@@ -2668,6 +2725,7 @@ let rec create com =
 
 
 ;;
 ;;
 unify_min_ref := unify_min;
 unify_min_ref := unify_min;
+unify_min_for_type_source_ref := unify_min_for_type_source;
 make_call_ref := make_call;
 make_call_ref := make_call;
 build_call_ref := build_call;
 build_call_ref := build_call;
 type_call_target_ref := type_call_target;
 type_call_target_ref := type_call_target;

+ 1 - 6
src/typing/typerBase.ml

@@ -4,11 +4,6 @@ open Type
 open Typecore
 open Typecore
 open Error
 open Error
 
 
-type access_mode =
-	| MGet
-	| MSet
-	| MCall
-
 type access_kind =
 type access_kind =
 	| AKNo of string
 	| AKNo of string
 	| AKExpr of texpr
 	| AKExpr of texpr
@@ -208,7 +203,7 @@ let get_abstract_froms a pl =
 		match follow (Type.field_type f) with
 		match follow (Type.field_type f) with
 		| TFun ([_,_,v],t) ->
 		| TFun ([_,_,v],t) ->
 			(try
 			(try
-				ignore(type_eq EqStrict t (TAbstract(a,List.map dup pl))); (* unify fields monomorphs *)
+				ignore(type_eq EqStrict t (TAbstract(a,List.map duplicate pl))); (* unify fields monomorphs *)
 				v :: acc
 				v :: acc
 			with Unify_error _ ->
 			with Unify_error _ ->
 				acc)
 				acc)

+ 17 - 11
src/typing/typerDisplay.ml

@@ -140,9 +140,9 @@ let get_expected_type ctx with_type =
 		| None -> None
 		| None -> None
 		| Some t -> Some (completion_type_of_type ctx t,completion_type_of_type ctx (follow t))
 		| Some t -> Some (completion_type_of_type ctx t,completion_type_of_type ctx (follow t))
 
 
-let raise_toplevel ctx dk with_type po p =
+let raise_toplevel ctx dk with_type (subject,psubject) po =
 	let expected_type = get_expected_type ctx with_type in
 	let expected_type = get_expected_type ctx with_type in
-	raise_fields (DisplayToplevel.collect ctx (match dk with DKPattern _ -> TKPattern p | _ -> TKExpr p) with_type) (CRToplevel expected_type) po
+	DisplayToplevel.collect_and_raise ctx (match dk with DKPattern _ -> TKPattern psubject | _ -> TKExpr psubject) with_type (CRToplevel expected_type) (subject,psubject) po
 
 
 let display_dollar_type ctx p make_type =
 let display_dollar_type ctx p make_type =
 	let mono = mk_mono() in
 	let mono = mk_mono() in
@@ -401,7 +401,11 @@ and display_expr ctx e_ast e dk with_type p =
 				display_fields e1 e2 (String.length s)
 				display_fields e1 e2 (String.length s)
 			| _ ->
 			| _ ->
 				if dk = DKDot then display_fields e_ast e 0
 				if dk = DKDot then display_fields e_ast e 0
-				else raise_toplevel ctx dk with_type None p
+				else begin
+					let name = try String.concat "." (string_list_of_expr_path_raise e_ast) with Exit -> "" in
+					let name = if name = "null" then "" else name in
+					raise_toplevel ctx dk with_type (name,pos e_ast) None
+				end
 		end
 		end
 	| DMDefault | DMNone | DMModuleSymbols _ | DMDiagnostics _ | DMStatistics ->
 	| DMDefault | DMNone | DMModuleSymbols _ | DMDiagnostics _ | DMStatistics ->
 		let fields = DisplayFields.collect ctx e_ast e dk with_type p in
 		let fields = DisplayFields.collect ctx e_ast e dk with_type p in
@@ -487,15 +491,15 @@ let handle_display ?resume_typing ctx e_ast dk with_type =
 		| Some fn -> fn ctx e_ast with_type
 		| Some fn -> fn ctx e_ast with_type
 	with Error (Unknown_ident n,_) when ctx.com.display.dms_kind = DMDefault ->
 	with Error (Unknown_ident n,_) when ctx.com.display.dms_kind = DMDefault ->
         if dk = DKDot && ctx.com.json_out = None then raise (Parser.TypePath ([n],None,false,p))
         if dk = DKDot && ctx.com.json_out = None then raise (Parser.TypePath ([n],None,false,p))
-		else raise_toplevel ctx dk with_type (Some p) p
+		else raise_toplevel ctx dk with_type (n,p) (Some p)
 	| Error ((Type_not_found (path,_) | Module_not_found path),_) as err when ctx.com.display.dms_kind = DMDefault ->
 	| Error ((Type_not_found (path,_) | Module_not_found path),_) as err when ctx.com.display.dms_kind = DMDefault ->
 		if ctx.com.json_out = None then	begin try
 		if ctx.com.json_out = None then	begin try
 			raise_fields (DisplayFields.get_submodule_fields ctx path) (CRField((make_ci_module path),p,None,None)) None
 			raise_fields (DisplayFields.get_submodule_fields ctx path) (CRField((make_ci_module path),p,None,None)) None
 		with Not_found ->
 		with Not_found ->
 			raise err
 			raise err
 		end else
 		end else
-			raise_toplevel ctx dk with_type (Some p) p
-	| DisplayException(DisplayFields Some(l,CRTypeHint,p)) when (match fst e_ast with ENew _ -> true | _ -> false) ->
+			raise_toplevel ctx dk with_type (s_type_path path,p) (Some p)
+	| DisplayException(DisplayFields Some({fkind = CRTypeHint} as r)) when (match fst e_ast with ENew _ -> true | _ -> false) ->
 		let timer = Timer.timer ["display";"toplevel";"filter ctors"] in
 		let timer = Timer.timer ["display";"toplevel";"filter ctors"] in
 		ctx.pass <- PBuildClass;
 		ctx.pass <- PBuildClass;
 		let l = List.filter (fun item ->
 		let l = List.filter (fun item ->
@@ -526,7 +530,9 @@ let handle_display ?resume_typing ctx e_ast dk with_type =
 						let mt = ctx.g.do_load_type_def ctx null_pos {tpackage=mt.pack;tname=mt.module_name;tsub=Some mt.name;tparams=[]} in
 						let mt = ctx.g.do_load_type_def ctx null_pos {tpackage=mt.pack;tname=mt.module_name;tsub=Some mt.name;tparams=[]} in
 						begin match resolve_typedef mt with
 						begin match resolve_typedef mt with
 						| TClassDecl c when has_constructor c -> true
 						| TClassDecl c when has_constructor c -> true
-						| TAbstractDecl {a_impl = Some c} -> PMap.mem "_new" c.cl_statics
+						| TAbstractDecl {a_impl = Some c} ->
+							ignore(c.cl_build());
+							PMap.mem "_new" c.cl_statics
 						| _ -> false
 						| _ -> false
 						end
 						end
 					with _ ->
 					with _ ->
@@ -536,9 +542,9 @@ let handle_display ?resume_typing ctx e_ast dk with_type =
 			| ITTypeParameter {cl_kind = KTypeParameter tl} when get_constructible_constraint ctx tl null_pos <> None ->
 			| ITTypeParameter {cl_kind = KTypeParameter tl} when get_constructible_constraint ctx tl null_pos <> None ->
 				true
 				true
 			| _ -> false
 			| _ -> false
-		) l in
+		) r.fitems in
 		timer();
 		timer();
-		raise_fields l CRNew p
+		raise_fields l CRNew r.finsert_pos
 	in
 	in
 	let e = match e.eexpr with
 	let e = match e.eexpr with
 		| TField(e1,FDynamic "bind") when (match follow e1.etype with TFun _ -> true | _ -> false) -> e1
 		| TField(e1,FDynamic "bind") when (match follow e1.etype with TFun _ -> true | _ -> false) -> e1
@@ -594,7 +600,7 @@ let handle_edisplay ?resume_typing ctx e dk with_type =
 	| DKPattern outermost,DMDefault ->
 	| DKPattern outermost,DMDefault ->
 		begin try
 		begin try
 			handle_display ctx e dk with_type
 			handle_display ctx e dk with_type
-		with DisplayException(DisplayFields Some(l,CRToplevel _,p)) ->
-			raise_fields l (CRPattern ((get_expected_type ctx with_type),outermost)) p
+		with DisplayException(DisplayFields Some({fkind = CRToplevel _} as r)) ->
+			raise_fields r.fitems (CRPattern ((get_expected_type ctx with_type),outermost)) r.finsert_pos
 		end
 		end
 	| _ -> handle_display ctx e dk with_type
 	| _ -> handle_display ctx e dk with_type

Энэ ялгаанд хэт олон файл өөрчлөгдсөн тул зарим файлыг харуулаагүй болно