Browse Source

Merge remote-tracking branch 'origin/development' into remove_err_depth

Rudy Ges 2 months ago
parent
commit
71c3ce265f
100 changed files with 1301 additions and 485 deletions
  1. 2 1
      .github/workflows/main.yml
  2. 2 1
      .github/workflows/target.yml
  3. 1 1
      Makefile
  4. 6 0
      WinSetup.ps1
  5. 20 0
      extra/CHANGES.txt
  6. 4 2
      extra/ImportAll.hx
  7. 2 1
      extra/github-actions/install-ocaml-windows.yml
  8. 1 1
      extra/haxelib_src
  9. 2 0
      libs/extc/extc.ml
  10. 25 2
      libs/extc/extc_stubs.c
  11. 3 1
      libs/objsize/objsize.ml
  12. 41 0
      src-json/define.json
  13. 4 4
      src/codegen/codegen.ml
  14. 1 1
      src/codegen/genxml.ml
  15. 11 7
      src/compiler/compilationCache.ml
  16. 2 2
      src/compiler/compiler.ml
  17. 1 0
      src/compiler/hxb/hxbReader.ml
  18. 1 0
      src/compiler/hxb/hxbWriter.ml
  19. 2 2
      src/compiler/server.ml
  20. 1 0
      src/compiler/serverCompilationContext.ml
  21. 5 1
      src/compiler/serverMessage.ml
  22. 40 6
      src/context/abstractCast.ml
  23. 119 37
      src/context/common.ml
  24. 1 1
      src/context/commonCache.ml
  25. 5 7
      src/context/display/deprecationCheck.ml
  26. 7 3
      src/context/display/diagnosticsPrinter.ml
  27. 31 4
      src/context/display/displayFields.ml
  28. 3 0
      src/context/display/displayMemory.ml
  29. 1 1
      src/context/display/findReferences.ml
  30. 0 1
      src/context/display/statistics.ml
  31. 17 0
      src/context/dotGraph.ml
  32. 32 14
      src/context/parallel.ml
  33. 1 1
      src/context/safeCom.ml
  34. 20 6
      src/context/typecore.ml
  35. 4 7
      src/core/define.ml
  36. 0 11
      src/core/display/completionItem.ml
  37. 12 0
      src/core/ds/threadSafeHashtbl.ml
  38. 2 1
      src/core/json/genjson.ml
  39. 1 1
      src/core/tOther.ml
  40. 1 0
      src/core/tPrinting.ml
  41. 11 1
      src/core/tType.ml
  42. 4 3
      src/core/tUnification.ml
  43. 10 0
      src/core/texpr.ml
  44. 1 9
      src/core/warning.ml
  45. 2 1
      src/filters/exception/saveStacks.ml
  46. 8 8
      src/filters/filters.ml
  47. 0 1
      src/filters/filtersCommon.ml
  48. 28 52
      src/filters/safe/capturedVars.ml
  49. 8 8
      src/generators/cpp/cppRetyper.ml
  50. 1 1
      src/generators/cpp/gen/cppCppia.ml
  51. 13 13
      src/generators/cpp/gen/cppGenClassImplementation.ml
  52. 4 4
      src/generators/flashProps.ml
  53. 2 2
      src/generators/gctx.ml
  54. 14 15
      src/generators/genhl.ml
  55. 1 1
      src/generators/genjvm.ml
  56. 8 0
      src/generators/genlua.ml
  57. 2 0
      src/generators/genphp7.ml
  58. 2 2
      src/generators/genpy.ml
  59. 4 4
      src/generators/genswf9.ml
  60. 87 0
      src/macro/eval/evalAtomic.ml
  61. 18 18
      src/macro/eval/evalEmitter.ml
  62. 24 1
      src/macro/eval/evalExceptions.ml
  63. 4 0
      src/macro/eval/evalHash.ml
  64. 3 3
      src/macro/eval/evalStackTrace.ml
  65. 7 1
      src/macro/eval/evalStdLib.ml
  66. 11 1
      src/macro/eval/evalValue.ml
  67. 10 1
      src/macro/macroApi.ml
  68. 7 13
      src/optimization/analyzer.ml
  69. 13 4
      src/optimization/analyzerTexpr.ml
  70. 10 4
      src/optimization/dce.ml
  71. 1 1
      src/optimization/inline.ml
  72. 20 17
      src/optimization/inlineConstructors.ml
  73. 20 2
      src/prebuild.ml
  74. 1 0
      src/syntax/grammar.ml
  75. 4 13
      src/syntax/lexer.ml
  76. 0 1
      src/syntax/parserConfig.ml
  77. 2 2
      src/typing/callUnification.ml
  78. 1 1
      src/typing/fieldAccess.ml
  79. 34 7
      src/typing/fields.ml
  80. 7 1
      src/typing/generic.ml
  81. 11 12
      src/typing/macroContext.ml
  82. 164 53
      src/typing/nullSafety.ml
  83. 8 5
      src/typing/operators.ml
  84. 3 0
      src/typing/typeload.ml
  85. 12 5
      src/typing/typeloadCheck.ml
  86. 24 9
      src/typing/typeloadFields.ml
  87. 0 1
      src/typing/typeloadModule.ml
  88. 18 11
      src/typing/typer.ml
  89. 51 1
      src/typing/typerEntry.ml
  90. 8 1
      std/cpp/_std/haxe/Exception.hx
  91. 47 0
      std/cpp/_std/haxe/atomic/AtomicBool.hx
  92. 43 11
      std/cpp/_std/haxe/atomic/AtomicInt.hx
  93. 2 0
      std/eval/_std/Sys.hx
  94. 16 1
      std/eval/_std/haxe/Exception.hx
  95. 5 1
      std/flash/_std/haxe/Exception.hx
  96. 1 1
      std/haxe/CallStack.hx
  97. 2 1
      std/haxe/Exception.hx
  98. 36 1
      std/haxe/Timer.hx
  99. 8 27
      std/haxe/atomic/AtomicBool.hx
  100. 1 0
      std/haxe/display/JsonModuleTypes.hx

+ 2 - 1
.github/workflows/main.yml

@@ -53,7 +53,8 @@ jobs:
         run: neko -version 2>&1
         run: neko -version 2>&1
 
 
       - name: Setup ocaml
       - name: Setup ocaml
-        uses: ocaml/setup-ocaml@v3
+      # Lock to 3.2.19 to work around an issue with 32-bit libraries getting installed
+        uses: ocaml/setup-ocaml@3d85bf33a66e089149cd1e9c75da7b9cb6d9d3a7
         with:
         with:
           ocaml-compiler: ${{ env.OCAML_VERSION }}
           ocaml-compiler: ${{ env.OCAML_VERSION }}
           opam-local-packages: |
           opam-local-packages: |

+ 2 - 1
.github/workflows/target.yml

@@ -8,12 +8,13 @@ on:
       - edited
       - edited
 jobs:
 jobs:
   check-branches:
   check-branches:
+    if: github.repository == 'HaxeFoundation/haxe'
     runs-on: ubuntu-latest
     runs-on: ubuntu-latest
     steps:
     steps:
       - name: Check branches
       - name: Check branches
         run: |
         run: |
           if [ ${{ github.base_ref }} != "development" ]; then
           if [ ${{ github.base_ref }} != "development" ]; then
-            echo "Merge requests should target `development`."
+            echo "Merge requests should target development."
             exit 1
             exit 1
           fi
           fi
 
 

+ 1 - 1
Makefile

@@ -59,7 +59,7 @@ PACKAGE_FILE_NAME=haxe_$(COMMIT_DATE)_$(COMMIT_SHA)
 HAXE_VERSION=$(shell $(CURDIR)/$(HAXE_OUTPUT) -version 2>&1 | awk '{print $$1;}')
 HAXE_VERSION=$(shell $(CURDIR)/$(HAXE_OUTPUT) -version 2>&1 | awk '{print $$1;}')
 HAXE_VERSION_SHORT=$(shell echo "$(HAXE_VERSION)" | grep -oE "^[0-9]+\.[0-9]+\.[0-9]+")
 HAXE_VERSION_SHORT=$(shell echo "$(HAXE_VERSION)" | grep -oE "^[0-9]+\.[0-9]+\.[0-9]+")
 
 
-NEKO_VERSION=2.4.0-rc.1
+NEKO_VERSION=2.4.1
 NEKO_MAJOR_VERSION=$(shell echo "$(NEKO_VERSION)" | grep -oE "^[0-9]+")
 NEKO_MAJOR_VERSION=$(shell echo "$(NEKO_VERSION)" | grep -oE "^[0-9]+")
 NEKO_VERSION_TAG=v$(shell echo "$(NEKO_VERSION)" | sed "s/\./-/g")
 NEKO_VERSION_TAG=v$(shell echo "$(NEKO_VERSION)" | sed "s/\./-/g")
 
 

+ 6 - 0
WinSetup.ps1

@@ -3,6 +3,12 @@
 # - install Neko
 # - install Neko
 # - checkout haxe git
 # - checkout haxe git
 # - run from command "powershell -noexit -ExecutionPolicy Bypass -File .\WinSetup.ps1"
 # - run from command "powershell -noexit -ExecutionPolicy Bypass -File .\WinSetup.ps1"
+#
+# Troubleshooting :
+# - make error #127 :
+#	  - cause : you have a local cygwin instance that takes precedence over the opam one.
+#     - solution : adjust your environment variables so opam takes precedence
+#
 
 
 function Cmd-Path($file) {
 function Cmd-Path($file) {
 	try { Split-Path -Parent (Get-Command "$file.exe" -ErrorAction Stop).Source } catch { "" }
 	try { Split-Path -Parent (Get-Command "$file.exe" -ErrorAction Stop).Source } catch { "" }

+ 20 - 0
extra/CHANGES.txt

@@ -1,3 +1,23 @@
+2025-05-09 4.3.7
+
+	General improvements:
+
+	all : update bundled haxelib version to 4.1.1
+	all : update bundled neko version to 2.4.1 (#12183)
+	all : use -w rules instead of defines to configure warnings (#11826, #12013)
+
+	Bugfixes:
+
+	all : fix compiler hanging issue (#11820)
+	all : local statics fixes (#11803, #11849)
+	all : fix for inline constructor bug triggering "Unbound variable" (#12169)
+	all : check caught error position when recovering from match typing failure (#12098)
+	macro : local statics vs ExprTools.map (#12030)
+	eval : https fixes (mbedtls update) (#11646)
+	eval : ssl cert verification failures on windows (#11838)
+	hl/c : fix comparison of HArray,HArray and HBytes,HBytes (#11610)
+	cppia : generate scriptable functions for overriden functions (#11773)
+
 2024-08-07 4.3.6
 2024-08-07 4.3.6
 
 
 	Bugfixes:
 	Bugfixes:

+ 4 - 2
extra/ImportAll.hx

@@ -78,8 +78,10 @@ class ImportAll {
 				if( !sys.FileSystem.exists(p) || !sys.FileSystem.isDirectory(p) )
 				if( !sys.FileSystem.exists(p) || !sys.FileSystem.isDirectory(p) )
 					continue;
 					continue;
 				for( file in sys.FileSystem.readDirectory(p) ) {
 				for( file in sys.FileSystem.readDirectory(p) ) {
-					if( file == ".svn" || file == "_std" )
-						continue;
+					switch (file) {
+						case ".svn" | "_std" | "import.hx":
+							continue;
+					}
 					var full = (pack == "") ? file : pack + "." + file;
 					var full = (pack == "") ? file : pack + "." + file;
 					if( StringTools.endsWith(file, ".hx") && file.substr(0, file.length - 3).indexOf(".") < 0 ) {
 					if( StringTools.endsWith(file, ".hx") && file.substr(0, file.length - 3).indexOf(".") < 0 ) {
 						var cl = full.substr(0, full.length - 3);
 						var cl = full.substr(0, full.length - 3);

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

@@ -1,5 +1,6 @@
 - name: Setup ocaml
 - name: Setup ocaml
-  uses: ocaml/setup-ocaml@v3
+# Lock to 3.2.19 to work around an issue with 32-bit libraries getting installed
+  uses: ocaml/setup-ocaml@3d85bf33a66e089149cd1e9c75da7b9cb6d9d3a7
   with:
   with:
     ocaml-compiler: ${{ env.OCAML_VERSION }}
     ocaml-compiler: ${{ env.OCAML_VERSION }}
     opam-local-packages: |
     opam-local-packages: |

+ 1 - 1
extra/haxelib_src

@@ -1 +1 @@
-Subproject commit 5a836287828fdaeb6aa91695a5eb399cee0f6640
+Subproject commit 436bd844f90c61100b13a108912c1f7e918aead3

+ 2 - 0
libs/extc/extc.ml

@@ -51,6 +51,8 @@ external zlib_crc32 : bytes -> int -> int32 = "zlib_crc32"
 
 
 external time : unit -> float = "sys_time"
 external time : unit -> float = "sys_time"
 
 
+external timestamp_ms : unit -> int64 = "sys_timestamp_ms"
+
 external getch : bool -> int = "sys_getch"
 external getch : bool -> int = "sys_getch"
 
 
 external filetime : string -> float = "sys_filetime"
 external filetime : string -> float = "sys_filetime"

+ 25 - 2
libs/extc/extc_stubs.c

@@ -487,11 +487,14 @@ CAMLprim value get_real_path( value path ) {
 #define TimeSpecToSeconds(ts) (double)ts.tv_sec + (double)ts.tv_nsec / 1000000000.0
 #define TimeSpecToSeconds(ts) (double)ts.tv_sec + (double)ts.tv_nsec / 1000000000.0
 #endif
 #endif
 
 
+#ifdef WIN32
+static LARGE_INTEGER freq;
+static int freq_init = -1;
+#endif
+
 CAMLprim value sys_time() {
 CAMLprim value sys_time() {
 #ifdef _WIN32
 #ifdef _WIN32
 #define EPOCH_DIFF	(134774*24*60*60.0)
 #define EPOCH_DIFF	(134774*24*60*60.0)
-	static LARGE_INTEGER freq;
-	static int freq_init = -1;
 	LARGE_INTEGER counter;
 	LARGE_INTEGER counter;
 	if( freq_init == -1 )
 	if( freq_init == -1 )
 		freq_init = QueryPerformanceFrequency(&freq);
 		freq_init = QueryPerformanceFrequency(&freq);
@@ -533,6 +536,26 @@ CAMLprim value sys_time() {
 #endif
 #endif
 }
 }
 
 
+CAMLprim value sys_timestamp_ms() {
+#ifdef _WIN32
+	if (-1 == freq_init) {
+		freq_init = QueryPerformanceFrequency(&freq);
+	}
+
+	LARGE_INTEGER time;
+	QueryPerformanceCounter(&time);
+
+	return caml_copy_int64(time.QuadPart * 1000LL / freq.QuadPart);
+#else
+	struct timespec ts;
+	if (clock_gettime(CLOCK_MONOTONIC, &ts)) {
+		caml_failwith("Failed to get time from the monotonic clock");
+	}
+
+	return caml_copy_int64(ts.tv_sec * 1000 + (ts.tv_nsec / 1000000));
+#endif
+}
+
 CAMLprim value sys_getch( value b ) {
 CAMLprim value sys_getch( value b ) {
 #	ifdef _WIN32
 #	ifdef _WIN32
 	return Val_int( Bool_val(b)?getche():getch() );
 	return Val_int( Bool_val(b)?getche():getch() );

+ 3 - 1
libs/objsize/objsize.ml

@@ -11,7 +11,9 @@ type info =
 
 
 external internal_objsize : Obj.t -> Obj.t list -> Obj.t list -> info = "ml_objsize"
 external internal_objsize : Obj.t -> Obj.t list -> Obj.t list -> info = "ml_objsize"
 
 
-let objsize obj exclude reach = internal_objsize (Obj.repr obj) exclude reach
+let objsize obj (exclude:Obj.t list) (reach:Obj.t list) =
+  (* internal_objsize (Obj.repr obj) exclude reach *)
+  {data = (Obj.reachable_words (Obj.repr obj)); headers = 0; depth = 0; reached = false}
 
 
 let size_with_headers i = (Sys.word_size/8) * (i.data + i.headers)
 let size_with_headers i = (Sys.word_size/8) * (i.data + i.headers)
 
 

+ 41 - 0
src-json/define.json

@@ -20,6 +20,7 @@
 		"name": "AnalyzerTimes",
 		"name": "AnalyzerTimes",
 		"define": "times.analyzer",
 		"define": "times.analyzer",
 		"deprecatedDefine": "analyzer-times",
 		"deprecatedDefine": "analyzer-times",
+		"signatureNeutral": true,
 		"doc": "Record detailed timers for the analyzer",
 		"doc": "Record detailed timers for the analyzer",
 		"params": ["level: 0 | 1 | 2"]
 		"params": ["level: 0 | 1 | 2"]
 	},
 	},
@@ -60,6 +61,7 @@
 	{
 	{
 		"name": "DceDebug",
 		"name": "DceDebug",
 		"define": "dce-debug",
 		"define": "dce-debug",
+		"signatureNeutral": true,
 		"doc": "Show DCE log.",
 		"doc": "Show DCE log.",
 		"links": ["https://haxe.org/manual/cr-dce.html"]
 		"links": ["https://haxe.org/manual/cr-dce.html"]
 	},
 	},
@@ -71,13 +73,21 @@
 	{
 	{
 		"name": "DisableHxbCache",
 		"name": "DisableHxbCache",
 		"define": "disable-hxb-cache",
 		"define": "disable-hxb-cache",
+		"signatureNeutral": true,
 		"doc": "Use in-memory cache instead of hxb powered cache."
 		"doc": "Use in-memory cache instead of hxb powered cache."
 	},
 	},
 	{
 	{
 		"name": "DisableHxbOptimizations",
 		"name": "DisableHxbOptimizations",
 		"define": "disable-hxb-optimizations",
 		"define": "disable-hxb-optimizations",
+		"signatureNeutral": true,
 		"doc": "Disable shortcuts used by hxb cache to speed up display requests."
 		"doc": "Disable shortcuts used by hxb cache to speed up display requests."
 	},
 	},
+	{
+		"name": "EnableParallelism",
+		"define": "enable-parallelism",
+		"signatureNeutral": true,
+		"doc": "Enable experimental uses of parallelism in the compiler."
+	},
 	{
 	{
 		"name": "DisableUnicodeStrings",
 		"name": "DisableUnicodeStrings",
 		"define": "disable-unicode-strings",
 		"define": "disable-unicode-strings",
@@ -87,14 +97,23 @@
 	{
 	{
 		"name": "Display",
 		"name": "Display",
 		"define": "display",
 		"define": "display",
+		"signatureNeutral": true,
 		"doc": "Activated during completion.",
 		"doc": "Activated during completion.",
 		"links": ["https://haxe.org/manual/cr-completion.html"]
 		"links": ["https://haxe.org/manual/cr-completion.html"]
 	},
 	},
 	{
 	{
 		"name": "DisplayStdin",
 		"name": "DisplayStdin",
 		"define": "display-stdin",
 		"define": "display-stdin",
+		"signatureNeutral": true,
 		"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": "DisplayDetails",
+		"define": "display-details",
+		"signatureNeutral": true,
+		"doc": "Not used anymore, but still sent by vshaxe.",
+		"deprecated": "This flag is no longer supported in Haxe 5"
+	},
 	{
 	{
 		"name": "DllExport",
 		"name": "DllExport",
 		"define": "dll-export",
 		"define": "dll-export",
@@ -109,12 +128,14 @@
 	{
 	{
 		"name": "Dump",
 		"name": "Dump",
 		"define": "dump",
 		"define": "dump",
+		"signatureNeutral": true,
 		"doc": "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"]
 		"params": ["mode: pretty | record | position | legacy"]
 	},
 	},
 	{
 	{
 		"name": "DumpStage",
 		"name": "DumpStage",
 		"define": "dump.stage",
 		"define": "dump.stage",
+		"signatureNeutral": true,
 		"doc": "The compiler stage after which to generate the dump",
 		"doc": "The compiler stage after which to generate the dump",
 		"params": ["stage: typing | casting | inlining | analyzing | dce"],
 		"params": ["stage: typing | casting | inlining | analyzing | dce"],
 		"default": "dce"
 		"default": "dce"
@@ -122,6 +143,7 @@
 	{
 	{
 		"name": "DumpPath",
 		"name": "DumpPath",
 		"define": "dump-path",
 		"define": "dump-path",
+		"signatureNeutral": true,
 		"doc": "Path to generate dumps to (default: \"dump\").",
 		"doc": "Path to generate dumps to (default: \"dump\").",
 		"default": "dump",
 		"default": "dump",
 		"params": ["path"]
 		"params": ["path"]
@@ -129,11 +151,13 @@
 	{
 	{
 		"name": "DumpDependencies",
 		"name": "DumpDependencies",
 		"define": "dump-dependencies",
 		"define": "dump-dependencies",
+		"signatureNeutral": true,
 		"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",
+		"signatureNeutral": true,
 		"doc": "Remove variable IDs from non-pretty dumps (helps with diff).",
 		"doc": "Remove variable IDs from non-pretty dumps (helps with diff).",
 		"default": "1"
 		"default": "1"
 	},
 	},
@@ -181,18 +205,21 @@
 		"name": "EvalTimes",
 		"name": "EvalTimes",
 		"define": "times.eval",
 		"define": "times.eval",
 		"deprecatedDefine": "eval-times",
 		"deprecatedDefine": "eval-times",
+		"signatureNeutral": true,
 		"doc": "Record per-method execution times in macro/interp mode. Implies eval-stack.",
 		"doc": "Record per-method execution times in macro/interp mode. Implies eval-stack.",
 		"platforms": ["eval"]
 		"platforms": ["eval"]
 	},
 	},
 	{
 	{
 		"name": "FailFast",
 		"name": "FailFast",
 		"define": "fail-fast",
 		"define": "fail-fast",
+		"signatureNeutral": true,
 		"doc": "Abort compilation when first error occurs."
 		"doc": "Abort compilation when first error occurs."
 	},
 	},
 	{
 	{
 		"name": "FilterTimes",
 		"name": "FilterTimes",
 		"define": "times.filter",
 		"define": "times.filter",
 		"deprecatedDefine": "filter-times",
 		"deprecatedDefine": "filter-times",
+		"signatureNeutral": true,
 		"doc": "Record per-filter execution times upon --times."
 		"doc": "Record per-filter execution times upon --times."
 	},
 	},
 	{
 	{
@@ -311,8 +338,15 @@
 		"name": "HxbTimes",
 		"name": "HxbTimes",
 		"define": "times.hxb",
 		"define": "times.hxb",
 		"deprecatedDefine": "hxb-times",
 		"deprecatedDefine": "hxb-times",
+		"signatureNeutral": true,
 		"doc": "Display hxb timing when used with `--times`."
 		"doc": "Display hxb timing when used with `--times`."
 	},
 	},
+	{
+		"name": "HxbStats",
+		"define": "hxb.stats",
+		"signatureNeutral": true,
+		"doc": "Display some hxb related stats (only with compilation server)."
+	},
 	{
 	{
 		"name": "HxcppApiLevel",
 		"name": "HxcppApiLevel",
 		"define": "hxcpp-api-level",
 		"define": "hxcpp-api-level",
@@ -550,6 +584,7 @@
 		"name": "MacroTimes",
 		"name": "MacroTimes",
 		"define": "times.macro",
 		"define": "times.macro",
 		"deprecatedDefine": "macro-times",
 		"deprecatedDefine": "macro-times",
+		"signatureNeutral": true,
 		"doc": "Display per-macro timing when used with `--times`."
 		"doc": "Display per-macro timing when used with `--times`."
 	},
 	},
 	{
 	{
@@ -582,6 +617,7 @@
 	{
 	{
 		"name": "NoCompilation",
 		"name": "NoCompilation",
 		"define": "no-compilation",
 		"define": "no-compilation",
+		"signatureNeutral": true,
 		"doc": "Disable final compilation.",
 		"doc": "Disable final compilation.",
 		"platforms": ["cpp", "hl"]
 		"platforms": ["cpp", "hl"]
 	},
 	},
@@ -843,6 +879,7 @@
 	{
 	{
 		"name": "MessageReporting",
 		"name": "MessageReporting",
 		"define": "message.reporting",
 		"define": "message.reporting",
+		"signatureNeutral": true,
 		"doc": "Select message reporting mode for compiler output. (default: pretty)",
 		"doc": "Select message reporting mode for compiler output. (default: pretty)",
 		"default": "pretty",
 		"default": "pretty",
 		"params": ["mode: classic | pretty | indent"]
 		"params": ["mode: classic | pretty | indent"]
@@ -850,21 +887,25 @@
 	{
 	{
 		"name": "MessageNoColor",
 		"name": "MessageNoColor",
 		"define": "message.no-color",
 		"define": "message.no-color",
+		"signatureNeutral": true,
 		"doc": "Disable ANSI color codes in message reporting."
 		"doc": "Disable ANSI color codes in message reporting."
 	},
 	},
 	{
 	{
 		"name": "MessageAbsolutePositions",
 		"name": "MessageAbsolutePositions",
 		"define": "message.absolute-positions",
 		"define": "message.absolute-positions",
+		"signatureNeutral": true,
 		"doc": "Use absolute character positions instead of line/columns for message reporting."
 		"doc": "Use absolute character positions instead of line/columns for message reporting."
 	},
 	},
 	{
 	{
 		"name": "MessageLogFile",
 		"name": "MessageLogFile",
 		"define": "message.log-file",
 		"define": "message.log-file",
+		"signatureNeutral": true,
 		"doc": "Path to a text file to write message reporting to, in addition to regular output."
 		"doc": "Path to a text file to write message reporting to, in addition to regular output."
 	},
 	},
 	{
 	{
 		"name": "MessageLogFormat",
 		"name": "MessageLogFormat",
 		"define": "message.log-format",
 		"define": "message.log-format",
+		"signatureNeutral": true,
 		"doc": "Select message reporting mode for message log file. (default: indent)",
 		"doc": "Select message reporting mode for message log file. (default: indent)",
 		"default": "indent",
 		"default": "indent",
 		"params": ["format: classic | pretty | indent"]
 		"params": ["format: classic | pretty | indent"]

+ 4 - 4
src/codegen/codegen.ml

@@ -28,8 +28,8 @@ open Extlib_leftovers
 let rec has_properties c =
 let rec has_properties c =
 	List.exists (fun f ->
 	List.exists (fun f ->
 		match f.cf_kind with
 		match f.cf_kind with
-		| Var { v_read = AccCall } -> true
-		| Var { v_write = AccCall } -> true
+		| Var { v_read = AccCall | AccPrivateCall } -> true
+		| Var { v_write = AccCall | AccPrivateCall } -> true
 		| _ when Meta.has Meta.Accessor f.cf_meta -> true
 		| _ when Meta.has Meta.Accessor f.cf_meta -> true
 		| _ -> false
 		| _ -> false
 	) c.cl_ordered_fields || (match c.cl_super with Some (c,_) -> has_properties c | _ -> false)
 	) c.cl_ordered_fields || (match c.cl_super with Some (c,_) -> has_properties c | _ -> false)
@@ -40,10 +40,10 @@ let get_properties fields =
 			(f.cf_name, f.cf_name) :: acc
 			(f.cf_name, f.cf_name) :: acc
 		else
 		else
 			let acc = (match f.cf_kind with
 			let acc = (match f.cf_kind with
-			| Var { v_read = AccCall } -> ("get_" ^ f.cf_name , "get_" ^ f.cf_name) :: acc
+			| Var { v_read = AccCall | AccPrivateCall } -> ("get_" ^ f.cf_name , "get_" ^ f.cf_name) :: acc
 			| _ -> acc) in
 			| _ -> acc) in
 			match f.cf_kind with
 			match f.cf_kind with
-			| Var { v_write = AccCall } -> ("set_" ^ f.cf_name , "set_" ^ f.cf_name) :: acc
+			| Var { v_write = AccCall | AccPrivateCall } -> ("set_" ^ f.cf_name , "set_" ^ f.cf_name) :: acc
 			| _ -> acc
 			| _ -> acc
 	) [] fields
 	) [] fields
 
 

+ 1 - 1
src/codegen/genxml.ml

@@ -135,7 +135,7 @@ and gen_field att f =
 		match acc with
 		match acc with
 		| AccNormal | AccRequire _ | AccCtor -> att
 		| AccNormal | AccRequire _ | AccCtor -> att
 		| AccNo | AccNever -> (name, "null") :: att
 		| AccNo | AccNever -> (name, "null") :: att
-		| AccCall -> (name,"accessor") :: att
+		| AccCall | AccPrivateCall -> (name,"accessor") :: att
 		| AccInline -> (name,"inline") :: att
 		| AccInline -> (name,"inline") :: att
 	in
 	in
 	let att = (match f.cf_expr with None -> att | Some e -> ("line",string_of_int (Lexer.get_error_line e.epos)) :: att) in
 	let att = (match f.cf_expr with None -> att | Some e -> ("line",string_of_int (Lexer.get_error_line e.epos)) :: att) in

+ 11 - 7
src/compiler/compilationCache.ml

@@ -36,6 +36,7 @@ class context_cache (index : int) (sign : Digest.t) = object(self)
 	val modules : (path,module_def) Hashtbl.t = Hashtbl.create 0
 	val modules : (path,module_def) Hashtbl.t = Hashtbl.create 0
 	val binary_cache : (path,HxbData.module_cache) Hashtbl.t = Hashtbl.create 0
 	val binary_cache : (path,HxbData.module_cache) Hashtbl.t = Hashtbl.create 0
 	val tmp_binary_cache : (path,HxbData.module_cache) Hashtbl.t = Hashtbl.create 0
 	val tmp_binary_cache : (path,HxbData.module_cache) Hashtbl.t = Hashtbl.create 0
+	val get_hxb_module_mutex = Mutex.create ()
 	val removed_files = Hashtbl.create 0
 	val removed_files = Hashtbl.create 0
 	val mutable json = JNull
 	val mutable json = JNull
 	val mutable initialized = false
 	val mutable initialized = false
@@ -68,13 +69,16 @@ class context_cache (index : int) (sign : Digest.t) = object(self)
 		Hashtbl.find_opt modules path
 		Hashtbl.find_opt modules path
 
 
 	method get_hxb_module path =
 	method get_hxb_module path =
-		try Hashtbl.find tmp_binary_cache path
-		with Not_found ->
-			let mc = Hashtbl.find binary_cache path in
-			let m_extra = { mc.mc_extra with m_deps = mc.mc_extra.m_deps } in
-			let mc = { mc with mc_extra = m_extra } in
-			Hashtbl.add tmp_binary_cache path mc;
-			mc
+		Mutex.protect get_hxb_module_mutex (fun () ->
+			try
+				Hashtbl.find tmp_binary_cache path
+			with Not_found ->
+				let mc = Hashtbl.find binary_cache path in
+				let m_extra = { mc.mc_extra with m_deps = mc.mc_extra.m_deps } in
+				let mc = { mc with mc_extra = m_extra } in
+				Hashtbl.add tmp_binary_cache path mc;
+				mc
+		)
 
 
 	method find_module_extra path =
 	method find_module_extra path =
 		try (Hashtbl.find modules path).m_extra
 		try (Hashtbl.find modules path).m_extra

+ 2 - 2
src/compiler/compiler.ml

@@ -270,6 +270,7 @@ module Setup = struct
 end
 end
 
 
 let check_defines com =
 let check_defines com =
+	if defined com Define.EnableParallelism then Parallel.enable := true;
 	PMap.iter (fun k v ->
 	PMap.iter (fun k v ->
 		try
 		try
 			let reason = Hashtbl.find Define.deprecation_lut k in
 			let reason = Hashtbl.find Define.deprecation_lut k in
@@ -297,6 +298,7 @@ let do_type ctx mctx actx display_file_dot_path =
 		Some (MacroContext.call_init_macro ctx.com mctx path)
 		Some (MacroContext.call_init_macro ctx.com mctx path)
 	) mctx (List.rev actx.config_macros) in
 	) mctx (List.rev actx.config_macros) in
 	enter_stage com CInitMacrosDone;
 	enter_stage com CInitMacrosDone;
+	check_defines ctx.com;
 	update_platform_config com; (* make sure to adapt all flags changes defined during init macros *)
 	update_platform_config com; (* make sure to adapt all flags changes defined during init macros *)
 	ServerMessage.compiler_stage com;
 	ServerMessage.compiler_stage com;
 
 
@@ -304,7 +306,6 @@ let do_type ctx mctx actx display_file_dot_path =
 	Setup.init_native_libs com actx.native_libs;
 	Setup.init_native_libs com actx.native_libs;
 	let tctx = Setup.create_typer_context ctx macros in
 	let tctx = Setup.create_typer_context ctx macros in
 	let display_file_dot_path = DisplayProcessing.maybe_load_display_file_before_typing tctx display_file_dot_path in
 	let display_file_dot_path = DisplayProcessing.maybe_load_display_file_before_typing tctx display_file_dot_path in
-	check_defines ctx.com;
 	DumpConfig.update_from_defines com.dump_config com.defines;
 	DumpConfig.update_from_defines com.dump_config com.defines;
 	CommonCache.lock_signature com "after_init_macros";
 	CommonCache.lock_signature com "after_init_macros";
 	Option.may (fun mctx -> MacroContext.finalize_macro_api tctx mctx) mctx;
 	Option.may (fun mctx -> MacroContext.finalize_macro_api tctx mctx) mctx;
@@ -347,7 +348,6 @@ let finalize_typing ctx tctx =
 
 
 let filter ctx tctx ectx before_destruction =
 let filter ctx tctx ectx before_destruction =
 	Timer.time ctx.timer_ctx ["filters"] (fun () ->
 	Timer.time ctx.timer_ctx ["filters"] (fun () ->
-		DeprecationCheck.run ctx.com;
 		run_or_diagnose ctx (fun () -> Filters.run tctx ectx ctx.com.main.main_expr before_destruction)
 		run_or_diagnose ctx (fun () -> Filters.run tctx ectx ctx.com.main.main_expr before_destruction)
 	) ()
 	) ()
 
 

+ 1 - 0
src/compiler/hxb/hxbReader.ml

@@ -993,6 +993,7 @@ class hxb_reader
 					let s = self#read_string in
 					let s = self#read_string in
 					let so = self#read_option (fun () -> self#read_string) in
 					let so = self#read_option (fun () -> self#read_string) in
 					AccRequire(s,so)
 					AccRequire(s,so)
+				| 7 -> AccPrivateCall
 				| i ->
 				| i ->
 					error (Printf.sprintf "Bad accessor kind: %i" i)
 					error (Printf.sprintf "Bad accessor kind: %i" i)
 			in
 			in

+ 1 - 0
src/compiler/hxb/hxbWriter.ml

@@ -1710,6 +1710,7 @@ module HxbWriter = struct
 					Chunk.write_u8 writer.chunk 6;
 					Chunk.write_u8 writer.chunk 6;
 					Chunk.write_string writer.chunk s;
 					Chunk.write_string writer.chunk s;
 					Chunk.write_option writer.chunk so (Chunk.write_string writer.chunk)
 					Chunk.write_option writer.chunk so (Chunk.write_string writer.chunk)
+				| AccPrivateCall -> Chunk.write_u8 writer.chunk 7
 			in
 			in
 			f r;
 			f r;
 			f w
 			f w

+ 2 - 2
src/compiler/server.ml

@@ -481,8 +481,8 @@ let handle_cache_bound_objects com cbol =
 			Hashtbl.replace com.resources name data
 			Hashtbl.replace com.resources name data
 		| IncludeFile(file,position) ->
 		| IncludeFile(file,position) ->
 			com.include_files <- (file,position) :: com.include_files
 			com.include_files <- (file,position) :: com.include_files
-		| Warning(w,msg,p) ->
-			com.warning w [] msg p
+		| Warning(w,options,msg,p) ->
+			com.warning w options msg p
 	) cbol
 	) cbol
 
 
 (* Adds module [m] and all its dependencies (recursively) from the cache to the current compilation
 (* Adds module [m] and all its dependencies (recursively) from the cache to the current compilation

+ 1 - 0
src/compiler/serverCompilationContext.ml

@@ -44,6 +44,7 @@ let reset sctx =
 	Hashtbl.clear sctx.changed_directories;
 	Hashtbl.clear sctx.changed_directories;
 	sctx.was_compilation <- false;
 	sctx.was_compilation <- false;
 	Parser.reset_state();
 	Parser.reset_state();
+	Parallel.enable := false;
 	Hashtbl.clear DeprecationCheck.warned_positions;
 	Hashtbl.clear DeprecationCheck.warned_positions;
 	stats.s_files_parsed := 0;
 	stats.s_files_parsed := 0;
 	stats.s_classes_built := 0;
 	stats.s_classes_built := 0;

+ 5 - 1
src/compiler/serverMessage.ml

@@ -24,6 +24,7 @@ type server_message_options = {
 	mutable print_signature : bool;
 	mutable print_signature : bool;
 	mutable print_display_position : bool;
 	mutable print_display_position : bool;
 	mutable print_stats : bool;
 	mutable print_stats : bool;
+	mutable print_gc_stats : bool;
 	mutable print_message : bool;
 	mutable print_message : bool;
 	mutable print_socket_message : bool;
 	mutable print_socket_message : bool;
 	mutable print_uncaught_error : bool;
 	mutable print_uncaught_error : bool;
@@ -51,6 +52,7 @@ let config = {
 	print_signature = false;
 	print_signature = false;
 	print_display_position = false;
 	print_display_position = false;
 	print_stats = false;
 	print_stats = false;
+	print_gc_stats = false;
 	print_message = false;
 	print_message = false;
 	print_socket_message = false;
 	print_socket_message = false;
 	print_uncaught_error = false;
 	print_uncaught_error = false;
@@ -143,7 +145,7 @@ let message s =
 	if config.print_message then print_endline ("> " ^ s)
 	if config.print_message then print_endline ("> " ^ s)
 
 
 let gc_stats time stats_before did_compact space_overhead =
 let gc_stats time stats_before did_compact space_overhead =
-	if config.print_stats then begin
+	if config.print_stats || config.print_gc_stats then begin
 		let stats = Gc.quick_stat() in
 		let stats = Gc.quick_stat() in
 		print_endline (Printf.sprintf "GC %s done in %.2fs with space_overhead = %i\n\tbefore: %s\n\tafter: %s"
 		print_endline (Printf.sprintf "GC %s done in %.2fs with space_overhead = %i\n\tbefore: %s\n\tafter: %s"
 			(if did_compact then "compaction" else "collection")
 			(if did_compact then "compaction" else "collection")
@@ -180,6 +182,7 @@ let enable_all () =
 	config.print_signature <- true;
 	config.print_signature <- true;
 	config.print_display_position <- true;
 	config.print_display_position <- true;
 	config.print_stats <- true;
 	config.print_stats <- true;
+	config.print_gc_stats <- true;
 	config.print_message <- true;
 	config.print_message <- true;
 	config.print_socket_message <- true;
 	config.print_socket_message <- true;
 	config.print_uncaught_error <- true;
 	config.print_uncaught_error <- true;
@@ -205,6 +208,7 @@ let set_by_name name value = match name with
 	| "signature" -> config.print_signature <- value;
 	| "signature" -> config.print_signature <- value;
 	| "displayPosition" -> config.print_display_position <- value;
 	| "displayPosition" -> config.print_display_position <- value;
 	| "stats" -> config.print_stats <- value;
 	| "stats" -> config.print_stats <- value;
+	| "gcStats" -> config.print_gc_stats <- value;
 	| "message" -> config.print_message <- value;
 	| "message" -> config.print_message <- value;
 	| "socketMessage" -> config.print_socket_message <- value;
 	| "socketMessage" -> config.print_socket_message <- value;
 	| "uncaughtError" -> config.print_uncaught_error <- value;
 	| "uncaughtError" -> config.print_uncaught_error <- value;

+ 40 - 6
src/context/abstractCast.ml

@@ -200,13 +200,45 @@ let find_array_write_access ctx a tl e1 e2 p =
 		let s_type = s_type (print_context()) in
 		let s_type = s_type (print_context()) in
 		raise_typing_error (Printf.sprintf "No @:arrayAccess function for %s accepts arguments of %s and %s" (s_type (TAbstract(a,tl))) (s_type e1.etype) (s_type e2.etype)) p
 		raise_typing_error (Printf.sprintf "No @:arrayAccess function for %s accepts arguments of %s and %s" (s_type (TAbstract(a,tl))) (s_type e1.etype) (s_type e2.etype)) p
 
 
+(* TODO: This duplicates pretty much all the code from unifies_to_field. The only reason for that is
+   that we want the monos so we can apply them to the type. Surely we can design our data better here... *)
+let find_to_field uctx b ab tl =
+	let a = TAbstract(ab,tl) in
+	let check t cf = match follow cf.cf_type with
+		| TFun((_,_,ta) :: _,_) ->
+			let map = apply_params ab.a_params tl in
+			let monos = Monomorph.spawn_constrained_monos map cf.cf_params in
+			let map t = map (apply_params cf.cf_params monos t) in
+			let uctx = get_abstract_context uctx a b ab in
+			let unify_func = get_abstract_unify_func uctx EqStrict in
+			let athis = map ab.a_this in
+			(* we cannot allow implicit casts when the this type is not completely known yet *)
+			if Meta.has Meta.MultiType ab.a_meta && has_mono athis then raise (Unify_error []);
+			with_variance uctx (type_eq_custom {uctx with equality_kind = EqStrict}) athis (map ta);
+			unify_func (map t) b;
+			t,cf,monos
+		| _ ->
+			die "" __LOC__
+	in
+	let rec loop cfl = match cfl with
+		| [] ->
+			raise Not_found
+		| (t,cf) :: cfl ->
+			begin try
+				check t cf
+			with Unify_error _ ->
+				loop cfl
+			end
+	in
+	loop ab.a_to_field
+
 let find_multitype_specialization' platform a pl p =
 let find_multitype_specialization' platform a pl p =
 	let uctx = default_unification_context () in
 	let uctx = default_unification_context () in
 	let m = mk_mono() in
 	let m = mk_mono() in
 	let tl,definitive_types = Abstract.find_multitype_params a pl in
 	let tl,definitive_types = Abstract.find_multitype_params a pl in
-	let _,cf =
+	let _,cf,field_monos =
 		try
 		try
-			let t = Abstract.find_to uctx m a tl in
+			let t = find_to_field uctx m a tl in
 			if List.exists (fun t -> has_mono t) definitive_types then begin
 			if List.exists (fun t -> has_mono t) definitive_types then begin
 				let at = apply_params a.a_params pl a.a_this in
 				let at = apply_params a.a_params pl a.a_this in
 				let st = s_type (print_context()) at in
 				let st = s_type (print_context()) at in
@@ -221,10 +253,10 @@ let find_multitype_specialization' platform a pl p =
 			else
 			else
 				raise_typing_error ("Abstract " ^ (s_type_path a.a_path) ^ " has no @:to function that accepts " ^ st) p;
 				raise_typing_error ("Abstract " ^ (s_type_path a.a_path) ^ " has no @:to function that accepts " ^ st) p;
 	in
 	in
-	cf,follow m,tl
+	cf,field_monos,follow m,tl
 
 
 let find_multitype_specialization platform a pl p =
 let find_multitype_specialization platform a pl p =
-	let cf,m,_ = find_multitype_specialization' platform a pl p in
+	let cf,field_monos,m,_ = find_multitype_specialization' platform a pl p in
 	(cf,m)
 	(cf,m)
 
 
 let handle_abstract_casts (scom : SafeCom.t) e =
 let handle_abstract_casts (scom : SafeCom.t) e =
@@ -238,8 +270,10 @@ let handle_abstract_casts (scom : SafeCom.t) e =
 				| _ -> raise_typing_error ("Cannot construct " ^ (s_type (print_context()) (TAbstract(a,pl)))) e.epos
 				| _ -> raise_typing_error ("Cannot construct " ^ (s_type (print_context()) (TAbstract(a,pl)))) e.epos
 			end else begin
 			end else begin
 				(* a TNew of an abstract implementation is only generated if it is a multi type abstract *)
 				(* a TNew of an abstract implementation is only generated if it is a multi type abstract *)
-				let cf,m,pl = find_multitype_specialization' scom.platform a pl e.epos in
-				let e = ExceptionFunctions.make_static_call scom c cf ((mk (TConst TNull) (TAbstract(a,pl)) e.epos) :: el)  m e.epos in
+				let cf,field_monos,m,pl = find_multitype_specialization' scom.platform a pl e.epos in
+				let e_this = Texpr.Builder.make_static_this c e.epos in
+				let ef = mk (TField(e_this,FStatic(c,cf))) (apply_params cf.cf_params field_monos cf.cf_type) e.epos in
+				let e = ExceptionFunctions.make_call scom ef ((mk (TConst TNull) (TAbstract(a,pl)) e.epos) :: el) m e.epos in
 				{e with etype = m}
 				{e with etype = m}
 			end
 			end
 		| TCall({eexpr = TField(_,FStatic({cl_path=[],"Std"},{cf_name = "string"}))},[e1]) when (match follow e1.etype with TAbstract({a_impl = Some _},_) -> true | _ -> false) ->
 		| TCall({eexpr = TField(_,FStatic({cl_path=[],"Std"},{cf_name = "string"}))},[e1]) when (match follow e1.etype with TAbstract({a_impl = Some _},_) -> true | _ -> false) ->

+ 119 - 37
src/context/common.ml

@@ -22,7 +22,6 @@ open Globals
 open Lookup
 open Lookup
 open Define
 open Define
 open NativeLibraries
 open NativeLibraries
-open Warning
 
 
 type package_rule =
 type package_rule =
 	| Forbidden
 	| Forbidden
@@ -234,6 +233,34 @@ type parser_state = {
 	special_identifier_files : (Path.UniqueKey.t,string) ThreadSafeHashtbl.t;
 	special_identifier_files : (Path.UniqueKey.t,string) ThreadSafeHashtbl.t;
 }
 }
 
 
+module LocalWrapper = struct
+	type t = <
+		captured_type : TType.t -> TType.t;
+		mk_init : tvar -> tvar -> pos -> texpr;
+		mk_ref : tvar -> texpr option -> pos -> texpr;
+		mk_ref_access : texpr -> tvar -> texpr
+	>
+
+	let null_wrapper = object
+		method captured_type =
+			(fun t -> t)
+
+		method mk_ref v ve p =
+			let ev = Texpr.Builder.make_local v p in
+			match ve with
+			| None ->
+				ev
+			| Some e ->
+				Texpr.Builder.binop OpAssign ev e ev.etype p
+
+		method mk_ref_access e v =
+			e
+
+		method mk_init av v p =
+			mk (TVar (av,Some (mk (TLocal v) v.v_type p))) t_dynamic p
+	end
+end
+
 type context = {
 type context = {
 	compilation_step : int;
 	compilation_step : int;
 	mutable stage : compiler_stage;
 	mutable stage : compiler_stage;
@@ -265,7 +292,7 @@ type context = {
 	mutable error_ext : Error.error -> unit;
 	mutable error_ext : Error.error -> unit;
 	mutable info : ?depth:int -> ?from_macro:bool -> string -> pos -> unit;
 	mutable info : ?depth:int -> ?from_macro:bool -> string -> pos -> unit;
 	mutable warning : Gctx.warning_function;
 	mutable warning : Gctx.warning_function;
-	mutable warning_options : Warning.warning_option list list;
+	mutable warning_options : warning_option list list;
 	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 run_command : string -> int;
 	mutable run_command : string -> int;
@@ -277,6 +304,7 @@ type context = {
 	mutable user_defines : (string, Define.user_define) Hashtbl.t;
 	mutable user_defines : (string, Define.user_define) Hashtbl.t;
 	mutable user_metas : (string, Meta.user_meta) Hashtbl.t;
 	mutable user_metas : (string, Meta.user_meta) Hashtbl.t;
 	mutable get_macros : unit -> context option;
 	mutable get_macros : unit -> context option;
+	mutable local_wrapper : LocalWrapper.t;
 	(* typing state *)
 	(* typing state *)
 	mutable std : tclass;
 	mutable std : tclass;
 	mutable global_metadata : (string list * metadata_entry * (bool * bool * bool)) list;
 	mutable global_metadata : (string list * metadata_entry * (bool * bool * bool)) list;
@@ -307,8 +335,6 @@ type context = {
 	mutable include_files : (string * string) list;
 	mutable include_files : (string * string) list;
 	mutable native_libs : native_libraries;
 	mutable native_libs : native_libraries;
 	mutable hxb_libs : abstract_hxb_lib list;
 	mutable hxb_libs : abstract_hxb_lib list;
-	mutable net_std : string list;
-	net_path_map : (path,string list * string list * string) Hashtbl.t;
 	mutable js_gen : (unit -> unit) option;
 	mutable js_gen : (unit -> unit) option;
 	(* misc *)
 	(* misc *)
 	mutable basic : basic_types;
 	mutable basic : basic_types;
@@ -354,7 +380,7 @@ let ignore_error com =
 	b
 	b
 
 
 let module_warning com m w options msg p =
 let module_warning com m w options msg p =
-	if com.display.dms_full_typing then DynArray.add m.m_extra.m_cache_bound_objects (Warning(w,msg,p));
+	if com.display.dms_full_typing then DynArray.add m.m_extra.m_cache_bound_objects (Warning(w,options,msg,p));
 	com.warning w options msg p
 	com.warning w options msg p
 
 
 (* Defines *)
 (* Defines *)
@@ -679,7 +705,8 @@ let get_config com =
 			pf_capture_policy = CPWrapRef;
 			pf_capture_policy = CPWrapRef;
 			pf_exceptions = { default_config.pf_exceptions with
 			pf_exceptions = { default_config.pf_exceptions with
 				ec_avoid_wrapping = false
 				ec_avoid_wrapping = false
-			}
+			};
+			pf_supports_atomics = true;
 		}
 		}
 
 
 let memory_marker = [|Unix.time()|]
 let memory_marker = [|Unix.time()|]
@@ -732,10 +759,8 @@ let create timer_ctx compilation_step cs version args display_mode =
 		fake_modules = Hashtbl.create 0;
 		fake_modules = Hashtbl.create 0;
 		flash_version = 10.;
 		flash_version = 10.;
 		resources = Hashtbl.create 0;
 		resources = Hashtbl.create 0;
-		net_std = [];
 		native_libs = create_native_libs();
 		native_libs = create_native_libs();
 		hxb_libs = [];
 		hxb_libs = [];
-		net_path_map = Hashtbl.create 0;
 		neko_lib_paths = [];
 		neko_lib_paths = [];
 		include_files = [];
 		include_files = [];
 		js_gen = None;
 		js_gen = None;
@@ -744,6 +769,7 @@ let create timer_ctx compilation_step cs version args display_mode =
 		user_defines = Hashtbl.create 0;
 		user_defines = Hashtbl.create 0;
 		user_metas = Hashtbl.create 0;
 		user_metas = Hashtbl.create 0;
 		get_macros = (fun() -> None);
 		get_macros = (fun() -> None);
+		local_wrapper = LocalWrapper.null_wrapper;
 		info = (fun ?depth ?from_macro _ _ -> die "" __LOC__);
 		info = (fun ?depth ?from_macro _ _ -> die "" __LOC__);
 		warning = (fun ?depth ?from_macro _ _ _ -> die "" __LOC__);
 		warning = (fun ?depth ?from_macro _ _ _ -> die "" __LOC__);
 		warning_options = [List.map (fun w -> {wo_warning = w;wo_mode = WMDisable}) WarningList.disabled_warnings];
 		warning_options = [List.map (fun w -> {wo_warning = w;wo_mode = WMDisable}) WarningList.disabled_warnings];
@@ -805,47 +831,103 @@ let log com str =
 	if com.verbose then com.print (str ^ "\n")
 	if com.verbose then com.print (str ^ "\n")
 
 
 let clone com is_macro_context =
 let clone com is_macro_context =
-	let t = com.basic in
-	{ com with
+	{
+		(* keeps *)
+		compilation_step = com.compilation_step;
+		cs = com.cs;
+		timer_ctx = com.timer_ctx;
+		version = com.version;
+		args = com.args;
+		shared = com.shared;
+		debug = com.debug;
+		display = com.display;
+		verbose = com.verbose;
+		foptimize = com.foptimize;
+		doinline = com.doinline;
+		platform = com.platform;
+		config = com.config;
+		print = com.print;
+		run_command = com.run_command;
+		run_command_args = com.run_command_args;
+		package_rules = com.package_rules;
+		file = com.file;
+		global_metadata = com.global_metadata;
+		flash_version = com.flash_version;
+		resources = com.resources;
+		native_libs = com.native_libs;
+		hxb_libs = com.hxb_libs;
+		neko_lib_paths = com.neko_lib_paths;
+		include_files = com.include_files;
+		js_gen = com.js_gen;
+		defines = {
+			values = com.defines.values;
+			defines_signature = com.defines.defines_signature;
+		};
+		user_defines = com.user_defines;
+		user_metas = com.user_metas;
+		get_macros = com.get_macros;
+		info = com.info;
+		warning = com.warning;
+		warning_options = com.warning_options;
+		error = com.error;
+		error_ext = com.error_ext;
+		get_messages = com.get_messages;
+		filter_messages = com.filter_messages;
+		pass_debug_messages = com.pass_debug_messages;
+		file_keys = com.file_keys;
+		stored_typed_exprs = com.stored_typed_exprs;
+		cached_macros = com.cached_macros;
+		memory_marker = com.memory_marker;
+		json_out = com.json_out;
+		has_error = com.has_error;
+		report_mode = com.report_mode;
+		hxb_writer_config = com.hxb_writer_config;
+		parser_state = com.parser_state;
+		dump_config = com.dump_config;
+		file_contents = com.file_contents;
+		(* reinits *)
 		cache = None;
 		cache = None;
 		stage = CCreated;
 		stage = CCreated;
-		basic = { t with
-			tvoid = mk_mono();
-			tany = mk_mono();
-			tint = mk_mono();
-			tfloat = mk_mono();
-			tbool = mk_mono();
-			tstring = mk_mono();
+		display_information = {
+			unresolved_identifiers = [];
+			display_module_has_macro_defines = false;
+			module_diagnostics = [];
 		};
 		};
+		features = Hashtbl.create 0;
+		empty_class_path = new ClassPath.directory_class_path "" User;
+		class_paths = new ClassPaths.class_paths;
 		main = {
 		main = {
 			main_path = None;
 			main_path = None;
 			main_file = None;
 			main_file = None;
 			main_expr = None;
 			main_expr = None;
 		};
 		};
-		features = Hashtbl.create 0;
+		types = [];
 		callbacks = new compiler_callbacks;
 		callbacks = new compiler_callbacks;
-		display_information = {
-			unresolved_identifiers = [];
-			display_module_has_macro_defines = false;
-			module_diagnostics = [];
-		};
-		defines = {
-			values = com.defines.values;
-			defines_signature = com.defines.defines_signature;
-		};
-		native_libs = create_native_libs();
-		is_macro_context = is_macro_context;
-		parser_cache = new hashtbl_lookup;
-		module_to_file = new hashtbl_lookup;
-		overload_cache = new hashtbl_lookup;
+		modules = [];
 		module_lut = new module_lut;
 		module_lut = new module_lut;
+		module_nonexistent_lut = new hashtbl_lookup;
 		fake_modules = Hashtbl.create 0;
 		fake_modules = Hashtbl.create 0;
-		hxb_reader_api = None;
-		hxb_reader_stats = HxbReader.create_hxb_reader_stats ();
+		load_extern_type = []; (* ! *)
+		basic = {
+			tvoid = mk_mono();
+			tany = mk_mono();
+			tint = mk_mono();
+			tfloat = mk_mono();
+			tbool = mk_mono();
+			tstring = mk_mono();
+			tnull = (fun _ -> die "Could use locate abstract Null<T> (was it redefined?)" __LOC__);
+			tarray = (fun _ -> die "Could not locate class Array<T> (was it redefined?)" __LOC__);
+			titerator = (fun _ -> die "Could not locate typedef Iterator<T> (was it redefined?)" __LOC__);
+		};
+		local_wrapper = LocalWrapper.null_wrapper;
 		std = null_class;
 		std = null_class;
+		module_to_file = new hashtbl_lookup;
+		parser_cache = new hashtbl_lookup;
+		overload_cache = new hashtbl_lookup; (* ! *)
+		is_macro_context = is_macro_context;
 		functional_interface_lut = new Lookup.hashtbl_lookup;
 		functional_interface_lut = new Lookup.hashtbl_lookup;
-		empty_class_path = new ClassPath.directory_class_path "" User;
-		class_paths = new ClassPaths.class_paths;
+		hxb_reader_api = None;
+		hxb_reader_stats = HxbReader.create_hxb_reader_stats ();
 	}
 	}
 
 
 let file_time file = Extc.filetime file
 let file_time file = Extc.filetime file
@@ -1059,4 +1141,4 @@ let make_unforced_lazy t_proc f where =
 			| Error.Error e ->
 			| Error.Error e ->
 				raise (Error.Fatal_error e)
 				raise (Error.Fatal_error e)
 	);
 	);
-	r
+	r

+ 1 - 1
src/context/commonCache.ml

@@ -122,7 +122,7 @@ let rec cache_context cs com =
 		| None -> ()
 		| None -> ()
 		| Some com -> cache_context cs com
 		| Some com -> cache_context cs com
 	end;
 	end;
-	if Define.raw_defined com.defines "hxb.stats" then
+	if Define.defined com.defines HxbStats then
 		HxbReader.dump_stats (platform_name com.platform) com.hxb_reader_stats
 		HxbReader.dump_stats (platform_name com.platform) com.hxb_reader_stats
 
 
 let maybe_add_context_sign cs com desc =
 let maybe_add_context_sign cs com desc =

+ 5 - 7
src/context/display/deprecationCheck.ml

@@ -22,11 +22,9 @@ let warned_positions = Hashtbl.create 0
 let warn_deprecation dctx s p_usage =
 let warn_deprecation dctx s p_usage =
 	let pkey p = (p.pfile,p.pmin) in
 	let pkey p = (p.pfile,p.pmin) in
 	if not (Hashtbl.mem warned_positions (pkey p_usage)) then begin
 	if not (Hashtbl.mem warned_positions (pkey p_usage)) then begin
-		Hashtbl.add warned_positions (pkey p_usage) (s,p_usage);
-		if not (is_diagnostics dctx.com) then begin
-			let options = Warning.from_meta (dctx.class_meta @ dctx.field_meta) in
-			module_warning dctx.com dctx.curmod WDeprecated options s p_usage;
-		end
+		let options = Warning.from_meta (dctx.class_meta @ dctx.field_meta) in
+		Hashtbl.add warned_positions (pkey p_usage) (s,p_usage,options);
+		module_warning dctx.com dctx.curmod WDeprecated options s p_usage;
 	end
 	end
 
 
 let print_deprecation_message dctx meta s p_usage =
 let print_deprecation_message dctx meta s p_usage =
@@ -101,7 +99,7 @@ let run_on_field dctx cf =
 	| _ ->
 	| _ ->
 		()
 		()
 
 
-let run com =
+let run com types =
 	let dctx = create_context com in
 	let dctx = create_context com in
 	List.iter (fun t -> match t with
 	List.iter (fun t -> match t with
 		| TClassDecl c when not (Meta.has Meta.Deprecated c.cl_meta) ->
 		| TClassDecl c when not (Meta.has Meta.Deprecated c.cl_meta) ->
@@ -112,7 +110,7 @@ let run com =
 			List.iter (run_on_field dctx) c.cl_ordered_fields;
 			List.iter (run_on_field dctx) c.cl_ordered_fields;
 		| _ ->
 		| _ ->
 			()
 			()
-	) com.types
+	) types
 
 
 let check_is com m cl_meta cf_meta name meta p =
 let check_is com m cl_meta cf_meta name meta p =
 	let dctx = {
 	let dctx = {

+ 7 - 3
src/context/display/diagnosticsPrinter.ml

@@ -183,9 +183,13 @@ let json_of_diagnostics com dctx =
 	(* non-append from here *)
 	(* non-append from here *)
 	begin match Warning.get_mode WDeprecated com.warning_options with
 	begin match Warning.get_mode WDeprecated com.warning_options with
 	| WMEnable ->
 	| WMEnable ->
-		Hashtbl.iter (fun _ (s,p) ->
-			let wobj = Warning.warning_obj WDeprecated in
-			add DKDeprecationWarning p MessageSeverity.Warning (Some wobj.w_name) (JString s);
+		Hashtbl.iter (fun _ (s,p,options) ->
+			begin match Warning.get_mode WDeprecated (com.warning_options @ options) with
+			| WMEnable ->
+				let wobj = Warning.warning_obj WDeprecated in
+				add DKDeprecationWarning p MessageSeverity.Warning (Some wobj.w_name) (JString s);
+			| WMDisable -> ()
+			end
 		) DeprecationCheck.warned_positions;
 		) DeprecationCheck.warned_positions;
 	| WMDisable ->
 	| WMDisable ->
 		()
 		()

+ 31 - 4
src/context/display/displayFields.ml

@@ -35,7 +35,7 @@ let get_submodule_fields ctx path =
 	) tl in
 	) tl in
 	tl
 	tl
 
 
-let collect_static_extensions ctx items e p =
+let collect_static_extensions ctx blocked_items items e p =
 	let opt_type t =
 	let opt_type t =
 		match t with
 		match t with
 		| TLazy f ->
 		| TLazy f ->
@@ -81,7 +81,13 @@ let collect_static_extensions ctx items e p =
 			end
 			end
 		| _ ->
 		| _ ->
 			acc
 			acc
-		in
+	in
+	let handle_field c cf acc =
+		if Hashtbl.mem blocked_items cf.cf_name then
+			acc
+		else
+			handle_field c cf acc
+	in
 	let rec loop acc = function
 	let rec loop acc = function
 		| [] ->
 		| [] ->
 			acc
 			acc
@@ -142,6 +148,17 @@ let collect ctx e_ast e dk with_type p =
 		let ct = CompletionType.from_type (get_import_status ctx) ~values:(get_value_meta cf.cf_meta) cf.cf_type in
 		let ct = CompletionType.from_type (get_import_status ctx) ~values:(get_value_meta cf.cf_meta) cf.cf_type in
 		make_ci_class_field (CompletionClassField.make cf CFSMember origin true) (cf.cf_type,ct)
 		make_ci_class_field (CompletionClassField.make cf CFSMember origin true) (cf.cf_type,ct)
 	in
 	in
+	let blocked_items = Hashtbl.create 0 in
+	let should_access c cf stat =
+		if Hashtbl.mem blocked_items cf.cf_name then
+			false
+		else if should_access c cf stat then
+			true
+		else begin
+			Hashtbl.add blocked_items cf.cf_name ();
+			false
+		end
+	in
 	let rec loop items t =
 	let rec loop items t =
 		let is_new_item items name = not (PMap.mem name items) in
 		let is_new_item items name = not (PMap.mem name items) in
 		let rec browse_interfaces c acc =
 		let rec browse_interfaces c acc =
@@ -345,7 +362,7 @@ let collect ctx e_ast e dk with_type p =
 	(* Collect fields of the type *)
 	(* Collect fields of the type *)
 	let items = loop items e.etype in
 	let items = loop items e.etype in
 	(* Add static extensions *)
 	(* Add static extensions *)
-	let items = collect_static_extensions ctx items e p in
+	let items = collect_static_extensions ctx blocked_items items e p in
 	let items = PMap.fold (fun item acc -> item :: acc) items [] in
 	let items = PMap.fold (fun item acc -> item :: acc) items [] in
 	let items = sort_fields items WithType.value (TKField p) in
 	let items = sort_fields items WithType.value (TKField p) in
 	try
 	try
@@ -358,7 +375,17 @@ let collect ctx e_ast e dk with_type p =
 let handle_missing_field_raise ctx tthis i mode with_type pfield =
 let handle_missing_field_raise ctx tthis i mode with_type pfield =
 	let tret = match with_type with
 	let tret = match with_type with
 		| WithType.WithType(t,_) -> t
 		| WithType.WithType(t,_) -> t
-		| WithType.Value _ -> mk_mono()
+		| WithType.Value _ ->
+			begin match mode with
+				| MSet (Some e) ->
+					begin try
+						let e = type_expr ctx e WithType.value in
+						e.etype
+					with _ ->
+						mk_mono()
+					end
+				| _ -> mk_mono()
+			end
 		| WithType.NoValue ->
 		| WithType.NoValue ->
 			match mode with
 			match mode with
 			| MCall _ -> ctx.t.tvoid
 			| MCall _ -> ctx.t.tvoid

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

@@ -7,6 +7,8 @@ open Type
 let get_memory_json (cs : CompilationCache.t) mreq =
 let get_memory_json (cs : CompilationCache.t) mreq =
 	begin match mreq with
 	begin match mreq with
 	| MCache ->
 	| MCache ->
+		let t0 = Extc.time() in
+		let stats = Gc.stat() in
 		let old_gc = Gc.get() in
 		let old_gc = Gc.get() in
 		Gc.set { old_gc with
 		Gc.set { old_gc with
 			Gc.max_overhead = 0;
 			Gc.max_overhead = 0;
@@ -14,6 +16,7 @@ let get_memory_json (cs : CompilationCache.t) mreq =
 		};
 		};
 		Gc.compact();
 		Gc.compact();
 		Gc.set old_gc;
 		Gc.set old_gc;
+		ServerMessage.gc_stats (Extc.time() -. t0) stats true 0;
 		let stat = Gc.quick_stat() in
 		let stat = Gc.quick_stat() in
 		let size = (float_of_int stat.Gc.heap_words) *. (float_of_int (Sys.word_size / 8)) in
 		let size = (float_of_int stat.Gc.heap_words) *. (float_of_int (Sys.word_size / 8)) in
 		let cache_mem = cs#get_pointers in
 		let cache_mem = cs#get_pointers in

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

@@ -39,7 +39,7 @@ let rec collect_reference_positions com (name,pos,kind) =
 			| Var vk ->
 			| Var vk ->
 				let host = FieldAccess.get_host c cf in
 				let host = FieldAccess.get_host c cf in
 				let check r mode = match r with
 				let check r mode = match r with
-					| AccCall ->
+					| AccCall | AccPrivateCall ->
 						begin match FieldAccess.find_accessor_for_field host cf cf.cf_type mode with
 						begin match FieldAccess.find_accessor_for_field host cf cf.cf_type mode with
 						| AccessorFound (cf_acc,new_host) ->
 						| AccessorFound (cf_acc,new_host) ->
 							let c_host = FieldAccess.get_host_class_raise new_host in
 							let c_host = FieldAccess.get_host_class_raise new_host in

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

@@ -1,7 +1,6 @@
 open Globals
 open Globals
 open Type
 open Type
 open Common
 open Common
-open Typecore
 open DisplayTypes
 open DisplayTypes
 
 
 type relation =
 type relation =

+ 17 - 0
src/context/dotGraph.ml

@@ -0,0 +1,17 @@
+open SafeCom
+
+let platform_name_macro com =
+	if Define.defined com.defines Define.Macro then "macro"
+	else Globals.platform_name com.platform
+
+let get_dump_path com path name =
+	com.dump_config.dump_path :: [platform_name_macro com] @ (fst path) @ [Printf.sprintf "%s.%s" (snd path) name]
+
+let start_graph ?(graph_config=[]) base_path suffix =
+	let ch = Path.create_file false suffix [] base_path in
+	Printf.fprintf ch "digraph graphname {\n";
+	List.iter (fun s -> Printf.fprintf ch "%s;\n" s) graph_config;
+	ch,(fun () ->
+		Printf.fprintf ch "}\n";
+		close_out ch
+	)

+ 32 - 14
src/context/parallel.ml

@@ -1,21 +1,36 @@
+let enable = ref false
+
 let run_parallel_for num_domains ?(chunk_size=0) length f =
 let run_parallel_for num_domains ?(chunk_size=0) length f =
-	let pool = Domainslib.Task.setup_pool ~num_domains:(num_domains - 1) () in
-	Domainslib.Task.run pool (fun _ -> Domainslib.Task.parallel_for pool ~chunk_size ~start:0 ~finish:(length-1) ~body:f);
-	Domainslib.Task.teardown_pool pool
+	if not !enable then begin
+		for i = 0 to length - 1 do
+			f i
+		done
+	end else
+		let pool = Domainslib.Task.setup_pool ~num_domains:(num_domains - 1) () in
+		Domainslib.Task.run pool (fun _ -> Domainslib.Task.parallel_for pool ~chunk_size ~start:0 ~finish:(length-1) ~body:f);
+		Domainslib.Task.teardown_pool pool
 
 
 module ParallelArray = struct
 module ParallelArray = struct
 	let iter pool f a =
 	let iter pool f a =
-		let f' idx = f a.(idx) in
-		Domainslib.Task.parallel_for pool ~start:0 ~finish:(Array.length a - 1) ~body:f'
+		match pool with
+		| None ->
+			Array.iter f a
+		| Some pool ->
+			let f' idx = f a.(idx) in
+			Domainslib.Task.parallel_for pool ~start:0 ~finish:(Array.length a - 1) ~body:f'
 
 
 	let map pool f a x =
 	let map pool f a x =
-		let length = Array.length a in
-		let a_out = Array.make length x in
-		let f' idx =
-			Array.unsafe_set a_out idx (f (Array.unsafe_get a idx))
-		in
-		Domainslib.Task.parallel_for pool ~start:0 ~finish:(length - 1) ~body:f';
-		a_out
+		match pool with
+		| None ->
+			Array.map f a
+		| Some pool ->
+			let length = Array.length a in
+			let a_out = Array.make length x in
+			let f' idx =
+				Array.unsafe_set a_out idx (f (Array.unsafe_get a idx))
+			in
+			Domainslib.Task.parallel_for pool ~start:0 ~finish:(length - 1) ~body:f';
+			a_out
 end
 end
 
 
 module ParallelSeq = struct
 module ParallelSeq = struct
@@ -24,5 +39,8 @@ module ParallelSeq = struct
 end
 end
 
 
 let run_in_new_pool timer_ctx f =
 let run_in_new_pool timer_ctx f =
-	let pool = Timer.time timer_ctx ["domainslib";"setup"] (Domainslib.Task.setup_pool ~num_domains:(Domain.recommended_domain_count() - 1)) () in
-	Std.finally (fun () -> Timer.time timer_ctx ["domainslib";"teardown"] Domainslib.Task.teardown_pool pool) (Domainslib.Task.run pool) (fun () -> f pool)
+	if not !enable then
+		f None
+	else
+		let pool = Timer.time timer_ctx ["domainslib";"setup"] (Domainslib.Task.setup_pool ~num_domains:(Domain.recommended_domain_count() - 1)) () in
+		Std.finally (fun () -> Timer.time timer_ctx ["domainslib";"teardown"] Domainslib.Task.teardown_pool pool) (Domainslib.Task.run pool) (fun () -> f (Some pool))

+ 1 - 1
src/context/safeCom.ml

@@ -5,7 +5,7 @@ open PlatformConfig
 type saved_warning = {
 type saved_warning = {
 	w_module : module_def;
 	w_module : module_def;
 	w_warning : WarningList.warning;
 	w_warning : WarningList.warning;
-	w_options : Warning.warning_option list list;
+	w_options : warning_option list list;
 	w_msg : string;
 	w_msg : string;
 	w_pos : pos;
 	w_pos : pos;
 }
 }

+ 20 - 6
src/context/typecore.ml

@@ -90,6 +90,10 @@ type typer_pass_tasks = {
 	mutable tasks : (unit -> unit) list;
 	mutable tasks : (unit -> unit) list;
 }
 }
 
 
+type function_mode =
+	| FunFunction
+	| FunNotFunction
+
 type typer_globals = {
 type typer_globals = {
 	mutable delayed : typer_pass_tasks Array.t;
 	mutable delayed : typer_pass_tasks Array.t;
 	mutable delayed_min_index : int;
 	mutable delayed_min_index : int;
@@ -122,7 +126,7 @@ type typer_globals = {
    is shared by local TFunctions. *)
    is shared by local TFunctions. *)
 and typer_expr = {
 and typer_expr = {
 	curfun : current_fun;
 	curfun : current_fun;
-	in_function : bool;
+	function_mode : function_mode;
 	mutable ret : t;
 	mutable ret : t;
 	mutable opened : anon_status ref list;
 	mutable opened : anon_status ref list;
 	mutable monomorphs : (tmono * pos) list;
 	mutable monomorphs : (tmono * pos) list;
@@ -215,10 +219,10 @@ module TyperManager = struct
 			in_call_args = false;
 			in_call_args = false;
 		}
 		}
 
 
-	let create_ctx_e curfun in_function =
+	let create_ctx_e curfun function_mode =
 		{
 		{
 			curfun;
 			curfun;
-			in_function;
+			function_mode;
 			ret = t_dynamic;
 			ret = t_dynamic;
 			opened = [];
 			opened = [];
 			monomorphs = [];
 			monomorphs = [];
@@ -281,8 +285,14 @@ module TyperManager = struct
 
 
 	let clone_for_type_parameter_expression ctx =
 	let clone_for_type_parameter_expression ctx =
 		let f = create_ctx_f ctx.f.curfield in
 		let f = create_ctx_f ctx.f.curfield in
-		let e = create_ctx_e ctx.e.curfun false in
+		let e = create_ctx_e ctx.e.curfun FunNotFunction in
 		create ctx ctx.m ctx.c f e PTypeField ctx.type_params
 		create ctx ctx.m ctx.c f e PTypeField ctx.type_params
+
+	let is_function_context ctx = match ctx.e.function_mode with
+		| FunFunction ->
+			true
+		| FunNotFunction ->
+			false
 end
 end
 
 
 type field_host =
 type field_host =
@@ -507,8 +517,12 @@ let needs_inline ctx c cf =
 	cf.cf_kind = Method MethInline && ctx.allow_inline && (ctx.com.doinline || is_forced_inline c cf)
 	cf.cf_kind = Method MethInline && ctx.allow_inline && (ctx.com.doinline || is_forced_inline c cf)
 
 
 (** checks if we can access to a given class field using current context *)
 (** checks if we can access to a given class field using current context *)
-let can_access ctx c cf stat =
-	if (has_class_field_flag cf CfPublic) then
+let can_access ctx c cf ?(check_prop=false) ?(is_setter=false) stat =
+	let is_private_prop = check_prop && match cf.cf_kind with
+		| Var { v_read = AccPrivateCall } when not is_setter -> true
+		| Var { v_write = AccPrivateCall } when is_setter -> true
+		| _ -> false in
+	if (not is_private_prop && has_class_field_flag cf CfPublic) then
 		true
 		true
 	else if c == ctx.c.curclass then
 	else if c == ctx.c.curclass then
 		true
 		true

+ 4 - 7
src/core/define.ml

@@ -155,16 +155,13 @@ let get_signature def =
 	| None ->
 	| None ->
 		let defines = PMap.foldi (fun k v acc ->
 		let defines = PMap.foldi (fun k v acc ->
 			(* don't make much difference between these special compilation flags *)
 			(* don't make much difference between these special compilation flags *)
-			match String.concat "_" (ExtString.String.nsplit k "-") with
+			let sanitized = String.concat "_" (ExtString.String.nsplit k "-") in
 			(* If we add something here that might be used in conditional compilation it should be added to
 			(* If we add something here that might be used in conditional compilation it should be added to
-			   Parser.parse_macro_ident as well (issue #5682).
-			   Note that we should removed flags like use_rtti_doc here.
+			   Grammar.parse_macro_ident as well (issue #5682).
 			*)
 			*)
-			| "display" | "use_rtti_doc" | "macro_times" | "display_details" | "no_copt" | "display_stdin" | "disable-hxb-cache" | "hxb.stats" | "fail_fast"
-			| "message.reporting" | "message.log_file" | "message.log_format" | "message.no_color"
-			| "dump" | "dump_dependencies" | "dump_ignore_var_ids" -> acc
-			| _ -> (k ^ "=" ^ v) :: acc
+			if DefineList.is_signature_neutral sanitized then acc else (sanitized ^ "=" ^ v) :: acc
 		) def.values [] in
 		) def.values [] in
+		let defines = Ast.remove_duplicates (fun a b -> a != b) defines in
 		let str = String.concat "@" (List.sort compare defines) in
 		let str = String.concat "@" (List.sort compare defines) in
 		let s = Digest.string str in
 		let s = Digest.string str in
 		def.defines_signature <- Some s;
 		def.defines_signature <- Some s;

+ 0 - 11
src/core/display/completionItem.ml

@@ -55,10 +55,6 @@ module CompletionModuleType = struct
 		| No
 		| No
 		| Maybe
 		| Maybe
 
 
-	type module_type_source =
-		| Syntax of type_def (* TODO: do we really want to keep this? *)
-		| Typed of module_type
-
 	type t = {
 	type t = {
 		pack : string list;
 		pack : string list;
 		name : string;
 		name : string;
@@ -73,7 +69,6 @@ module CompletionModuleType = struct
 		is_abstract : bool;
 		is_abstract : bool;
 		kind : CompletionModuleKind.t;
 		kind : CompletionModuleKind.t;
 		has_constructor : not_bool;
 		has_constructor : not_bool;
-		source : module_type_source;
 	}
 	}
 
 
 	let of_type_decl pack module_name (td,p) = match td with
 	let of_type_decl pack module_name (td,p) = match td with
@@ -101,7 +96,6 @@ module CompletionModuleType = struct
 				is_abstract = List.mem HAbstract d.d_flags;
 				is_abstract = List.mem HAbstract d.d_flags;
 				kind = if List.mem HInterface d.d_flags then Interface else Class;
 				kind = if List.mem HInterface d.d_flags then Interface else Class;
 				has_constructor = ctor;
 				has_constructor = ctor;
-				source = Syntax td;
 			}
 			}
 		| EEnum d -> {
 		| EEnum d -> {
 				pack = pack;
 				pack = pack;
@@ -117,7 +111,6 @@ module CompletionModuleType = struct
 				is_abstract = false;
 				is_abstract = false;
 				kind = Enum;
 				kind = Enum;
 				has_constructor = No;
 				has_constructor = No;
-				source = Syntax td;
 			}
 			}
 		| ETypedef d ->
 		| ETypedef d ->
 			let kind = match fst d.d_data with CTAnonymous _ -> Struct | _ -> TypeAlias in
 			let kind = match fst d.d_data with CTAnonymous _ -> Struct | _ -> TypeAlias in
@@ -135,7 +128,6 @@ module CompletionModuleType = struct
 				is_abstract = false;
 				is_abstract = false;
 				kind = kind;
 				kind = kind;
 				has_constructor = if kind = Struct then No else Maybe;
 				has_constructor = if kind = Struct then No else Maybe;
-				source = Syntax td;
 			}
 			}
 		| EAbstract d ->
 		| EAbstract d ->
 			let ctor =
 			let ctor =
@@ -159,7 +151,6 @@ module CompletionModuleType = struct
 				is_abstract = false;
 				is_abstract = false;
 				kind = if List.mem AbEnum d.d_flags then EnumAbstract else Abstract;
 				kind = if List.mem AbEnum d.d_flags then EnumAbstract else Abstract;
 				has_constructor = ctor;
 				has_constructor = ctor;
-				source = Syntax td;
 			}
 			}
 		| EStatic d ->
 		| EStatic d ->
 			{
 			{
@@ -176,7 +167,6 @@ module CompletionModuleType = struct
 				is_abstract = false;
 				is_abstract = false;
 				kind = Static;
 				kind = Static;
 				has_constructor = No;
 				has_constructor = No;
-				source = Syntax td;
 			}
 			}
 		| EImport _ | EUsing _ ->
 		| EImport _ | EUsing _ ->
 			raise Exit
 			raise Exit
@@ -243,7 +233,6 @@ module CompletionModuleType = struct
 			is_abstract = is_abstract;
 			is_abstract = is_abstract;
 			kind = kind;
 			kind = kind;
 			has_constructor = ctor;
 			has_constructor = ctor;
-			source = Typed mt;
 		}
 		}
 
 
 	let get_path cm = (cm.pack,cm.name)
 	let get_path cm = (cm.pack,cm.name)

+ 12 - 0
src/core/ds/threadSafeHashtbl.ml

@@ -17,6 +17,18 @@ let replace h k v =
 let find h k =
 let find h k =
 	Mutex.protect h.mutex (fun () -> Hashtbl.find h.h) k
 	Mutex.protect h.mutex (fun () -> Hashtbl.find h.h) k
 
 
+let find_or_add h k f =
+	Mutex.lock h.mutex;
+	try
+		let r = Hashtbl.find h.h k in
+		Mutex.unlock h.mutex;
+		r
+	with Not_found ->
+		let r = f () in
+		Hashtbl.add h.h k r;
+		Mutex.unlock h.mutex;
+		r
+
 let mem h k =
 let mem h k =
 	Mutex.protect h.mutex (fun () -> Hashtbl.mem h.h) k
 	Mutex.protect h.mutex (fun () -> Hashtbl.mem h.h) k
 
 

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

@@ -497,6 +497,7 @@ and generate_class_field' ctx cfs cf =
 				| AccNever -> "AccNever",None
 				| AccNever -> "AccNever",None
 				| AccCtor -> "AccCtor",None
 				| AccCtor -> "AccCtor",None
 				| AccCall -> "AccCall",None
 				| AccCall -> "AccCall",None
+				| AccPrivateCall -> "AccPrivateCall",None
 				| AccInline -> "AccInline",None
 				| AccInline -> "AccInline",None
 				| AccRequire(s,so) -> "AccRequire",Some (jobject ["require",jstring s;"message",jopt jstring so])
 				| AccRequire(s,so) -> "AccRequire",Some (jobject ["require",jstring s;"message",jopt jstring so])
 			in
 			in
@@ -736,4 +737,4 @@ let generate timer_ctx types file =
 		let ch = open_out_bin file in
 		let ch = open_out_bin file in
 		Json.write_json (output_string ch) json;
 		Json.write_json (output_string ch) json;
 		close_out ch;
 		close_out ch;
-	) ()
+	) ()

+ 1 - 1
src/core/tOther.ml

@@ -58,7 +58,7 @@ module TExprToExpr = struct
 								| AccNormal | AccCtor | AccInline | AccRequire _ -> "default"
 								| AccNormal | AccCtor | AccInline | AccRequire _ -> "default"
 								| AccNo -> "null"
 								| AccNo -> "null"
 								| AccNever -> "never"
 								| AccNever -> "never"
-								| AccCall -> get_or_set
+								| AccCall | AccPrivateCall -> get_or_set
 							in
 							in
 							let read = (var_access_to_string v.v_read "get",null_pos) in
 							let read = (var_access_to_string v.v_read "get",null_pos) in
 							let write = (var_access_to_string v.v_write "set",null_pos) in
 							let write = (var_access_to_string v.v_write "set",null_pos) in

+ 1 - 0
src/core/tPrinting.ml

@@ -164,6 +164,7 @@ let s_access is_read = function
 	| AccNo -> "null"
 	| AccNo -> "null"
 	| AccNever -> "never"
 	| AccNever -> "never"
 	| AccCall -> if is_read then "get" else "set"
 	| AccCall -> if is_read then "get" else "set"
+	| AccPrivateCall -> if is_read then "private get" else "private set"
 	| AccInline	-> "inline"
 	| AccInline	-> "inline"
 	| AccRequire (n,_) -> "require " ^ n
 	| AccRequire (n,_) -> "require " ^ n
 	| AccCtor -> "ctor"
 	| AccCtor -> "ctor"

+ 11 - 1
src/core/tType.ml

@@ -16,6 +16,7 @@ and var_access =
 	| AccNever          (* can't be accessed, even in subclasses *)
 	| AccNever          (* can't be accessed, even in subclasses *)
 	| AccCtor           (* can only be accessed from the constructor *)
 	| AccCtor           (* can only be accessed from the constructor *)
 	| AccCall           (* perform a method call when accessed *)
 	| AccCall           (* perform a method call when accessed *)
+	| AccPrivateCall    (* perform a method call when accessed, but private like AccNo *)
 	| AccInline         (* similar to Normal but inline when accessed *)
 	| AccInline         (* similar to Normal but inline when accessed *)
 	| AccRequire of string * string option (* set when @:require(cond) fails *)
 	| AccRequire of string * string option (* set when @:require(cond) fails *)
 
 
@@ -59,10 +60,19 @@ type type_param_host =
 	| TPHLocal
 	| TPHLocal
 	| TPHUnbound
 	| TPHUnbound
 
 
+type warning_mode =
+	| WMEnable
+	| WMDisable
+
+type warning_option = {
+	wo_warning : WarningList.warning;
+	wo_mode : warning_mode;
+}
+
 type cache_bound_object =
 type cache_bound_object =
 	| Resource of string * string
 	| Resource of string * string
 	| IncludeFile of string * string
 	| IncludeFile of string * string
-	| Warning of WarningList.warning * string * pos
+	| Warning of WarningList.warning * (warning_option list list) * string * pos
 
 
 type t =
 type t =
 	| TMono of tmono
 	| TMono of tmono

+ 4 - 3
src/core/tUnification.ml

@@ -511,11 +511,12 @@ let unify_access a1 a2 =
 	a1 = a2 || match a1, a2 with
 	a1 = a2 || match a1, a2 with
 	| _, AccNo | _, AccNever -> true
 	| _, AccNo | _, AccNever -> true
 	| AccInline, AccNormal -> true
 	| AccInline, AccNormal -> true
+	| AccCall, AccPrivateCall -> true
 	| _ -> false
 	| _ -> false
 
 
 let direct_access = function
 let direct_access = function
 	| AccNo | AccNever | AccNormal | AccInline | AccRequire _ | AccCtor -> true
 	| AccNo | AccNever | AccNormal | AccInline | AccRequire _ | AccCtor -> true
-	| AccCall -> false
+	| AccCall | AccPrivateCall -> false
 
 
 let unify_kind ~(strict:bool) k1 k2 =
 let unify_kind ~(strict:bool) k1 k2 =
 	k1 = k2 || match k1, k2 with
 	k1 = k2 || match k1, k2 with
@@ -908,8 +909,8 @@ let rec unify (uctx : unification_context) a b =
 							with Not_found ->
 							with Not_found ->
 								()
 								()
 						in
 						in
-						(match vk.v_read with AccCall -> check ("get_" ^ f1.cf_name) | _ -> ());
-						(match vk.v_write with AccCall -> check ("set_" ^ f1.cf_name) | _ -> ());
+						(match vk.v_read with AccCall | AccPrivateCall -> check ("get_" ^ f1.cf_name) | _ -> ());
+						(match vk.v_write with AccCall | AccPrivateCall -> check ("set_" ^ f1.cf_name) | _ -> ());
 					| _ -> ()
 					| _ -> ()
 				end;
 				end;
 				(match f1.cf_kind with
 				(match f1.cf_kind with

+ 10 - 0
src/core/texpr.ml

@@ -547,6 +547,16 @@ module Builder = struct
 	let index basic e index t p =
 	let index basic e index t p =
 		mk (TArray (e,mk (TConst (TInt (Int32.of_int index))) basic.tint p)) t p
 		mk (TArray (e,mk (TConst (TInt (Int32.of_int index))) basic.tint p)) t p
 
 
+	let default_value t p = match follow_without_null t with
+		| TAbstract({a_path = ([],"Int")},[]) ->
+			mk (TConst (TInt (Int32.zero))) t p
+		| TAbstract({a_path = ([],"Float")},[]) ->
+			mk (TConst (TFloat "0.0")) t p
+		| TAbstract({a_path = ([],"Bool")},[]) ->
+			mk (TConst (TBool false)) t p
+		| _ ->
+			mk (TConst TNull) t p
+
 	let resolve_and_make_static_call c name args p =
 	let resolve_and_make_static_call c name args p =
 		ignore(c.cl_build());
 		ignore(c.cl_build());
 		let cf = try
 		let cf = try

+ 1 - 9
src/core/warning.ml

@@ -1,16 +1,8 @@
 open Globals
 open Globals
 open Error
 open Error
+open TType
 include WarningList
 include WarningList
 
 
-type warning_mode =
-	| WMEnable
-	| WMDisable
-
-type warning_option = {
-	wo_warning : warning;
-	wo_mode : warning_mode;
-}
-
 let parse_options lctx s ps lexbuf =
 let parse_options lctx s ps lexbuf =
 	let fail msg p =
 	let fail msg p =
 		raise_typing_error msg {p with pmin = ps.pmin + p.pmin; pmax = ps.pmin + p.pmax}
 		raise_typing_error msg {p with pmin = ps.pmin + p.pmin; pmax = ps.pmin + p.pmax}

+ 2 - 1
src/filters/exception/saveStacks.ml

@@ -111,7 +111,8 @@ let patch_constructors ectx =
 							}
 							}
 						| _ -> die "" __LOC__
 						| _ -> die "" __LOC__
 					)
 					)
-				| None -> die "" __LOC__
+				| None ->
+					raise_typing_error "Could not patch constructor on this function because there isn't one" cls.cl_name_pos
 				| _ -> ()
 				| _ -> ()
 				)
 				)
 			| _ -> ()
 			| _ -> ()

+ 8 - 8
src/filters/filters.ml

@@ -417,9 +417,9 @@ let might_need_cf_unoptimized c cf =
 	| _ ->
 	| _ ->
 		has_class_field_flag cf CfGeneric
 		has_class_field_flag cf CfGeneric
 
 
-let run_safe_filters ectx com (scom : SafeCom.t) new_types_array cv_wrapper_impl rename_locals_config pool =
+let run_safe_filters ectx com (scom : SafeCom.t) all_types_array new_types_array rename_locals_config pool =
 	let detail_times = Timer.level_from_define scom.defines Define.FilterTimes in
 	let detail_times = Timer.level_from_define scom.defines Define.FilterTimes in
-
+	let cv_wrapper_impl = com.Common.local_wrapper in
 	let filters_before_inlining = [
 	let filters_before_inlining = [
 		"handle_abstract_casts",AbstractCast.handle_abstract_casts;
 		"handle_abstract_casts",AbstractCast.handle_abstract_casts;
 		"local_statics",LocalStatic.run;
 		"local_statics",LocalStatic.run;
@@ -454,7 +454,7 @@ let run_safe_filters ectx com (scom : SafeCom.t) new_types_array cv_wrapper_impl
 	Dump.maybe_generate_dump com AfterInlining;
 	Dump.maybe_generate_dump com AfterInlining;
 
 
 	Common.enter_stage com CAnalyzerStart;
 	Common.enter_stage com CAnalyzerStart;
-	if scom.platform <> Cross then Analyzer.Run.run_on_types scom pool new_types_array;
+	if scom.platform <> Cross then Analyzer.Run.run_on_types scom pool all_types_array new_types_array;
 	Dump.maybe_generate_dump com AfterAnalyzing;
 	Dump.maybe_generate_dump com AfterAnalyzing;
 	Common.enter_stage com CAnalyzerDone;
 	Common.enter_stage com CAnalyzerDone;
 
 
@@ -491,6 +491,7 @@ let run com ectx main before_destruction =
 		not cached
 		not cached
 	) com.types in
 	) com.types in
 	let new_types_array = Array.of_list new_types in
 	let new_types_array = Array.of_list new_types in
+	let all_types_array = Array.of_list com.types in
 
 
 	(* IMPORTANT:
 	(* IMPORTANT:
 	    There may be types in new_types which have already been post-processed, but then had their m_processed flag unset
 	    There may be types in new_types which have already been post-processed, but then had their m_processed flag unset
@@ -498,15 +499,15 @@ let run com ectx main before_destruction =
 		It is important that all filters from here up to save_class_state only process fields which do not have the
 		It is important that all filters from here up to save_class_state only process fields which do not have the
 		CfPostProcessed flag set.
 		CfPostProcessed flag set.
 
 
-		This is mostly covered by run_expression_filters already, but any new additions which don't utilize that have to
-		be aware of this.
+		This is mostly covered by run_expression_filters_safe already, but any new additions which don't utilize that have
+		to be aware of this.
 	*)
 	*)
+	DeprecationCheck.run com new_types;
 	NullSafety.run com new_types;
 	NullSafety.run com new_types;
-	let cv_wrapper_impl = CapturedVars.get_wrapper_implementation com in
 	let rename_locals_config = RenameVars.init scom.SafeCom.platform_config com.types in
 	let rename_locals_config = RenameVars.init scom.SafeCom.platform_config com.types in
 	Parallel.run_in_new_pool scom.timer_ctx (fun pool ->
 	Parallel.run_in_new_pool scom.timer_ctx (fun pool ->
 		SafeCom.run_with_scom com scom (fun () ->
 		SafeCom.run_with_scom com scom (fun () ->
-			run_safe_filters ectx com scom new_types_array cv_wrapper_impl rename_locals_config pool
+			run_safe_filters ectx com scom all_types_array new_types_array rename_locals_config pool
 		)
 		)
 	);
 	);
 	with_timer com.timer_ctx detail_times "callbacks" None (fun () ->
 	with_timer com.timer_ctx detail_times "callbacks" None (fun () ->
@@ -528,5 +529,4 @@ let run com ectx main before_destruction =
 		com.callbacks#run com.error_ext com.callbacks#get_after_save;
 		com.callbacks#run com.error_ext com.callbacks#get_after_save;
 	);
 	);
 	before_destruction();
 	before_destruction();
-	let all_types_array = Array.of_list com.types in
 	destruction com scom ectx detail_times main rename_locals_config com.types all_types_array
 	destruction com scom ectx detail_times main rename_locals_config com.types all_types_array

+ 0 - 1
src/filters/filtersCommon.ml

@@ -16,7 +16,6 @@
 	along with this program; if not, write to the Free Software
 	along with this program; if not, write to the Free Software
 	Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 	Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 *)
 *)
-open Globals
 open Type
 open Type
 open Common
 open Common
 open Typecore
 open Typecore

+ 28 - 52
src/filters/safe/capturedVars.ml

@@ -16,56 +16,10 @@
 	along with this program; if not, write to the Free Software
 	along with this program; if not, write to the Free Software
 	Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 	Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
  *)
  *)
-open Globals
 open SafeCom
 open SafeCom
 open Type
 open Type
 open LocalUsage
 open LocalUsage
 
 
-let get_wrapper_implementation com =
-	let t = com.Common.basic in
-	match com.platform with
-	(* optimized version for Java - use native arrays *)
-	| Jvm ->
-		let cnativearray =
-			match (List.find (fun md -> match md with
-					| TClassDecl ({ cl_path = ["jvm"],"NativeArray" }) -> true
-					| _ -> false
-				) com.types)
-			with TClassDecl cl -> cl | _ -> die "" __LOC__
-		in
-
-		object
-			method captured_type t = TInst (cnativearray,[t])
-
-			method mk_ref v ve p =
-				match ve with
-				| None ->
-					let eone = mk (TConst (TInt (Int32.of_int 1))) t.tint p in
-					let t = match v.v_type with TInst (_, [t]) -> t | _ -> die "" __LOC__ in
-					mk (TNew (cnativearray,[t],[eone])) v.v_type p
-				| Some e ->
-					{ (Inline.mk_untyped_call "__array__" p [e]) with etype = v.v_type }
-
-			method mk_ref_access e v =
-				mk (TArray ({ e with etype = v.v_type }, mk (TConst (TInt 0l)) t.tint e.epos)) e.etype e.epos
-
-			method mk_init av v pos =
-				let elocal = mk (TLocal v) v.v_type pos in
-				let earray = { (Inline.mk_untyped_call "__array__" pos [elocal]) with etype = av.v_type } in
-				mk (TVar (av,Some earray)) t.tvoid pos
-		end
-	(* default implementation - use haxe array *)
-	| _ ->
-		object
-			method captured_type = t.tarray
-			method mk_ref v ve p =
-				mk (TArrayDecl (match ve with None -> [] | Some e -> [e])) v.v_type p
-			method mk_ref_access e v =
-				mk (TArray ({ e with etype = v.v_type }, mk (TConst (TInt 0l)) t.tint e.epos)) e.etype e.epos
-			method mk_init av v pos =
-				mk (TVar (av,Some (mk (TArrayDecl [mk (TLocal v) v.v_type pos]) av.v_type pos))) t.tvoid pos
-		end
-
 (* BLOCK VARIABLES CAPTURE *)
 (* BLOCK VARIABLES CAPTURE *)
 (*
 (*
 	For some platforms, it will simply mark the variables which are used in closures
 	For some platforms, it will simply mark the variables which are used in closures
@@ -225,8 +179,26 @@ let captured_vars scom impl e =
 	and all_vars e =
 	and all_vars e =
 		let vars = ref PMap.empty in
 		let vars = ref PMap.empty in
 		let used = ref PMap.empty in
 		let used = ref PMap.empty in
+		let in_loop = ref false in
+		let loop_vars = ref PMap.empty in
 		let assigned = ref PMap.empty in
 		let assigned = ref PMap.empty in
 		let depth = ref 0 in
 		let depth = ref 0 in
+		let mark_assigned v =
+			assigned := PMap.add v.v_id v !assigned;
+			(* Remove from vars lookup because we're done with it *)
+			vars := PMap.remove v.v_id !vars;
+		in
+		let check_loop_var v is_assign =
+			try
+				let is_assign' = PMap.find v.v_id !loop_vars in
+				(* If we have both read and write in the same loop we need to wrap. *)
+				if is_assign <> is_assign' then mark_assigned v
+			with Not_found ->
+				loop_vars := PMap.add v.v_id is_assign !loop_vars
+		in
+		let check_loop_var v is_assign =
+			if !in_loop then check_loop_var v is_assign
+		in
 		let rec collect_vars = function
 		let rec collect_vars = function
 		| Block f ->
 		| Block f ->
 			let old = !vars in
 			let old = !vars in
@@ -234,7 +206,12 @@ let captured_vars scom impl e =
 			vars := old;
 			vars := old;
 		| Loop f ->
 		| Loop f ->
 			let old = !vars in
 			let old = !vars in
+			let old_loop_vars = !loop_vars in
+			let old_loop = !in_loop in
+			in_loop := true;
 			f collect_vars;
 			f collect_vars;
+			in_loop := old_loop;
+			loop_vars := old_loop_vars;
 			vars := old;
 			vars := old;
 		| Function f ->
 		| Function f ->
 			incr depth;
 			incr depth;
@@ -246,8 +223,8 @@ let captured_vars scom impl e =
 			(try
 			(try
 				let d = PMap.find v.v_id !vars in
 				let d = PMap.find v.v_id !vars in
 				if d <> !depth then begin
 				if d <> !depth then begin
+					check_loop_var v false;
 					used := PMap.add v.v_id v !used;
 					used := PMap.add v.v_id v !used;
-					if has_var_flag v VAssigned then assigned := PMap.add v.v_id v !assigned;
 				end
 				end
 			with Not_found -> ())
 			with Not_found -> ())
 		| Assign v ->
 		| Assign v ->
@@ -256,13 +233,12 @@ let captured_vars scom impl e =
 				(* different depth - needs wrap *)
 				(* different depth - needs wrap *)
 				if d <> !depth then begin
 				if d <> !depth then begin
 					used := PMap.add v.v_id v !used;
 					used := PMap.add v.v_id v !used;
-					assigned := PMap.add v.v_id v !assigned;
-				end
+					mark_assigned v
 				(* same depth but assigned after being used on a different depth - needs wrap *)
 				(* same depth but assigned after being used on a different depth - needs wrap *)
-				else if PMap.mem v.v_id !used then
-					assigned := PMap.add v.v_id v !assigned
+				end else if PMap.mem v.v_id !used then
+					mark_assigned v
 				else
 				else
-					add_var_flag v VAssigned;
+					check_loop_var v true
 			with Not_found -> ())
 			with Not_found -> ())
 		in
 		in
 		local_usage collect_vars e;
 		local_usage collect_vars e;

+ 8 - 8
src/generators/cpp/cppRetyper.ml

@@ -1505,7 +1505,7 @@ let get_id path ids =
   | None ->
   | None ->
     let new_id = make_id 0 in
     let new_id = make_id 0 in
     (new_id, ObjectIds.add path new_id ids)
     (new_id, ObjectIds.add path new_id ids)
-  
+
 let native_field_name_remap field =
 let native_field_name_remap field =
   match get_meta_string field.cf_meta Meta.Native with
   match get_meta_string field.cf_meta Meta.Native with
   | Some nativeImpl ->
   | Some nativeImpl ->
@@ -1533,7 +1533,7 @@ let rec tcpp_class_from_tclass ctx ids slots class_def class_params =
     tcv_type = field.cf_type;
     tcv_type = field.cf_type;
     tcv_default = None;
     tcv_default = None;
 
 
-    tcv_has_getter = (match field.cf_kind with | Var { v_read = AccCall } -> true | _ -> false);
+    tcv_has_getter = (match field.cf_kind with | Var { v_read = AccCall | AccPrivateCall } -> true | _ -> false);
     tcv_is_stackonly = has_meta Meta.StackOnly field.cf_meta;
     tcv_is_stackonly = has_meta Meta.StackOnly field.cf_meta;
     tcv_is_reflective = reflective class_def field;
     tcv_is_reflective = reflective class_def field;
     tcv_is_gc_element = cpp_type_of field.cf_type |> is_gc_element ctx;
     tcv_is_gc_element = cpp_type_of field.cf_type |> is_gc_element ctx;
@@ -1567,14 +1567,14 @@ let rec tcpp_class_from_tclass ctx ids slots class_def class_params =
             (* We can't implement abstract functions as pure virtual due to cppia needing to construct the class *)
             (* We can't implement abstract functions as pure virtual due to cppia needing to construct the class *)
             let map_arg (name, _, t) =
             let map_arg (name, _, t) =
               ( (alloc_var VGenerated name t null_pos), (get_default_value name) ) in
               ( (alloc_var VGenerated name t null_pos), (get_default_value name) ) in
-            let expr = 
+            let expr =
               match follow ret with
               match follow ret with
               | TAbstract ({ a_path = ([], "Void") }, _) ->
               | TAbstract ({ a_path = ([], "Void") }, _) ->
                 { eexpr = TReturn None; etype = ret; epos = null_pos }
                 { eexpr = TReturn None; etype = ret; epos = null_pos }
               | _ ->
               | _ ->
                 let zero_val = Some { eexpr = TConst (TInt Int32.zero); etype = ret; epos = null_pos } in
                 let zero_val = Some { eexpr = TConst (TInt Int32.zero); etype = ret; epos = null_pos } in
                 { eexpr = TReturn zero_val; etype = ret; epos = null_pos } in
                 { eexpr = TReturn zero_val; etype = ret; epos = null_pos } in
-            
+
             {
             {
               tf_args = args |> List.map map_arg;
               tf_args = args |> List.map map_arg;
               tf_type = ret;
               tf_type = ret;
@@ -1611,7 +1611,7 @@ let rec tcpp_class_from_tclass ctx ids slots class_def class_params =
       | Var _, _ ->
       | Var _, _ ->
         Some (create_variable field)
         Some (create_variable field)
       (* Dynamic methods are implemented as a physical field holding a closure *)
       (* Dynamic methods are implemented as a physical field holding a closure *)
-      | Method MethDynamic, Some { eexpr = TFunction func } -> 
+      | Method MethDynamic, Some { eexpr = TFunction func } ->
         Some (create_variable { field with cf_expr = None; cf_kind = Var ({ v_read = AccNormal; v_write = AccNormal }) })
         Some (create_variable { field with cf_expr = None; cf_kind = Var ({ v_read = AccNormal; v_write = AccNormal }) })
       (* Below should cause abstracts which have functions with no implementation to be generated as a field *)
       (* Below should cause abstracts which have functions with no implementation to be generated as a field *)
       (* See Int32.hx as an example *)
       (* See Int32.hx as an example *)
@@ -1631,7 +1631,7 @@ let rec tcpp_class_from_tclass ctx ids slots class_def class_params =
       None in
       None in
 
 
   let id, ids = get_id class_def.cl_path ids in
   let id, ids = get_id class_def.cl_path ids in
-  
+
   let static_functions =
   let static_functions =
     class_def.cl_ordered_statics
     class_def.cl_ordered_statics
     |> List.filter_map (filter_functions true) in
     |> List.filter_map (filter_functions true) in
@@ -1650,7 +1650,7 @@ let rec tcpp_class_from_tclass ctx ids slots class_def class_params =
     |> List.filter (fun field -> field.cf_name <> "__meta__" && field.cf_name <> "__rtti")
     |> List.filter (fun field -> field.cf_name <> "__meta__" && field.cf_name <> "__rtti")
     |> List.filter_map filter_properties in
     |> List.filter_map filter_properties in
 
 
-  let functions = 
+  let functions =
     class_def.cl_ordered_fields
     class_def.cl_ordered_fields
     |> List.filter_map (filter_functions true) in
     |> List.filter_map (filter_functions true) in
 
 
@@ -1822,4 +1822,4 @@ and tcpp_enum_from_tenum ctx ids enum_def =
   in
   in
   let enum = { te_enum = enum_def; te_id = self_id; te_constructors = constructors } in
   let enum = { te_enum = enum_def; te_id = self_id; te_constructors = constructors } in
 
 
-  (ids, enum)
+  (ids, enum)

+ 1 - 1
src/generators/cpp/gen/cppCppia.ml

@@ -1799,7 +1799,7 @@ let generate_script_class common_ctx script class_def =
           | AccNormal | AccCtor -> IaAccessNormal
           | AccNormal | AccCtor -> IaAccessNormal
           | AccNo -> IaAccessNot
           | AccNo -> IaAccessNot
           | AccNever -> IaAccessNot
           | AccNever -> IaAccessNot
-          | AccCall ->
+          | AccCall | AccPrivateCall ->
               if
               if
                 Meta.has Meta.NativeProperty class_def.cl_meta
                 Meta.has Meta.NativeProperty class_def.cl_meta
                 || Meta.has Meta.NativeProperty field.cf_meta
                 || Meta.has Meta.NativeProperty field.cf_meta

+ 13 - 13
src/generators/cpp/gen/cppGenClassImplementation.ml

@@ -47,7 +47,7 @@ let gen_function ctx class_def class_name is_static func =
       (gen_cpp_function_body ctx class_def is_static func.tcf_field.cf_name func.tcf_func code tail_code);
       (gen_cpp_function_body ctx class_def is_static func.tcf_field.cf_name func.tcf_func code tail_code);
 
 
     output "\n\n";
     output "\n\n";
-    
+
     (* generate dynamic version too ... *)
     (* generate dynamic version too ... *)
     if (not func.tcf_is_virtual || not func.tcf_is_overriding) && func.tcf_is_reflective then
     if (not func.tcf_is_virtual || not func.tcf_is_overriding) && func.tcf_is_reflective then
       let tcpp_args = List.map (fun (v, _) -> cpp_type_of v.v_type) func.tcf_func.tf_args in
       let tcpp_args = List.map (fun (v, _) -> cpp_type_of v.v_type) func.tcf_func.tf_args in
@@ -85,7 +85,7 @@ let gen_function ctx class_def class_name is_static func =
             Printf.sprintf "(::cpp::Struct< %s >) a%i" (tcpp_to_string arg) idx
             Printf.sprintf "(::cpp::Struct< %s >) a%i" (tcpp_to_string arg) idx
           | _ ->
           | _ ->
             Printf.sprintf "a%i" idx in
             Printf.sprintf "a%i" idx in
-            
+
         tcpp_args
         tcpp_args
         |> ExtList.List.mapi cast_prefix
         |> ExtList.List.mapi cast_prefix
         |> String.concat ", "
         |> String.concat ", "
@@ -120,7 +120,7 @@ let gen_dynamic_function ctx class_def class_name is_static is_for_static_var (f
   let ret = if is_void then "(void)" else "return " in
   let ret = if is_void then "(void)" else "return " in
 
 
   ctx.ctx_real_this_ptr <- false;
   ctx.ctx_real_this_ptr <- false;
-  Printf.sprintf "HX_BEGIN_DEFAULT_FUNC(%s, %s)\n" func_name class_name |> output; 
+  Printf.sprintf "HX_BEGIN_DEFAULT_FUNC(%s, %s)\n" func_name class_name |> output;
   Printf.sprintf "%s _hx_run(%s)" return_type_str (print_arg_list func.tcf_func.tf_args "__o_") |> output;
   Printf.sprintf "%s _hx_run(%s)" return_type_str (print_arg_list func.tcf_func.tf_args "__o_") |> output;
 
 
   gen_cpp_function_body ctx class_def is_static func_name func.tcf_func "" "" no_debug;
   gen_cpp_function_body ctx class_def is_static func_name func.tcf_func "" "" no_debug;
@@ -273,7 +273,7 @@ let generate_native_class base_ctx tcpp_class =
   output_cpp "\n";
   output_cpp "\n";
 
 
   gen_dynamic_function_allocator ctx output_cpp tcpp_class;
   gen_dynamic_function_allocator ctx output_cpp tcpp_class;
-  
+
   generate_native_constructor ctx output_cpp class_def false;
   generate_native_constructor ctx output_cpp class_def false;
   gen_boot_field ctx output_cpp tcpp_class;
   gen_boot_field ctx output_cpp tcpp_class;
 
 
@@ -394,13 +394,13 @@ let generate_managed_class base_ctx tcpp_class =
     let impl_name = cpp_class_name class_def in
     let impl_name = cpp_class_name class_def in
 
 
     let fold_interface (glued, acc) interface =
     let fold_interface (glued, acc) interface =
-    
+
       let rec gen_interface_funcs interface =
       let rec gen_interface_funcs interface =
 
 
         let fold_field (glued, acc) func =
         let fold_field (glued, acc) func =
           let cast      = cpp_tfun_signature false func.iff_args func.iff_return in
           let cast      = cpp_tfun_signature false func.iff_args func.iff_return in
           let real_name = cpp_member_name_of func.iff_field in
           let real_name = cpp_member_name_of func.iff_field in
-          
+
           (* C++ can't work out which function it needs to take the addrss of
           (* C++ can't work out which function it needs to take the addrss of
               when the implementation is overloaded - currently the map-set functions.
               when the implementation is overloaded - currently the map-set functions.
               Change the castKey to force a glue function in this case (could double-cast the pointer, but it is ugly)
               Change the castKey to force a glue function in this case (could double-cast the pointer, but it is ugly)
@@ -452,7 +452,7 @@ let generate_managed_class base_ctx tcpp_class =
       let call     = Printf.sprintf "static %s %s_%s = {\n%s\n};\n" (cpp_class_name interface.if_class) cname interface_name combined in
       let call     = Printf.sprintf "static %s %s_%s = {\n%s\n};\n" (cpp_class_name interface.if_class) cname interface_name combined in
       (glued, call :: acc)
       (glued, call :: acc)
     in
     in
-    
+
     let glued, calls =
     let glued, calls =
       List.fold_left
       List.fold_left
         fold_interface
         fold_interface
@@ -615,7 +615,7 @@ let generate_managed_class base_ctx tcpp_class =
     else
     else
       acc
       acc
   in
   in
-  
+
   let castable f =
   let castable f =
     match cpp_type_of f.cf_type with
     match cpp_type_of f.cf_type with
     | TCppInst (t, _) as inst when Meta.has Meta.StructAccess t.cl_meta ->
     | TCppInst (t, _) as inst when Meta.has Meta.StructAccess t.cl_meta ->
@@ -671,7 +671,7 @@ let generate_managed_class base_ctx tcpp_class =
           Printf.sprintf "%s = inValue.Cast< %s >(); return inValue;" var.tcv_name casted in
           Printf.sprintf "%s = inValue.Cast< %s >(); return inValue;" var.tcv_name casted in
 
 
         match var.tcv_field.cf_kind with
         match var.tcv_field.cf_kind with
-        | Var { v_write = AccCall } ->
+        | Var { v_write = AccCall | AccPrivateCall } ->
           let prop_call = checkPropCall var.tcv_field in
           let prop_call = checkPropCall var.tcv_field in
           let setter    = Printf.sprintf "set_%s" var.tcv_field.cf_name |> get_wrapper var.tcv_field in
           let setter    = Printf.sprintf "set_%s" var.tcv_field.cf_name |> get_wrapper var.tcv_field in
           let call      = Printf.sprintf "if (%s) { return ::hx::Val( %s(inValue.Cast< %s >()) ); } else { %s }" prop_call setter casted default in
           let call      = Printf.sprintf "if (%s) { return ::hx::Val( %s(inValue.Cast< %s >()) ); } else { %s }" prop_call setter casted default in
@@ -690,7 +690,7 @@ let generate_managed_class base_ctx tcpp_class =
         let casted  = castable var.tcv_field in
         let casted  = castable var.tcv_field in
 
 
         match var.tcv_field.cf_kind with
         match var.tcv_field.cf_kind with
-        | Var { v_write = AccCall } ->
+        | Var { v_write = AccCall | AccPrivateCall } ->
           let prop_call = checkPropCall var.tcv_field in
           let prop_call = checkPropCall var.tcv_field in
           let setter    = Printf.sprintf "set_%s" var.tcv_field.cf_name |> get_wrapper var.tcv_field in
           let setter    = Printf.sprintf "set_%s" var.tcv_field.cf_name |> get_wrapper var.tcv_field in
           let call      = Printf.sprintf "if (%s) { return ::hx::Val( %s(inValue.Cast< %s >()) ); }" prop_call setter casted in
           let call      = Printf.sprintf "if (%s) { return ::hx::Val( %s(inValue.Cast< %s >()) ); }" prop_call setter casted in
@@ -717,7 +717,7 @@ let generate_managed_class base_ctx tcpp_class =
         let casted = castable var.tcv_field in
         let casted = castable var.tcv_field in
 
 
         match var.tcv_field.cf_kind with
         match var.tcv_field.cf_kind with
-        | Var { v_write = AccCall } ->
+        | Var { v_write = AccCall | AccPrivateCall } ->
           let prop_call = checkPropCall var.tcv_field in
           let prop_call = checkPropCall var.tcv_field in
           let setter    = Printf.sprintf "set_%s" var.tcv_field.cf_name |> get_wrapper var.tcv_field in
           let setter    = Printf.sprintf "set_%s" var.tcv_field.cf_name |> get_wrapper var.tcv_field in
           let call      = Printf.sprintf "if (%s) { ioValue = %s(ioValue.Cast< %s >()); } else { %s = ioValue.Cast< %s >(); } return true;" prop_call setter casted var.tcv_name casted in
           let call      = Printf.sprintf "if (%s) { ioValue = %s(ioValue.Cast< %s >()); } else { %s = ioValue.Cast< %s >(); } return true;" prop_call setter casted var.tcv_name casted in
@@ -734,7 +734,7 @@ let generate_managed_class base_ctx tcpp_class =
     let fold_property (var:tcpp_class_variable) acc =
     let fold_property (var:tcpp_class_variable) acc =
       if var.tcv_is_reflective && not (is_abstract_impl class_def) then
       if var.tcv_is_reflective && not (is_abstract_impl class_def) then
         match var.tcv_field.cf_kind with
         match var.tcv_field.cf_kind with
-        | Var { v_write = AccCall } ->
+        | Var { v_write = AccCall | AccPrivateCall } ->
           let prop_call = checkPropCall var.tcv_field in
           let prop_call = checkPropCall var.tcv_field in
           let setter    = Printf.sprintf "set_%s" var.tcv_field.cf_name |> get_wrapper var.tcv_field in
           let setter    = Printf.sprintf "set_%s" var.tcv_field.cf_name |> get_wrapper var.tcv_field in
           let casted    = castable var.tcv_field in
           let casted    = castable var.tcv_field in
@@ -965,7 +965,7 @@ let generate_managed_class base_ctx tcpp_class =
           | _ -> [] in
           | _ -> [] in
         current_virtual_functions_rev cls initial
         current_virtual_functions_rev cls initial
       in
       in
-    
+
       flatten_tcpp_class_functions_rec tcpp_class |> List.rev
       flatten_tcpp_class_functions_rec tcpp_class |> List.rev
     in
     in
 
 

+ 4 - 4
src/generators/flashProps.ml

@@ -29,8 +29,8 @@ let find_property_for_accessor ~isget cl tl accessor_name =
 		match Type.class_field cl tl prop_name with
 		match Type.class_field cl tl prop_name with
 		| Some (prop_cl, prop_tl), _, prop_cf ->
 		| Some (prop_cl, prop_tl), _, prop_cf ->
 			(match prop_cf.cf_kind with
 			(match prop_cf.cf_kind with
-			| Var { v_read = AccCall; v_write = AccCall | AccNever } when isget && is_flash_property prop_cf -> Some (prop_cl, prop_tl, prop_cf)
-			| Var { v_read = AccCall | AccNever; v_write = AccCall } when not isget && is_flash_property prop_cf -> Some (prop_cl, prop_tl, prop_cf)
+			| Var { v_read = AccCall | AccPrivateCall; v_write = AccCall | AccPrivateCall | AccNever } when isget && is_flash_property prop_cf -> Some (prop_cl, prop_tl, prop_cf)
+			| Var { v_read = AccCall | AccPrivateCall | AccNever; v_write = AccCall | AccPrivateCall } when not isget && is_flash_property prop_cf -> Some (prop_cl, prop_tl, prop_cf)
 			| _ -> None)
 			| _ -> None)
 		| _ -> None
 		| _ -> None
 	with Not_found ->
 	with Not_found ->
@@ -47,8 +47,8 @@ let find_static_property_for_accessor ~isget cl accessor_name =
 	try
 	try
 		let prop_cf = PMap.find prop_name cl.cl_statics in
 		let prop_cf = PMap.find prop_name cl.cl_statics in
 		(match prop_cf.cf_kind with
 		(match prop_cf.cf_kind with
-		| Var { v_read = AccCall; v_write = AccCall | AccNever } when isget && is_flash_property prop_cf -> Some prop_cf
-		| Var { v_read = AccCall | AccNever; v_write = AccCall } when not isget && is_flash_property prop_cf -> Some prop_cf
+		| Var { v_read = AccCall | AccPrivateCall; v_write = AccCall | AccPrivateCall | AccNever } when isget && is_flash_property prop_cf -> Some prop_cf
+		| Var { v_read = AccCall | AccPrivateCall | AccNever; v_write = AccCall | AccPrivateCall } when not isget && is_flash_property prop_cf -> Some prop_cf
 		| _ -> None)
 		| _ -> None)
 	with Not_found ->
 	with Not_found ->
 		None
 		None

+ 2 - 2
src/generators/gctx.ml

@@ -8,7 +8,7 @@ type context_main = {
 	mutable main_expr : texpr option;
 	mutable main_expr : texpr option;
 }
 }
 
 
-type warning_function = ?depth:int -> ?from_macro:bool -> warning -> Warning.warning_option list list -> string -> pos -> unit
+type warning_function = ?depth:int -> ?from_macro:bool -> warning -> warning_option list list -> string -> pos -> unit
 type error_function = string -> pos -> unit
 type error_function = string -> pos -> unit
 
 
 type t = {
 type t = {
@@ -118,4 +118,4 @@ let get_es_version defines =
 let map_source_header defines f =
 let map_source_header defines f =
 	match Define.defined_value_safe defines Define.SourceHeader with
 	match Define.defined_value_safe defines Define.SourceHeader with
 	| "" -> ()
 	| "" -> ()
-	| s -> f s
+	| s -> f s

+ 14 - 15
src/generators/genhl.ml

@@ -333,18 +333,8 @@ let make_debug ctx arr =
 		| true -> if (Filename.is_relative p.pfile)
 		| true -> if (Filename.is_relative p.pfile)
 			then Filename.concat (Sys.getcwd()) p.pfile
 			then Filename.concat (Sys.getcwd()) p.pfile
 			else p.pfile
 			else p.pfile
-		| false -> try
-			(* lookup relative path *)
-			let len = String.length p.pfile in
-			let base = ctx.com.class_paths#find (fun path ->
-				let path = path#path in
-				let l = String.length path in
-				len > l && String.sub p.pfile 0 l = path
-			) in
-			let l = String.length base#path in
-			String.sub p.pfile l (len - l)
-		with Not_found ->
-			p.pfile
+		| false ->
+			ctx.com.class_paths#relative_path p.pfile
 	in
 	in
 	let pos = ref (0,0,Globals.null_pos) in
 	let pos = ref (0,0,Globals.null_pos) in
 	let cur_file = ref 0 in
 	let cur_file = ref 0 in
@@ -783,6 +773,7 @@ and enum_class ctx e =
 					let old = ctx.m in
 					let old = ctx.m in
 					let ft = to_type ctx ef.ef_type in
 					let ft = to_type ctx ef.ef_type in
 					ctx.m <- method_context eid ft null_capture false;
 					ctx.m <- method_context eid ft null_capture false;
+					set_curpos ctx ef.ef_pos;
 					let arg_regs = List.map (fun t -> alloc_fresh ctx t) fargs in
 					let arg_regs = List.map (fun t -> alloc_fresh ctx t) fargs in
 					let ret_reg = alloc_fresh ctx tret in
 					let ret_reg = alloc_fresh ctx tret in
 					op ctx (OMakeEnum (ret_reg, ef.ef_index, arg_regs));
 					op ctx (OMakeEnum (ret_reg, ef.ef_index, arg_regs));
@@ -2408,8 +2399,14 @@ and eval_expr ctx e =
 		| HFun _ -> cast_to ctx r to_t e.epos
 		| HFun _ -> cast_to ctx r to_t e.epos
 		| _ -> unsafe_cast_to ctx r to_t e.epos)
 		| _ -> unsafe_cast_to ctx r to_t e.epos)
 	| TObjectDecl fl ->
 	| TObjectDecl fl ->
-		(match to_type ctx e.etype with
-		| HVirtual vp as t when Array.length vp.vfields = List.length fl && not (List.exists (fun ((s,_,_),e) -> (try ignore(PMap.find s vp.vindex); false with Not_found -> true) || (s = "toString" && is_to_string e.etype)) fl) ->
+		(* We cannot rely on e.etype because it might have optional field etc, see jvm *)
+		let fields = List.fold_left (fun acc ((name,_,_),e) ->
+			let cf = mk_field name e.etype e.epos e.epos in
+			PMap.add name cf acc
+		) PMap.empty fl in
+		let rt = to_type ctx (mk_anon ~fields (ref Closed)) in
+		(match rt with
+		| HVirtual vp as t when safe_cast rt (to_type ctx e.etype) && not (List.exists (fun ((s,_,_),e) -> s = "toString" && is_to_string e.etype) fl) ->
 			let r = alloc_tmp ctx t in
 			let r = alloc_tmp ctx t in
 			op ctx (ONew r);
 			op ctx (ONew r);
 			hold ctx r;
 			hold ctx r;
@@ -3284,6 +3281,7 @@ and gen_method_wrapper ctx rt t p =
 		let targs, tret = (match t with HFun (args, ret) -> args, ret | _ -> die "" __LOC__) in
 		let targs, tret = (match t with HFun (args, ret) -> args, ret | _ -> die "" __LOC__) in
 		let iargs, iret = (match rt with HFun (args, ret) -> args, ret | _ -> die "" __LOC__) in
 		let iargs, iret = (match rt with HFun (args, ret) -> args, ret | _ -> die "" __LOC__) in
 		ctx.m <- method_context fid HDyn null_capture false;
 		ctx.m <- method_context fid HDyn null_capture false;
+		set_curpos ctx p;
 		let rfun = alloc_tmp ctx rt in
 		let rfun = alloc_tmp ctx rt in
 		let rargs = List.map (fun t ->
 		let rargs = List.map (fun t ->
 			let r = alloc_tmp ctx t in
 			let r = alloc_tmp ctx t in
@@ -3831,7 +3829,8 @@ let generate_static_init ctx types main =
 	| Some e -> exprs := e :: !exprs);
 	| Some e -> exprs := e :: !exprs);
 	let fid = lookup_alloc ctx.cfids () in
 	let fid = lookup_alloc ctx.cfids () in
 	let exprs = List.rev !init_exprs @ List.rev !exprs in
 	let exprs = List.rev !init_exprs @ List.rev !exprs in
-	ignore(make_fun ~gen_content ctx ("","") fid { tf_expr = mk (TBlock exprs) t_void null_pos; tf_args = []; tf_type = t_void } None None);
+	let initpos = fake_pos "fun$init" in
+	ignore(make_fun ~gen_content ctx ("","") fid { tf_expr = mk (TBlock exprs) t_void initpos; tf_args = []; tf_type = t_void } None None);
 	fid
 	fid
 
 
 (* --------------------------------------------------------------------------------------------------------------------- *)
 (* --------------------------------------------------------------------------------------------------------------------- *)

+ 1 - 1
src/generators/genjvm.ml

@@ -1963,7 +1963,7 @@ class texpr_to_jvm
 		if not jm#is_terminated then self#texpr' ret e
 		if not jm#is_terminated then self#texpr' ret e
 
 
 	method texpr' ret e =
 	method texpr' ret e =
-		code#set_line (Lexer.get_error_line_if_exists e.epos);
+		code#set_line (Lexer.get_error_line e.epos);
 		match e.eexpr with
 		match e.eexpr with
 		| TVar(v,Some e1) ->
 		| TVar(v,Some e1) ->
 			self#texpr (rvalue_type gctx v.v_type (Some v.v_name)) e1;
 			self#texpr (rvalue_type gctx v.v_type (Some v.v_name)) e1;

+ 8 - 0
src/generators/genlua.ml

@@ -574,7 +574,9 @@ and gen_cond ctx cond =
 
 
 and gen_loop ctx cond do_while e =
 and gen_loop ctx cond do_while e =
     let old_in_loop = ctx.in_loop in
     let old_in_loop = ctx.in_loop in
+    let old_in_loop_try = ctx.in_loop_try in
     ctx.in_loop <- true;
     ctx.in_loop <- true;
+    ctx.in_loop_try <- false;
     let old_handle_continue = ctx.handle_continue in
     let old_handle_continue = ctx.handle_continue in
     let will_continue = has_continue e in
     let will_continue = has_continue e in
     ctx.handle_continue <- has_continue e;
     ctx.handle_continue <- has_continue e;
@@ -610,6 +612,7 @@ and gen_loop ctx cond do_while e =
     b();
     b();
     newline ctx;
     newline ctx;
     print ctx "end";
     print ctx "end";
+    ctx.in_loop_try <- old_in_loop_try;
     ctx.in_loop <- old_in_loop;
     ctx.in_loop <- old_in_loop;
     ctx.break_depth <- ctx.break_depth-1;
     ctx.break_depth <- ctx.break_depth-1;
     ctx.handle_continue <- old_handle_continue;
     ctx.handle_continue <- old_handle_continue;
@@ -1296,6 +1299,9 @@ and gen_value ctx e =
 and gen_tbinop ctx op e1 e2 =
 and gen_tbinop ctx op e1 e2 =
     (match op, e1.eexpr, e2.eexpr with
     (match op, e1.eexpr, e2.eexpr with
      | Ast.OpAssign, TField(e3, (FInstance _ as ci)), TFunction f ->
      | Ast.OpAssign, TField(e3, (FInstance _ as ci)), TFunction f ->
+         let old = ctx.in_value, ctx.in_loop in
+         ctx.in_value <- None;
+         ctx.in_loop <- false;
          gen_expr ctx e1;
          gen_expr ctx e1;
          spr ctx " = " ;
          spr ctx " = " ;
          let fn_args = List.map ident (List.map arg_name f.tf_args) in
          let fn_args = List.map ident (List.map arg_name f.tf_args) in
@@ -1323,6 +1329,8 @@ and gen_tbinop ctx op e1 e2 =
               bend();
               bend();
               newline ctx;
               newline ctx;
           | _ -> gen_value ctx e2);
           | _ -> gen_value ctx e2);
+         ctx.in_value <- fst old;
+         ctx.in_loop <- snd old;
          spr ctx " end"
          spr ctx " end"
      | Ast.OpAssign, _, _ ->
      | Ast.OpAssign, _, _ ->
          let iife_assign = ctx.iife_assign in
          let iife_assign = ctx.iife_assign in

+ 2 - 0
src/generators/genphp7.ml

@@ -3891,6 +3891,8 @@ class class_builder ctx (cls:tclass) =
 					| Var { v_read = read; v_write = write } ->
 					| Var { v_read = read; v_write = write } ->
 						if read = AccCall then getters := field.cf_name :: !getters;
 						if read = AccCall then getters := field.cf_name :: !getters;
 						if write = AccCall then setters := field.cf_name :: !setters;
 						if write = AccCall then setters := field.cf_name :: !setters;
+						if read = AccPrivateCall then getters := field.cf_name :: !getters;
+						if write = AccPrivateCall then setters := field.cf_name :: !setters;
 					| _ -> ()
 					| _ -> ()
 			in
 			in
 			List.iter collect cls.cl_ordered_fields;
 			List.iter collect cls.cl_ordered_fields;

+ 2 - 2
src/generators/genpy.ml

@@ -1718,7 +1718,7 @@ module Generator = struct
 			match cf.cf_kind with
 			match cf.cf_kind with
 				| Var _ when not (is_physical_field cf) ->
 				| Var _ when not (is_physical_field cf) ->
 					()
 					()
-				| Var({v_read = AccCall}) ->
+				| Var({v_read = AccCall | AccPrivateCall}) ->
 					if Meta.has Meta.IsVar cf.cf_meta then
 					if Meta.has Meta.IsVar cf.cf_meta then
 						DynArray.add fields cf.cf_name
 						DynArray.add fields cf.cf_name
 					else
 					else
@@ -1922,7 +1922,7 @@ module Generator = struct
 			print ctx "    @staticmethod\n    def _hx_empty_init(_hx_o):";
 			print ctx "    @staticmethod\n    def _hx_empty_init(_hx_o):";
 			let found_fields = ref false in
 			let found_fields = ref false in
 			List.iter (fun cf -> match cf.cf_kind with
 			List.iter (fun cf -> match cf.cf_kind with
-					| Var ({v_read = AccCall}) ->
+					| Var ({v_read = AccCall | AccPrivateCall}) ->
 						()
 						()
 					| Var _ ->
 					| Var _ ->
 						found_fields := true;
 						found_fields := true;

+ 4 - 4
src/generators/genswf9.ml

@@ -2324,7 +2324,7 @@ let realize_required_accessors ctx cl =
 				if not (is_implemented_by_super ci) then begin
 				if not (is_implemented_by_super ci) then begin
 					List.iter (fun cf ->
 					List.iter (fun cf ->
 						match cf.cf_kind with
 						match cf.cf_kind with
-						| Var { v_read = (AccCall | AccNever) as read; v_write = (AccCall | AccNever) as write } ->
+						| Var { v_read = (AccCall | AccPrivateCall | AccNever) as read; v_write = (AccCall | AccPrivateCall | AccNever) as write } ->
 							begin try
 							begin try
 								let read', write', native = Hashtbl.find h cf.cf_name in
 								let read', write', native = Hashtbl.find h cf.cf_name in
 								let read = if read = AccNever then read' else true in
 								let read = if read = AccNever then read' else true in
@@ -2496,10 +2496,10 @@ let generate_class ctx c =
 				maybe_gen_instance_setter ctx c f acc alloc_slot
 				maybe_gen_instance_setter ctx c f acc alloc_slot
 			else
 			else
 				maybe_gen_static_setter ctx c f acc alloc_slot
 				maybe_gen_static_setter ctx c f acc alloc_slot
-		| Var { v_read = (AccCall | AccNever) as read; v_write = (AccCall | AccNever) as write } when not (has_class_flag c CInterface) && not (Meta.has Meta.IsVar f.cf_meta) ->
+		| Var { v_read = (AccCall | AccPrivateCall | AccNever) as read; v_write = (AccCall | AccPrivateCall | AccNever) as write } when not (has_class_flag c CInterface) && not (Meta.has Meta.IsVar f.cf_meta) ->
 			(* if the accessor methods were defined in super classes, we still need to generate native getter/setter *)
 			(* if the accessor methods were defined in super classes, we still need to generate native getter/setter *)
 			let acc =
 			let acc =
-				if read = AccCall then begin
+				if read = AccCall || read = AccPrivateCall then begin
 					try
 					try
 						begin
 						begin
 						let tl = extract_param_types c.cl_params in
 						let tl = extract_param_types c.cl_params in
@@ -2524,7 +2524,7 @@ let generate_class ctx c =
 						acc
 						acc
 				end else acc
 				end else acc
 			in
 			in
-			if write = AccCall then begin
+			if write = AccCall || write = AccPrivateCall then begin
 				try
 				try
 					begin
 					begin
 					let tl = extract_param_types c.cl_params in
 					let tl = extract_param_types c.cl_params in

+ 87 - 0
src/macro/eval/evalAtomic.ml

@@ -0,0 +1,87 @@
+open EvalValue
+open EvalEncode
+open EvalDecode
+open EvalExceptions
+open EvalHash
+
+let as_atomic_bool vthis = match vthis with
+	| VInstance {ikind = IAtomicBool i} -> i
+	| _ -> unexpected_value vthis "AtomicBool"
+let as_atomic_int vthis = match vthis with
+	| VInstance {ikind = IAtomicInt i} -> i
+	| _ -> unexpected_value vthis "AtomicInt"
+let as_atomic_object vthis = match vthis with
+	| VInstance {ikind = IAtomicObject i} -> i
+	| _ -> unexpected_value vthis "AtomicObject"
+
+let atomic_object_fields = [
+        "_hx_new", vfun1 (fun v -> encode_instance key_haxe_atomic_AtomicObject ~kind:(IAtomicObject (Atomic.make v)));
+        "load", vfun1 (fun v -> Atomic.get (as_atomic_object v));
+        "store", vfun2 (fun a v -> Atomic.set (as_atomic_object a) v; v);
+        "exchange", vfun2 (fun a v -> Atomic.exchange (as_atomic_object a) v);
+        "compareExchange", vfun3 (fun vthis a b ->
+            let vthis = as_atomic_object vthis in
+            let rec loop () = begin
+                let original = Atomic.get vthis in
+                let real_replacement = if EvalValue.equals original a then b else original in
+                if not (Atomic.compare_and_set vthis original real_replacement) then 
+                    loop ()
+                else
+                    original
+            end
+            in loop ());
+]
+
+let atomic_bool_fields = [
+        "_hx_new", vfun1 (fun v -> encode_instance key_haxe_atomic_AtomicBool ~kind:(IAtomicBool (Atomic.make (decode_bool v))));
+        "load", vfun1 (fun v -> vbool (Atomic.get (as_atomic_bool v)));
+        "store", vfun2 (fun a v -> Atomic.set (as_atomic_bool a) (decode_bool v); v);
+        "exchange", vfun2 (fun a v -> vbool (Atomic.exchange (as_atomic_bool a) (decode_bool v)));
+        "compareExchange", vfun3 (fun vthis a b ->
+            let vthis = as_atomic_bool vthis in
+            let a = decode_bool a and b = decode_bool b in
+            let rec loop () = begin
+                let original = Atomic.get vthis in
+                let real_replacement = if original = a then b else original in
+                if not (Atomic.compare_and_set vthis original real_replacement) then 
+                    loop ()
+                else
+                    vbool original
+            end
+            in loop ());
+]
+
+let fetch_update (this: 'a Atomic.t) (f: 'a -> 'a) =
+    let rec loop () = begin
+        let original = Atomic.get this in
+        let replacement = f original in
+        if not (Atomic.compare_and_set this original replacement) then 
+            loop ()
+        else
+            original
+    end
+    in loop ()
+
+let atomic_int_fields = [
+        "_hx_new", vfun1 (fun v -> encode_instance key_haxe_atomic_AtomicInt ~kind:(IAtomicInt (Atomic.make (decode_int v))));
+        "load", vfun1 (fun v -> vint (Atomic.get (as_atomic_int v)));
+        "store", vfun2 (fun a v -> Atomic.set (as_atomic_int a) (decode_int v); v);
+        "exchange", vfun2 (fun a v -> vint (Atomic.exchange (as_atomic_int a) (decode_int v)));
+        "compareExchange", vfun3 (fun vthis a b ->
+            let vthis = as_atomic_int vthis in
+            let a = decode_int a and b = decode_int b in
+            let rec loop () = begin
+                let original = Atomic.get vthis in
+                let real_replacement = if original = a then b else original in
+                if not (Atomic.compare_and_set vthis original real_replacement) then 
+                    loop ()
+                else
+                    vint original
+            end
+            in loop ());
+        "add", vfun2 (fun a v -> vint (Atomic.fetch_and_add (as_atomic_int a) (decode_int v)));
+        "sub", vfun2 (fun a v -> vint (Atomic.fetch_and_add (as_atomic_int a) (-(decode_int v))));
+        "and", vfun2 (fun a v -> let v = decode_int v in vint (fetch_update (as_atomic_int a) (fun orig -> orig land v)));
+        "or", vfun2 (fun a v -> let v = decode_int v in vint (fetch_update (as_atomic_int a) (fun orig -> orig lor v)));
+        "xor", vfun2 (fun a v -> let v = decode_int v in vint (fetch_update (as_atomic_int a) (fun orig -> orig lxor v)));
+]

+ 18 - 18
src/macro/eval/evalEmitter.ml

@@ -759,33 +759,33 @@ let process_arguments fl vl env =
 
 
 let create_function_noret ctx eci exec fl vl =
 let create_function_noret ctx eci exec fl vl =
 	let env = push_environment ctx eci in
 	let env = push_environment ctx eci in
-	process_arguments fl vl env;
-	let v = exec env in
-	pop_environment ctx env;
-	v
+	Std.finally (fun () -> pop_environment ctx env) (fun () ->
+		process_arguments fl vl env;
+		exec env
+	) ()
 
 
 let create_function ctx eci exec fl vl =
 let create_function ctx eci exec fl vl =
 	let env = push_environment ctx eci in
 	let env = push_environment ctx eci in
-	process_arguments fl vl env;
-	let v = try exec env with Return v -> v in
-	pop_environment ctx env;
-	v
+	Std.finally (fun () -> pop_environment ctx env) (fun () ->
+		process_arguments fl vl env;
+		try exec env with Return v -> v
+	) ()
 
 
 let create_closure_noret ctx eci refs exec fl vl =
 let create_closure_noret ctx eci refs exec fl vl =
 	let env = push_environment ctx eci in
 	let env = push_environment ctx eci in
-	Array.iter (fun (i,vr) -> env.env_captures.(i) <- vr) refs;
-	process_arguments fl vl env;
-	let v = exec env in
-	pop_environment ctx env;
-	v
+	Std.finally (fun () -> pop_environment ctx env) (fun () ->
+		Array.iter (fun (i,vr) -> env.env_captures.(i) <- vr) refs;
+		process_arguments fl vl env;
+		exec env
+	) ()
 
 
 let create_closure refs ctx eci exec fl vl =
 let create_closure refs ctx eci exec fl vl =
 	let env = push_environment ctx eci in
 	let env = push_environment ctx eci in
-	Array.iter (fun (i,vr) -> env.env_captures.(i) <- vr) refs;
-	process_arguments fl vl env;
-	let v = try exec env with Return v -> v in
-	pop_environment ctx env;
-	v
+	Std.finally (fun () -> pop_environment ctx env) (fun () ->
+		Array.iter (fun (i,vr) -> env.env_captures.(i) <- vr) refs;
+		process_arguments fl vl env;
+		try exec env with Return v -> v
+	) ()
 
 
 let emit_closure ctx mapping eci hasret exec fl env =
 let emit_closure ctx mapping eci hasret exec fl env =
 	let refs = Array.map (fun (i,slot) -> i,emit_capture_read slot env) mapping in
 	let refs = Array.map (fun (i,slot) -> i,emit_capture_read slot env) mapping in

+ 24 - 1
src/macro/eval/evalExceptions.ml

@@ -130,7 +130,30 @@ let catch_exceptions ctx ?(final=(fun() -> ())) f p =
 				| l when p' = null_pos -> l (* If the exception position is null_pos, we're "probably" in a built-in function. *)
 				| l when p' = null_pos -> l (* If the exception position is null_pos, we're "probably" in a built-in function. *)
 				| _ :: l -> l (* Otherwise, ignore topmost frame position. *)
 				| _ :: l -> l (* Otherwise, ignore topmost frame position. *)
 			in
 			in
-			get_exc_error_stack ctx stack
+			let def () =
+				get_exc_error_stack ctx stack
+			in
+			begin match v with
+			| VInstance vi when is v key_haxe_Exception ->
+				begin try
+					let vf = instance_field vi key_custom_stack in
+					begin match vf with
+					| VVector vv ->
+						Array.to_list vv |> List.map (fun v -> match v with
+							| VEnumValue {enpos = Some p} ->
+								p
+							| _ ->
+								die "" __LOC__
+						)
+					| _ ->
+						def();
+					end
+				with Not_found ->
+					def ()
+				end
+			| _ ->
+				def();
+			end
 		in
 		in
 
 
 		if is v key_haxe_macro_Error then begin
 		if is v key_haxe_macro_Error then begin

+ 4 - 0
src/macro/eval/evalHash.ml

@@ -48,6 +48,7 @@ let key_error = hash "error"
 let key_exception_message = hash "__exceptionMessage"
 let key_exception_message = hash "__exceptionMessage"
 let key_native_exception = hash "__nativeException"
 let key_native_exception = hash "__nativeException"
 let key_native_stack = hash "__nativeStack"
 let key_native_stack = hash "__nativeStack"
+let key_custom_stack = hash "__customStack"
 let key_Array = hash "Array"
 let key_Array = hash "Array"
 let key_eval_Vector = hash "eval.Vector"
 let key_eval_Vector = hash "eval.Vector"
 let key_String = hash "String"
 let key_String = hash "String"
@@ -211,3 +212,6 @@ let key_address = hash "address"
 let key_netmask = hash "netmask"
 let key_netmask = hash "netmask"
 let key_previous = hash "previous"
 let key_previous = hash "previous"
 let key_current = hash "current"
 let key_current = hash "current"
+let key_haxe_atomic_AtomicBool = hash "haxe.atomic.AtomicBool" 
+let key_haxe_atomic_AtomicInt = hash "haxe.atomic.AtomicInt" 
+let key_haxe_atomic_AtomicObject = hash "haxe.atomic.AtomicObject" 

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

@@ -10,14 +10,14 @@ let make_stack envs =
 	List.iter (fun (pos,kind) ->
 	List.iter (fun (pos,kind) ->
 		let file_pos s =
 		let file_pos s =
 			let line1,col1,_,_ = Lexer.get_pos_coords pos in
 			let line1,col1,_,_ = Lexer.get_pos_coords pos in
-			encode_enum_value key_haxe_StackItem 2 [|s;create_unknown pos.pfile;vint line1;vint col1|] None
+			encode_enum_value key_haxe_StackItem 2 [|s;create_unknown pos.pfile;vint line1;vint col1|] (Some pos)
 		in
 		in
 		match kind with
 		match kind with
 		| EKLocalFunction i ->
 		| EKLocalFunction i ->
-			let local_function = encode_enum_value key_haxe_StackItem 4 [|vint i|] None in
+			let local_function = encode_enum_value key_haxe_StackItem 4 [|vint i|] (Some pos) in
 			DynArray.add l (file_pos local_function);
 			DynArray.add l (file_pos local_function);
 		| EKMethod(st,sf) ->
 		| EKMethod(st,sf) ->
-			let local_function = encode_enum_value key_haxe_StackItem 3 [|create_unknown (rev_hash st); create_unknown (rev_hash sf)|] None in
+			let local_function = encode_enum_value key_haxe_StackItem 3 [|create_unknown (rev_hash st); create_unknown (rev_hash sf)|] (Some pos) in
 			DynArray.add l (file_pos local_function);
 			DynArray.add l (file_pos local_function);
 		| EKMacro(st,sf) ->
 		| EKMacro(st,sf) ->
 			()
 			()

+ 7 - 1
src/macro/eval/evalStdLib.ml

@@ -2709,6 +2709,8 @@ module StdSys = struct
 		)
 		)
 
 
 	let time = vfun0 (fun () -> vfloat (catch_unix_error Unix.gettimeofday()))
 	let time = vfun0 (fun () -> vfloat (catch_unix_error Unix.gettimeofday()))
+
+	let timestamp_ms = vfun0 (fun () -> EvalIntegers.encode_haxe_i64_direct (* TODO: use vint64 once that works *) (Extc.timestamp_ms()))
 end
 end
 
 
 module StdThread = struct
 module StdThread = struct
@@ -3727,6 +3729,7 @@ let init_standard_library builtins =
 		"stdout",StdSys.stdout;
 		"stdout",StdSys.stdout;
 		"systemName",StdSys.systemName;
 		"systemName",StdSys.systemName;
 		"time",StdSys.time;
 		"time",StdSys.time;
+		"timestamp_ms",StdSys.timestamp_ms;
 	] [];
 	] [];
 	init_fields builtins (["eval";"vm"],"NativeThread") [
 	init_fields builtins (["eval";"vm"],"NativeThread") [
 		"delay",StdThread.delay;
 		"delay",StdThread.delay;
@@ -3849,4 +3852,7 @@ let init_standard_library builtins =
 	init_fields builtins (["eval";"luv";"_Prepare"], "Prepare_Impl_") EvalLuv.prepare_fields [];
 	init_fields builtins (["eval";"luv";"_Prepare"], "Prepare_Impl_") EvalLuv.prepare_fields [];
 	init_fields builtins (["eval";"luv";"_Check"], "Check_Impl_") EvalLuv.check_fields [];
 	init_fields builtins (["eval";"luv";"_Check"], "Check_Impl_") EvalLuv.check_fields [];
 	init_fields builtins (["eval";"luv"], "Version") EvalLuv.version_fields [];
 	init_fields builtins (["eval";"luv"], "Version") EvalLuv.version_fields [];
-	EvalSsl.init_fields init_fields builtins
+	EvalSsl.init_fields init_fields builtins;
+	init_fields builtins (["haxe";"atomic"; "_AtomicBool"], "AtomicBool_Impl_") EvalAtomic.atomic_bool_fields [];
+	init_fields builtins (["haxe";"atomic"; "_AtomicInt"], "AtomicInt_Impl_") EvalAtomic.atomic_int_fields [];
+	init_fields builtins (["haxe";"atomic"; "_AtomicObject"], "AtomicObject_Impl_") EvalAtomic.atomic_object_fields [];

+ 11 - 1
src/macro/eval/evalValue.ml

@@ -214,6 +214,9 @@ and vinstance_kind =
 	| IMbedtlsSsl of Mbedtls.mbedtls_ssl_context
 	| IMbedtlsSsl of Mbedtls.mbedtls_ssl_context
 	| IMbedtlsX509Crt of Mbedtls.mbedtls_x509_crt
 	| IMbedtlsX509Crt of Mbedtls.mbedtls_x509_crt
 	| INormal
 	| INormal
+	| IAtomicBool of bool Atomic.t
+	| IAtomicInt of int Atomic.t
+	| IAtomicObject of value Atomic.t
 
 
 and vinstance = {
 and vinstance = {
 	(* The fields of this instance. *)
 	(* The fields of this instance. *)
@@ -238,7 +241,7 @@ and venum_value = {
 	eindex : int;
 	eindex : int;
 	eargs : value array;
 	eargs : value array;
 	epath : int;
 	epath : int;
-	enpos : pos option;
+	mutable enpos : pos option;
 }
 }
 
 
 and vthread = {
 and vthread = {
@@ -347,6 +350,7 @@ let vfield_closure v f = VFieldClosure(v,f)
 let vobject o = VObject o
 let vobject o = VObject o
 let vint i = VInt32 (Int32.of_int i)
 let vint i = VInt32 (Int32.of_int i)
 let vint32 i = VInt32 i
 let vint32 i = VInt32 i
+let vint64 i = VInt64 i
 let vfloat f = VFloat f
 let vfloat f = VFloat f
 let venum_value e = VEnumValue e
 let venum_value e = VEnumValue e
 let vnative_string s = VNativeString s
 let vnative_string s = VNativeString s
@@ -356,3 +360,9 @@ let s_expr_pretty e = (Type.s_expr_pretty false "" false (Type.s_type (Type.prin
 let rec vresolve v = match v with
 let rec vresolve v = match v with
 	| VLazy f -> vresolve (Lazy.force f)
 	| VLazy f -> vresolve (Lazy.force f)
 	| _ -> v
 	| _ -> v
+
+let associate_enum_value_pos ve p = match ve with
+	| VEnumValue ve ->
+		ve.enpos <- Some p
+	| _ ->
+		()

+ 10 - 1
src/macro/macroApi.ml

@@ -174,6 +174,8 @@ module type InterpApi = sig
 	val handle_decoding_error : (string -> unit) -> value -> Type.t -> (string * int) list
 	val handle_decoding_error : (string -> unit) -> value -> Type.t -> (string * int) list
 
 
 	val get_api_call_pos : unit -> pos
 	val get_api_call_pos : unit -> pos
+
+	val associate_enum_value_pos : value -> pos -> unit
 end
 end
 
 
 let s_type_path = Globals.s_type_path
 let s_type_path = Globals.s_type_path
@@ -1124,6 +1126,7 @@ and encode_var_access a =
 		| AccInline	-> 5, []
 		| AccInline	-> 5, []
 		| AccRequire (s,msg) -> 6, [encode_string s; null encode_string msg]
 		| AccRequire (s,msg) -> 6, [encode_string s; null encode_string msg]
 		| AccCtor -> 7, []
 		| AccCtor -> 7, []
+		| AccPrivateCall -> 8, []
 	) in
 	) in
 	encode_enum IVarAccess tag pl
 	encode_enum IVarAccess tag pl
 
 
@@ -1450,6 +1453,7 @@ let decode_var_access v =
 	| 5, [] -> AccInline
 	| 5, [] -> AccInline
 	| 6, [s1;s2] -> AccRequire(decode_string s1, opt decode_string s2)
 	| 6, [s1;s2] -> AccRequire(decode_string s1, opt decode_string s2)
 	| 7, [] -> AccCtor
 	| 7, [] -> AccCtor
+	| 8, [] -> AccPrivateCall
 	| _ -> raise Invalid_expr
 	| _ -> raise Invalid_expr
 
 
 let decode_method_kind v =
 let decode_method_kind v =
@@ -2432,6 +2436,11 @@ let macro_api ccom get_api =
 		"set_hxb_writer_config", vfun1 (fun v ->
 		"set_hxb_writer_config", vfun1 (fun v ->
 			(get_api()).set_hxb_writer_config v;
 			(get_api()).set_hxb_writer_config v;
 			vnull
 			vnull
-		)
+		);
+		"associate_enum_value_pos",vfun2 (fun ve vp ->
+			let p = decode_pos vp in
+			associate_enum_value_pos ve p;
+			vnull;
+		);
 	]
 	]
 end
 end

+ 7 - 13
src/optimization/analyzer.ml

@@ -880,13 +880,7 @@ module Debug = struct
 	let dot_debug ctx c cf =
 	let dot_debug ctx c cf =
 		let g = ctx.graph in
 		let g = ctx.graph in
 		let start_graph ?(graph_config=[]) suffix =
 		let start_graph ?(graph_config=[]) suffix =
-			let ch = Path.create_file false suffix [] (get_dump_path ctx c cf) in
-			Printf.fprintf ch "digraph graphname {\n";
-			List.iter (fun s -> Printf.fprintf ch "%s;\n" s) graph_config;
-			ch,(fun () ->
-				Printf.fprintf ch "}\n";
-				close_out ch
-			)
+			DotGraph.start_graph ~graph_config (DotGraph.get_dump_path ctx.com c cf) suffix
 		in
 		in
 		let ch,f = start_graph "-cfg.dot" in
 		let ch,f = start_graph "-cfg.dot" in
 		List.iter (fun bb -> dot_debug_node g ch [NILoopGroups;NIScopes;NIPhi;NIExpr] bb) g.g_nodes;
 		List.iter (fun bb -> dot_debug_node g ch [NILoopGroups;NIScopes;NIPhi;NIExpr] bb) g.g_nodes;
@@ -1118,12 +1112,12 @@ module Run = struct
 					print_endline (Type.s_expr_pretty true "" false (s_type (print_context())) e);
 					print_endline (Type.s_expr_pretty true "" false (s_type (print_context())) e);
 					print_endline (Printf.sprintf "</%s>" s);
 					print_endline (Printf.sprintf "</%s>" s);
 				) (List.rev actx.debug_exprs);
 				) (List.rev actx.debug_exprs);
-				Debug.dot_debug actx c cf;
-				print_endline (Printf.sprintf "dot graph written to %s" (String.concat "/" (Debug.get_dump_path actx c cf)));
+				Debug.dot_debug actx c.cl_path cf.cf_name;
+				print_endline (Printf.sprintf "dot graph written to %s" (String.concat "/" (DotGraph.get_dump_path actx.com c.cl_path cf.cf_name)));
 			in
 			in
 			let maybe_debug () = match config.debug_kind with
 			let maybe_debug () = match config.debug_kind with
 				| DebugNone -> ()
 				| DebugNone -> ()
-				| DebugDot -> Debug.dot_debug actx c cf;
+				| DebugDot -> Debug.dot_debug actx c.cl_path cf.cf_name;
 				| DebugFull -> debug()
 				| DebugFull -> debug()
 			in
 			in
 			begin try
 			begin try
@@ -1190,13 +1184,13 @@ module Run = struct
 		| TTypeDecl _ -> ()
 		| TTypeDecl _ -> ()
 		| TAbstractDecl _ -> ()
 		| TAbstractDecl _ -> ()
 
 
-	let run_on_types scom pool types =
+	let run_on_types scom pool all_types new_types =
 		let config = get_base_config scom in
 		let config = get_base_config scom in
 		with_timer scom.timer_ctx config.detail_times None ["other"] (fun () ->
 		with_timer scom.timer_ctx config.detail_times None ["other"] (fun () ->
 			if config.optimize && config.purity_inference then
 			if config.optimize && config.purity_inference then
-				with_timer scom.timer_ctx config.detail_times None ["optimize";"purity-inference"] (fun () -> Purity.infer types);
+				with_timer scom.timer_ctx config.detail_times None ["optimize";"purity-inference"] (fun () -> Purity.infer all_types);
 			let exc_out = Atomic.make None in
 			let exc_out = Atomic.make None in
-			Parallel.ParallelArray.iter pool (run_on_type scom exc_out pool config) types;
+			Parallel.ParallelArray.iter pool (run_on_type scom exc_out pool config) new_types;
 			check_exc_out exc_out
 			check_exc_out exc_out
 		)
 		)
 end
 end

+ 13 - 4
src/optimization/analyzerTexpr.ml

@@ -1006,10 +1006,19 @@ end
 
 
 module Cleanup = struct
 module Cleanup = struct
 	let apply com e =
 	let apply com e =
-		let if_or_op e e1 e2 e3 = match (Texpr.skip e1).eexpr,(Texpr.skip e3).eexpr with
-			| TUnop(Not,Prefix,e1),TConst (TBool true) -> optimize_binop {e with eexpr = TBinop(OpBoolOr,e1,e2)} OpBoolOr e1 e2
-			| _,TConst (TBool false) -> optimize_binop {e with eexpr = TBinop(OpBoolAnd,e1,e2)} OpBoolAnd e1 e2
-			| _,TBlock [] -> {e with eexpr = TIf(e1,e2,None)}
+		let if_or_op e e1 e2 e3 = match (Texpr.skip e1).eexpr,(Texpr.skip e2).eexpr,(Texpr.skip e3).eexpr with
+			| _,TReturn(Some b),TReturn(Some {eexpr = TConst (TBool false)}) ->
+				let binop = optimize_binop {e with eexpr = TBinop(OpBoolAnd,e1,b)} OpBoolAnd e1 b in
+				{e with eexpr = TReturn(Some binop)}
+			| TUnop(Not,Prefix,e1),TReturn(Some b),TReturn(Some {eexpr = TConst (TBool true)}) ->
+				let binop = optimize_binop {e with eexpr = TBinop(OpBoolOr,e1,b)} OpBoolOr e1 b in
+				{e with eexpr = TReturn(Some binop)}
+			| TUnop(Not,Prefix,e1),_,TConst (TBool true) ->
+				optimize_binop {e with eexpr = TBinop(OpBoolOr,e1,e2)} OpBoolOr e1 e2
+			| _,_,TConst (TBool false) ->
+				optimize_binop {e with eexpr = TBinop(OpBoolAnd,e1,e2)} OpBoolAnd e1 e2
+			| _,_,TBlock [] ->
+				{e with eexpr = TIf(e1,e2,None)}
 			| _ -> match (Texpr.skip e2).eexpr with
 			| _ -> match (Texpr.skip e2).eexpr with
 				| TBlock [] ->
 				| TBlock [] ->
 					let e1' = mk (TUnop(Not,Prefix,e1)) e1.etype e1.epos in
 					let e1' = mk (TUnop(Not,Prefix,e1)) e1.etype e1.epos in

+ 10 - 4
src/optimization/dce.ml

@@ -140,8 +140,8 @@ let rec keep_field dce cf c kind =
 			with Not_found -> false
 			with Not_found -> false
 		in
 		in
 		match cf.cf_kind with
 		match cf.cf_kind with
-		| Var { v_read = AccCall } -> check_accessor "get_"
-		| Var { v_write = AccCall } -> check_accessor "set_"
+		| Var { v_read = AccCall | AccPrivateCall } -> check_accessor "get_"
+		| Var { v_write = AccCall | AccPrivateCall } -> check_accessor "set_"
 		| _ -> false
 		| _ -> false
 	end
 	end
 
 
@@ -747,11 +747,17 @@ let fix_accessors types =
 				| Var {v_read = AccCall; v_write = a} ->
 				| Var {v_read = AccCall; v_write = a} ->
 					let s = "get_" ^ cf.cf_name in
 					let s = "get_" ^ cf.cf_name in
 					cf.cf_kind <- Var {v_read = if has_accessor c s stat then AccCall else AccNever; v_write = a}
 					cf.cf_kind <- Var {v_read = if has_accessor c s stat then AccCall else AccNever; v_write = a}
+				| Var {v_read = AccPrivateCall; v_write = a} ->
+					let s = "get_" ^ cf.cf_name in
+					cf.cf_kind <- Var {v_read = if has_accessor c s stat then AccPrivateCall else AccNever; v_write = a}
 				| _ -> ());
 				| _ -> ());
 				(match cf.cf_kind with
 				(match cf.cf_kind with
 				| Var {v_write = AccCall; v_read = a} ->
 				| Var {v_write = AccCall; v_read = a} ->
 					let s = "set_" ^ cf.cf_name in
 					let s = "set_" ^ cf.cf_name in
 					cf.cf_kind <- Var {v_write = if has_accessor c s stat then AccCall else AccNever; v_read = a}
 					cf.cf_kind <- Var {v_write = if has_accessor c s stat then AccCall else AccNever; v_read = a}
+				| Var {v_write = AccPrivateCall; v_read = a} ->
+					let s = "set_" ^ cf.cf_name in
+					cf.cf_kind <- Var {v_write = if has_accessor c s stat then AccPrivateCall else AccNever; v_read = a}
 				| _ -> ())
 				| _ -> ())
 			in
 			in
 			List.iter (check_prop true) c.cl_ordered_statics;
 			List.iter (check_prop true) c.cl_ordered_statics;
@@ -863,7 +869,7 @@ let sweep dce types =
 					if not (Meta.has Meta.Accessor cf.cf_meta) then cf.cf_meta <- (Meta.Accessor,[],mk_zero_range_pos c.cl_pos) :: cf.cf_meta
 					if not (Meta.has Meta.Accessor cf.cf_meta) then cf.cf_meta <- (Meta.Accessor,[],mk_zero_range_pos c.cl_pos) :: cf.cf_meta
 				in
 				in
 				begin match cf.cf_kind with
 				begin match cf.cf_kind with
-				| Var {v_read = AccCall} ->
+				| Var {v_read = AccCall | AccPrivateCall} ->
 					begin try
 					begin try
 						add_accessor_metadata (PMap.find ("get_" ^ cf.cf_name) (if stat then c.cl_statics else c.cl_fields))
 						add_accessor_metadata (PMap.find ("get_" ^ cf.cf_name) (if stat then c.cl_statics else c.cl_fields))
 					with Not_found ->
 					with Not_found ->
@@ -873,7 +879,7 @@ let sweep dce types =
 					()
 					()
 				end;
 				end;
 				begin match cf.cf_kind with
 				begin match cf.cf_kind with
-				| Var {v_write = AccCall} ->
+				| Var {v_write = AccCall | AccPrivateCall} ->
 					begin try
 					begin try
 						add_accessor_metadata (PMap.find ("set_" ^ cf.cf_name) (if stat then c.cl_statics else c.cl_fields))
 						add_accessor_metadata (PMap.find ("set_" ^ cf.cf_name) (if stat then c.cl_statics else c.cl_fields))
 					with Not_found ->
 					with Not_found ->

+ 1 - 1
src/optimization/inline.ml

@@ -268,7 +268,7 @@ let inline_config cls_opt cf call_args return_type =
 let inline_metadata e meta =
 let inline_metadata e meta =
 	let inline_meta e meta = match meta with
 	let inline_meta e meta = match meta with
 		| Meta.Pure,[EConst(Ident "inferredPure"),_],_ -> e
 		| Meta.Pure,[EConst(Ident "inferredPure"),_],_ -> e
-		| (Meta.Deprecated | Meta.Pure),_,_ -> mk (TMeta(meta,e)) e.etype e.epos
+		| (Meta.Deprecated | Meta.Pure | Meta.NullSafety),_,_ -> mk (TMeta(meta,e)) e.etype e.epos
 		| _ -> e
 		| _ -> e
 	in
 	in
 	List.fold_left inline_meta e meta
 	List.fold_left inline_meta e meta

+ 20 - 17
src/optimization/inlineConstructors.ml

@@ -232,23 +232,26 @@ let inline_constructors (scom : SafeCom.t) original_e =
 		The id is incremented each time and is used later in the final_map phase to identify the correct inline_object.
 		The id is incremented each time and is used later in the final_map phase to identify the correct inline_object.
 	*)
 	*)
 	let rec mark_ctors ?(force_inline=false) e : texpr =
 	let rec mark_ctors ?(force_inline=false) e : texpr =
-		let is_meta_inline = match e.eexpr with (TMeta((Meta.Inline,_,_),e)) -> true | _ -> false in
-		let e = Type.map_expr (mark_ctors ~force_inline:is_meta_inline) e in
-		let mark() =
-			incr curr_io_id;
-			let id_expr = (EConst(Int (string_of_int !curr_io_id, None)), e.epos) in
-			let meta = (Meta.InlineObject, [id_expr], e.epos) in
-			mk (TMeta(meta, e)) e.etype e.epos
-		in
-		match e.eexpr, force_inline with
-			| TObjectDecl _, _
-			| TArrayDecl _, _
-			| TNew _, true ->
-				mark()
-			| TNew({ cl_constructor = Some ({cf_kind = Method MethInline; cf_expr = Some ({eexpr = TFunction _})} as cf)} as c,_,_), _ ->
-				if needs_inline scom (Some c) cf then mark()
-				else e
-			| _ -> e
+		match e.eexpr with
+			| TMeta((Meta.InlineConstructorArgument _,_,_),_) -> e
+			| _ ->
+				let is_meta_inline = match e.eexpr with (TMeta((Meta.Inline,_,_),e)) -> true | _ -> false in
+				let e = Type.map_expr (mark_ctors ~force_inline:is_meta_inline) e in
+				let mark() =
+					incr curr_io_id;
+					let id_expr = (EConst(Int (string_of_int !curr_io_id, None)), e.epos) in
+					let meta = (Meta.InlineObject, [id_expr], e.epos) in
+					mk (TMeta(meta, e)) e.etype e.epos
+				in
+				match e.eexpr, force_inline with
+					| TObjectDecl _, _
+					| TArrayDecl _, _
+					| TNew _, true ->
+						mark()
+					| TNew({ cl_constructor = Some ({cf_kind = Method MethInline; cf_expr = Some ({eexpr = TFunction _})} as cf)} as c,_,_), _ ->
+						if needs_inline scom (Some c) cf then mark()
+						else e
+					| _ -> e
 	in
 	in
 
 
 	(*
 	(*

+ 20 - 2
src/prebuild.ml

@@ -115,6 +115,7 @@ type parsed_define = {
 	d_deprecated : string option;
 	d_deprecated : string option;
 	d_deprecated_define : string option;
 	d_deprecated_define : string option;
 	d_default : string option;
 	d_default : string option;
+	d_signature_neutral : bool option;
 }
 }
 let parse_define json =
 let parse_define json =
 	let fields = match json with
 	let fields = match json with
@@ -131,6 +132,7 @@ let parse_define json =
 		d_deprecated = get_optional_field2 "deprecated" as_string fields;
 		d_deprecated = get_optional_field2 "deprecated" as_string fields;
 		d_deprecated_define = get_optional_field2 "deprecatedDefine" as_string fields;
 		d_deprecated_define = get_optional_field2 "deprecatedDefine" as_string fields;
 		d_default = get_optional_field2 "default" as_string fields;
 		d_default = get_optional_field2 "default" as_string fields;
+		d_signature_neutral = get_optional_field2 "signatureNeutral" as_bool fields;
 	}
 	}
 
 
 let parse_meta json =
 let parse_meta json =
@@ -204,6 +206,7 @@ let gen_option f = function
 let gen_define_info defines =
 let gen_define_info defines =
 	let deprecations = DynArray.create() in
 	let deprecations = DynArray.create() in
 	let default_values = DynArray.create() in
 	let default_values = DynArray.create() in
+	let sig_neutral = DynArray.create() in
 	let define_str = List.map (function
 	let define_str = List.map (function
 		def ->
 		def ->
 			let platforms_str = gen_platforms def.d_platforms in
 			let platforms_str = gen_platforms def.d_platforms in
@@ -233,12 +236,21 @@ let gen_define_info defines =
 					DynArray.add default_values (Printf.sprintf "\t(%S,%S)" define x);
 					DynArray.add default_values (Printf.sprintf "\t(%S,%S)" define x);
 					[Printf.sprintf "DefaultValue(%s)" quoted]
 					[Printf.sprintf "DefaultValue(%s)" quoted]
 			in
 			in
+			(match def.d_signature_neutral with
+				| Some true ->
+					DynArray.add sig_neutral (Printf.sprintf "| %S" (convert_define define));
+					begin match def.d_deprecated_define with
+					| None -> ()
+					| Some s -> DynArray.add sig_neutral (Printf.sprintf "| %S" (convert_define s))
+					end
+				| _ -> ());
 			"\t| " ^ def.d_name ^ " -> \"" ^ define ^ "\",(" ^ (Printf.sprintf "%S" def.d_doc) ^ ",[" ^ (String.concat "; " (platforms_str @ params_str @ links_str @ deprecated @ default)) ^ "])"
 			"\t| " ^ def.d_name ^ " -> \"" ^ define ^ "\",(" ^ (Printf.sprintf "%S" def.d_doc) ^ ",[" ^ (String.concat "; " (platforms_str @ params_str @ links_str @ deprecated @ default)) ^ "])"
 	) defines in
 	) defines in
 	(
 	(
 		String.concat "\n" define_str,
 		String.concat "\n" define_str,
 		String.concat "\n" (DynArray.to_list deprecations),
 		String.concat "\n" (DynArray.to_list deprecations),
-		String.concat ";\n" (DynArray.to_list default_values)
+		String.concat ";\n" (DynArray.to_list default_values),
+		String.concat " " (DynArray.to_list sig_neutral)
 	)
 	)
 
 
 let gen_meta_type metas =
 let gen_meta_type metas =
@@ -379,10 +391,16 @@ match Array.to_list (Sys.argv) with
 		Printf.printf "type strict_defined =\n";
 		Printf.printf "type strict_defined =\n";
 		Printf.printf "%s" (gen_define_type defines);
 		Printf.printf "%s" (gen_define_type defines);
 		Printf.printf "\n\t| Last\n\t| Custom of string\n\n";
 		Printf.printf "\n\t| Last\n\t| Custom of string\n\n";
-		let infos,deprecations,default_values = gen_define_info defines in
+		let infos,deprecations,default_values,sig_neutral = gen_define_info defines in
 		Printf.printf "let infos = function\n";
 		Printf.printf "let infos = function\n";
 		Printf.printf "%s" infos;
 		Printf.printf "%s" infos;
 		Printf.printf "\n\t| Last -> die \"\" __LOC__\n\t| Custom s -> s,(\"\",[])\n";
 		Printf.printf "\n\t| Last -> die \"\" __LOC__\n\t| Custom s -> s,(\"\",[])\n";
+		if sig_neutral = "" then
+			Printf.printf "let is_signature_neutral _ = false\n"
+		else begin
+			Printf.printf "let is_signature_neutral = function\n";
+			Printf.printf "\t%s -> true\n\t| _ -> false\n" sig_neutral;
+		end;
 		Printf.printf "\nlet deprecated_defines = [\n%s\n]\n" deprecations;
 		Printf.printf "\nlet deprecated_defines = [\n%s\n]\n" deprecations;
 		Printf.printf "\nlet default_values = [\n%s\n]\n" default_values;
 		Printf.printf "\nlet default_values = [\n%s\n]\n" default_values;
 	| [_; "meta"; meta_path]->
 	| [_; "meta"; meta_path]->

+ 1 - 0
src/syntax/grammar.ml

@@ -85,6 +85,7 @@ let lower_ident_or_macro = function%parser
 
 
 let property_ident = function%parser
 let property_ident = function%parser
 	| [ ident as i ] -> i
 	| [ ident as i ] -> i
+	| [ (Kwd Private,p1); (Const (Ident i),p2) ] -> "private " ^ i, punion p1 p2
 	| [ (Kwd Dynamic,p) ] -> "dynamic",p
 	| [ (Kwd Dynamic,p) ] -> "dynamic",p
 	| [ (Kwd Default,p) ] -> "default",p
 	| [ (Kwd Default,p) ] -> "default",p
 	| [ (Kwd Null,p) ] -> "null",p
 	| [ (Kwd Null,p) ] -> "null",p

+ 4 - 13
src/syntax/lexer.ml

@@ -270,15 +270,13 @@ let resolve_file_pos file =
 		f
 		f
 
 
 let find_file file =
 let find_file file =
-	try
-		ThreadSafeHashtbl.find all_files file
-	with Not_found ->
+	ThreadSafeHashtbl.find_or_add all_files file (fun () ->
 		try
 		try
-			let f = resolve_file_pos file in
-			ThreadSafeHashtbl.add all_files file f;
-			f
+			(* TODO: It's actually stupid to block the entire Hashtbl while we're reading a file... *)
+			resolve_file_pos file
 		with Sys_error _ ->
 		with Sys_error _ ->
 			make_file file
 			make_file file
+	)
 
 
 let find_pos p =
 let find_pos p =
 	find_line p.pmin (find_file p.pfile)
 	find_line p.pmin (find_file p.pfile)
@@ -287,13 +285,6 @@ let get_error_line p =
 	let l, _ = find_pos p in
 	let l, _ = find_pos p in
 	l
 	l
 
 
-let get_error_line_if_exists p =
-	try
-		let file = ThreadSafeHashtbl.find all_files p.pfile in
-		fst (find_line p.pmin file)
-	with Not_found ->
-		0
-
 let get_pos_coords p =
 let get_pos_coords p =
 	let file = find_file p.pfile in
 	let file = find_file p.pfile in
 	let l1, p1 = find_line p.pmin file in
 	let l1, p1 = find_line p.pmin file in

+ 0 - 1
src/syntax/parserConfig.ml

@@ -1,6 +1,5 @@
 open Globals
 open Globals
 open Common
 open Common
-open DisplayPosition
 
 
 let default_config defines =
 let default_config defines =
 	Parser.create_config defines false false DMNone false None
 	Parser.create_config defines false false DMNone false None

+ 2 - 2
src/typing/callUnification.ml

@@ -625,7 +625,7 @@ object(self)
 			end;
 			end;
 		| Var v ->
 		| Var v ->
 			begin match (if is_set then v.v_write else v.v_read) with
 			begin match (if is_set then v.v_write else v.v_read) with
-			| AccCall ->
+			| AccCall | AccPrivateCall ->
 				self#accessor_call fa el_typed el
 				self#accessor_call fa el_typed el
 			| _ ->
 			| _ ->
 				self#expr_call (FieldAccess.get_field_expr fa FCall) el_typed el
 				self#expr_call (FieldAccess.get_field_expr fa FCall) el_typed el
@@ -664,4 +664,4 @@ let make_static_call_better ctx c cf tl el t p =
 	let e1 = Builder.make_static_this c p in
 	let e1 = Builder.make_static_this c p in
 	let fa = FieldAccess.create e1 cf fh false p in
 	let fa = FieldAccess.create e1 cf fh false p in
 	let fcc = unify_field_call ctx fa el [] p false in
 	let fcc = unify_field_call ctx fa el [] p false in
-	fcc.fc_data()
+	fcc.fc_data()

+ 1 - 1
src/typing/fieldAccess.ml

@@ -93,7 +93,7 @@ let get_field_expr fa mode =
 let find_accessor_for_field host cf t mode = match cf.cf_kind with
 let find_accessor_for_field host cf t mode = match cf.cf_kind with
 	| Var v ->
 	| Var v ->
 		begin match (match mode with MSet _ -> v.v_write | _ -> v.v_read) with
 		begin match (match mode with MSet _ -> v.v_write | _ -> v.v_read) with
-			| AccCall ->
+			| AccCall | AccPrivateCall ->
 				let name = (match mode with MSet _ -> "set_" | _ -> "get_") ^ cf.cf_name in
 				let name = (match mode with MSet _ -> "set_" | _ -> "get_") ^ cf.cf_name in
 				let forward cf_acc new_host =
 				let forward cf_acc new_host =
 					(cf_acc,new_host)
 					(cf_acc,new_host)

+ 34 - 7
src/typing/fields.ml

@@ -163,26 +163,53 @@ let field_access ctx mode f fh e pfield =
 			AKUsingField sea
 			AKUsingField sea
 		end;
 		end;
 	| Var v ->
 	| Var v ->
+		let is_prop_access access =
+			match access with
+				| AccCall | AccPrivateCall -> ctx.e.bypass_accessor = 0
+				| _ -> false
+		in
+		let check_field_with_mode c stat =
+			begin match mode with
+				| MGet when is_prop_access v.v_read ->
+					let can = can_access ctx c f ~check_prop:true ~is_setter:false stat in
+					if not can then
+						raise_typing_error "This property cannot be accessed for reading" pfield
+				| MSet _ when is_prop_access v.v_write ->
+					let can = can_access ctx c f ~check_prop:true ~is_setter:true stat in
+					if not can then
+						raise_typing_error "This property cannot be accessed for writing" pfield
+				| _ -> check_field_access ctx c f stat pfield
+			end
+		in
 		begin match fh with
 		begin match fh with
 		| FHStatic c | FHAbstract(_,_,c) ->
 		| FHStatic c | FHAbstract(_,_,c) ->
-			check_field_access ctx c f true pfield
+			check_field_with_mode c true;
 		| FHInstance _ ->
 		| FHInstance _ ->
 			begin match follow e.etype with
 			begin match follow e.etype with
 			| TInst(c,_) ->
 			| TInst(c,_) ->
-				check_field_access ctx c f false pfield
+				check_field_with_mode c false;
 			| _ ->
 			| _ ->
 				()
 				()
 			end;
 			end;
 			if e.eexpr = TConst TSuper then begin match mode with
 			if e.eexpr = TConst TSuper then begin match mode with
-				| MGet | MCall _ when v.v_read = AccCall ->
+				| MGet | MCall _ when v.v_read = AccCall || v.v_read = AccPrivateCall ->
 					()
 					()
-				| MSet _ when v.v_write = AccCall ->
+				| MSet _ when v.v_write = AccCall || v.v_write = AccPrivateCall ->
 					()
 					()
 				| _ ->
 				| _ ->
 					display_error ctx.com "Normal variables cannot be accessed with 'super', use 'this' instead" pfield;
 					display_error ctx.com "Normal variables cannot be accessed with 'super', use 'this' instead" pfield;
 			end;
 			end;
 		| FHAnon ->
 		| FHAnon ->
-			()
+			let is_private_access access =
+				access = AccPrivateCall && not (Meta.has Meta.PrivateAccess ctx.f.meta) && ctx.e.bypass_accessor = 0
+			in
+			begin match mode with
+				| MGet when is_private_access v.v_read ->
+					raise_typing_error "This property cannot be accessed for reading" pfield
+				| MSet _ when is_private_access v.v_write ->
+					raise_typing_error "This property cannot be accessed for writing" pfield
+				| _ -> ()
+			end;
 		end;
 		end;
 		let normal inline =
 		let normal inline =
 			AKField (make_access inline)
 			AKField (make_access inline)
@@ -203,9 +230,9 @@ let field_access ctx mode f fh e pfield =
 				if ctx.f.untyped then normal false else normal_failure())
 				if ctx.f.untyped then normal false else normal_failure())
 		| AccNormal | AccNo ->
 		| AccNormal | AccNo ->
 			normal false
 			normal false
-		| AccCall when (not ctx.allow_transform) || (ctx.f.in_display && DisplayPosition.display_position#enclosed_in pfull) ->
+		| AccCall | AccPrivateCall when (not ctx.allow_transform) || (ctx.f.in_display && DisplayPosition.display_position#enclosed_in pfull) ->
 			normal false
 			normal false
-		| AccCall ->
+		| AccCall | AccPrivateCall ->
 			let m = (match mode with MSet _ -> "set_" | _ -> "get_") ^ f.cf_name in
 			let m = (match mode with MSet _ -> "set_" | _ -> "get_") ^ f.cf_name in
 			let bypass_accessor =
 			let bypass_accessor =
 				(
 				(

+ 7 - 1
src/typing/generic.ml

@@ -121,7 +121,8 @@ let generic_substitute_expr gctx e =
 	in
 	in
 	let rec build_expr e =
 	let rec build_expr e =
 		let e = match e.eexpr with
 		let e = match e.eexpr with
-		| TField(e1, FInstance({cl_kind = KGeneric} as c,tl,cf)) ->
+		| TField(e1, (FInstance({cl_kind = KGeneric} as c,tl,cf) as fa_orig)) 
+		| TField(e1, (FClosure(Some ({cl_kind = KGeneric} as c, tl), cf) as fa_orig)) ->
 			let info = gctx.ctx.g.get_build_info gctx.ctx (TClassDecl c) gctx.p in
 			let info = gctx.ctx.g.get_build_info gctx.ctx (TClassDecl c) gctx.p in
 			let t = info.build_apply (List.map (generic_substitute_type' gctx true) tl) in
 			let t = info.build_apply (List.map (generic_substitute_type' gctx true) tl) in
 			begin match follow t with
 			begin match follow t with
@@ -134,6 +135,11 @@ let generic_substitute_expr gctx e =
 				with Not_found ->
 				with Not_found ->
 					raise_typing_error (Printf.sprintf "Type %s has no field %s (possible typing order issue)" (s_type (print_context()) t) cf.cf_name) e.epos
 					raise_typing_error (Printf.sprintf "Type %s has no field %s (possible typing order issue)" (s_type (print_context()) t) cf.cf_name) e.epos
 				in
 				in
+				(* preserve FClosure *)
+				let fa = match fa_orig, fa with
+					| FClosure _, FInstance(c,tl,cf) -> FClosure(Some(c,tl),cf)
+					| _ -> fa
+				in
 				build_expr {e with eexpr = TField(e1,fa)}
 				build_expr {e with eexpr = TField(e1,fa)}
 			end;
 			end;
 		| TTypeExpr (TClassDecl ({cl_kind = KTypeParameter _;} as c)) when Meta.has Meta.Const c.cl_meta ->
 		| TTypeExpr (TClassDecl ({cl_kind = KTypeParameter _;} as c)) when Meta.has Meta.Const c.cl_meta ->

+ 11 - 12
src/typing/macroContext.ml

@@ -57,15 +57,15 @@ let safe_decode com v expected t p f =
 			raise_decode_error (Printf.sprintf "Expected %s but got %s" expected (Interp.value_string v))
 			raise_decode_error (Printf.sprintf "Expected %s but got %s" expected (Interp.value_string v))
 
 
 
 
-let macro_timer timer_ctx level label identifier f arg =
-	let id = Timer.determine_id level ["macro"] [label] identifier in
+let macro_timer timer_ctx level s identifier f arg =
+	let id = Timer.determine_id level ["macro"] s identifier in
 	Timer.time timer_ctx id f arg
 	Timer.time timer_ctx id f arg
 
 
 let typing_timer ctx need_type f =
 let typing_timer ctx need_type f =
 	let t = Timer.start_timer ctx.com.timer_ctx ["typing"] in
 	let t = Timer.start_timer ctx.com.timer_ctx ["typing"] in
 	let ctx = if need_type && ctx.pass < PTypeField then begin
 	let ctx = if need_type && ctx.pass < PTypeField then begin
 		enter_field_typing_pass ctx.g ("typing_timer",[]);
 		enter_field_typing_pass ctx.g ("typing_timer",[]);
-		TyperManager.clone_for_expr ctx ctx.e.curfun false
+		TyperManager.clone_for_expr ctx ctx.e.curfun FunFunction
 	end else
 	end else
 		ctx
 		ctx
 	in
 	in
@@ -141,22 +141,22 @@ let make_macro_com_api com mcom p =
 		);
 		);
 		after_init_macros = (fun f ->
 		after_init_macros = (fun f ->
 			com.callbacks#add_after_init_macros (fun () ->
 			com.callbacks#add_after_init_macros (fun () ->
-				macro_timer com.timer_ctx timer_level "afterInitMacros" None f ();
+				macro_timer com.timer_ctx timer_level ["afterInitMacros"] None f ();
 			)
 			)
 		);
 		);
 		after_typing = (fun f ->
 		after_typing = (fun f ->
 			com.callbacks#add_after_typing (fun tl ->
 			com.callbacks#add_after_typing (fun tl ->
-				macro_timer com.timer_ctx timer_level "afterTyping" None f tl;
+				macro_timer com.timer_ctx timer_level ["afterTyping"] None f tl;
 			)
 			)
 		);
 		);
 		on_generate = (fun f b ->
 		on_generate = (fun f b ->
 			(if b then com.callbacks#add_before_save else com.callbacks#add_after_save) (fun() ->
 			(if b then com.callbacks#add_before_save else com.callbacks#add_after_save) (fun() ->
-				macro_timer com.timer_ctx timer_level "onGenerate"None f (List.map type_of_module_type com.types);
+				macro_timer com.timer_ctx timer_level ["onGenerate"] None f (List.map type_of_module_type com.types);
 			)
 			)
 		);
 		);
 		after_generate = (fun f ->
 		after_generate = (fun f ->
 			com.callbacks#add_after_generation (fun() ->
 			com.callbacks#add_after_generation (fun() ->
-				macro_timer com.timer_ctx timer_level "afterGenerate" None f ();
+				macro_timer com.timer_ctx timer_level ["afterGenerate"] None f ();
 			)
 			)
 		);
 		);
 		on_type_not_found = (fun f ->
 		on_type_not_found = (fun f ->
@@ -653,12 +653,11 @@ and flush_macro_context mint mctx =
 			if apply_native then Native.apply_native_paths t
 			if apply_native then Native.apply_native_paths t
 		in
 		in
 		let scom = SafeCom.of_typer mctx in
 		let scom = SafeCom.of_typer mctx in
-		let cv_wrapper_impl = CapturedVars.get_wrapper_implementation mctx.com in
 		let expr_filters = [
 		let expr_filters = [
 			"handle_abstract_casts",AbstractCast.handle_abstract_casts;
 			"handle_abstract_casts",AbstractCast.handle_abstract_casts;
 			"local_statics",LocalStatic.run;
 			"local_statics",LocalStatic.run;
 			"Exceptions",(fun _ -> Exceptions.filter ectx);
 			"Exceptions",(fun _ -> Exceptions.filter ectx);
-			"captured_vars",(fun scom -> CapturedVars.captured_vars scom cv_wrapper_impl);
+			"captured_vars",(fun scom -> CapturedVars.captured_vars scom mctx.com.local_wrapper);
 		] in
 		] in
 		let type_filters = [
 		let type_filters = [
 			(fun _ -> FiltersCommon.remove_generic_base);
 			(fun _ -> FiltersCommon.remove_generic_base);
@@ -677,7 +676,7 @@ and flush_macro_context mint mctx =
 		with Error err -> raise (Fatal_error err));
 		with Error err -> raise (Fatal_error err));
 	in
 	in
 	let timer_level = Timer.level_from_define mctx.com.defines Define.MacroTimes in
 	let timer_level = Timer.level_from_define mctx.com.defines Define.MacroTimes in
-	macro_timer mctx.com.timer_ctx timer_level "flush" None f ()
+	macro_timer mctx.com.timer_ctx timer_level ["flush"] None f ()
 
 
 let create_macro_interp api mctx =
 let create_macro_interp api mctx =
 	let com2 = mctx.com in
 	let com2 = mctx.com in
@@ -810,7 +809,7 @@ let load_macro'' com mctx display cpath fname p =
 			mctx.com.cached_macros#add (cpath,fname) meth;
 			mctx.com.cached_macros#add (cpath,fname) meth;
 			meth
 			meth
 		in
 		in
-		macro_timer com.timer_ctx timer_level "typing" (Some (s_type_path cpath ^ "." ^ fname)) f ()
+		macro_timer com.timer_ctx timer_level ["typing";s_type_path cpath ^ "." ^ fname] None f ()
 
 
 let load_macro' ctx display cpath f p =
 let load_macro' ctx display cpath f p =
 	(* TODO: The only reason this nonsense is here is because this is the signature
 	(* TODO: The only reason this nonsense is here is because this is the signature
@@ -823,7 +822,7 @@ let do_call_macro com api cpath name args p =
 	incr stats.s_macros_called;
 	incr stats.s_macros_called;
 	let timer_level = Timer.level_from_define com.defines Define.MacroTimes in
 	let timer_level = Timer.level_from_define com.defines Define.MacroTimes in
 	let f = Interp.call_path (Interp.get_ctx()) ((fst cpath) @ [snd cpath]) name args in
 	let f = Interp.call_path (Interp.get_ctx()) ((fst cpath) @ [snd cpath]) name args in
-	let r = macro_timer com.timer_ctx timer_level "execution" (Some (s_type_path cpath ^ "." ^ name)) f api in
+	let r = macro_timer com.timer_ctx timer_level ["execution";s_type_path cpath ^ "." ^ name] None f api in
 	if com.verbose then Common.log com ("Exiting macro " ^ s_type_path cpath ^ "." ^ name);
 	if com.verbose then Common.log com ("Exiting macro " ^ s_type_path cpath ^ "." ^ name);
 	r
 	r
 
 

+ 164 - 53
src/typing/nullSafety.ml

@@ -367,9 +367,26 @@ let rec process_condition mode condition (is_nullable_expr:texpr->bool) callback
 		if to_nulls then nulls := expr :: !nulls
 		if to_nulls then nulls := expr :: !nulls
 		else not_nulls := expr :: !not_nulls
 		else not_nulls := expr :: !not_nulls
 	in
 	in
+	let remove expr =
+		let expr = reveal_expr expr in
+		let subj = get_subject mode expr in
+		nulls := List.filter (fun e ->
+			let e_subj = get_subject mode (reveal_expr e) in
+			e_subj <> subj
+		) !nulls;
+		not_nulls := List.filter (fun e ->
+			let e_subj = get_subject mode (reveal_expr e) in
+			e_subj <> subj
+		) !not_nulls;
+	in
 	let rec traverse positive e =
 	let rec traverse positive e =
 		match e.eexpr with
 		match e.eexpr with
 			| TUnop (Not, Prefix, e) -> traverse (not positive) e
 			| TUnop (Not, Prefix, e) -> traverse (not positive) e
+			| TBinop (OpAssign, checked_expr, e) when is_suitable mode checked_expr && (is_nullable_expr e) ->
+				(* remove expr from both list if there is `e = nullable` in condition *)
+				remove checked_expr
+			| TBlock exprs ->
+				List.iter (fun e -> traverse positive e) exprs
 			| TBinop (OpEq, { eexpr = TConst TNull }, checked_expr) when is_suitable mode checked_expr ->
 			| TBinop (OpEq, { eexpr = TConst TNull }, checked_expr) when is_suitable mode checked_expr ->
 				add positive checked_expr
 				add positive checked_expr
 			| TBinop (OpEq, checked_expr, { eexpr = TConst TNull }) when is_suitable mode checked_expr ->
 			| TBinop (OpEq, checked_expr, { eexpr = TConst TNull }) when is_suitable mode checked_expr ->
@@ -834,12 +851,13 @@ class local_safety (mode:safety_mode) =
 				| TWhile (condition, body, NormalWhile) ->
 				| TWhile (condition, body, NormalWhile) ->
 					condition_callback condition;
 					condition_callback condition;
 					let (nulls, not_nulls) = process_condition mode condition is_nullable_expr (fun _ -> ()) in
 					let (nulls, not_nulls) = process_condition mode condition is_nullable_expr (fun _ -> ()) in
+					let original_safe = self#get_safe_locals_copy in
 					(** execute `body` with known not-null variables *)
 					(** execute `body` with known not-null variables *)
 					List.iter self#get_current_scope#add_to_safety not_nulls;
 					List.iter self#get_current_scope#add_to_safety not_nulls;
 					body_callback
 					body_callback
 						(fun () -> List.iter self#get_current_scope#add_to_safety not_nulls)
 						(fun () -> List.iter self#get_current_scope#add_to_safety not_nulls)
 						body;
 						body;
-					List.iter self#get_current_scope#remove_from_safety not_nulls;
+					self#get_current_scope#filter_safety original_safe;
 				| _ -> fail ~msg:"Expected TWhile" expr.epos __POS__
 				| _ -> fail ~msg:"Expected TWhile" expr.epos __POS__
 		(**
 		(**
 			Should be called for bodies of loops (for, while)
 			Should be called for bodies of loops (for, while)
@@ -955,18 +973,46 @@ class local_safety (mode:safety_mode) =
 		*)
 		*)
 		method process_and left_expr right_expr is_nullable_expr (callback:texpr->unit) =
 		method process_and left_expr right_expr is_nullable_expr (callback:texpr->unit) =
 			callback left_expr;
 			callback left_expr;
-			let (_, not_nulls) = process_condition mode left_expr is_nullable_expr (fun e -> ()) in
-			List.iter self#get_current_scope#add_to_safety not_nulls;
+			let original_safe = self#get_safe_locals_copy in
+			(* save not_nulls for `a != null && a > 0` *)
+			let (_, not_nulls) = process_condition mode left_expr is_nullable_expr (fun _ -> ()) in
+			(* create temp scope for right_expr *)
+			let temp_scope = new safety_scope mode STNormal (Hashtbl.copy original_safe) (Hashtbl.create 10) in
+			List.iter temp_scope#add_to_safety not_nulls;
+			scopes <- temp_scope :: scopes;
 			callback right_expr;
 			callback right_expr;
-			List.iter self#get_current_scope#remove_from_safety not_nulls
+			self#scope_closed;
+
+			let safe_after_rhs = temp_scope#get_safe_locals in
+			let final_safe = Hashtbl.create (Hashtbl.length original_safe) in
+			Hashtbl.iter (fun subj e ->
+				if Hashtbl.mem original_safe subj && Hashtbl.mem safe_after_rhs subj then
+					Hashtbl.replace final_safe subj e
+			) original_safe;
+
+			self#get_current_scope#reset_to final_safe;
 		(**
 		(**
 			Handle boolean OR outside of `if` condition.
 			Handle boolean OR outside of `if` condition.
 		*)
 		*)
 		method process_or left_expr right_expr is_nullable_expr (callback:texpr->unit) =
 		method process_or left_expr right_expr is_nullable_expr (callback:texpr->unit) =
+			let original_safe = self#get_safe_locals_copy in
+			(* save nulls for `a == null || a > 0` *)
 			let (nulls, _) = process_condition mode left_expr is_nullable_expr callback in
 			let (nulls, _) = process_condition mode left_expr is_nullable_expr callback in
-			List.iter self#get_current_scope#add_to_safety nulls;
+			(* create temp scope for right_expr *)
+			let temp_scope = new safety_scope mode STNormal (Hashtbl.copy original_safe) (Hashtbl.create 10) in
+			List.iter temp_scope#add_to_safety nulls;
+			scopes <- temp_scope :: scopes;
 			callback right_expr;
 			callback right_expr;
-			List.iter self#get_current_scope#remove_from_safety nulls
+			self#scope_closed;
+
+			let safe_after_rhs = temp_scope#get_safe_locals in
+			let final_safe = Hashtbl.create (Hashtbl.length original_safe) in
+			Hashtbl.iter (fun subj e ->
+				if Hashtbl.mem original_safe subj && Hashtbl.mem safe_after_rhs subj then
+					Hashtbl.replace final_safe subj e
+			) original_safe;
+
+			self#get_current_scope#reset_to final_safe;
 		(**
 		(**
 			Remove subject from the safety list if a nullable value is assigned or if an object with safe field is reassigned.
 			Remove subject from the safety list if a nullable value is assigned or if an object with safe field is reassigned.
 		*)
 		*)
@@ -1072,8 +1118,10 @@ class expr_checker mode immediate_execution report =
 					is_nullable_type e.etype && not (local_safety#is_safe e)
 					is_nullable_type e.etype && not (local_safety#is_safe e)
 		(**
 		(**
 			Check if `expr` can be passed to a place where `to_type` is expected.
 			Check if `expr` can be passed to a place where `to_type` is expected.
-			This method has side effect: it logs an error if `expr` has a type parameter incompatible with the type parameter of `to_type`.
-			E.g.: `Array<Null<String>>` vs `Array<String>` returns `true`, but also adds a compilation error.
+			This method has side effects:
+			- it logs an error if `expr` has a type parameter incompatible with the type parameter of `to_type`.
+				E.g.: `Array<Null<String>>` vs `Array<String>` returns `true`, but also adds a compilation error.
+			- it logs an error on anon structure field nullability mismatch to report specific field error and returns `true`.
 		*)
 		*)
 		method can_pass_expr expr to_type p =
 		method can_pass_expr expr to_type p =
 			let try_unify expr to_type =
 			let try_unify expr to_type =
@@ -1093,28 +1141,26 @@ class expr_checker mode immediate_execution report =
 							fail ~msg:"Null safety unification failure" expr.epos __POS__
 							fail ~msg:"Null safety unification failure" expr.epos __POS__
 				end
 				end
 			in
 			in
+			let check_anon_fields fields to_type =
+				List.fold_left (fun acc ((name, _, _), field_expr) ->
+					try
+						let field_to_type = PMap.find name to_type.a_fields in
+						let field_pos = field_expr.epos in
+						if not (self#can_pass_expr field_expr field_to_type.cf_type field_pos) then
+							self#error "Cannot assign nullable value here." [field_pos];
+						acc && true
+					with Not_found -> false) true fields
+			in
 			match expr.eexpr, to_type with
 			match expr.eexpr, to_type with
 				| TLocal v, _ when contains_unsafe_meta v.v_meta -> true
 				| TLocal v, _ when contains_unsafe_meta v.v_meta -> true
 				| TObjectDecl fields, TAbstract ({ a_path = ([],"Null") }, [TAnon to_type])
 				| TObjectDecl fields, TAbstract ({ a_path = ([],"Null") }, [TAnon to_type])
 				| TObjectDecl fields, TAnon to_type ->
 				| 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
+					check_anon_fields fields to_type
 				| TObjectDecl fields, TAbstract ({ a_path = ([],"Null") }, [TType (t,tl)])
 				| TObjectDecl fields, TAbstract ({ a_path = ([],"Null") }, [TType (t,tl)])
 				| TObjectDecl fields, TType (t,tl) ->
 				| TObjectDecl fields, TType (t,tl) ->
 					(match follow_without_null t.t_type with
 					(match follow_without_null t.t_type with
 							| TAnon to_type ->
 							| 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
+								check_anon_fields fields to_type
 							| _ -> try_unify expr to_type
 							| _ -> try_unify expr to_type
 					)
 					)
 				| _, _ -> try_unify expr to_type
 				| _, _ -> try_unify expr to_type
@@ -1488,7 +1534,7 @@ class expr_checker mode immediate_execution report =
 			traverse 0 args types meta
 			traverse 0 args types meta
 	end
 	end
 
 
-class class_checker cls immediate_execution report =
+class class_checker cls immediate_execution report (main_expr : texpr option) =
 	let cls_meta = cls.cl_meta @ (match cls.cl_kind with KAbstractImpl a -> a.a_meta | _ -> []) in
 	let cls_meta = cls.cl_meta @ (match cls.cl_kind with KAbstractImpl a -> a.a_meta | _ -> []) in
 	object (self)
 	object (self)
 			val is_safe_class = (safety_enabled cls_meta)
 			val is_safe_class = (safety_enabled cls_meta)
@@ -1546,7 +1592,9 @@ class class_checker cls immediate_execution report =
 										| _ -> ()
 										| _ -> ()
 					in
 					in
 					if read_access = AccCall then check_accessor "get_";
 					if read_access = AccCall then check_accessor "get_";
-					if write_access = AccCall then check_accessor "set_"
+					if write_access = AccCall then check_accessor "set_";
+					if read_access = AccPrivateCall then check_accessor "get_";
+					if write_access = AccPrivateCall then check_accessor "set_";
 				| _ -> ()
 				| _ -> ()
 		(**
 		(**
 			Get safety mode for the current class
 			Get safety mode for the current class
@@ -1570,34 +1618,84 @@ class class_checker cls immediate_execution report =
 		*)
 		*)
 		method private is_in_safety field =
 		method private is_in_safety field =
 			(is_safe_class && not (contains_unsafe_meta field.cf_meta)) || safety_enabled field.cf_meta
 			(is_safe_class && not (contains_unsafe_meta field.cf_meta)) || safety_enabled field.cf_meta
+		(**
+			Extract `tf_expr` from `com.main.main_expr` if this expr in current class
+		*)
+		method private get_main_tf_expr (main_expr : texpr option) =
+			match main_expr with
+				| Some main_expr ->
+					begin match main_expr.eexpr with
+						| TCall ({ eexpr = TField (_, FStatic (cl, field))}, _) when cl == cls ->
+							begin match field.cf_expr with
+								| Some ({ eexpr = TFunction { tf_expr = e } }) ->
+									Some e
+								| _ -> None
+							end
+						| _ -> None
+					end
+				| None -> None
 		(**
 		(**
 			Check `var` fields are initialized properly
 			Check `var` fields are initialized properly
 		*)
 		*)
 		method check_var_fields =
 		method check_var_fields =
 			let check_field is_static field =
 			let check_field is_static field =
 				validate_safety_meta report field.cf_meta;
 				validate_safety_meta report field.cf_meta;
-				if should_be_initialized field then
-					if not (is_nullable_type field.cf_type) && self#is_in_safety field then
-						match field.cf_expr with
-							| None ->
-								if is_static then
-									checker#error
-										("Field \"" ^ field.cf_name ^ "\" is not nullable thus should have an initial value.")
-										[field.cf_pos]
-							| Some e ->
-								if not (checker#can_pass_expr e field.cf_type e.epos) then
-									checker#error ("Cannot set nullable initial value for not-nullable field \"" ^ field.cf_name ^ "\".") [field.cf_pos]
+				if
+					should_be_initialized field
+					&& not (is_nullable_type field.cf_type)
+					&& self#is_in_safety field
+				then
+					match field.cf_expr with
+						| Some e ->
+							if not (checker#can_pass_expr e field.cf_type e.epos) then
+								checker#error
+								("Cannot set nullable initial value for not-nullable field \"" ^ field.cf_name ^ "\".") [field.cf_pos]
+						| None -> ()
 			in
 			in
 			List.iter (check_field false) cls.cl_ordered_fields;
 			List.iter (check_field false) cls.cl_ordered_fields;
 			List.iter (check_field true) cls.cl_ordered_statics;
 			List.iter (check_field true) cls.cl_ordered_statics;
+
+			self#check_statics_initialization ();
 			self#check_fields_initialization_in_constructor ()
 			self#check_fields_initialization_in_constructor ()
+
+		method private check_statics_initialization () =
+			let fields_to_initialize = Hashtbl.create 20 in
+			List.iter
+				(fun f ->
+					if
+						should_be_initialized f
+						&& not (is_nullable_type f.cf_type)
+						&& not (contains_unsafe_meta f.cf_meta)
+					then
+						match f.cf_expr with
+							| Some _ -> ()
+							| None -> Hashtbl.add fields_to_initialize f.cf_name f
+				)
+				cls.cl_ordered_statics;
+
+			begin match TClass.get_cl_init cls with
+				| Some init_expr ->
+					ignore (self#check_fields_initialization fields_to_initialize init_expr true);
+				| None -> ()
+			end;
+			let main_tf_expr = self#get_main_tf_expr main_expr in
+			(match main_tf_expr with
+				| Some tf_expr ->
+					ignore (self#check_fields_initialization fields_to_initialize tf_expr true);
+				| _ -> ()
+			);
+			Hashtbl.iter
+				(fun name field ->
+					checker#error
+						("Field \"" ^ name ^ "\" is not nullable thus should have an initial value.")
+						[field.cf_pos]
+				)
+				fields_to_initialize
 		(**
 		(**
 			Check instance fields without initial values are properly initialized in constructor
 			Check instance fields without initial values are properly initialized in constructor
 		*)
 		*)
 		method private check_fields_initialization_in_constructor () =
 		method private check_fields_initialization_in_constructor () =
-			let fields_to_initialize = Hashtbl.create 20
-			(* Compiler-autogenerated local vars for transfering `this` to local functions *)
-			and this_vars = Hashtbl.create 5 in
+			let fields_to_initialize = Hashtbl.create 20 in
 			List.iter
 			List.iter
 				(fun f ->
 				(fun f ->
 					if
 					if
@@ -1610,10 +1708,30 @@ class class_checker cls immediate_execution report =
 							| None -> Hashtbl.add fields_to_initialize f.cf_name f
 							| None -> Hashtbl.add fields_to_initialize f.cf_name f
 				)
 				)
 				cls.cl_ordered_fields;
 				cls.cl_ordered_fields;
+
+			(match cls.cl_constructor with
+				| Some { cf_expr = Some { eexpr = TFunction { tf_expr = e } } } ->
+					ignore (self#check_fields_initialization fields_to_initialize e false);
+				| _ -> ()
+			);
+			Hashtbl.iter
+				(fun name field ->
+					checker#error
+						("Field \"" ^ name ^ "\" is not nullable thus should have an initial value or should be initialized in constructor.")
+						[field.cf_pos]
+				)
+				fields_to_initialize
+
+		method private check_fields_initialization fields_to_initialize tf_expr is_static =
+			(* Compiler-autogenerated local vars for transfering `this` to local functions *)
+			let this_vars = Hashtbl.create 5 in
 			let rec check_unsafe_usage init_list safety_enabled e =
 			let rec check_unsafe_usage init_list safety_enabled e =
 				if Hashtbl.length init_list > 0 then
 				if Hashtbl.length init_list > 0 then
 					match e.eexpr with
 					match e.eexpr with
-						| TField ({ eexpr = TConst TThis }, FInstance (_, _, field)) ->
+						| TField ({ eexpr = TConst TThis }, FInstance (_, _, field)) when not is_static ->
+							if Hashtbl.mem init_list field.cf_name then
+								checker#error ("Cannot use field " ^ field.cf_name ^ " until initialization.") [e.epos]
+						| TField (_, FStatic (_, field)) when is_static ->
 							if Hashtbl.mem init_list field.cf_name then
 							if Hashtbl.mem init_list field.cf_name then
 								checker#error ("Cannot use field " ^ field.cf_name ^ " until initialization.") [e.epos]
 								checker#error ("Cannot use field " ^ field.cf_name ^ " until initialization.") [e.epos]
 						| TField ({ eexpr = TConst TThis }, FClosure (_, field)) ->
 						| TField ({ eexpr = TConst TThis }, FClosure (_, field)) ->
@@ -1634,7 +1752,11 @@ class class_checker cls immediate_execution report =
 			in
 			in
 			let rec traverse init_list e =
 			let rec traverse init_list e =
 				(match e.eexpr with
 				(match e.eexpr with
-					| TBinop (OpAssign, { eexpr = TField ({ eexpr = TConst TThis }, FInstance (_, _, f)) }, right_expr) ->
+					| TBinop (OpAssign, { eexpr = TField ({ eexpr = TConst TThis }, FInstance (_, _, f)) }, right_expr)
+						when not is_static ->
+						Hashtbl.remove init_list f.cf_name;
+						ignore (traverse init_list right_expr)
+					| TBinop (OpAssign, { eexpr = TField(_, FStatic(_, f)) }, right_expr) when is_static ->
 						Hashtbl.remove init_list f.cf_name;
 						Hashtbl.remove init_list f.cf_name;
 						ignore (traverse init_list right_expr)
 						ignore (traverse init_list right_expr)
 					| TWhile (condition, body, DoWhile) ->
 					| TWhile (condition, body, DoWhile) ->
@@ -1656,18 +1778,7 @@ class class_checker cls immediate_execution report =
 				);
 				);
 				init_list
 				init_list
 			in
 			in
-			(match cls.cl_constructor with
-				| Some { cf_expr = Some { eexpr = TFunction { tf_expr = e } } } ->
-					ignore (traverse fields_to_initialize e);
-				| _ -> ()
-			);
-			Hashtbl.iter
-				(fun name field ->
-					checker#error
-						("Field \"" ^ name ^ "\" is not nullable thus should have an initial value or should be initialized in constructor.")
-						[field.cf_pos]
-				)
-				fields_to_initialize
+			traverse fields_to_initialize tf_expr
 	end
 	end
 
 
 (**
 (**
@@ -1682,7 +1793,7 @@ let run (com:Common.context) (types:module_type list) =
 				| TEnumDecl enm -> ()
 				| TEnumDecl enm -> ()
 				| TTypeDecl typedef -> ()
 				| TTypeDecl typedef -> ()
 				| TAbstractDecl abstr -> ()
 				| TAbstractDecl abstr -> ()
-				| TClassDecl cls -> (new class_checker cls immediate_execution report)#check
+				| TClassDecl cls -> (new class_checker cls immediate_execution report com.main.main_expr)#check
 		in
 		in
 		List.iter traverse types;
 		List.iter traverse types;
 		report;
 		report;

+ 8 - 5
src/typing/operators.ml

@@ -451,7 +451,7 @@ let find_abstract_binop_overload ctx op e1 e2 a c tl left is_assign_op p =
 	let is_eq_op = match op with OpEq | OpNotEq -> true | _ -> false in
 	let is_eq_op = match op with OpEq | OpNotEq -> true | _ -> false in
 	if is_eq_op then begin match follow e1.etype,follow e2.etype with
 	if is_eq_op then begin match follow e1.etype,follow e2.etype with
 		| TMono _,_ | _,TMono _ ->
 		| TMono _,_ | _,TMono _ ->
-			Type.unify e1.etype e2.etype
+			(try Type.unify e1.etype e2.etype with Unify_error _ -> () (* this will fail later again *));
 		| _ ->
 		| _ ->
 			()
 			()
 	end;
 	end;
@@ -677,7 +677,8 @@ type 'a assign_op_api = {
 
 
 let handle_assign_op ctx api e1 e2 with_type p =
 let handle_assign_op ctx api e1 e2 with_type p =
 	let field_rhs_by_name name ev with_type =
 	let field_rhs_by_name name ev with_type =
-		let access_get = type_field_default_cfg ctx ev name p MGet with_type in
+		let field_pos = snd e1 in
+		let access_get = type_field_default_cfg ctx ev name field_pos MGet with_type in
 		let e_get = acc_get ctx access_get in
 		let e_get = acc_get ctx access_get in
 		e_get,api.type_rhs e_get e2
 		e_get,api.type_rhs e_get e2
 	in
 	in
@@ -944,7 +945,8 @@ let type_unop ctx op flag e with_type p =
 				e_lhs,None
 				e_lhs,None
 		in
 		in
 		let read_on vr ef fa =
 		let read_on vr ef fa =
-			let access_get = type_field_default_cfg ctx ef fa.fa_field.cf_name p MGet WithType.value in
+			let field_pos = snd e in
+			let access_get = type_field_default_cfg ctx ef fa.fa_field.cf_name field_pos MGet WithType.value in
 			let e_lhs = acc_get ctx access_get in
 			let e_lhs = acc_get ctx access_get in
 			let e_lhs,e_out = maybe_tempvar_postfix vr e_lhs in
 			let e_lhs,e_out = maybe_tempvar_postfix vr e_lhs in
 			e_lhs,e_out
 			e_lhs,e_out
@@ -969,7 +971,8 @@ let type_unop ctx op flag e with_type p =
 			| AKField fa ->
 			| AKField fa ->
 				let vr = new value_reference ctx in
 				let vr = new value_reference ctx in
 				let ef = vr#get_expr_part "fh" fa.fa_on in
 				let ef = vr#get_expr_part "fh" fa.fa_on in
-				let access_get = type_field_default_cfg ctx ef fa.fa_field.cf_name p MGet WithType.value in
+				let field_pos = snd e in
+				let access_get = type_field_default_cfg ctx ef fa.fa_field.cf_name field_pos MGet WithType.value in
 				let e,e_out = match access_get with
 				let e,e_out = match access_get with
 				| AKField _ ->
 				| AKField _ ->
 					let e = FieldAccess.get_field_expr {fa with fa_on = ef} FGet in
 					let e = FieldAccess.get_field_expr {fa with fa_on = ef} FGet in
@@ -1028,4 +1031,4 @@ let type_unop ctx op flag e with_type p =
 			| AKUsingField _ | AKResolve _ ->
 			| AKUsingField _ | AKResolve _ ->
 				raise_typing_error "Invalid operation" p
 				raise_typing_error "Invalid operation" p
 		in
 		in
-		loop (!type_access_ref ctx (fst e) (snd e) (MSet None) WithType.value (* WITHTYPETODO *))
+		loop (!type_access_ref ctx (fst e) (snd e) (MSet None) WithType.value (* WITHTYPETODO *))

+ 3 - 0
src/typing/typeload.ml

@@ -582,6 +582,8 @@ and load_complex_type' ctx allow_display mode (t,p) =
 						| "dynamic" -> AccCall
 						| "dynamic" -> AccCall
 						| "get" when get -> AccCall
 						| "get" when get -> AccCall
 						| "set" when not get -> AccCall
 						| "set" when not get -> AccCall
+						| "private get" when get -> AccPrivateCall
+						| "private set" when not get -> AccPrivateCall
 						| x when get && x = "get_" ^ n -> AccCall
 						| x when get && x = "get_" ^ n -> AccCall
 						| x when not get && x = "set_" ^ n -> AccCall
 						| x when not get && x = "set_" ^ n -> AccCall
 						| _ ->
 						| _ ->
@@ -793,6 +795,7 @@ let load_core_class ctx c =
 			com2.defines.Define.values <- PMap.empty;
 			com2.defines.Define.values <- PMap.empty;
 			Common.define com2 Define.CoreApi;
 			Common.define com2 Define.CoreApi;
 			Common.define com2 Define.Sys;
 			Common.define com2 Define.Sys;
+			allow_package com2 "sys";
 			Define.raw_define_value com2.defines "target.threaded" "true"; (* hack because we check this in sys.thread classes *)
 			Define.raw_define_value com2.defines "target.threaded" "true"; (* hack because we check this in sys.thread classes *)
 			if ctx.com.is_macro_context then Common.define com2 Define.Macro;
 			if ctx.com.is_macro_context then Common.define com2 Define.Macro;
 			com2.class_paths#lock_context (platform_name_macro ctx.com) true;
 			com2.class_paths#lock_context (platform_name_macro ctx.com) true;

+ 12 - 5
src/typing/typeloadCheck.ml

@@ -65,10 +65,10 @@ let valid_redefinition map1 map2 f1 t1 f2 t2 = (* child, parent *)
 	begin match f1.cf_kind,f2.cf_kind with
 	begin match f1.cf_kind,f2.cf_kind with
 	| Method m1, Method m2 when not (m1 = MethDynamic) && not (m2 = MethDynamic) ->
 	| Method m1, Method m2 when not (m1 = MethDynamic) && not (m2 = MethDynamic) ->
 		begin match follow t1, follow t2 with
 		begin match follow t1, follow t2 with
-		| TFun (args1,r1) , TFun (args2,r2) -> (
+		| TFun (args1,r1) , TFun (args2,r2) ->
 			if not (List.length args1 = List.length args2) then raise (Unify_error [Unify_custom "Different number of function arguments"]);
 			if not (List.length args1 = List.length args2) then raise (Unify_error [Unify_custom "Different number of function arguments"]);
 			let i = ref 0 in
 			let i = ref 0 in
-			try
+			begin try
 				valid r1 r2;
 				valid r1 r2;
 				List.iter2 (fun (n,o1,a1) (_,o2,a2) ->
 				List.iter2 (fun (n,o1,a1) (_,o2,a2) ->
 					incr i;
 					incr i;
@@ -77,7 +77,8 @@ let valid_redefinition map1 map2 f1 t1 f2 t2 = (* child, parent *)
 				) args1 args2;
 				) args1 args2;
 			with Unify_error l ->
 			with Unify_error l ->
 				let msg = if !i = 0 then Invalid_return_type else Invalid_function_argument(!i,List.length args1) in
 				let msg = if !i = 0 then Invalid_return_type else Invalid_function_argument(!i,List.length args1) in
-				raise (Unify_error (Cannot_unify (t1,t2) :: msg :: l)))
+				raise (Unify_error (Cannot_unify (t1,t2) :: msg :: l))
+			end
 		| _ ->
 		| _ ->
 			die "" __LOC__
 			die "" __LOC__
 		end
 		end
@@ -106,7 +107,13 @@ let valid_redefinition map1 map2 f1 t1 f2 t2 = (* child, parent *)
 		| ct1,ct2 ->
 		| ct1,ct2 ->
 			List.iter (fun t2 ->
 			List.iter (fun t2 ->
 				let t2 = map2 t2 in
 				let t2 = map2 t2 in
-				if not (List.exists (fun t1 -> does_unify (map1 t1) t2) ct1) then
+				if not (List.exists (fun t1 ->
+					try
+						Type.unify_custom uctx (map1 t1) t2;
+						true
+					with Unify_error _ ->
+						false
+				) ct1) then
 					raise (Unify_error ([Unify_custom (Printf.sprintf "Constraint unsatisfied for type parameter %s: %s" ttp2.ttp_name (s_type (print_context()) t2))]))
 					raise (Unify_error ([Unify_custom (Printf.sprintf "Constraint unsatisfied for type parameter %s: %s" ttp2.ttp_name (s_type (print_context()) t2))]))
 			) ct2
 			) ct2
 	in
 	in
@@ -384,7 +391,7 @@ module Inheritance = struct
 					if (has_class_field_flag f CfPublic) && not (has_class_field_flag f2 CfPublic) && not (Meta.has Meta.CompilerGenerated f.cf_meta) then
 					if (has_class_field_flag f CfPublic) && not (has_class_field_flag f2 CfPublic) && not (Meta.has Meta.CompilerGenerated f.cf_meta) then
 						display_error com ("Field " ^ f.cf_name ^ " should be public as requested by " ^ s_type_path intf.cl_path) p
 						display_error com ("Field " ^ f.cf_name ^ " should be public as requested by " ^ s_type_path intf.cl_path) p
 					else if not (unify_kind ~strict:false f2.cf_kind f.cf_kind) || not (match f.cf_kind, f2.cf_kind with Var _ , Var _ -> true | Method m1, Method m2 -> mkind m1 = mkind m2 | _ -> false) then
 					else if not (unify_kind ~strict:false f2.cf_kind f.cf_kind) || not (match f.cf_kind, f2.cf_kind with Var _ , Var _ -> true | Method m1, Method m2 -> mkind m1 = mkind m2 | _ -> false) then
-						display_error com ("Field " ^ f.cf_name ^ " has different property access than in " ^ s_type_path intf.cl_path ^ " (" ^ s_kind f2.cf_kind ^ " should be " ^ s_kind f.cf_kind ^ ")") p
+						display_error com ("Field " ^ f.cf_name ^ " has different property access than in " ^ s_type_path intf.cl_path ^ ": " ^ s_kind f2.cf_kind ^ " should be " ^ s_kind f.cf_kind) p
 					else try
 					else try
 						let map1 = TClass.get_map_function  intf params in
 						let map1 = TClass.get_map_function  intf params in
 						valid_redefinition map1 map2 f2 t2 f (apply_params intf.cl_params params f.cf_type)
 						valid_redefinition map1 map2 f2 t2 f (apply_params intf.cl_params params f.cf_type)

+ 24 - 9
src/typing/typeloadFields.ml

@@ -734,7 +734,7 @@ module TypeBinding = struct
 		let c = cctx.tclass in
 		let c = cctx.tclass in
 		let t = cf.cf_type in
 		let t = cf.cf_type in
 		let p = cf.cf_pos in
 		let p = cf.cf_pos in
-		let ctx = TyperManager.clone_for_expr ctx_f (if fctx.is_static then FunStatic else FunMember) false in
+		let ctx = TyperManager.clone_for_expr ctx_f (if fctx.is_static then FunStatic else FunMember) FunNotFunction in
 		if (has_class_flag c CInterface) then unexpected_expression ctx.com fctx "Initialization on field of interface" (pos e);
 		if (has_class_flag c CInterface) then unexpected_expression ctx.com fctx "Initialization on field of interface" (pos e);
 		cf.cf_meta <- ((Meta.Value,[e],mk_zero_range_pos cf.cf_pos) :: cf.cf_meta);
 		cf.cf_meta <- ((Meta.Value,[e],mk_zero_range_pos cf.cf_pos) :: cf.cf_meta);
 		let check_cast e =
 		let check_cast e =
@@ -825,9 +825,9 @@ module TypeBinding = struct
 		| Some e ->
 		| Some e ->
 			bind_var_expression ctx cctx fctx cf e
 			bind_var_expression ctx cctx fctx cf e
 
 
-	let bind_method ctx_f cctx fctx fmode cf t args ret e p =
+	let bind_method ctx_f cctx fctx fmode cf t args ret e function_mode p =
 		let c = cctx.tclass in
 		let c = cctx.tclass in
-		let ctx = TyperManager.clone_for_expr ctx_f fmode true in
+		let ctx = TyperManager.clone_for_expr ctx_f fmode function_mode in
 		let bind () =
 		let bind () =
 			incr stats.s_methods_typed;
 			incr stats.s_methods_typed;
 			if ctx.com.verbose then Common.log ctx.com ("Typing " ^ (if ctx.com.is_macro_context then "macro " else "") ^ s_type_path c.cl_path ^ "." ^ cf.cf_name);
 			if ctx.com.verbose then Common.log ctx.com ("Typing " ^ (if ctx.com.is_macro_context then "macro " else "") ^ s_type_path c.cl_path ^ "." ^ cf.cf_name);
@@ -1142,7 +1142,8 @@ let setup_args_ret ctx cctx fctx name fd p =
 		let name = String.sub name 4 (String.length name - 4) in
 		let name = String.sub name 4 (String.length name - 4) in
 		let cf = if fctx.is_static then PMap.find name c.cl_statics else PMap.find name c.cl_fields (* TODO: inheritance? *) in
 		let cf = if fctx.is_static then PMap.find name c.cl_statics else PMap.find name c.cl_fields (* TODO: inheritance? *) in
 		match Lazy.force mk, cf.cf_kind with
 		match Lazy.force mk, cf.cf_kind with
-			| MKGetter, Var({v_read = AccCall}) | MKSetter, Var({v_write = AccCall}) -> cf.cf_type
+			| MKGetter, Var({v_read = AccCall | AccPrivateCall})
+			| MKSetter, Var({v_write = AccCall | AccPrivateCall}) -> cf.cf_type
 			| _ -> raise Not_found;
 			| _ -> raise Not_found;
 	in
 	in
 	let maybe_use_property_type th check def =
 	let maybe_use_property_type th check def =
@@ -1256,7 +1257,9 @@ let create_method (ctx,cctx,fctx) c f cf fd p =
 
 
 	ctx.type_params <- params @ ctx.type_params;
 	ctx.type_params <- params @ ctx.type_params;
 	let args,ret = setup_args_ret ctx cctx fctx (fst f.cff_name) fd p in
 	let args,ret = setup_args_ret ctx cctx fctx (fst f.cff_name) fd p in
-	let t = TFun (args#for_type,ret) in
+	let function_mode = FunFunction in
+	let targs = args#for_type in
+	let t = TFun (targs,ret) in
 	cf.cf_type <- t;
 	cf.cf_type <- t;
 	cf.cf_kind <- Method (if fctx.is_macro then MethMacro else if fctx.is_inline then MethInline else if dynamic then MethDynamic else MethNormal);
 	cf.cf_kind <- Method (if fctx.is_macro then MethMacro else if fctx.is_inline then MethInline else if dynamic then MethDynamic else MethNormal);
 	cf.cf_params <- params;
 	cf.cf_params <- params;
@@ -1327,18 +1330,18 @@ let create_method (ctx,cctx,fctx) c f cf fd p =
 	in
 	in
 	init_meta_overloads ctx (Some c) cf;
 	init_meta_overloads ctx (Some c) cf;
 	if fctx.do_bind then
 	if fctx.do_bind then
-		TypeBinding.bind_method ctx cctx fctx fmode cf t args ret fd.f_expr (match fd.f_expr with Some e -> snd e | None -> f.cff_pos)
+		TypeBinding.bind_method ctx cctx fctx fmode cf t args ret fd.f_expr function_mode (match fd.f_expr with Some e -> snd e | None -> f.cff_pos)
 	else begin
 	else begin
 		if fctx.is_display_field then begin
 		if fctx.is_display_field then begin
 			delay ctx.g PTypeField (fun () ->
 			delay ctx.g PTypeField (fun () ->
 				(* We never enter type_function so we're missing out on the argument processing there. Let's do it here. *)
 				(* We never enter type_function so we're missing out on the argument processing there. Let's do it here. *)
-				let ctx = TyperManager.clone_for_expr ctx fmode true in
+				let ctx = TyperManager.clone_for_expr ctx fmode function_mode in
 				ignore(args#for_expr ctx)
 				ignore(args#for_expr ctx)
 			);
 			);
 			check_field_display ctx fctx c cf;
 			check_field_display ctx fctx c cf;
 		end else
 		end else
 			delay ctx.g PTypeField (fun () ->
 			delay ctx.g PTypeField (fun () ->
-				let ctx = TyperManager.clone_for_expr ctx fmode true in
+				let ctx = TyperManager.clone_for_expr ctx fmode function_mode in
 				args#verify_extern ctx
 				args#verify_extern ctx
 			);
 			);
 		if fd.f_expr <> None then begin
 		if fd.f_expr <> None then begin
@@ -1457,6 +1460,11 @@ let create_property (ctx,cctx,fctx) c f cf (get,set,t,eo) p =
 			if fctx.is_display_field && DisplayPosition.display_position#enclosed_in pget then delay ctx.g PConnectField (fun () -> display_accessor get pget);
 			if fctx.is_display_field && DisplayPosition.display_position#enclosed_in pget then delay ctx.g PConnectField (fun () -> display_accessor get pget);
 			if not cctx.is_lib then delay_check (fun() -> check_method get t_get true);
 			if not cctx.is_lib then delay_check (fun() -> check_method get t_get true);
 			AccCall
 			AccCall
+		| "private get",pget ->
+			let get = "get_" ^ name in
+			if fctx.is_display_field && DisplayPosition.display_position#enclosed_in pget then delay ctx.g PConnectField (fun () -> display_accessor get pget);
+			if not cctx.is_lib then delay_check (fun() -> check_method get t_get true);
+			AccPrivateCall
 		| _,pget ->
 		| _,pget ->
 			display_error ctx.com (name ^ ": Custom property accessor is no longer supported, please use `get`") pget;
 			display_error ctx.com (name ^ ": Custom property accessor is no longer supported, please use `get`") pget;
 			AccCall
 			AccCall
@@ -1476,11 +1484,18 @@ let create_property (ctx,cctx,fctx) c f cf (get,set,t,eo) p =
 			if fctx.is_display_field && DisplayPosition.display_position#enclosed_in pset then delay ctx.g PConnectField (fun () -> display_accessor set pset);
 			if fctx.is_display_field && DisplayPosition.display_position#enclosed_in pset then delay ctx.g PConnectField (fun () -> display_accessor set pset);
 			if not cctx.is_lib then delay_check (fun() -> check_method set t_set false);
 			if not cctx.is_lib then delay_check (fun() -> check_method set t_set false);
 			AccCall
 			AccCall
+		| "private set",pset ->
+			let set = "set_" ^ name in
+			if fctx.is_display_field && DisplayPosition.display_position#enclosed_in pset then delay ctx.g PConnectField (fun () -> display_accessor set pset);
+			if not cctx.is_lib then delay_check (fun() -> check_method set t_set false);
+			AccPrivateCall
 		| _,pset ->
 		| _,pset ->
 			display_error ctx.com (name ^ ": Custom property accessor is no longer supported, please use `set`") pset;
 			display_error ctx.com (name ^ ": Custom property accessor is no longer supported, please use `set`") pset;
 			AccCall
 			AccCall
 	) in
 	) in
-	if (set = AccNever && get = AccNever)  then raise_typing_error (name ^ ": Unsupported property combination") p;
+	if (set = AccNever && get = AccNever) then raise_typing_error (name ^ ": Unsupported property combination") p;
+	if (set = AccPrivateCall && get = AccPrivateCall && has_class_field_flag cf CfPublic) then
+		raise_typing_error (name ^ ": (private get, private set) property cannot be public") p;
 	cf.cf_kind <- Var { v_read = get; v_write = set };
 	cf.cf_kind <- Var { v_read = get; v_write = set };
 	if fctx.is_extern then add_class_field_flag cf CfExtern;
 	if fctx.is_extern then add_class_field_flag cf CfExtern;
 	if List.mem_assoc AEnum f.cff_access then add_class_field_flag cf CfEnum;
 	if List.mem_assoc AEnum f.cff_access then add_class_field_flag cf CfEnum;

+ 0 - 1
src/typing/typeloadModule.ml

@@ -27,7 +27,6 @@ open DisplayTypes.DisplayMode
 open Common
 open Common
 open Typeload
 open Typeload
 open Error
 open Error
-open Resolution
 
 
 let get_policy g mpath =
 let get_policy g mpath =
 	let sl1 = full_dot_path2 mpath mpath in
 	let sl1 = full_dot_path2 mpath mpath in

+ 18 - 11
src/typing/typer.ml

@@ -693,29 +693,35 @@ and type_object_decl ctx fl with_type p =
 		let fl = List.map (fun ((n,pn,qs),e) ->
 		let fl = List.map (fun ((n,pn,qs),e) ->
 			let is_valid = Lexer.is_valid_identifier n in
 			let is_valid = Lexer.is_valid_identifier n in
 			if PMap.mem n !fields then raise_typing_error ("Duplicate field in object declaration : " ^ n) pn;
 			if PMap.mem n !fields then raise_typing_error ("Duplicate field in object declaration : " ^ n) pn;
-			let is_final = ref false in
-			let e = try
-				let t = match !dynamic_parameter with
-					| Some t -> t
+			let e,cfo = try
+				let t,cfo = match !dynamic_parameter with
+					| Some t ->
+						t,None
 					| None ->
 					| None ->
 						let cf = PMap.find n field_map in
 						let cf = PMap.find n field_map in
-						if (has_class_field_flag cf CfFinal) then is_final := true;
 						if ctx.f.in_display && DisplayPosition.display_position#enclosed_in pn then DisplayEmitter.display_field ctx Unknown CFSMember cf pn;
 						if ctx.f.in_display && DisplayPosition.display_position#enclosed_in pn then DisplayEmitter.display_field ctx Unknown CFSMember cf pn;
-						cf.cf_type
+						cf.cf_type,Some cf
 				in
 				in
 				let e = type_expr ctx e (WithType.with_structure_field t n) in
 				let e = type_expr ctx e (WithType.with_structure_field t n) in
 				let e = AbstractCast.cast_or_unify ctx t e e.epos in
 				let e = AbstractCast.cast_or_unify ctx t e e.epos in
 				let e = if is_null t && not (is_null e.etype) then mk (TCast(e,None)) (ctx.t.tnull e.etype) e.epos else e in
 				let e = if is_null t && not (is_null e.etype) then mk (TCast(e,None)) (ctx.t.tnull e.etype) e.epos else e in
-				(try type_eq EqStrict e.etype t; e with Unify_error _ -> mk (TCast (e,None)) t e.epos)
+				(try type_eq EqStrict e.etype t; e with Unify_error _ -> mk (TCast (e,None)) t e.epos),cfo
 			with Not_found ->
 			with Not_found ->
 				if is_valid then
 				if is_valid then
 					extra_fields := (n,pn) :: !extra_fields;
 					extra_fields := (n,pn) :: !extra_fields;
-				type_expr ctx e WithType.value
+				type_expr ctx e WithType.value,None
 			in
 			in
 			if is_valid then begin
 			if is_valid then begin
 				if starts_with n '$' then raise_typing_error "Field names starting with a dollar are not allowed" p;
 				if starts_with n '$' then raise_typing_error "Field names starting with a dollar are not allowed" p;
 				let cf = mk_field n e.etype (punion pn e.epos) pn in
 				let cf = mk_field n e.etype (punion pn e.epos) pn in
-				if !is_final then add_class_field_flag cf CfFinal;
+				begin match cfo with
+					| Some cf' ->
+						(* If we're assigning to an existing field, copy some of its characteristics *)
+						if has_class_field_flag cf' CfFinal then add_class_field_flag cf CfFinal;
+						cf.cf_kind <- cf'.cf_kind;
+					| None ->
+						()
+				end;
 				fields := PMap.add n cf !fields;
 				fields := PMap.add n cf !fields;
 			end;
 			end;
 			((n,pn,qs),e)
 			((n,pn,qs),e)
@@ -1109,7 +1115,8 @@ and type_local_function ctx_from kind f with_type p =
 		| FunMemberAbstractLocal -> FunMemberAbstractLocal
 		| FunMemberAbstractLocal -> FunMemberAbstractLocal
 		| _ -> FunMemberClassLocal
 		| _ -> FunMemberClassLocal
 	in
 	in
-	let ctx = TyperManager.clone_for_expr ctx_from curfun true in
+	let function_mode = FunFunction in
+	let ctx = TyperManager.clone_for_expr ctx_from curfun function_mode in
 	let vname,pname= match name with
 	let vname,pname= match name with
 		| None ->
 		| None ->
 			if params <> [] then begin
 			if params <> [] then begin
@@ -1850,7 +1857,7 @@ and type_expr ?(mode=MGet) ctx (e,p) (with_type:WithType.t) =
 		let e = Matcher.Match.match_expr ctx e1 cases def with_type false p in
 		let e = Matcher.Match.match_expr ctx e1 cases def with_type false p in
 		wrap e
 		wrap e
 	| EReturn e ->
 	| EReturn e ->
-		if not ctx.e.in_function then begin
+		if not (TyperManager.is_function_context ctx) then begin
 			display_error ctx.com "Return outside function" p;
 			display_error ctx.com "Return outside function" p;
 			match e with
 			match e with
 			| None ->
 			| None ->

+ 51 - 1
src/typing/typerEntry.ml

@@ -135,6 +135,55 @@ let load_enum_tools ctx =
 	| _ ->
 	| _ ->
 		die "" __LOC__
 		die "" __LOC__
 
 
+let load_local_wrapper ctx =
+	let t = ctx.t in
+	match ctx.com.platform with
+	(* optimized version for Java - use native arrays *)
+	| Jvm ->
+		let cnativearray =
+			let m = TypeloadModule.load_module ctx (["jvm"],"NativeArray") null_pos in
+			let mt = List.find (fun md -> match md with
+					| TClassDecl ({ cl_path = ["jvm"],"NativeArray" }) -> true
+					| _ -> false
+				) m.m_types
+			in
+			match mt with
+			| TClassDecl cl -> cl
+			| _ -> die "" __LOC__
+		in
+
+		object
+			method captured_type t = TInst (cnativearray,[t])
+
+			method mk_ref v ve p =
+				match ve with
+				| None ->
+					let eone = mk (TConst (TInt (Int32.of_int 1))) t.tint p in
+					let t = match v.v_type with TInst (_, [t]) -> t | _ -> die "" __LOC__ in
+					mk (TNew (cnativearray,[t],[eone])) v.v_type p
+				| Some e ->
+					{ (Inline.mk_untyped_call "__array__" p [e]) with etype = v.v_type }
+
+			method mk_ref_access e v =
+				mk (TArray ({ e with etype = v.v_type }, mk (TConst (TInt 0l)) t.tint e.epos)) e.etype e.epos
+
+			method mk_init av v pos =
+				let elocal = mk (TLocal v) v.v_type pos in
+				let earray = { (Inline.mk_untyped_call "__array__" pos [elocal]) with etype = av.v_type } in
+				mk (TVar (av,Some earray)) t.tvoid pos
+		end
+	(* default implementation - use haxe array *)
+	| _ ->
+		object
+			method captured_type = t.tarray
+			method mk_ref v ve p =
+				mk (TArrayDecl (match ve with None -> [] | Some e -> [e])) v.v_type p
+			method mk_ref_access e v =
+				mk (TArray ({ e with etype = v.v_type }, mk (TConst (TInt 0l)) t.tint e.epos)) e.etype e.epos
+			method mk_init av v pos =
+				mk (TVar (av,Some (mk (TArrayDecl [mk (TLocal v) v.v_type pos]) av.v_type pos))) t.tvoid pos
+		end
+
 let create com macros =
 let create com macros =
 	let rec ctx = {
 	let rec ctx = {
 		com = com;
 		com = com;
@@ -179,7 +228,7 @@ let create com macros =
 			get_build_infos = (fun() -> None);
 			get_build_infos = (fun() -> None);
 		};
 		};
 		f = TyperManager.create_ctx_f null_field;
 		f = TyperManager.create_ctx_f null_field;
-		e = TyperManager.create_ctx_e FunStatic false;
+		e = TyperManager.create_ctx_e FunStatic FunFunction;
 		pass = PBuildModule;
 		pass = PBuildModule;
 		allow_inline = true;
 		allow_inline = true;
 		allow_transform = true;
 		allow_transform = true;
@@ -194,6 +243,7 @@ let create com macros =
 	load_array ctx;
 	load_array ctx;
 	load_enum_tools ctx;
 	load_enum_tools ctx;
 	ignore(TypeloadModule.load_module ctx (["haxe"],"Exception") null_pos);
 	ignore(TypeloadModule.load_module ctx (["haxe"],"Exception") null_pos);
+	ctx.com.local_wrapper <- load_local_wrapper ctx;
 	ctx.g.complete <- true;
 	ctx.g.complete <- true;
 	ctx
 	ctx
 
 

+ 8 - 1
std/cpp/_std/haxe/Exception.hx

@@ -4,7 +4,7 @@ package haxe;
 @:coreApi
 @:coreApi
 class Exception {
 class Exception {
 	public var message(get,never):String;
 	public var message(get,never):String;
-	public var stack(get,never):CallStack;
+	public var stack(get,set):CallStack;
 	public var previous(get,never):Null<Exception>;
 	public var previous(get,never):Null<Exception>;
 	public var native(get,never):Any;
 	public var native(get,never):Any;
 
 
@@ -14,6 +14,7 @@ class Exception {
 	@:noCompletion @:ifFeature("haxe.Exception.get_stack") var __skipStack:Int = 0;
 	@:noCompletion @:ifFeature("haxe.Exception.get_stack") var __skipStack:Int = 0;
 	@:noCompletion var __nativeException:Any;
 	@:noCompletion var __nativeException:Any;
 	@:noCompletion var __previousException:Null<Exception>;
 	@:noCompletion var __previousException:Null<Exception>;
+	@:noCompletion var _hx_customStack:Null<String>;
 
 
 	static function caught(value:Any):Exception {
 	static function caught(value:Any):Exception {
 		if(Std.isOfType(value, Exception)) {
 		if(Std.isOfType(value, Exception)) {
@@ -90,5 +91,11 @@ class Exception {
 			case s: s;
 			case s: s;
 		}
 		}
 	}
 	}
+
+	function set_stack(stack:CallStack) {
+		_hx_customStack = CallStack.toString(stack);
+
+		return __exceptionStack = stack;
+	}
 }
 }
 
 

+ 47 - 0
std/cpp/_std/haxe/atomic/AtomicBool.hx

@@ -0,0 +1,47 @@
+package haxe.atomic;
+
+#if doc_gen
+@:coreApi
+@:coreType
+abstract AtomicBool {
+	public function new(value:Bool):Void;
+
+	public function compareExchange(expected:Bool, replacement:Bool):Bool;
+
+	public function exchange(value:Bool):Bool;
+
+	public function load():Bool;
+
+	public function store(value:Bool):Bool;
+}
+#else
+abstract AtomicBool(AtomicInt) {
+	private inline function toInt(v:Bool):Int {
+		return v ? 1 : 0;
+	}
+
+	private inline function toBool(v:Int):Bool {
+		return v == 1;
+	}
+
+	public inline function new(value:Bool):Void {
+		this = new AtomicInt(toInt(value));
+	}
+
+	public inline function compareExchange(expected:Bool, replacement:Bool):Bool {
+		return toBool(this.compareExchange(toInt(expected), toInt(replacement)));
+	}
+
+	public inline function exchange(value:Bool):Bool {
+		return toBool(this.exchange(toInt(value)));
+	}
+
+	public inline function load():Bool {
+		return toBool(this.load());
+	}
+
+	public inline function store(value:Bool):Bool {
+		return toBool(this.store(toInt(value)));
+	}
+}
+#end

+ 43 - 11
std/cpp/_std/haxe/atomic/AtomicInt.hx

@@ -1,9 +1,40 @@
 package haxe.atomic;
 package haxe.atomic;
 
 
+#if doc_gen
+@:coreApi
+@:coreType
+abstract AtomicInt {
+	public function new(value:Int):Void;
+
+	public function add(b:Int):Int;
+
+	public function sub(b:Int):Int;
+
+	public function and(b:Int):Int;
+
+	public function or(b:Int):Int;
+
+	public function xor(b:Int):Int;
+
+	public function compareExchange(expected:Int, replacement:Int):Int;
+
+	public function exchange(value:Int):Int;
+
+	public function load():Int;
+
+	public function store(value:Int):Int;
+}
+#else
+private final class Data {
+	public var value:Int;
+	public function new(value:Int) {
+		this.value = value;
+	}
+}
 #if cppia
 #if cppia
 extern
 extern
 #end
 #end
-abstract AtomicInt(cpp.Pointer<Int>) {
+abstract AtomicInt(Data) {
 	#if cppia
 	#if cppia
 	public function new(value:Int):Void;
 	public function new(value:Int):Void;
 
 
@@ -26,43 +57,44 @@ abstract AtomicInt(cpp.Pointer<Int>) {
 	public function store(value:Int):Int;
 	public function store(value:Int):Int;
 	#else
 	#else
 	public #if !scriptable inline #end function new(value:Int) {
 	public #if !scriptable inline #end function new(value:Int) {
-		this = cpp.Pointer.ofArray([value]);
+		this = new Data(value);
 	}
 	}
 
 
 	public #if !scriptable inline #end function add(b:Int):Int {
 	public #if !scriptable inline #end function add(b:Int):Int {
-		return untyped __cpp__("_hx_atomic_add({0}, {1})", this, b);
+		return untyped __cpp__("_hx_atomic_add(&{0}, {1})", this.value, b);
 	}
 	}
 
 
 	public #if !scriptable inline #end function sub(b:Int):Int {
 	public #if !scriptable inline #end function sub(b:Int):Int {
-		return untyped __cpp__("_hx_atomic_sub({0}, {1})", this, b);
+		return untyped __cpp__("_hx_atomic_sub(&{0}, {1})", this.value, b);
 	}
 	}
 
 
 	public #if !scriptable inline #end function and(b:Int):Int {
 	public #if !scriptable inline #end function and(b:Int):Int {
-		return untyped __cpp__("_hx_atomic_and({0}, {1})", this, b);
+		return untyped __cpp__("_hx_atomic_and(&{0}, {1})", this.value, b);
 	}
 	}
 
 
 	public #if !scriptable inline #end function or(b:Int):Int {
 	public #if !scriptable inline #end function or(b:Int):Int {
-		return untyped __cpp__("_hx_atomic_or({0}, {1})", this, b);
+		return untyped __cpp__("_hx_atomic_or(&{0}, {1})", this.value, b);
 	}
 	}
 
 
 	public #if !scriptable inline #end function xor(b:Int):Int {
 	public #if !scriptable inline #end function xor(b:Int):Int {
-		return untyped __cpp__("_hx_atomic_xor({0}, {1})", this, b);
+		return untyped __cpp__("_hx_atomic_xor(&{0}, {1})", this.value, b);
 	}
 	}
 
 
 	public #if !scriptable inline #end function compareExchange(expected:Int, replacement:Int):Int {
 	public #if !scriptable inline #end function compareExchange(expected:Int, replacement:Int):Int {
-		return untyped __cpp__("_hx_atomic_compare_exchange({0}, {1}, {2})", this, expected, replacement);
+		return untyped __cpp__("_hx_atomic_compare_exchange(&{0}, {1}, {2})", this.value, expected, replacement);
 	}
 	}
 
 
 	public #if !scriptable inline #end function exchange(value:Int):Int {
 	public #if !scriptable inline #end function exchange(value:Int):Int {
-		return untyped __cpp__("_hx_atomic_exchange({0}, {1})", this, value);
+		return untyped __cpp__("_hx_atomic_exchange(&{0}, {1})", this.value, value);
 	}
 	}
 
 
 	public #if !scriptable inline #end function load():Int {
 	public #if !scriptable inline #end function load():Int {
-		return untyped __cpp__("_hx_atomic_load({0})", this);
+		return untyped __cpp__("_hx_atomic_load(&{0})", this.value);
 	}
 	}
 
 
 	public #if !scriptable inline #end function store(value:Int):Int {
 	public #if !scriptable inline #end function store(value:Int):Int {
-		return untyped __cpp__("_hx_atomic_store({0}, {1})", this, value);
+		return untyped __cpp__("_hx_atomic_store(&{0}, {1})", this.value, value);
 	}
 	}
 	#end
 	#end
 }
 }
+#end

+ 2 - 0
std/eval/_std/Sys.hx

@@ -75,6 +75,8 @@ class Sys {
 
 
 	extern static public function time():Float;
 	extern static public function time():Float;
 
 
+	extern static function timestamp_ms():haxe.Int64;
+
 	extern static public function cpuTime():Float;
 	extern static public function cpuTime():Float;
 
 
 	extern static public function programPath():String;
 	extern static public function programPath():String;

+ 16 - 1
std/eval/_std/haxe/Exception.hx

@@ -3,7 +3,7 @@ package haxe;
 @:coreApi
 @:coreApi
 class Exception {
 class Exception {
 	public var message(get,never):String;
 	public var message(get,never):String;
-	public var stack(get,never):CallStack;
+	public var stack(get,set):CallStack;
 	public var previous(get,never):Null<Exception>;
 	public var previous(get,never):Null<Exception>;
 	public var native(get,never):Any;
 	public var native(get,never):Any;
 
 
@@ -13,6 +13,7 @@ class Exception {
 	@:noCompletion @:ifFeature("haxe.Exception.get_stack") var __skipStack:Int = 0;
 	@:noCompletion @:ifFeature("haxe.Exception.get_stack") var __skipStack:Int = 0;
 	@:noCompletion var __nativeException:Any;
 	@:noCompletion var __nativeException:Any;
 	@:noCompletion var __previousException:Null<Exception>;
 	@:noCompletion var __previousException:Null<Exception>;
+	@:noCompletion var __customStack:haxe.ds.Vector<Dynamic>;
 
 
 	static function caught(value:Any):Exception {
 	static function caught(value:Any):Exception {
 		if(Std.isOfType(value, Exception)) {
 		if(Std.isOfType(value, Exception)) {
@@ -95,4 +96,18 @@ class Exception {
 			case s: s;
 			case s: s;
 		}
 		}
 	}
 	}
+
+	function set_stack(stack:CallStack) {
+		var items = stack.asArray();
+		var a:Array<Dynamic> = [];
+		for (item in items) {
+			switch (item) {
+				case FilePos(Method(_), _):
+					a.push(item);
+				case _:
+			}
+		}
+		__customStack = haxe.ds.Vector.fromArrayCopy(a);
+		return __nativeStack = __exceptionStack = stack;
+	}
 }
 }

+ 5 - 1
std/flash/_std/haxe/Exception.hx

@@ -5,7 +5,7 @@ import flash.errors.Error;
 @:coreApi
 @:coreApi
 class Exception extends NativeException {
 class Exception extends NativeException {
 	public var message(get,never):String;
 	public var message(get,never):String;
-	public var stack(get,never):CallStack;
+	public var stack(get,set):CallStack;
 	public var previous(get,never):Null<Exception>;
 	public var previous(get,never):Null<Exception>;
 	public var native(get,never):Any;
 	public var native(get,never):Any;
 
 
@@ -86,6 +86,10 @@ class Exception extends NativeException {
 			case s: s;
 			case s: s;
 		}
 		}
 	}
 	}
+
+	function set_stack(stack:CallStack) {
+		return __exceptionStack = stack;
+	}
 }
 }
 
 
 @:dox(hide)
 @:dox(hide)

+ 1 - 1
std/haxe/CallStack.hx

@@ -112,7 +112,7 @@ abstract CallStack(Array<StackItem>) from Array<StackItem> {
 		return this[index];
 		return this[index];
 	}
 	}
 
 
-	inline function asArray():Array<StackItem> {
+	public inline function asArray():Array<StackItem> {
 		return this;
 		return this;
 	}
 	}
 
 

+ 2 - 1
std/haxe/Exception.hx

@@ -51,8 +51,9 @@ extern class Exception {
 	/**
 	/**
 		The call stack at the moment of the exception creation.
 		The call stack at the moment of the exception creation.
 	**/
 	**/
-	public var stack(get,never):CallStack;
+	public var stack(get,set):CallStack;
 	private function get_stack():CallStack;
 	private function get_stack():CallStack;
+	private function set_stack(stack:CallStack):CallStack;
 
 
 	/**
 	/**
 		Contains an exception, which was passed to `previous` constructor argument.
 		Contains an exception, which was passed to `previous` constructor argument.

+ 36 - 1
std/haxe/Timer.hx

@@ -22,6 +22,7 @@
 
 
 package haxe;
 package haxe;
 
 
+import haxe.Int64;
 #if (target.threaded && !cppia)
 #if (target.threaded && !cppia)
 import sys.thread.Thread;
 import sys.thread.Thread;
 import sys.thread.EventLoop;
 import sys.thread.EventLoop;
@@ -43,7 +44,7 @@ import sys.thread.EventLoop;
 
 
 	Notice for threaded targets:
 	Notice for threaded targets:
 	`Timer` instances require threads they were created in to run with Haxe's event loops.
 	`Timer` instances require threads they were created in to run with Haxe's event loops.
-	Main thread of a Haxe program always contains an event loop. For other cases use 
+	Main thread of a Haxe program always contains an event loop. For other cases use
 	`sys.thread.Thread.createWithEventLoop` and `sys.thread.Thread.runWithEventLoop` methods.
 	`sys.thread.Thread.createWithEventLoop` and `sys.thread.Thread.runWithEventLoop` methods.
 **/
 **/
 class Timer {
 class Timer {
@@ -195,4 +196,38 @@ class Timer {
 		return 0;
 		return 0;
 		#end
 		#end
 	}
 	}
+
+	/**
+	 * Returns a monotonically increasing timestamp with millisecond resolution.
+	 *
+	 * The precision and epoch of the timer is platform defined.
+	 */
+	public static inline function milliseconds():Int64 {
+		#if flash
+		return flash.Lib.getTimer();
+		#elseif js
+		#if nodejs
+		var hrtime = js.Syntax.code('process.hrtime()'); // [seconds, remaining nanoseconds]
+		return hrtime[0] * 1000 + (hrtime[1] / 1000000i64);
+		#else
+		return Std.int(@:privateAccess HxOverrides.now());
+		#end
+		#elseif cpp
+		return untyped __global__.__time_stamp_ms();
+		#elseif python
+		#if (python_version >= 3.7)
+		return python.lib.Time.perf_counter_ns() / 1000000i64;
+		#else
+		return Std.int(stamp() * 1000);
+		#end
+		#elseif (hl && hl_ver >= version("1.16.0"))
+		return hl.Api.timestampMs();
+		#elseif jvm
+		return java.lang.System.nanoTime() / 1000000i64;
+		#elseif eval
+		return @:privateAccess Sys.timestamp_ms();
+		#else
+		return Int64.mul(Int64.fromFloat(stamp()), 1000);
+		#end
+	}
 }
 }

+ 8 - 27
std/haxe/atomic/AtomicBool.hx

@@ -9,47 +9,28 @@ package haxe.atomic;
 	(js) The Atomics and SharedArrayBuffer objects need to be available. Errors will be thrown if this is not the case.
 	(js) The Atomics and SharedArrayBuffer objects need to be available. Errors will be thrown if this is not the case.
 **/
 **/
 @:coreApi
 @:coreApi
-abstract AtomicBool(AtomicInt) {
-	private inline function toInt(v:Bool):Int {
-		return v ? 1 : 0;
-	}
-
-	private inline function toBool(v:Int):Bool {
-		return v == 1;
-	}
-
-	public inline function new(value:Bool):Void {
-		this = new AtomicInt(toInt(value));
-	}
+@:coreType
+abstract AtomicBool {
+	public function new(value:Bool):Void;
 
 
 	/**
 	/**
 		Atomically compares the value of `a` with `expected` and replaces `a` with `replacement` if they are equal..
 		Atomically compares the value of `a` with `expected` and replaces `a` with `replacement` if they are equal..
 		Returns the original value of `a`.
 		Returns the original value of `a`.
 	**/
 	**/
-	public inline function compareExchange(expected:Bool, replacement:Bool):Bool {
-		return toBool(this.compareExchange(toInt(expected), toInt(replacement)));
-	}
+	public function compareExchange(expected:Bool, replacement:Bool):Bool;
 
 
 	/**
 	/**
 		Atomically exchanges `a` with `value`.
 		Atomically exchanges `a` with `value`.
 		Returns the original value of `a`.
 		Returns the original value of `a`.
 	**/
 	**/
-	public inline function exchange(value:Bool):Bool {
-		return toBool(this.exchange(toInt(value)));
-	}
-
+	public function exchange(value:Bool):Bool;
 	/**
 	/**
 		Atomically fetches the value of `a`.
 		Atomically fetches the value of `a`.
 	**/
 	**/
-	public inline function load():Bool {
-		return toBool(this.load());
-	}
-
+	public function load():Bool;
 	/**
 	/**
 		Atomically stores `value` into `a`.
 		Atomically stores `value` into `a`.
 		Returns the value that has been stored.
 		Returns the value that has been stored.
 	**/
 	**/
-	public inline function store(value:Bool):Bool {
-		return toBool(this.store(toInt(value)));
-	}
-}
+	public function store(value:Bool):Bool;
+}

+ 1 - 0
std/haxe/display/JsonModuleTypes.hx

@@ -213,6 +213,7 @@ enum abstract JsonVarAccessKind<T>(String) {
 	var AccNever;
 	var AccNever;
 	var AccResolve;
 	var AccResolve;
 	var AccCall;
 	var AccCall;
+	var AccPrivateCall;
 	var AccInline;
 	var AccInline;
 	var AccRequire:JsonVarAccessKind<{require:String, message:Null<String>}>;
 	var AccRequire:JsonVarAccessKind<{require:String, message:Null<String>}>;
 	var AccCtor;
 	var AccCtor;

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