浏览代码

Merge branch 'development' into out_of_curiosity

# Conflicts:
#	src/codegen/gencommon/castDetect.ml
#	src/codegen/gencommon/closuresToClass.ml
#	src/codegen/gencommon/dynamicFieldAccess.ml
#	src/codegen/gencommon/enumToClass.ml
#	src/codegen/gencommon/gencommon.ml
#	src/codegen/gencommon/overloadingConstructor.ml
#	src/codegen/gencommon/realTypeParams.ml
#	src/codegen/gencommon/renameTypeParameters.ml
#	src/filters/filters.ml
#	src/generators/gencs.ml
#	src/generators/genjava.ml
Simon Krajewski 1 年之前
父节点
当前提交
2a6e013d6f
共有 100 个文件被更改,包括 2538 次插入1688 次删除
  1. 113 0
      src-json/define.json
  2. 20 15
      src/codegen/codegen.ml
  3. 4 7
      src/codegen/overloads.ml
  4. 1 1
      src/compiler/args.ml
  5. 4 4
      src/compiler/compiler.ml
  6. 1 1
      src/compiler/displayOutput.ml
  7. 3 3
      src/compiler/displayProcessing.ml
  8. 31 18
      src/compiler/messageReporting.ml
  9. 12 2
      src/compiler/server.ml
  10. 6 2
      src/compiler/serverCompilationContext.ml
  11. 7 4
      src/context/abstractCast.ml
  12. 54 167
      src/context/common.ml
  13. 6 3
      src/context/display/deprecationCheck.ml
  14. 4 227
      src/context/display/display.ml
  15. 1 1
      src/context/display/displayEmitter.ml
  16. 6 5
      src/context/display/displayFields.ml
  17. 1 1
      src/context/display/displayJson.ml
  18. 1 1
      src/context/display/displayTexpr.ml
  19. 2 4
      src/context/display/displayToplevel.ml
  20. 224 0
      src/context/display/exprPreprocessing.ml
  21. 11 0
      src/context/feature.ml
  22. 98 0
      src/context/formatString.ml
  23. 113 0
      src/context/lookup.ml
  24. 2 2
      src/context/memory.ml
  25. 14 48
      src/context/typecore.ml
  26. 13 0
      src/core/ast.ml
  27. 6 8
      src/core/display/completionItem.ml
  28. 1 1
      src/core/displayTypes.ml
  29. 8 2
      src/core/globals.ml
  30. 5 9
      src/core/json/genjson.ml
  31. 86 0
      src/core/naming.ml
  32. 12 1
      src/core/socket.ml
  33. 117 21
      src/core/tFunctions.ml
  34. 88 14
      src/core/tOther.ml
  35. 49 27
      src/core/tPrinting.ml
  36. 37 16
      src/core/tType.ml
  37. 19 18
      src/core/tUnification.ml
  38. 4 5
      src/core/texpr.ml
  39. 68 0
      src/filters/addFieldInits.ml
  40. 22 0
      src/filters/exceptionFunctions.ml
  41. 2 25
      src/filters/exceptions.ml
  42. 5 209
      src/filters/filters.ml
  43. 17 5
      src/filters/filtersCommon.ml
  44. 62 0
      src/filters/localStatic.ml
  45. 3 3
      src/filters/renameVars.ml
  46. 23 3
      src/generators/gencpp.ml
  47. 41 7
      src/generators/genhl.ml
  48. 11 144
      src/generators/genjs.ml
  49. 17 15
      src/generators/genjvm.ml
  50. 40 5
      src/generators/genlua.ml
  51. 1 2
      src/generators/genpy.ml
  52. 1 3
      src/generators/genswf.ml
  53. 4 4
      src/generators/genswf9.ml
  54. 16 2
      src/generators/hl2c.ml
  55. 13 0
      src/generators/hlcode.ml
  56. 6 6
      src/generators/hlinterp.ml
  57. 11 0
      src/generators/hlopt.ml
  58. 158 0
      src/generators/jsSourcemap.ml
  59. 5 0
      src/macro/eval/eval.ml
  60. 0 5
      src/macro/eval/evalContext.ml
  61. 1 1
      src/macro/eval/evalDebugSocket.ml
  62. 0 1
      src/macro/eval/evalExceptions.ml
  63. 2 1
      src/macro/eval/evalLuv.ml
  64. 2 1
      src/macro/eval/evalMain.ml
  65. 1 1
      src/macro/eval/evalStdLib.ml
  66. 1 1
      src/macro/eval/evalThread.ml
  67. 1 0
      src/macro/eval/evalTypes.ml
  68. 10 38
      src/macro/macroApi.ml
  69. 2 2
      src/optimization/analyzer.ml
  70. 26 23
      src/optimization/dce.ml
  71. 6 4
      src/optimization/inline.ml
  72. 18 2
      src/syntax/grammar.mly
  73. 26 10
      src/typing/callUnification.ml
  74. 39 0
      src/typing/fieldCallCandidate.ml
  75. 2 2
      src/typing/fields.ml
  76. 4 4
      src/typing/finalization.ml
  77. 1 1
      src/typing/forLoop.ml
  78. 1 1
      src/typing/functionArguments.ml
  79. 22 23
      src/typing/generic.ml
  80. 9 17
      src/typing/macroContext.ml
  81. 6 2
      src/typing/matcher/exprToPattern.ml
  82. 6 2
      src/typing/operators.ml
  83. 1 1
      src/typing/overloadResolution.ml
  84. 36 16
      src/typing/tanon_identification.ml
  85. 76 96
      src/typing/typeload.ml
  86. 23 56
      src/typing/typeloadCheck.ml
  87. 10 14
      src/typing/typeloadFields.ml
  88. 4 4
      src/typing/typeloadFunction.ml
  89. 15 31
      src/typing/typeloadModule.ml
  90. 26 172
      src/typing/typer.ml
  91. 3 4
      src/typing/typerBase.ml
  92. 3 3
      src/typing/typerDisplay.ml
  93. 167 0
      src/typing/typerEntry.ml
  94. 3 0
      std/hl/Api.hx
  95. 4 21
      std/hl/CArray.hx
  96. 1 1
      std/js/Object.hx
  97. 43 1
      std/js/html/Navigator.hx
  98. 74 0
      std/js/html/WakeLock.hx
  99. 151 53
      std/js/lib/Object.hx
  100. 2 2
      std/js/lib/Proxy.hx

+ 113 - 0
src-json/define.json

@@ -275,6 +275,114 @@
 		"doc": "Include additional information for hxcpp-debugger.",
 		"platforms": ["cpp"]
 	},
+	{
+		"name": "HxcppGcMoving",
+		"define": "HXCPP-GC-MOVING",
+		"doc": "Allow garbage collector to move memory to reduce fragmentation",
+		"platforms": ["cpp"]
+	},
+	{
+		"name": "HxcppGcSummary",
+		"define": "HXCPP-GC-SUMMARY",
+		"doc": "Print small profiling summary at end of program",
+		"platforms": ["cpp"]
+	},
+	{
+		"name": "HxcppGcDynamicSize",
+		"define": "HXCPP-GC-DYNAMIC-SIZE",
+		"doc": "Monitor GC times and expand memory working space if required",
+		"platforms": ["cpp"]
+	},
+	{
+		"name": "HxcppGcBigBlocks",
+		"define": "HXCPP-GC-BIG-BLOCKS",
+		"doc": "Allow working memory greater than 1 Gig",
+		"platforms": ["cpp"]
+	},
+	{
+		"name": "HxcppGcDebugLevel",
+		"define": "HXCPP-GC-DEBUG-LEVEL",
+		"doc": "Number 1-4 indicating additional debugging in GC",
+		"platforms": ["cpp"]
+	},
+	{
+		"name": "HxcppDebugLink",
+		"define": "HXCPP-DEBUG-LINK",
+		"doc": "Add symbols to final binary, even in release mode.",
+		"platforms": ["cpp"]
+	},
+	{
+		"name": "HxcppStackTrace",
+		"define": "HXCPP-STACK-TRACE",
+		"doc": "Have valid function-level stack traces, even in release mode.",
+		"platforms": ["cpp"]
+	},
+	{
+		"name": "HxcppStackLine",
+		"define": "HXCPP-STACK-LINE",
+		"doc": "Include line information in stack traces, even in release mode.",
+		"platforms": ["cpp"]
+	},
+	{
+		"name": "HxcppCheckPointer",
+		"define": "HXCPP-CHECK-POINTER",
+		"doc": "Add null-pointer checks, even in release mode.",
+		"platforms": ["cpp"]
+	},
+	{
+		"name": "HxcppProfiler",
+		"define": "HXCPP-PROFILER",
+		"doc": "Add profiler support",
+		"platforms": ["cpp"]
+	},
+	{
+		"name": "HxcppTelemetry",
+		"define": "HXCPP-TELEMETRY",
+		"doc": "Add telemetry support",
+		"platforms": ["cpp"]
+	},
+	{
+		"name": "HxcppCpp11",
+		"define": "HXCPP-CPP11",
+		"doc": "Use C++11 features and link libraries",
+		"platforms": ["cpp"]
+	},
+	{
+		"name": "HxcppVerbose",
+		"define": "HXCPP-VERBOSE",
+		"doc": "Print extra output from build tool.",
+		"platforms": ["cpp"]
+	},
+	{
+		"name": "HxcppTimes",
+		"define": "HXCPP-TIMES",
+		"doc": "Show some basic profiling information",
+		"platforms": ["cpp"]
+	},
+	{
+		"name": "HxcppM32",
+		"define": "HXCPP-M32",
+		"doc": "Force 32-bit compile for current desktop",
+		"platforms": ["cpp"]
+	},
+	{
+		"name": "HxcppM64",
+		"define": "HXCPP-M64",
+		"doc": "Force 64-bit compile for current desktop",
+		"platforms": ["cpp"]
+	},
+	{
+		"name": "HxcppArm64",
+		"define": "HXCPP-ARM64",
+		"doc": "Compile arm-based devices for 64 bits",
+		"platforms": ["cpp"]
+	},
+	{
+		"name": "HxcppLinuxArm64",
+		"define": "HXCPP-LINUX-ARM64",
+		"doc": "Run on a linux ARM64 device",
+		"platforms": ["cpp"]
+	},
 	{
 		"name": "HxcppSmartStings",
 		"define": "hxcpp-smart-strings",
@@ -681,6 +789,11 @@
 		"define": "message.no-color",
 		"doc": "Disable ANSI color codes in message reporting."
 	},
+	{
+		"name": "MessageAbsolutePositions",
+		"define": "message.absolute-positions",
+		"doc": "Use absolute character positions instead of line/columns for message reporting."
+	},
 	{
 		"name": "MessageLogFile",
 		"define": "message.log-file",

+ 20 - 15
src/codegen/codegen.ml

@@ -122,8 +122,13 @@ let fix_override com c f fd =
 					(* Flash generates type parameters with a single constraint as that constraint type, so we
 					   have to detect this case and change the variable (issue #2712). *)
 					begin match follow v.v_type with
-						| TInst({cl_kind = KTypeParameter [tc]} as cp,_) when com.platform = Flash ->
-							if List.exists (fun tp -> tp.ttp_name = (snd cp.cl_path)) c.cl_params then raise (Unify_error [])
+						| TInst({cl_kind = KTypeParameter ttp} as cp,_) when com.platform = Flash ->
+							begin match get_constraints ttp with
+							| [tc] ->
+								if List.exists (fun tp -> tp.ttp_name = (snd cp.cl_path)) c.cl_params then raise (Unify_error [])
+							| _ ->
+								()
+							end
 						| _ ->
 							()
 					end;
@@ -235,11 +240,16 @@ module Dump = struct
 		let buf,close = create_dumpfile [] ((dump_path com) :: (platform_name_macro com) :: fst path @ [snd path]) in
 		buf,close
 
-	let dump_types com s_expr =
+	let dump_types com pretty =
 		let s_type = s_type (Type.print_context()) in
+		let s_expr,s_type_param = if not pretty then
+			(Type.s_expr_ast (not (Common.defined com Define.DumpIgnoreVarIds)) "\t"),(Printer.s_type_param "")
+		else
+			(Type.s_expr_pretty false "\t" true),(s_type_param s_type)
+		in
 		let params tl = match tl with
 			| [] -> ""
-			| l -> Printf.sprintf "<%s>" (String.concat ", " (List.map Printer.s_type_param l))
+			| l -> Printf.sprintf "<%s>" (String.concat ", " (List.map s_type_param l))
 		in
 		List.iter (fun mt ->
 			let path = Type.t_path mt in
@@ -371,10 +381,10 @@ module Dump = struct
 
 	let dump_types com =
 		match Common.defined_value_safe com Define.Dump with
-			| "pretty" -> dump_types com (Type.s_expr_pretty false "\t" true)
+			| "pretty" -> dump_types com true
 			| "record" -> dump_record com
 			| "position" -> dump_position com
-			| _ -> dump_types com (Type.s_expr_ast (not (Common.defined com Define.DumpIgnoreVarIds)) "\t")
+			| _ -> dump_types com false 
 
 	let dump_dependencies ?(target_override=None) com =
 		let target_name = match target_override with
@@ -388,7 +398,7 @@ module Dump = struct
 		List.iter (fun m ->
 			print "%s:\n" (Path.UniqueKey.lazy_path m.m_extra.m_file);
 			PMap.iter (fun _ (sign,mpath) ->
-				let m2 = (com.cs#get_context sign)#find_module mpath in
+				let m2 = com.module_lut#find mpath in
 				let file = Path.UniqueKey.lazy_path m2.m_extra.m_file in
 				print "\t%s\n" file;
 				let l = try Hashtbl.find dep file with Not_found -> [] in
@@ -414,16 +424,10 @@ end
 *)
 let default_cast ?(vtmp="$t") com e texpr t p =
 	let api = com.basic in
-	let mk_texpr = function
-		| TClassDecl c -> mk_anon (ref (ClassStatics c))
-		| TEnumDecl e -> mk_anon (ref (EnumStatics e))
-		| TAbstractDecl a -> mk_anon (ref (AbstractStatics a))
-		| TTypeDecl _ -> die "" __LOC__
-	in
 	let vtmp = alloc_var VGenerated vtmp e.etype e.epos in
 	let var = mk (TVar (vtmp,Some e)) api.tvoid p in
 	let vexpr = mk (TLocal vtmp) e.etype p in
-	let texpr = mk (TTypeExpr texpr) (mk_texpr texpr) p in
+	let texpr = Texpr.Builder.make_typeexpr texpr p in
 	let std = (try List.find (fun t -> t_path t = ([],"Std")) com.types with Not_found -> die "" __LOC__) in
 	let fis = (try
 			let c = (match std with TClassDecl c -> c | _ -> die "" __LOC__) in
@@ -431,7 +435,7 @@ let default_cast ?(vtmp="$t") com e texpr t p =
 		with Not_found ->
 			die "" __LOC__
 	) in
-	let std = mk (TTypeExpr std) (mk_texpr std) p in
+	let std = Texpr.Builder.make_typeexpr std p in
 	let is = mk (TField (std,fis)) (tfun [t_dynamic;t_dynamic] api.tbool) p in
 	let is = mk (TCall (is,[vexpr;texpr])) api.tbool p in
 	let enull = Texpr.Builder.make_null vexpr.etype p in
@@ -515,3 +519,4 @@ module ExtClass = struct
 		let e_assign = mk (TBinop(OpAssign,ef1,e)) e.etype p in
 		add_cl_init c e_assign
 end
+	

+ 4 - 7
src/codegen/overloads.ml

@@ -1,6 +1,6 @@
 open Globals
 open Type
-open Typecore
+open FieldCallCandidate
 
 let same_overload_args ?(get_vmtype) t1 t2 f1 f2 =
 	let f_transform = match get_vmtype with
@@ -13,13 +13,10 @@ let same_overload_args ?(get_vmtype) t1 t2 f1 f2 =
 			| [],[] ->
 				true
 			| tp1 :: params1,tp2 :: params2 ->
-				let constraints_equal t1 t2 = match follow t1,follow t2 with
-					| TInst({cl_kind = KTypeParameter tl1},_),TInst({cl_kind = KTypeParameter tl2},_) ->
-						Ast.safe_for_all2 f_eq tl1 tl2
-					| _ ->
-						false
+				let constraints_equal ttp1 ttp2 = 
+					Ast.safe_for_all2 f_eq (get_constraints ttp2) (get_constraints ttp2)
 				in
-				tp1.ttp_name = tp2.ttp_name && constraints_equal tp1.ttp_type tp2.ttp_type && loop params1 params2
+				tp1.ttp_name = tp2.ttp_name && constraints_equal tp1 tp2 && loop params1 params2
 			| [],_
 			| _,[] ->
 				false

+ 1 - 1
src/compiler/args.ml

@@ -42,7 +42,7 @@ let process_args arg_spec =
 
 let parse_args com =
 	let usage = Printf.sprintf
-		"Haxe Compiler %s - (C)2005-2023 Haxe Foundation\nUsage: haxe%s <target> [options] [hxml files and dot paths...]\n"
+		"Haxe Compiler %s - (C)2005-2024 Haxe Foundation\nUsage: haxe%s <target> [options] [hxml files and dot paths...]\n"
 		s_version_full (if Sys.os_type = "Win32" then ".exe" else "")
 	in
 	let actx = {

+ 4 - 4
src/compiler/compiler.ml

@@ -172,7 +172,7 @@ module Setup = struct
 		let fl = List.map (fun (file,extern) -> NativeLibraryHandler.add_native_lib com file extern) (List.rev native_libs) in
 		(* Native lib pass 2: Initialize *)
 		List.iter (fun f -> f()) fl;
-		Typer.create com macros
+		TyperEntry.create com macros
 
 	let executable_path() =
 		Extc.executable_path()
@@ -418,7 +418,7 @@ with
 		error ctx ("Error: No completion point was found") null_pos
 	| DisplayException.DisplayException dex ->
 		DisplayOutput.handle_display_exception ctx dex
-	| Out_of_memory | EvalExceptions.Sys_exit _ | Hlinterp.Sys_exit _ | DisplayProcessingGlobals.Completion _ as exc ->
+	| Out_of_memory | EvalTypes.Sys_exit _ | Hlinterp.Sys_exit _ | DisplayProcessingGlobals.Completion _ as exc ->
 		(* We don't want these to be caught by the catchall below *)
 		raise exc
 	| e when (try Sys.getenv "OCAMLRUNPARAM" <> "b" with _ -> true) && not Helper.is_debug_run ->
@@ -443,7 +443,7 @@ let catch_completion_and_exit ctx callbacks run =
 			ServerMessage.completion str;
 			ctx.comm.write_err str;
 			0
-		| EvalExceptions.Sys_exit i | Hlinterp.Sys_exit i ->
+		| EvalTypes.Sys_exit i | Hlinterp.Sys_exit i ->
 			if i <> 0 then ctx.has_error <- true;
 			finalize ctx;
 			i
@@ -476,7 +476,7 @@ let compile_ctx callbacks ctx =
 		catch_completion_and_exit ctx callbacks run
 
 let create_context comm cs compilation_step params = {
-	com = Common.create compilation_step cs version params;
+	com = Common.create compilation_step cs version params (DisplayTypes.DisplayMode.create !Parser.display_mode);
 	messages = [];
 	has_next = false;
 	has_error = false;

+ 1 - 1
src/compiler/displayOutput.ml

@@ -344,7 +344,7 @@ let handle_type_path_exception ctx p c is_import pos =
 			| None ->
 				DisplayPath.TypePathHandler.complete_type_path com p
 			| Some (c,cur_package) ->
-				let ctx = Typer.create com None in
+				let ctx = TyperEntry.create com None in
 				DisplayPath.TypePathHandler.complete_type_path_inner ctx p c cur_package is_import
 		end with Error.Fatal_error err ->
 			error_ext ctx err;

+ 3 - 3
src/compiler/displayProcessing.ml

@@ -48,7 +48,7 @@ let handle_display_argument_old com file_pos actx =
 			| "diagnostics" ->
 				com.report_mode <- RMLegacyDiagnostics [file_unique];
 				let dm = create DMNone in
-				{dm with dms_display_file_policy = DFPAlso; dms_per_file = true; dms_populate_cache = !ServerConfig.populate_cache_from_display}
+				{dm with dms_display_file_policy = DFPOnly; dms_per_file = true; dms_populate_cache = !ServerConfig.populate_cache_from_display}
 			| "statistics" ->
 				com.report_mode <- RMStatistics;
 				let dm = create DMNone in
@@ -200,11 +200,11 @@ let load_display_module_in_macro tctx display_file_dot_path clear = match displa
 				begin try
 					let m = mctx.com.module_lut#find cpath in
 					mctx.com.module_lut#remove cpath;
-					mctx.com.type_to_module#remove cpath;
+					mctx.com.module_lut#get_type_lut#remove cpath;
 					List.iter (fun mt ->
 						let ti = Type.t_infos mt in
 						mctx.com.module_lut#remove ti.mt_path;
-						mctx.com.type_to_module#remove ti.mt_path;
+						mctx.com.module_lut#get_type_lut#remove ti.mt_path;
 					) m.m_types
 				with Not_found ->
 					()

+ 31 - 18
src/compiler/messageReporting.ml

@@ -65,13 +65,15 @@ let resolve_file ctx f =
 let error_printer file line = Printf.sprintf "%s:%d:" file line
 
 type error_context = {
+	absolute_positions : bool;
 	mutable last_positions : pos IntMap.t;
 	mutable max_lines : int IntMap.t;
 	mutable gutter : int IntMap.t;
 	mutable previous : (pos * MessageSeverity.t * int) option;
 }
 
-let create_error_context () = {
+let create_error_context absolute_positions = {
+	absolute_positions = absolute_positions;
 	last_positions = IntMap.empty;
 	max_lines = IntMap.empty;
 	gutter = IntMap.empty;
@@ -97,7 +99,10 @@ let compiler_pretty_message_string com ectx cm =
 				let f = Common.find_file com f in
 				let l1, p1, l2, p2 = Lexer.get_pos_coords cm.cm_pos in
 				let lines = resolve_source f l1 p1 l2 p2 in
-				let epos = Lexer.get_error_pos error_printer cm.cm_pos in
+				let epos =
+					if ectx.absolute_positions then TPrinting.Printer.s_pos cm.cm_pos
+					else Lexer.get_error_pos error_printer cm.cm_pos
+				in
 				(l1, p1, l2, p2, epos, lines)
 			end with Not_found | Sys_error _ ->
 				(1, 1, 1, 1, cm.cm_pos.pfile, [])
@@ -243,7 +248,7 @@ let compiler_pretty_message_string com ectx cm =
 		)
 	end
 
-let compiler_message_string cm =
+let compiler_message_string ectx cm =
 	let str = match cm.cm_severity with
 		| MessageSeverity.Warning -> "Warning : " ^ cm.cm_message
 		| Information | Error | Hint -> cm.cm_message
@@ -252,7 +257,10 @@ let compiler_message_string cm =
 	if cm.cm_pos = null_pos then
 		Some str
 	else begin
-		let epos = Lexer.get_error_pos error_printer cm.cm_pos in
+		let epos =
+			if ectx.absolute_positions then TPrinting.Printer.s_pos cm.cm_pos
+			else Lexer.get_error_pos error_printer cm.cm_pos
+		in
 		let str =
 			let lines =
 				match (ExtString.String.nsplit str "\n") with
@@ -264,7 +272,7 @@ let compiler_message_string cm =
 		Some (Printf.sprintf "%s : %s" epos str)
 	end
 
-let compiler_indented_message_string cm =
+let compiler_indented_message_string ectx cm =
 	match cm.cm_message with
 	(* Filter some messages that don't add much when using this message renderer *)
 	| "End of overload failure reasons" -> None
@@ -278,7 +286,10 @@ let compiler_indented_message_string cm =
 		if cm.cm_pos = null_pos then
 			Some str
 		else begin
-			let epos = Lexer.get_error_pos error_printer cm.cm_pos in
+			let epos =
+				if ectx.absolute_positions then TPrinting.Printer.s_pos cm.cm_pos
+				else Lexer.get_error_pos error_printer cm.cm_pos
+			in
 			let lines =
 				match (ExtString.String.nsplit str "\n") with
 				| first :: rest -> (cm.cm_depth, first) :: List.map (fun msg -> (cm.cm_depth+1, msg)) rest
@@ -299,10 +310,10 @@ let get_max_line max_lines messages =
 
 exception ConfigError of string
 
-let get_formatter com ectx def default =
+let get_formatter com def default =
 	let format_mode = Define.defined_value_safe ~default com.defines def in
 	match format_mode with
-		| "pretty" -> compiler_pretty_message_string com ectx
+		| "pretty" -> compiler_pretty_message_string com
 		| "indent" -> compiler_indented_message_string
 		| "classic" -> compiler_message_string
 		| m -> begin
@@ -318,11 +329,12 @@ let print_error (err : Error.error) =
 	!ret
 
 let format_messages com messages =
-	let ectx = create_error_context () in
+	let absolute_positions = Define.defined com.defines Define.MessageAbsolutePositions in
+	let ectx = create_error_context absolute_positions in
 	ectx.max_lines <- get_max_line ectx.max_lines messages;
-	let message_formatter = get_formatter com ectx Define.MessageReporting "classic" in
+	let message_formatter = get_formatter com Define.MessageReporting "classic" in
 	let lines = List.rev (
-		List.fold_left (fun lines cm -> match (message_formatter cm) with
+		List.fold_left (fun lines cm -> match (message_formatter ectx cm) with
 			| None -> lines
 			| Some str -> str :: lines
 		) [] messages
@@ -330,18 +342,19 @@ let format_messages com messages =
 	ExtLib.String.join "\n" lines
 
 let display_messages ctx on_message = begin
-	let ectx = create_error_context () in
+	let absolute_positions = Define.defined ctx.com.defines Define.MessageAbsolutePositions in
+	let ectx = create_error_context absolute_positions in
 	ectx.max_lines <- get_max_line ectx.max_lines ctx.messages;
 
-	let get_formatter _ _ def default =
-		try get_formatter ctx.com ectx def default
+	let get_formatter _ def default =
+		try get_formatter ctx.com def default
 		with | ConfigError s ->
 			error ctx s null_pos;
 			compiler_message_string
 	in
 
-	let message_formatter = get_formatter ctx.com ectx Define.MessageReporting "classic" in
-	let log_formatter = get_formatter ctx.com ectx Define.MessageLogFormat "indent" in
+	let message_formatter = get_formatter ctx.com Define.MessageReporting "classic" in
+	let log_formatter = get_formatter ctx.com Define.MessageLogFormat "indent" in
 
 	let log_messages = ref (Define.defined ctx.com.defines Define.MessageLogFile) in
 	let log_message = ref None in
@@ -358,7 +371,7 @@ let display_messages ctx on_message = begin
 			in
 
 			log_message := (Some (fun msg ->
-				match (log_formatter msg) with
+				match (log_formatter ectx msg) with
 					| None -> ()
 					| Some str -> Rbuffer.add_string buf (str ^ "\n")));
 
@@ -378,7 +391,7 @@ let display_messages ctx on_message = begin
 	List.iter (fun cm ->
 		if !log_messages then (Option.get !log_message) cm;
 
-		match (message_formatter cm) with
+		match (message_formatter ectx cm) with
 			| None -> ()
 			| Some str -> on_message cm.cm_severity str
 	) (List.rev ctx.messages);

+ 12 - 2
src/compiler/server.ml

@@ -395,6 +395,16 @@ let check_module sctx ctx m p =
 	end;
 	state
 
+let handle_cache_bound_objects com cbol =
+	DynArray.iter (function
+		| Resource(name,data) ->
+			Hashtbl.replace com.resources name data
+		| IncludeFile(file,position) ->
+			com.include_files <- (file,position) :: com.include_files
+		| Warning(w,msg,p) ->
+			com.warning w [] msg p
+	) cbol
+
 (* Adds module [m] and all its dependencies (recursively) from the cache to the current compilation
    context. *)
 let add_modules sctx ctx m p =
@@ -404,7 +414,7 @@ let add_modules sctx ctx m p =
 			(match m0.m_extra.m_kind, m.m_extra.m_kind with
 			| MCode, MMacro | MMacro, MCode ->
 				(* this was just a dependency to check : do not add to the context *)
-				PMap.iter (Hashtbl.replace com.resources) m.m_extra.m_binded_res;
+				handle_cache_bound_objects com m.m_extra.m_cache_bound_objects;
 			| _ ->
 				m.m_extra.m_added <- ctx.com.compilation_step;
 				ServerMessage.reusing com tabs m;
@@ -412,7 +422,7 @@ let add_modules sctx ctx m p =
 					(t_infos t).mt_restore()
 				) m.m_types;
 				TypeloadModule.ModuleLevel.add_module ctx m p;
-				PMap.iter (Hashtbl.replace com.resources) m.m_extra.m_binded_res;
+				handle_cache_bound_objects com m.m_extra.m_cache_bound_objects;
 				PMap.iter (fun _ (sign,mpath) ->
 					let m2 = (com.cs#get_context sign)#find_module mpath in
 					add_modules (tabs ^ "  ") m0 m2

+ 6 - 2
src/compiler/serverCompilationContext.ml

@@ -70,5 +70,9 @@ let ensure_macro_setup sctx =
 	end
 
 let cleanup () = match !MacroContext.macro_interp_cache with
-	| Some interp -> EvalContext.GlobalState.cleanup interp
-	| None -> ()
+	| Some interp ->
+		(* curapi holds a reference to the typing context which we don't want to persist. Let's unset it so the
+		   context can be collected. *)
+		interp.curapi <- Obj.magic ""
+	| None ->
+		()

+ 7 - 4
src/context/abstractCast.ml

@@ -88,7 +88,9 @@ and do_check_cast ctx uctx tleft eright p =
 					end
 				| TInst(c,tl), TFun _ when has_class_flag c CFunctionalInterface ->
 					let cf = ctx.g.functional_interface_lut#find c.cl_path in
-					unify_raise_custom uctx eright.etype (apply_params c.cl_params tl cf.cf_type) p;
+					let map = apply_params c.cl_params tl in
+					let monos = Monomorph.spawn_constrained_monos map cf.cf_params in
+					unify_raise_custom uctx eright.etype (map (apply_params cf.cf_params monos cf.cf_type)) p;
 					eright
 				| _ ->
 					raise Not_found
@@ -119,10 +121,11 @@ let prepare_array_access_field ctx a pl cf p =
 	let monos = List.map (fun _ -> spawn_monomorph ctx p) cf.cf_params in
 	let map t = apply_params a.a_params pl (apply_params cf.cf_params monos t) in
 	let check_constraints () =
-		List.iter2 (fun m tp -> match follow tp.ttp_type with
-			| TInst ({ cl_kind = KTypeParameter constr },_) when constr <> [] ->
+		List.iter2 (fun m ttp -> match get_constraints ttp with
+			| [] ->
+				()
+			| constr ->
 				List.iter (fun tc -> match follow m with TMono _ -> raise (Unify_error []) | _ -> Type.unify m (map tc) ) constr
-			| _ -> ()
 		) monos cf.cf_params;
 	in
 	let get_ta() =

+ 54 - 167
src/context/common.ml

@@ -20,6 +20,7 @@ open Extlib_leftovers
 open Ast
 open Type
 open Globals
+open Lookup
 open Define
 open NativeLibraries
 open Warning
@@ -293,66 +294,44 @@ type report_mode =
 	| RMDiagnostics of (Path.UniqueKey.t list)
 	| RMStatistics
 
-class virtual ['key,'value] lookup = object(self)
-	method virtual add : 'key -> 'value -> unit
-	method virtual remove : 'key -> unit
-	method virtual find : 'key -> 'value
-	method virtual iter : ('key -> 'value -> unit) -> unit
-	method virtual fold : 'acc . ('key -> 'value -> 'acc -> 'acc) -> 'acc -> 'acc
-	method virtual mem : 'key -> bool
-	method virtual clear : unit
-end
-
-class ['key,'value] pmap_lookup = object(self)
-	inherit ['key,'value] lookup
-	val mutable lut : ('key,'value) PMap.t = PMap.empty
-
-	method add (key : 'key) (value : 'value) =
-		lut <- PMap.add key value lut
-
-	method remove (key : 'key) =
-		lut <- PMap.remove key lut
-
-	method find (key : 'key) : 'value =
-		PMap.find key lut
-
-	method iter (f : 'key -> 'value -> unit) =
-		PMap.iter f lut
-
-	method fold : 'acc . ('key -> 'value -> 'acc -> 'acc) -> 'acc -> 'acc = fun f acc ->
-		PMap.foldi f lut acc
+class module_lut = object(self)
+	inherit [path,module_def] hashtbl_lookup as super
 
-	method mem (key : 'key) =
-		PMap.mem key lut
+	val type_lut : (path,path) lookup = new hashtbl_lookup
 
-	method clear =
-		lut <- PMap.empty
-end
-
-class ['key,'value] hashtbl_lookup = object(self)
-	inherit ['key,'value] lookup
-	val lut : ('key,'value) Hashtbl.t = Hashtbl.create 0
-
-	method add (key : 'key) (value : 'value) =
-		Hashtbl.replace lut key value
-
-	method remove (key : 'key) =
-		Hashtbl.remove lut key
+	method add_module_type (m : module_def) (mt : module_type) =
+		let t = t_infos mt in
+		try
+			let path2 = type_lut#find t.mt_path in
+			let p = t.mt_pos in
+			if m.m_path <> path2 && String.lowercase_ascii (s_type_path path2) = String.lowercase_ascii (s_type_path m.m_path) then Error.raise_typing_error ("Module " ^ s_type_path path2 ^ " is loaded with a different case than " ^ s_type_path m.m_path) p;
+			let m2 = self#find path2 in
+			let hex1 = Digest.to_hex m.m_extra.m_sign in
+			let hex2 = Digest.to_hex m2.m_extra.m_sign in
+			let s = if hex1 = hex2 then hex1 else Printf.sprintf "was %s, is %s" hex2 hex1 in
+			Error.raise_typing_error (Printf.sprintf "Type name %s is redefined from module %s (%s)" (s_type_path t.mt_path)  (s_type_path path2) s) p
+		with Not_found ->
+			type_lut#add t.mt_path m.m_path
 
-	method find (key : 'key) : 'value =
-		Hashtbl.find lut key
+	method! add (path : path) (m : module_def) =
+		super#add path m;
+		List.iter (fun mt -> self#add_module_type m mt) m.m_types
 
-	method iter (f : 'key -> 'value -> unit) =
-		Hashtbl.iter f lut
+	method! remove (path : path) =
+		try
+			List.iter (fun mt -> type_lut#remove (t_path mt)) (self#find path).m_types;
+			super#remove path;
+		with Not_found ->
+			()
 
-	method fold : 'acc . ('key -> 'value -> 'acc -> 'acc) -> 'acc -> 'acc = fun f acc ->
-		Hashtbl.fold f lut acc
+	method find_by_type (path : path) =
+		self#find (type_lut#find path)
 
-	method mem (key : 'key) =
-		Hashtbl.mem lut key
+	method! clear =
+		super#clear;
+		type_lut#clear
 
-	method clear =
-		Hashtbl.clear lut
+	method get_type_lut = type_lut
 end
 
 type context = {
@@ -408,9 +387,8 @@ type context = {
 	cached_macros : (path * string,(((string * bool * t) list * t * tclass * Type.tclass_field) * module_def)) lookup;
 	stored_typed_exprs : (int, texpr) lookup;
 	overload_cache : ((path * string),(Type.t * tclass_field) list) lookup;
-	module_lut : (path,module_def) lookup;
+	module_lut : module_lut;
 	module_nonexistent_lut : (path,bool) lookup;
-	type_to_module : (path,path) lookup;
 	mutable has_error : bool;
 	pass_debug_messages : string DynArray.t;
 	(* output *)
@@ -443,6 +421,10 @@ let ignore_error com =
 	if b then com.has_error <- true;
 	b
 
+let module_warning com m w options msg p =
+	DynArray.add m.m_extra.m_cache_bound_objects (Warning(w,msg,p));
+	com.warning w options msg p
+
 (* Defines *)
 
 module Define = Define
@@ -761,8 +743,7 @@ let get_config com =
 
 let memory_marker = [|Unix.time()|]
 
-let create compilation_step cs version args =
-	let m = Type.mk_mono() in
+let create compilation_step cs version args display_mode =
 	let rec com = {
 		compilation_step = compilation_step;
 		cs = cs;
@@ -782,7 +763,7 @@ let create compilation_step cs version args =
 		};
 		sys_args = args;
 		debug = false;
-		display = DisplayTypes.DisplayMode.create !Parser.display_mode;
+		display = display_mode;
 		verbose = false;
 		foptimize = true;
 		features = Hashtbl.create 0;
@@ -800,9 +781,8 @@ let create compilation_step cs version args =
 		callbacks = new compiler_callbacks;
 		global_metadata = [];
 		modules = [];
-		module_lut = new hashtbl_lookup;
+		module_lut = new module_lut;
 		module_nonexistent_lut = new hashtbl_lookup;
-		type_to_module = new hashtbl_lookup;
 		main = None;
 		flash_version = 10.;
 		resources = Hashtbl.create 0;
@@ -830,12 +810,12 @@ let create compilation_step cs version args =
 		filter_messages = (fun _ -> ());
 		pass_debug_messages = DynArray.create();
 		basic = {
-			tvoid = m;
-			tint = m;
-			tfloat = m;
-			tbool = m;
+			tvoid = 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__);
-			tstring = m;
 			tarray = (fun _ -> die "Could not locate class Array<T> (was it redefined?)" __LOC__);
 		};
 		file_lookup_cache = new hashtbl_lookup;
@@ -871,7 +851,12 @@ let clone com is_macro_context =
 	let t = com.basic in
 	{ com with
 		cache = None;
-		basic = { t with tvoid = t.tvoid };
+		basic = { t with
+			tint = mk_mono();
+			tfloat = mk_mono();
+			tbool = mk_mono();
+			tstring = mk_mono();
+		};
 		main_class = None;
 		features = Hashtbl.create 0;
 		callbacks = new compiler_callbacks;
@@ -891,8 +876,7 @@ let clone com is_macro_context =
 		parser_cache = new hashtbl_lookup;
 		module_to_file = new hashtbl_lookup;
 		overload_cache = new hashtbl_lookup;
-		module_lut = new hashtbl_lookup;
-		type_to_module = new hashtbl_lookup;
+		module_lut = new module_lut;
 	}
 
 let file_time file = Extc.filetime file
@@ -1106,7 +1090,7 @@ let cache_directory ctx class_path dir f_dir =
 	in
 	Option.may (Array.iter prepare_file) dir_listing
 
-let find_file ctx f =
+let find_file ctx ?(class_path=ctx.class_path) f =
 	try
 		match ctx.file_lookup_cache#find f with
 		| None -> raise Exit
@@ -1141,7 +1125,7 @@ let find_file ctx f =
 						loop (had_empty || p = "") l
 				end
 		in
-		let r = try Some (loop false ctx.class_path) with Not_found -> None in
+		let r = try Some (loop false class_path) with Not_found -> None in
 		ctx.file_lookup_cache#add f r;
 		match r with
 		| None -> raise Not_found
@@ -1297,100 +1281,3 @@ let get_entry_point com =
 		let e = Option.get com.main in (* must be present at this point *)
 		(snd path, c, e)
 	) com.main_class
-
-let format_string com s p process_expr =
-	let e = ref None in
-	let pmin = ref p.pmin in
-	let min = ref (p.pmin + 1) in
-	let add_expr (enext,p) len =
-		min := !min + len;
-		let enext = process_expr enext p in
-		match !e with
-		| None -> e := Some enext
-		| Some prev ->
-			e := Some (EBinop (OpAdd,prev,enext),punion (pos prev) p)
-	in
-	let add enext len =
-		let p = { p with pmin = !min; pmax = !min + len } in
-		add_expr (enext,p) len
-	in
-	let add_sub start pos =
-		let len = pos - start in
-		if len > 0 || !e = None then add (EConst (String (String.sub s start len,SDoubleQuotes))) len
-	in
-	let len = String.length s in
-	let rec parse start pos =
-		if pos = len then add_sub start pos else
-		let c = String.unsafe_get s pos in
-		let pos = pos + 1 in
-		if c = '\'' then begin
-			incr pmin;
-			incr min;
-		end;
-		if c <> '$' || pos = len then parse start pos else
-		match String.unsafe_get s pos with
-		| '$' ->
-			(* double $ *)
-			add_sub start pos;
-			parse (pos + 1) (pos + 1)
-		| '{' ->
-			parse_group start pos '{' '}' "brace"
-		| 'a'..'z' | 'A'..'Z' | '_' ->
-			add_sub start (pos - 1);
-			incr min;
-			let rec loop i =
-				if i = len then i else
-				let c = String.unsafe_get s i in
-				match c with
-				| 'a'..'z' | 'A'..'Z' | '0'..'9' | '_' -> loop (i+1)
-				| _ -> i
-			in
-			let iend = loop (pos + 1) in
-			let len = iend - pos in
-			add (EConst (Ident (String.sub s pos len))) len;
-			parse (pos + len) (pos + len)
-		| _ ->
-			(* keep as-it *)
-			parse start pos
-	and parse_group start pos gopen gclose gname =
-		add_sub start (pos - 1);
-		let rec loop groups i =
-			if i = len then
-				match groups with
-				| [] -> die "" __LOC__
-				| g :: _ -> Error.raise_typing_error ("Unclosed " ^ gname) { p with pmin = !pmin + g + 1; pmax = !pmin + g + 2 }
-			else
-				let c = String.unsafe_get s i in
-				if c = gopen then
-					loop (i :: groups) (i + 1)
-				else if c = gclose then begin
-					let groups = List.tl groups in
-					if groups = [] then i else loop groups (i + 1)
-				end else
-					loop groups (i + 1)
-		in
-		let send = loop [pos] (pos + 1) in
-		let slen = send - pos - 1 in
-		let scode = String.sub s (pos + 1) slen in
-		min := !min + 2;
-		begin
-			let e =
-				let ep = { p with pmin = !pmin + pos + 2; pmax = !pmin + send + 1 } in
-				let error msg pos =
-					if Lexer.string_is_whitespace scode then Error.raise_typing_error "Expression cannot be empty" ep
-					else Error.raise_typing_error msg pos
-				in
-				match ParserEntry.parse_expr_string com.defines scode ep error true with
-					| ParseSuccess(data,_,_) -> data
-					| ParseError(_,(msg,p),_) -> error (Parser.error_msg msg) p
-			in
-			add_expr e slen
-		end;
-		min := !min + 1;
-		parse (send + 1) (send + 1)
-	in
-	parse 0 0;
-	match !e with
-	| None -> die "" __LOC__
-	| Some e -> e
-

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

@@ -7,12 +7,14 @@ type deprecation_context = {
 	com        : Common.context;
 	class_meta : metadata_entry list;
 	field_meta : metadata_entry list;
+	curmod     : module_def;
 }
 
 let create_context com = {
 	com = com;
 	class_meta = [];
 	field_meta = [];
+	curmod = null_module;
 }
 
 let warned_positions = Hashtbl.create 0
@@ -23,7 +25,7 @@ let warn_deprecation dctx s p_usage =
 		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
-			dctx.com.warning WDeprecated options s p_usage;
+			module_warning dctx.com dctx.curmod WDeprecated options s p_usage;
 		end
 	end
 
@@ -103,7 +105,7 @@ let run com =
 	let dctx = create_context com in
 	List.iter (fun t -> match t with
 		| TClassDecl c when not (Meta.has Meta.Deprecated c.cl_meta) ->
-			let dctx = {dctx with class_meta = c.cl_meta} in
+			let dctx = {dctx with class_meta = c.cl_meta; curmod = c.cl_module} in
 			(match c.cl_constructor with None -> () | Some cf -> run_on_field dctx cf);
 			(match c.cl_init with None -> () | Some e -> run_on_expr dctx e);
 			List.iter (run_on_field dctx) c.cl_ordered_statics;
@@ -112,11 +114,12 @@ let run com =
 			()
 	) com.types
 
-let check_is com cl_meta cf_meta name meta p =
+let check_is com m cl_meta cf_meta name meta p =
 	let dctx = {
 		com = com;
 		class_meta = cl_meta;
 		field_meta = cf_meta;
+		curmod = m;
 	} in
 	if is_next dctx.com && name = "is" && not (Meta.has Meta.Deprecated meta) then
 		warn_deprecation dctx "Using \"is\" as an identifier is deprecated" p

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

@@ -30,233 +30,10 @@ module ReferencePosition = struct
 	let reset () = reference_position := ("",null_pos,SKOther)
 end
 
-module ExprPreprocessing = struct
-	let find_before_pos dm e =
-		let display_pos = ref (DisplayPosition.display_position#get) in
-		let was_annotated = ref false in
-		let is_annotated,is_completion = match dm with
-			| DMDefault -> (fun p -> not !was_annotated && encloses_position !display_pos p),true
-			| DMHover -> (fun p -> not !was_annotated && encloses_position_gt !display_pos p),false
-			| _ -> (fun p -> not !was_annotated && encloses_position !display_pos p),false
-		in
-		let annotate e dk =
-			was_annotated := true;
-			(EDisplay(e,dk),pos e)
-		in
-		let annotate_marked e = annotate e DKMarked in
-		let mk_null p = annotate_marked ((EConst(Ident "null")),p) in
-		let loop_el el =
-			let pr = DisplayPosition.display_position#with_pos (pos e) in
-			let rec loop el = match el with
-				| [] -> [mk_null pr]
-				| e :: el ->
-					if (pos e).pmin >= pr.pmax then (mk_null pr) :: e :: el
-					else e :: loop el
-			in
-			(* print_endline (Printf.sprintf "%i-%i: PR" pr.pmin pr.pmax);
-			List.iter (fun e ->
-				print_endline (Printf.sprintf "%i-%i: %s" (pos e).pmin (pos e).pmax (Ast.s_expr e));
-			) el; *)
-			match el with
-			| [] -> [mk_null pr]
-			| e :: el ->
-				if (pos e).pmin >= pr.pmax then (mk_null pr) :: e :: el
-				else loop (e :: el)
-		in
-		let in_pattern = ref false in
-		let loop e =
-			(* print_endline (Printf.sprintf "%i-%i: %s" (pos e).pmin (pos e).pmax (Ast.s_expr e)); *)
-			match fst e with
-			| EFunction(FKNamed((_,p),_),_) when is_annotated p && is_completion ->
-				raise Exit
-			| EVars vl when is_annotated (pos e) && is_completion ->
-				let rec loop2 acc mark vl = match vl with
-					| v :: vl ->
-						if mark then
-							loop2 (v :: acc) mark vl
-						else if is_annotated (snd v.ev_name) then
-							(* If the name is the display position, mark the expression *)
-							loop2 (v :: acc) true vl
-						else begin match v.ev_expr with
-							| None ->
-								(* If there is no expression, we don't have to do anything.
-								   Should the display position be on the type-hint, it will
-								   be picked up while loading the type. *)
-								loop2 (v :: acc) mark vl
-							| Some e ->
-								(* Determine the area between the `|` in `var x| = | e`. This is not really
-								   correct because we don't want completion on the left side of the `=`, but
-								   we cannot determine that correctly without knowing its position.
-								   Note: We know `e` itself isn't the display position because this entire
-								   algorithm is bottom-up and it would be marked already if it was. *)
-								let p0 = match v.ev_type with
-									| Some (_,pt) -> pt
-									| None -> snd v.ev_name
-								in
-								let p = {p0 with pmax = (pos e).pmin} in
-								let e = if is_annotated p then annotate_marked e else e in
-								loop2 ({ v with ev_expr = Some e } :: acc) mark vl
-						end
-					| [] ->
-						List.rev acc,mark
-				in
-				let vl,mark = loop2 [] false vl in
-				let e = EVars (List.rev vl),pos e in
-				if !was_annotated then e else raise Exit
-			| EBinop((OpAssign | OpAssignOp _) as op,e1,e2) when is_annotated (pos e) && is_completion ->
-				(* Special case for assign ops: If the expression is marked, but none of its operands are,
-				   we are "probably" interested in the rhs. Like with EVars, this isn't accurate because we
-				   could be on the left side of the `=`. I don't think there's a reason for requesting
-				   completion there though. *)
-				(EBinop(op,e1,annotate_marked e2)),(pos e)
-			| EBinop(OpOr,e1,(EIf(_,(EConst(Ident "null"),_),None),p1)) when is_annotated (pos e) && is_completion && !in_pattern ->
-				(* This HAS TO come from an attempted `case pattern | guard:` completion (issue #7068). *)
-				let p = { p1 with pmin = (pos e1).pmax; pmax = p1.pmin } in
-				EBinop(OpOr,e1,mk_null p),(pos e)
-			| EIf(_,(EConst(Ident "null"),_),None) when is_completion && !in_pattern ->
-				(* This is fine. *)
-				mk_null (pos e)
-			| EBlock [] when is_annotated (pos e) ->
-				annotate e DKStructure
-			| EBlock [EDisplay((EConst(Ident s),pn),DKMarked),_] when is_completion ->
-				let e = EObjectDecl [(s,pn,NoQuotes),(EConst (Ident "null"),null_pos)],(pos e) in
-				annotate e DKStructure
-			| EBlock el when is_annotated (pos e) && is_completion ->
-				let el = loop_el el in
-				EBlock el,(pos e)
-			| ECall(e1,el) when is_annotated (pos e) && is_completion ->
-				let el = loop_el el in
-				ECall(e1,el),(pos e)
-			| ENew(ptp,el) when is_annotated (pos e) && is_completion ->
-				if is_annotated ptp.pos_full || ptp.pos_full.pmax >= (DisplayPosition.display_position#get).pmax then
-					annotate_marked e
-				else begin
-					let el = loop_el el in
-					ENew(ptp,el),(pos e)
-				end
-			| EArrayDecl el when is_annotated (pos e) && is_completion ->
-				let el = loop_el el in
-				EArrayDecl el,(pos e)
-			| EObjectDecl fl when is_annotated (pos e) && is_completion ->
-				annotate e DKStructure
-			| ESwitch(e1,cases,def) when is_annotated (pos e) ->
-				(* We must be "between" two cases, or at the end of the last case.
-				   Let's find the last case which has a position that is < the display
-				   position and mark it. *)
-				let did_mark = ref false in
-				let mark_case ec p =
-					did_mark := true;
-					let ep = mk_null p in
-					match ec with
-					| Some ec ->
-						let ec = match fst ec with
-							| EBlock el -> (EBlock (el @ [ep]),p)
-							| _ -> (EBlock [ec;ep],p)
-						in
-						Some ec
-					| None ->
-						Some (mk_null p)
-				in
-				let rec loop cases = match cases with
-					| [el,eg,ec,p1] ->
-						let ec = match def with
-						| None when (pos e).pmax > !display_pos.pmin -> (* this is so we don't trigger if we're on the } *)
-							mark_case ec p1 (* no default, must be the last case *)
-						| Some (_,p2) when p1.pmax <= !display_pos.pmin && p2.pmin >= !display_pos.pmax ->
-							mark_case ec p1 (* default is beyond display position, mark *)
-						| _ ->
-							ec (* default contains display position, don't mark *)
-						in
-						[el,eg,ec,p1]
-					| (el1,eg1,ec1,p1) :: (el2,eg2,ec2,p2) :: cases ->
-						if p1.pmax <= !display_pos.pmin && p2.pmin >= !display_pos.pmax then
-							(el1,eg1,mark_case ec1 p1,p1) :: (el2,eg2,ec2,p2) :: cases
-						else
-							(el1,eg1,ec1,p1) :: loop ((el2,eg2,ec2,p2) :: cases)
-					| [] ->
-						[]
-				in
-				let cases = loop cases in
-				let def = if !did_mark then
-					def
-				else match def with
-					| Some(eo,p) when (pos e).pmax > !display_pos.pmin -> Some (mark_case eo p,p)
-					| _ -> def
-				in
-				ESwitch(e1,cases,def),pos e
-			| EDisplay _ ->
-				raise Exit
-			| EMeta((Meta.Markup,_,_),(EConst(String _),p)) when is_annotated p ->
-				annotate_marked e
-			| EConst (String (_,q)) when ((q <> SSingleQuotes) || !Parser.was_auto_triggered) && is_annotated (pos e) && is_completion ->
-				(* TODO: check if this makes any sense *)
-				raise Exit
-			| EConst(Regexp _) when is_annotated (pos e) && is_completion ->
-				raise Exit
-			| EVars vl when is_annotated (pos e) ->
-				(* We only want to mark EVars if we're on a var name. *)
-				if List.exists (fun v -> is_annotated (snd v.ev_name)) vl then
-					annotate_marked e
-				else
-					raise Exit
-			| _ ->
-				if is_annotated (pos e) then
-					annotate_marked e
-				else
-					e
-		in
-		let opt f o =
-			match o with None -> None | Some v -> Some (f v)
-		in
-		let rec map e = match fst e with
-			| ESwitch(e1,cases,def) when is_annotated (pos e) ->
-				let e1 = map e1 in
-				let cases = List.map (fun (el,eg,e,p) ->
-					let old = !in_pattern in
-					in_pattern := true;
-					let el = List.map map el in
-					in_pattern := old;
-					let eg = opt map eg in
-					let e = opt map e in
-					el,eg,e,p
-				) cases in
-				let def = opt (fun (eo,p) -> opt map eo,p) def in
-				loop (ESwitch (e1, cases, def),(pos e))
-			| _ ->
-				loop (Ast.map_expr map e)
-		in
-		try map e with Exit -> e
-
-	let find_display_call e =
-		let found = ref false in
-		let handle_el e el =
-			let call_arg_is_marked () =
-				el = [] || List.exists (fun (e,_) -> match e with EDisplay(_,DKMarked) -> true | _ -> false) el
-			in
-			if not !Parser.was_auto_triggered || call_arg_is_marked () then begin
-			found := true;
-			Parser.mk_display_expr e DKCall
-			end else
-				e
-		in
-		let loop e = match fst e with
-			| ECall(_,el) | ENew(_,el) when not !found && display_position#enclosed_in (pos e) ->
-				handle_el e el
-			| EArray(e1,e2) when not !found && display_position#enclosed_in (pos e2) ->
-				handle_el e [e2]
-			| EDisplay(_,DKCall) ->
-				raise Exit
-			| _ -> e
-		in
-		let rec map e = loop (Ast.map_expr map e) in
-		try map e with Exit -> e
-
-
-	let process_expr com e = match com.display.dms_kind with
-		| DMDefinition | DMTypeDefinition | DMUsage _ | DMImplementation | DMHover | DMDefault -> find_before_pos com.display.dms_kind e
-		| DMSignature -> find_display_call e
-		| _ -> e
-end
+let preprocess_expr com e = match com.display.dms_kind with
+	| DMDefinition | DMTypeDefinition | DMUsage _ | DMImplementation | DMHover | DMDefault -> ExprPreprocessing.find_before_pos com.display.dms_kind e
+	| DMSignature -> ExprPreprocessing.find_display_call e
+	| _ -> e
 
 let get_expected_name with_type = match with_type with
 	| WithType.Value (Some src) | WithType.WithType(_,Some src) ->

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

@@ -168,7 +168,7 @@ let check_display_metadata ctx meta =
 		if display_position#enclosed_in p then display_meta ctx.com meta p;
 		List.iter (fun e ->
 			if display_position#enclosed_in (pos e) then begin
-				let e = ExprPreprocessing.process_expr ctx.com e in
+				let e = preprocess_expr ctx.com e in
 				delay ctx PTypeField (fun _ -> ignore(type_expr ctx e WithType.value));
 			end
 		) args

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

@@ -56,10 +56,11 @@ let collect_static_extensions ctx items e p =
 		| TFun((_,_,t) :: args, ret) ->
 			begin try
 				let e = TyperBase.unify_static_extension ctx {e with etype = dup e.etype} t p in
-				List.iter2 (fun m tp -> match follow tp.ttp_type with
-					| TInst ({ cl_kind = KTypeParameter constr },_) when constr <> [] ->
+				List.iter2 (fun m ttp -> match get_constraints ttp with
+					| [] ->
+						()
+					| constr ->
 						List.iter (fun tc -> unify_raise m (map tc) e.epos) constr
-					| _ -> ()
 				) monos f.cf_params;
 				if not (can_access ctx c f true) || follow e.etype == t_dynamic && follow t != t_dynamic then
 					acc
@@ -157,9 +158,9 @@ let collect ctx e_ast e dk with_type p =
 				List.fold_left fold_constraints items l
 			in
 			fold_constraints items (Monomorph.classify_down_constraints m)
-		| TInst ({cl_kind = KTypeParameter tl},_) ->
+		| TInst ({cl_kind = KTypeParameter ttp},_) ->
 			(* Type parameters can access the fields of their constraints *)
-			List.fold_left (fun acc t -> loop acc t) items tl
+			List.fold_left (fun acc t -> loop acc t) items (get_constraints ttp)
 		| TInst(c0,tl) ->
 			(* For classes, browse the hierarchy *)
 			let fields = TClass.get_all_fields c0 tl in

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

@@ -378,7 +378,7 @@ let handler =
 			let file = hctx.jsonrpc#get_string_param "file" in
 			let fkey = hctx.com.file_keys#get file in
 			let cs = hctx.display#get_cs in
-			cs#taint_modules fkey "server/invalidate";
+			cs#taint_modules fkey ServerInvalidate;
 			cs#remove_files fkey;
 			hctx.send_result jnull
 		);

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

@@ -178,7 +178,7 @@ let check_display_file ctx cs =
 			let fkey = DisplayPosition.display_position#get_file_key in
 			(* force parsing again : if the completion point have been changed *)
 			cs#remove_files fkey;
-			cs#taint_modules fkey "check_display_file";
+			cs#taint_modules fkey CheckDisplayFile;
 		end
 	| None ->
 		()

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

@@ -449,10 +449,8 @@ let collect ctx tk with_type sort =
 	end;
 
 	(* type params *)
-	List.iter (fun tp -> match follow tp.ttp_type with
-		| TInst(c,_) ->
-			add (make_ci_type_param c (tpair tp.ttp_type)) (Some (snd c.cl_path))
-		| _ -> die "" __LOC__
+	List.iter (fun tp ->
+		add (make_ci_type_param tp.ttp_class (tpair tp.ttp_type)) (Some (snd tp.ttp_class.cl_path))
 	) ctx.type_params;
 
 	(* module types *)

+ 224 - 0
src/context/display/exprPreprocessing.ml

@@ -0,0 +1,224 @@
+open Globals
+open Ast
+open DisplayTypes.DisplayMode
+open DisplayPosition
+
+let find_before_pos dm e =
+	let display_pos = ref (DisplayPosition.display_position#get) in
+	let was_annotated = ref false in
+	let is_annotated,is_completion = match dm with
+		| DMDefault -> (fun p -> not !was_annotated && encloses_position !display_pos p),true
+		| DMHover -> (fun p -> not !was_annotated && encloses_position_gt !display_pos p),false
+		| _ -> (fun p -> not !was_annotated && encloses_position !display_pos p),false
+	in
+	let annotate e dk =
+		was_annotated := true;
+		(EDisplay(e,dk),pos e)
+	in
+	let annotate_marked e = annotate e DKMarked in
+	let mk_null p = annotate_marked ((EConst(Ident "null")),p) in
+	let loop_el el =
+		let pr = DisplayPosition.display_position#with_pos (pos e) in
+		let rec loop el = match el with
+			| [] -> [mk_null pr]
+			| e :: el ->
+				if (pos e).pmin >= pr.pmax then (mk_null pr) :: e :: el
+				else e :: loop el
+		in
+		(* print_endline (Printf.sprintf "%i-%i: PR" pr.pmin pr.pmax);
+		List.iter (fun e ->
+			print_endline (Printf.sprintf "%i-%i: %s" (pos e).pmin (pos e).pmax (Ast.s_expr e));
+		) el; *)
+		match el with
+		| [] -> [mk_null pr]
+		| e :: el ->
+			if (pos e).pmin >= pr.pmax then (mk_null pr) :: e :: el
+			else loop (e :: el)
+	in
+	let in_pattern = ref false in
+	let loop e =
+		(* print_endline (Printf.sprintf "%i-%i: %s" (pos e).pmin (pos e).pmax (Ast.s_expr e)); *)
+		match fst e with
+		| EFunction(FKNamed((_,p),_),_) when is_annotated p && is_completion ->
+			raise Exit
+		| EVars vl when is_annotated (pos e) && is_completion ->
+			let rec loop2 acc mark vl = match vl with
+				| v :: vl ->
+					if mark then
+						loop2 (v :: acc) mark vl
+					else if is_annotated (snd v.ev_name) then
+						(* If the name is the display position, mark the expression *)
+						loop2 (v :: acc) true vl
+					else begin match v.ev_expr with
+						| None ->
+							(* If there is no expression, we don't have to do anything.
+							   Should the display position be on the type-hint, it will
+							   be picked up while loading the type. *)
+							loop2 (v :: acc) mark vl
+						| Some e ->
+							(* Determine the area between the `|` in `var x| = | e`. This is not really
+							   correct because we don't want completion on the left side of the `=`, but
+							   we cannot determine that correctly without knowing its position.
+							   Note: We know `e` itself isn't the display position because this entire
+							   algorithm is bottom-up and it would be marked already if it was. *)
+							let p0 = match v.ev_type with
+								| Some (_,pt) -> pt
+								| None -> snd v.ev_name
+							in
+							let p = {p0 with pmax = (pos e).pmin} in
+							let e = if is_annotated p then annotate_marked e else e in
+							loop2 ({ v with ev_expr = Some e } :: acc) mark vl
+					end
+				| [] ->
+					List.rev acc,mark
+			in
+			let vl,mark = loop2 [] false vl in
+			let e = EVars (List.rev vl),pos e in
+			if !was_annotated then e else raise Exit
+		| EBinop((OpAssign | OpAssignOp _) as op,e1,e2) when is_annotated (pos e) && is_completion ->
+			(* Special case for assign ops: If the expression is marked, but none of its operands are,
+			   we are "probably" interested in the rhs. Like with EVars, this isn't accurate because we
+			   could be on the left side of the `=`. I don't think there's a reason for requesting
+			   completion there though. *)
+			(EBinop(op,e1,annotate_marked e2)),(pos e)
+		| EBinop(OpOr,e1,(EIf(_,(EConst(Ident "null"),_),None),p1)) when is_annotated (pos e) && is_completion && !in_pattern ->
+			(* This HAS TO come from an attempted `case pattern | guard:` completion (issue #7068). *)
+			let p = { p1 with pmin = (pos e1).pmax; pmax = p1.pmin } in
+			EBinop(OpOr,e1,mk_null p),(pos e)
+		| EIf(_,(EConst(Ident "null"),_),None) when is_completion && !in_pattern ->
+			(* This is fine. *)
+			mk_null (pos e)
+		| EBlock [] when is_annotated (pos e) ->
+			annotate e DKStructure
+		| EBlock [EDisplay((EConst(Ident s),pn),DKMarked),_] when is_completion ->
+			let e = EObjectDecl [(s,pn,NoQuotes),(EConst (Ident "null"),null_pos)],(pos e) in
+			annotate e DKStructure
+		| EBlock el when is_annotated (pos e) && is_completion ->
+			let el = loop_el el in
+			EBlock el,(pos e)
+		| ECall(e1,el) when is_annotated (pos e) && is_completion ->
+			let el = loop_el el in
+			ECall(e1,el),(pos e)
+		| ENew(ptp,el) when is_annotated (pos e) && is_completion ->
+			if is_annotated ptp.pos_full || ptp.pos_full.pmax >= (DisplayPosition.display_position#get).pmax then
+				annotate_marked e
+			else begin
+				let el = loop_el el in
+				ENew(ptp,el),(pos e)
+			end
+		| EArrayDecl el when is_annotated (pos e) && is_completion ->
+			let el = loop_el el in
+			EArrayDecl el,(pos e)
+		| EObjectDecl fl when is_annotated (pos e) && is_completion ->
+			annotate e DKStructure
+		| ESwitch(e1,cases,def) when is_annotated (pos e) ->
+			(* We must be "between" two cases, or at the end of the last case.
+			   Let's find the last case which has a position that is < the display
+			   position and mark it. *)
+			let did_mark = ref false in
+			let mark_case ec p =
+				did_mark := true;
+				let ep = mk_null p in
+				match ec with
+				| Some ec ->
+					let ec = match fst ec with
+						| EBlock el -> (EBlock (el @ [ep]),p)
+						| _ -> (EBlock [ec;ep],p)
+					in
+					Some ec
+				| None ->
+					Some (mk_null p)
+			in
+			let rec loop cases = match cases with
+				| [el,eg,ec,p1] ->
+					let ec = match def with
+					| None when (pos e).pmax > !display_pos.pmin -> (* this is so we don't trigger if we're on the } *)
+						mark_case ec p1 (* no default, must be the last case *)
+					| Some (_,p2) when p1.pmax <= !display_pos.pmin && p2.pmin >= !display_pos.pmax ->
+						mark_case ec p1 (* default is beyond display position, mark *)
+					| _ ->
+						ec (* default contains display position, don't mark *)
+					in
+					[el,eg,ec,p1]
+				| (el1,eg1,ec1,p1) :: (el2,eg2,ec2,p2) :: cases ->
+					if p1.pmax <= !display_pos.pmin && p2.pmin >= !display_pos.pmax then
+						(el1,eg1,mark_case ec1 p1,p1) :: (el2,eg2,ec2,p2) :: cases
+					else
+						(el1,eg1,ec1,p1) :: loop ((el2,eg2,ec2,p2) :: cases)
+				| [] ->
+					[]
+			in
+			let cases = loop cases in
+			let def = if !did_mark then
+				def
+			else match def with
+				| Some(eo,p) when (pos e).pmax > !display_pos.pmin -> Some (mark_case eo p,p)
+				| _ -> def
+			in
+			ESwitch(e1,cases,def),pos e
+		| EDisplay _ ->
+			raise Exit
+		| EMeta((Meta.Markup,_,_),(EConst(String _),p)) when is_annotated p ->
+			annotate_marked e
+		| EConst (String (_,q)) when ((q <> SSingleQuotes) || !Parser.was_auto_triggered) && is_annotated (pos e) && is_completion ->
+			(* TODO: check if this makes any sense *)
+			raise Exit
+		| EConst(Regexp _) when is_annotated (pos e) && is_completion ->
+			raise Exit
+		| EVars vl when is_annotated (pos e) ->
+			(* We only want to mark EVars if we're on a var name. *)
+			if List.exists (fun v -> is_annotated (snd v.ev_name)) vl then
+				annotate_marked e
+			else
+				raise Exit
+		| _ ->
+			if is_annotated (pos e) then
+				annotate_marked e
+			else
+				e
+	in
+	let opt f o =
+		match o with None -> None | Some v -> Some (f v)
+	in
+	let rec map e = match fst e with
+		| ESwitch(e1,cases,def) when is_annotated (pos e) ->
+			let e1 = map e1 in
+			let cases = List.map (fun (el,eg,e,p) ->
+				let old = !in_pattern in
+				in_pattern := true;
+				let el = List.map map el in
+				in_pattern := old;
+				let eg = opt map eg in
+				let e = opt map e in
+				el,eg,e,p
+			) cases in
+			let def = opt (fun (eo,p) -> opt map eo,p) def in
+			loop (ESwitch (e1, cases, def),(pos e))
+		| _ ->
+			loop (Ast.map_expr map e)
+	in
+	try map e with Exit -> e
+
+let find_display_call e =
+	let found = ref false in
+	let handle_el e el =
+		let call_arg_is_marked () =
+			el = [] || List.exists (fun (e,_) -> match e with EDisplay(_,DKMarked) -> true | _ -> false) el
+		in
+		if not !Parser.was_auto_triggered || call_arg_is_marked () then begin
+		found := true;
+		Parser.mk_display_expr e DKCall
+		end else
+			e
+	in
+	let loop e = match fst e with
+		| ECall(_,el) | ENew(_,el) when not !found && display_position#enclosed_in (pos e) ->
+			handle_el e el
+		| EArray(e1,e2) when not !found && display_position#enclosed_in (pos e2) ->
+			handle_el e [e2]
+		| EDisplay(_,DKCall) ->
+			raise Exit
+		| _ -> e
+	in
+	let rec map e = loop (Ast.map_expr map e) in
+	try map e with Exit -> e

+ 11 - 0
src/context/feature.ml

@@ -0,0 +1,11 @@
+open Ast
+open Type
+open Error
+
+let rec check_if_feature = function
+	| [] -> []
+	| (Meta.IfFeature,el,_) :: _ -> List.map (fun (e,p) -> match e with EConst (String(s,_)) -> s | _ -> raise_typing_error "String expected" p) el
+	| _ :: l -> check_if_feature l
+
+let set_feature m cf_ref s =
+	m.m_extra.m_if_feature <- (s, cf_ref) :: m.m_extra.m_if_feature

+ 98 - 0
src/context/formatString.ml

@@ -0,0 +1,98 @@
+open Globals
+open Ast
+
+let format_string defines s p process_expr =
+	let e = ref None in
+	let pmin = ref p.pmin in
+	let min = ref (p.pmin + 1) in
+	let add_expr (enext,p) len =
+		min := !min + len;
+		let enext = process_expr enext p in
+		match !e with
+		| None -> e := Some enext
+		| Some prev ->
+			e := Some (EBinop (OpAdd,prev,enext),punion (pos prev) p)
+	in
+	let add enext len =
+		let p = { p with pmin = !min; pmax = !min + len } in
+		add_expr (enext,p) len
+	in
+	let add_sub start pos =
+		let len = pos - start in
+		if len > 0 || !e = None then add (EConst (String (String.sub s start len,SDoubleQuotes))) len
+	in
+	let len = String.length s in
+	let rec parse start pos =
+		if pos = len then add_sub start pos else
+		let c = String.unsafe_get s pos in
+		let pos = pos + 1 in
+		if c = '\'' then begin
+			incr pmin;
+			incr min;
+		end;
+		if c <> '$' || pos = len then parse start pos else
+		match String.unsafe_get s pos with
+		| '$' ->
+			(* double $ *)
+			add_sub start pos;
+			parse (pos + 1) (pos + 1)
+		| '{' ->
+			parse_group start pos '{' '}' "brace"
+		| 'a'..'z' | 'A'..'Z' | '_' ->
+			add_sub start (pos - 1);
+			incr min;
+			let rec loop i =
+				if i = len then i else
+				let c = String.unsafe_get s i in
+				match c with
+				| 'a'..'z' | 'A'..'Z' | '0'..'9' | '_' -> loop (i+1)
+				| _ -> i
+			in
+			let iend = loop (pos + 1) in
+			let len = iend - pos in
+			add (EConst (Ident (String.sub s pos len))) len;
+			parse (pos + len) (pos + len)
+		| _ ->
+			(* keep as-it *)
+			parse start pos
+	and parse_group start pos gopen gclose gname =
+		add_sub start (pos - 1);
+		let rec loop groups i =
+			if i = len then
+				match groups with
+				| [] -> die "" __LOC__
+				| g :: _ -> Error.raise_typing_error ("Unclosed " ^ gname) { p with pmin = !pmin + g + 1; pmax = !pmin + g + 2 }
+			else
+				let c = String.unsafe_get s i in
+				if c = gopen then
+					loop (i :: groups) (i + 1)
+				else if c = gclose then begin
+					let groups = List.tl groups in
+					if groups = [] then i else loop groups (i + 1)
+				end else
+					loop groups (i + 1)
+		in
+		let send = loop [pos] (pos + 1) in
+		let slen = send - pos - 1 in
+		let scode = String.sub s (pos + 1) slen in
+		min := !min + 2;
+		begin
+			let e =
+				let ep = { p with pmin = !pmin + pos + 2; pmax = !pmin + send + 1 } in
+				let error msg pos =
+					if Lexer.string_is_whitespace scode then Error.raise_typing_error "Expression cannot be empty" ep
+					else Error.raise_typing_error msg pos
+				in
+				match ParserEntry.parse_expr_string defines scode ep error true with
+					| ParseSuccess(data,_,_) -> data
+					| ParseError(_,(msg,p),_) -> error (Parser.error_msg msg) p
+			in
+			add_expr e slen
+		end;
+		min := !min + 1;
+		parse (send + 1) (send + 1)
+	in
+	parse 0 0;
+	match !e with
+	| None -> die "" __LOC__
+	| Some e -> e

+ 113 - 0
src/context/lookup.ml

@@ -0,0 +1,113 @@
+
+class virtual ['key,'value] lookup = object(self)
+	method virtual add : 'key -> 'value -> unit
+	method virtual remove : 'key -> unit
+	method virtual find : 'key -> 'value
+	method virtual iter : ('key -> 'value -> unit) -> unit
+	method virtual fold : 'acc . ('key -> 'value -> 'acc -> 'acc) -> 'acc -> 'acc
+	method virtual mem : 'key -> bool
+	method virtual clear : unit
+
+	method virtual start_group : int
+	method virtual commit_group : int -> int
+	method virtual discard_group : int -> int
+end
+
+class ['key,'value] pmap_lookup = object(self)
+	inherit ['key,'value] lookup
+	val mutable lut : ('key,'value) PMap.t = PMap.empty
+
+	val mutable group_id : int ref = ref 0
+	val mutable groups : (int,'key list) PMap.t = PMap.empty
+
+	method add (key : 'key) (value : 'value) =
+		groups <- PMap.map (fun modules -> key :: modules) groups;
+		lut <- PMap.add key value lut
+
+	method remove (key : 'key) =
+		lut <- PMap.remove key lut
+
+	method find (key : 'key) : 'value =
+		PMap.find key lut
+
+	method iter (f : 'key -> 'value -> unit) =
+		PMap.iter f lut
+
+	method fold : 'acc . ('key -> 'value -> 'acc -> 'acc) -> 'acc -> 'acc = fun f acc ->
+		PMap.foldi f lut acc
+
+	method mem (key : 'key) =
+		PMap.mem key lut
+
+	method clear =
+		lut <- PMap.empty
+
+	method start_group =
+		incr group_id;
+		let i = !group_id in
+		groups <- PMap.add i [] groups;
+		i
+
+	method commit_group i =
+		let group = PMap.find i groups in
+		let n = List.length group in
+		groups <- PMap.remove i groups;
+		n
+
+	method discard_group i =
+		let group = PMap.find i groups in
+		let n = List.length group in
+		List.iter (fun mpath -> self#remove mpath) group;
+		groups <- PMap.remove i groups;
+		n
+end
+
+class ['key,'value] hashtbl_lookup = object(self)
+	inherit ['key,'value] lookup
+	val lut : ('key,'value) Hashtbl.t = Hashtbl.create 0
+
+	val mutable group_id : int ref = ref 0
+	val mutable groups : (int,'key list) Hashtbl.t = Hashtbl.create 0
+
+	method add (key : 'key) (value : 'value) =
+		Hashtbl.iter (fun i modules -> Hashtbl.replace groups i (key :: modules)) groups;
+		Hashtbl.replace lut key value
+
+	method remove (key : 'key) =
+		Hashtbl.remove lut key
+
+	method find (key : 'key) : 'value =
+		Hashtbl.find lut key
+
+	method iter (f : 'key -> 'value -> unit) =
+		Hashtbl.iter f lut
+
+	method fold : 'acc . ('key -> 'value -> 'acc -> 'acc) -> 'acc -> 'acc = fun f acc ->
+		Hashtbl.fold f lut acc
+
+	method mem (key : 'key) =
+		Hashtbl.mem lut key
+
+	method clear =
+		Hashtbl.clear lut
+
+	method start_group =
+		incr group_id;
+		let i = !group_id in
+		Hashtbl.replace groups i [];
+		i
+
+	method commit_group i =
+		let group = Hashtbl.find groups i in
+		let n = List.length group in
+		Hashtbl.remove groups i;
+		n
+
+	method discard_group i =
+		let group = Hashtbl.find groups i in
+		let n = List.length group in
+		List.iter (fun mpath -> self#remove mpath) group;
+		Hashtbl.remove groups i;
+		n
+end
+

+ 2 - 2
src/context/memory.ml

@@ -122,8 +122,8 @@ let get_memory_json (cs : CompilationCache.t) mreq =
 				"nativeLibCache",jint (mem_size cache_mem.(3));
 				"additionalSizes",jarray [
 					jobject ["name",jstring "macro interpreter";"size",jint (mem_size (MacroContext.macro_interp_cache))];
-					jobject ["name",jstring "macro stdlib";"size",jint (mem_size (EvalContext.GlobalState.stdlib))];
-					jobject ["name",jstring "macro macro_lib";"size",jint (mem_size (EvalContext.GlobalState.macro_lib))];
+					(* jobject ["name",jstring "macro stdlib";"size",jint (mem_size (EvalContext.GlobalState.stdlib))];
+					jobject ["name",jstring "macro macro_lib";"size",jint (mem_size (EvalContext.GlobalState.macro_lib))]; *)
 					jobject ["name",jstring "last completion result";"size",jint (mem_size (DisplayException.last_completion_result))];
 					jobject ["name",jstring "Lexer file cache";"size",jint (mem_size (Lexer.all_files))];
 					jobject ["name",jstring "GC heap words";"size",jint (int_of_float size)];

+ 14 - 48
src/context/typecore.ml

@@ -20,9 +20,11 @@
 open Globals
 open Ast
 open Common
+open Lookup
 open Type
 open Error
 open Resolution
+open FieldCallCandidate
 
 type type_patch = {
 	mutable tp_type : complex_type option;
@@ -98,7 +100,8 @@ type typer_globals = {
 	retain_meta : bool;
 	mutable core_api : typer option;
 	mutable macros : ((unit -> unit) * typer) option;
-	mutable std : module_def;
+	mutable std : tclass;
+	mutable std_types : module_def;
 	type_patches : (path, (string * bool, type_patch) Hashtbl.t * type_patch) Hashtbl.t;
 	mutable module_check_policies : (string list * module_check_policy list * bool) list;
 	mutable global_using : (tclass * pos) list;
@@ -162,24 +165,6 @@ and monomorphs = {
 	mutable perfunction : (tmono * pos) list;
 }
 
-(* This record holds transient information about an (attempted) call on a field. It is created when resolving
-   field calls and is passed to overload filters. *)
-type 'a field_call_candidate = {
-	(* The argument expressions for this call and whether or not the argument is optional on the
-	   target function. *)
-	fc_args  : texpr list;
-	(* The applied return type. *)
-	fc_ret   : Type.t;
-	(* The applied function type. *)
-	fc_type  : Type.t;
-	(* The class field being called. *)
-	fc_field : tclass_field;
-	(* The field monomorphs that were created for this call. *)
-	fc_monos : Type.t list;
-	(* The custom data associated with this call. *)
-	fc_data  : 'a;
-}
-
 type field_host =
 	| FHStatic of tclass
 	| FHInstance of tclass * tparams
@@ -256,7 +241,11 @@ let pass_name = function
 
 let warning ?(depth=0) ctx w msg p =
 	let options = (Warning.from_meta ctx.curclass.cl_meta) @ (Warning.from_meta ctx.curfield.cf_meta) in
-	ctx.com.warning ~depth w options msg p
+	match Warning.get_mode w options with
+	| WMEnable ->
+		module_warning ctx.com ctx.m.curmod w options msg p
+	| WMDisable ->
+		()
 
 let make_call ctx e el t p = (!make_call_ref) ctx e el t p
 
@@ -273,12 +262,8 @@ let spawn_monomorph' ctx p =
 let spawn_monomorph ctx p =
 	TMono (spawn_monomorph' ctx p)
 
-let make_static_this c p =
-	let ta = mk_anon ~fields:c.cl_statics (ref (ClassStatics c)) in
-	mk (TTypeExpr (TClassDecl c)) ta p
-
 let make_static_field_access c cf t p =
-	let ethis = make_static_this c p in
+	let ethis = Texpr.Builder.make_static_this c p in
 	mk (TField (ethis,(FStatic (c,cf)))) t p
 
 let make_static_call ctx c cf map args t p =
@@ -495,7 +480,7 @@ let create_fake_module ctx file =
 			m_path = (["$DEP"],file);
 			m_types = [];
 			m_statics = None;
-			m_extra = module_extra file (Define.get_signature ctx.com.defines) (file_time file) MFake [];
+			m_extra = module_extra file (Define.get_signature ctx.com.defines) (file_time file) MFake ctx.com.compilation_step [];
 		} in
 		Hashtbl.add fake_modules key mdep;
 		mdep
@@ -616,8 +601,8 @@ let can_access ctx c cf stat =
 	loop c
 	(* access is also allowed of we access a type parameter which is constrained to our (base) class *)
 	|| (match c.cl_kind with
-		| KTypeParameter tl ->
-			List.exists (fun t -> match follow t with TInst(c,_) -> loop c | _ -> false) tl
+		| KTypeParameter ttp ->
+			List.exists (fun t -> match follow t with TInst(c,_) -> loop c | _ -> false) (get_constraints ttp)
 		| _ -> false)
 	|| (Meta.has Meta.PrivateAccess ctx.meta)
 
@@ -698,26 +683,6 @@ let safe_mono_close ctx m p =
 		Unify_error l ->
 			raise_or_display ctx l p
 
-let make_field_call_candidate args ret monos t cf data = {
-	fc_args  = args;
-	fc_type  = t;
-	fc_field = cf;
-	fc_data  = data;
-	fc_ret   = ret;
-	fc_monos = monos;
-}
-
-let s_field_call_candidate fcc =
-	let pctx = print_context() in
-	let se = s_expr_pretty false "" false (s_type pctx) in
-	let sl_args = List.map se fcc.fc_args in
-	Printer.s_record_fields "" [
-		"fc_args",String.concat ", " sl_args;
-		"fc_type",s_type pctx fcc.fc_type;
-		"fc_field",Printf.sprintf "%s: %s" fcc.fc_field.cf_name (s_type pctx fcc.fc_field.cf_type)
-	]
-
-
 let relative_path ctx file =
 	let slashes path = String.concat "/" (ExtString.String.nsplit path "\\") in
 	let fpath = slashes (Path.get_full_path file) in
@@ -790,6 +755,7 @@ let create_deprecation_context ctx = {
 	(DeprecationCheck.create_context ctx.com) with
 	class_meta = ctx.curclass.cl_meta;
 	field_meta = ctx.curfield.cf_meta;
+	curmod = ctx.m.curmod;
 }
 
 (* -------------- debug functions to activate when debugging typer passes ------------------------------- *)

+ 13 - 0
src/core/ast.ml

@@ -863,6 +863,19 @@ let iter_expr loop (e,p) =
 		opt f.f_expr
 	| EVars vl -> List.iter (fun v -> opt v.ev_expr) vl
 
+let exists check e =
+	let rec loop (e,p) =
+		if check e then
+			raise Exit
+		else
+			iter_expr loop (e,p)
+	in
+	try
+		loop e;
+		false
+	with Exit ->
+		true
+
 let s_object_key_name name =  function
 	| DoubleQuotes -> "\"" ^ StringHelper.s_escape name ^ "\""
 	| NoQuotes -> name

+ 6 - 8
src/core/display/completionItem.ml

@@ -223,16 +223,14 @@ module CompletionModuleType = struct
 		in
 		let is_extern,is_final,is_abstract,kind,ctor = ctor_info mt in
 		let infos = t_infos mt in
-		let convert_type_param tp = match follow tp.ttp_type with
-			| TInst(c,_) -> {
-				tp_name = tp.ttp_name,null_pos;
+		let convert_type_param ttp =
+			{
+				tp_name = ttp.ttp_name,null_pos;
 				tp_params = [];
 				tp_constraints = None; (* TODO? *)
 				tp_default = None; (* TODO? *)
-				tp_meta = c.cl_meta
+				tp_meta = ttp.ttp_class.cl_meta
 			}
-			| _ ->
-				die "" __LOC__
 		in
 		{
 			pack = fst infos.mt_path;
@@ -784,11 +782,11 @@ let to_json ctx index item =
 		| ITExpression e -> "Expression",generate_texpr ctx e
 		| ITTypeParameter c ->
 			begin match c.cl_kind with
-			| KTypeParameter tl ->
+			| KTypeParameter ttp ->
 				"TypeParameter",jobject [
 					"name",jstring (snd c.cl_path);
 					"meta",generate_metadata ctx c.cl_meta;
-					"constraints",jlist (generate_type ctx) tl;
+					"constraints",jlist (generate_type ctx) (get_constraints ttp);
 				]
 			| _ -> die "" __LOC__
 			end

+ 1 - 1
src/core/displayTypes.ml

@@ -352,4 +352,4 @@ type display_exception_kind =
 	| DisplayPositions of pos list
 	| DisplayFields of fields_result
 	| DisplayPackage of string list
-	| DisplayNoResult
+	| DisplayNoResult

+ 8 - 2
src/core/globals.ml

@@ -167,8 +167,14 @@ let die ?p msg ml_loc =
 	in
 	let ver = s_version_full
 	and os_type = if Sys.unix then "unix" else "windows" in
-	Printf.eprintf "%s\nHaxe: %s; OS type: %s;\n%s\n%s" msg ver os_type ml_loc backtrace;
-	assert false
+	let s = Printf.sprintf "%s\nHaxe: %s; OS type: %s;\n%s\n%s" msg ver os_type ml_loc backtrace in
+	failwith s
+
+let dump_callstack () =
+	print_endline (Printexc.raw_backtrace_to_string (Printexc.get_callstack 200))
+
+let dump_backtrace () =
+	print_endline (Printexc.raw_backtrace_to_string (Printexc.get_raw_backtrace ()))
 
 module MessageSeverity = struct
 	type t =

+ 5 - 9
src/core/json/genjson.ml

@@ -276,15 +276,11 @@ and generate_type_path_with_params ctx mpath tpath tl meta =
 
 (* type parameter *)
 
-and generate_type_parameter ctx tp =
-	let generate_constraints () = match follow tp.ttp_type with
-		| TInst({cl_kind = KTypeParameter tl},_) -> generate_types ctx tl
-		| _ -> die "" __LOC__
-	in
+and generate_type_parameter ctx ttp =
 	jobject [
-		"name",jstring tp.ttp_name;
-		"constraints",generate_constraints ();
-		"defaultType",jopt (generate_type ctx) tp.ttp_default;
+		"name",jstring ttp.ttp_name;
+		"constraints",generate_types ctx (get_constraints ttp);
+		"defaultType",jopt (generate_type ctx) ttp.ttp_default;
 	]
 
 (* texpr *)
@@ -602,7 +598,7 @@ let generate_class ctx c =
 	let generate_class_kind ck =
 		let ctor,args = match ck with
 		| KNormal -> "KNormal",None
-		| KTypeParameter tl -> "KTypeParameter",Some (generate_types ctx tl)
+		| KTypeParameter ttp -> "KTypeParameter",Some (generate_types ctx (get_constraints ttp))
 		| KExpr e -> "KExpr",Some (generate_expr ctx e)
 		| KGeneric -> "KGeneric",None
 		| KGenericInstance(c,tl) -> "KGenericInstance",Some (generate_type_path_with_params ctx c.cl_module.m_path c.cl_path tl c.cl_meta)

+ 86 - 0
src/core/naming.ml

@@ -0,0 +1,86 @@
+open Globals
+open Ast
+open Type
+
+(** retrieve string from @:native metadata or raise Not_found *)
+let get_native_name meta =
+	let rec get_native meta = match meta with
+		| [] -> raise Not_found
+		| (Meta.Native,[v],p as meta) :: _ ->
+			meta
+		| _ :: meta ->
+			get_native meta
+	in
+	let (_,e,mp) = get_native meta in
+	match e with
+	| [Ast.EConst (Ast.String(name,_)),p] ->
+		name,p
+	| [] ->
+		raise Not_found
+	| _ ->
+		Error.raise_typing_error "String expected" mp
+
+(* Rewrites class or enum paths if @:native metadata is set *)
+let apply_native_paths t =
+	let get_real_name meta name =
+		let name',p = get_native_name meta in
+		(Meta.RealPath,[Ast.EConst (Ast.String (name,SDoubleQuotes)), p], p), name'
+	in
+	let get_real_path meta path =
+		let name,p = get_native_name meta in
+		(Meta.RealPath,[Ast.EConst (Ast.String (s_type_path path,SDoubleQuotes)), p], p), parse_path name
+	in
+	try
+		(match t with
+		| TClassDecl c ->
+			let did_change = ref false in
+			let field cf = try
+				let meta,name = get_real_name cf.cf_meta cf.cf_name in
+				cf.cf_name <- name;
+				cf.cf_meta <- meta :: cf.cf_meta;
+				List.iter (fun cf -> cf.cf_name <- name) cf.cf_overloads;
+				did_change := true
+			with Not_found ->
+				()
+			in
+			let fields cfs old_map =
+				did_change := false;
+				List.iter field cfs;
+				if !did_change then
+					List.fold_left (fun map f -> PMap.add f.cf_name f map) PMap.empty cfs
+				else
+					old_map
+			in
+			c.cl_fields <- fields c.cl_ordered_fields c.cl_fields;
+			c.cl_statics <- fields c.cl_ordered_statics c.cl_statics;
+			let meta,path = get_real_path c.cl_meta c.cl_path in
+			c.cl_meta <- meta :: c.cl_meta;
+			c.cl_path <- path;
+		| TEnumDecl e ->
+			let did_change = ref false in
+			let field _ ef = try
+				let meta,name = get_real_name ef.ef_meta ef.ef_name in
+				ef.ef_name <- name;
+				ef.ef_meta <- meta :: ef.ef_meta;
+				did_change := true;
+			with Not_found ->
+				()
+			in
+			PMap.iter field e.e_constrs;
+			if !did_change then begin
+				let names = ref [] in
+				e.e_constrs <- PMap.fold
+					(fun ef map ->
+						names := ef.ef_name :: !names;
+						PMap.add ef.ef_name ef map
+					)
+					e.e_constrs PMap.empty;
+				e.e_names <- !names;
+			end;
+			let meta,path = get_real_path e.e_meta e.e_path in
+			e.e_meta <- meta :: e.e_meta;
+			e.e_path <- path;
+		| _ ->
+			())
+	with Not_found ->
+		()

+ 12 - 1
src/core/socket.ml

@@ -37,6 +37,17 @@ let read_string socket =
 			let _ = recv socket buf 0 i [] in
 			Bytes.to_string buf
 
+let write_byte this i v =
+	Bytes.set this i (Char.unsafe_chr v)	
+
+let write_i32 this i v =
+	let base = Int32.to_int v in
+	let big = Int32.to_int (Int32.shift_right_logical v 24) in
+	write_byte this i base;
+	write_byte this (i + 1) (base lsr 8);
+	write_byte this (i + 2) (base lsr 16);
+	write_byte this (i + 3) big
+
 let send_string socket s =
 	match socket.socket with
 	| None ->
@@ -45,7 +56,7 @@ let send_string socket s =
 		let b = Bytes.unsafe_of_string s in
 		let l = Bytes.length b in
 		let buf = Bytes.make 4 ' ' in
-		EvalBytes.write_i32 buf 0 (Int32.of_int l);
+		write_i32 buf 0 (Int32.of_int l);
 		ignore(send socket buf 0 4 []);
 		let rec loop length offset =
 			if length <= 0 then

+ 117 - 21
src/core/tFunctions.ml

@@ -150,7 +150,7 @@ let mk_typedef m path pos name_pos t =
 		t_restore = (fun () -> ());
 	}
 
-let module_extra file sign time kind policy =
+let module_extra file sign time kind added policy =
 	{
 		m_file = Path.UniqueKey.create_lazy file;
 		m_sign = sign;
@@ -160,13 +160,13 @@ let module_extra file sign time kind policy =
 			m_import_positions = PMap.empty;
 		};
 		m_cache_state = MSGood;
-		m_added = 0;
+		m_added = added;
 		m_checked = 0;
 		m_time = time;
 		m_processed = 0;
 		m_deps = PMap.empty;
 		m_kind = kind;
-		m_binded_res = PMap.empty;
+		m_cache_bound_objects = DynArray.create ();
 		m_if_feature = [];
 		m_features = Hashtbl.create 0;
 		m_check_policy = policy;
@@ -198,20 +198,63 @@ let mk_field name ?(public = true) ?(static = false) t p name_pos = {
 	);
 }
 
+let find_field c name kind =
+	match kind with
+	| CfrConstructor ->
+		begin match c.cl_constructor with Some cf -> cf | None -> raise Not_found end
+	| CfrStatic ->
+		PMap.find name c.cl_statics
+	| CfrMember ->
+		PMap.find name c.cl_fields
+
 let null_module = {
-		m_id = alloc_mid();
-		m_path = [] , "";
-		m_types = [];
-		m_statics = None;
-		m_extra = module_extra "" "" 0. MFake [];
-	}
+	m_id = alloc_mid();
+	m_path = [] , "";
+	m_types = [];
+	m_statics = None;
+	m_extra = module_extra "" (Digest.string "") 0. MFake 0 [];
+}
 
 let null_class =
 	let c = mk_class null_module ([],"") null_pos null_pos in
 	c.cl_private <- true;
 	c
 
+let null_typedef =
+	let t = mk_typedef null_module ([],"") null_pos null_pos (TDynamic None) in
+	t.t_private <- true;
+	t
+
+let null_tanon = { a_fields = PMap.empty; a_status = ref Closed }
+
+let null_enum = {
+	e_path = ([],"");
+	e_module = null_module;
+	e_pos = null_pos;
+	e_name_pos = null_pos;
+	e_private = true;
+	e_doc = None;
+	e_meta = [];
+	e_params = [];
+	e_using = [];
+	e_restore = (fun () -> ());
+	e_type = t_dynamic;
+	e_extern = false;
+	e_constrs = PMap.empty;
+	e_names = [];
+}
+
 let null_field = mk_field "" t_dynamic null_pos null_pos
+let null_enum_field = {
+	ef_name = "";
+	ef_type = TEnum (null_enum, []);
+	ef_pos = null_pos;
+	ef_name_pos = null_pos;
+	ef_doc = None;
+	ef_index = 0;
+	ef_params = [];
+	ef_meta = [];
+}
 
 let null_abstract = {
 	a_path = ([],"");
@@ -373,15 +416,11 @@ let apply_params ?stack cparams params t =
 	let rec loop l1 l2 =
 		match l1, l2 with
 		| [] , [] -> []
-		| {ttp_type = TLazy f} as tp :: l1, _ -> loop ({tp with ttp_type = lazy_type f} :: l1) l2
-		| tp :: l1 , t2 :: l2 -> (tp.ttp_type,t2) :: loop l1 l2
+		| ttp :: l1 , t2 :: l2 -> (ttp.ttp_class,t2) :: loop l1 l2
 		| _ -> die "" __LOC__
 	in
 	let subst = loop cparams params in
 	let rec loop t =
-		try
-			List.assq t subst
-		with Not_found ->
 		match t with
 		| TMono r ->
 			(match r.tm_type with
@@ -444,6 +483,12 @@ let apply_params ?stack cparams params t =
 			(match tl with
 			| [] -> t
 			| _ -> TAbstract (a,List.map loop tl))
+		| TInst ({cl_kind = KTypeParameter _} as c,[]) ->
+			begin try
+				List.assq c subst
+			with Not_found ->
+				t
+			end
 		| TInst (c,tl) ->
 			(match tl with
 			| [] ->
@@ -516,6 +561,15 @@ let rec follow t =
 		follow t
 	| _ -> t
 
+let rec follow_lazy t =
+	match t with
+	| TLazy f ->
+		(match !f with
+		| LAvailable t -> follow_lazy t
+		| _ -> follow_lazy (lazy_type f)
+		)
+	| _ -> t
+
 let follow_once t =
 	match t with
 	| TMono r ->
@@ -553,6 +607,14 @@ let rec follow_without_type t =
 		follow_without_type t
 	| _ -> t
 
+let rec follow_lazy_and_mono t = match t with
+	| TMono {tm_type = Some t} ->
+		follow_lazy_and_mono t
+	| TLazy f ->
+		follow_lazy_and_mono (lazy_type f)
+	| _ ->
+		t
+
 let rec ambiguate_funs t =
 	match follow t with
 	| TFun _ -> TFun ([], t_dynamic)
@@ -653,9 +715,12 @@ let lookup_param n l =
 	in
 	loop l
 
-let mk_type_param n t def = {
-	ttp_name = n;
-	ttp_type = t;
+let mk_type_param c host def constraints = {
+	ttp_name = snd c.cl_path;
+	ttp_type = TInst(c,[]);
+	ttp_class = c;
+	ttp_host = host;
+	ttp_constraints = constraints;
 	ttp_default = def;
 }
 
@@ -687,13 +752,19 @@ let tconst_to_const = function
 	| TThis -> Ident "this"
 	| TSuper -> Ident "super"
 
+let get_constraints ttp = match ttp.ttp_constraints with
+	| None ->
+		[]
+	| Some r ->
+		Lazy.force r
+
 let has_ctor_constraint c = match c.cl_kind with
-	| KTypeParameter tl ->
+	| KTypeParameter ttp ->
 		List.exists (fun t -> match follow t with
 			| TAnon a when PMap.mem "new" a.a_fields -> true
 			| TAbstract({a_path=["haxe"],"Constructible"},_) -> true
 			| _ -> false
-		) tl;
+		) (get_constraints ttp);
 	| _ -> false
 
 (* ======= Field utility ======= *)
@@ -741,7 +812,7 @@ let rec raw_class_field build_type c tl i =
 			c2, apply_params c.cl_params tl t , f
 	with Not_found ->
 		match c.cl_kind with
-		| KTypeParameter tl ->
+		| KTypeParameter ttp ->
 			let rec loop = function
 				| [] ->
 					raise Not_found
@@ -762,7 +833,7 @@ let rec raw_class_field build_type c tl i =
 					| _ ->
 						loop ctl
 			in
-			loop tl
+			loop (get_constraints ttp)
 		| _ ->
 			if not (has_class_flag c CInterface) then raise Not_found;
 			(*
@@ -868,3 +939,28 @@ let var_extra params e = {
 	v_params = params;
 	v_expr = e;
 }
+
+let class_module_type c =
+	let path = ([],"Class<" ^ (s_type_path c.cl_path) ^ ">") in
+	let t = mk_anon ~fields:c.cl_statics (ref (ClassStatics c)) in
+	{ (mk_typedef c.cl_module path c.cl_pos null_pos t) with t_private = true}
+
+let enum_module_type en fields =
+	let path = ([], "Enum<" ^ (s_type_path en.e_path) ^ ">") in
+	let t = mk_anon ~fields (ref (EnumStatics en)) in
+	{(mk_typedef en.e_module path en.e_pos null_pos t) with t_private = true}
+
+let abstract_module_type a tl =
+	let path = ([],Printf.sprintf "Abstract<%s>" (s_type_path a.a_path)) in
+	let t = mk_anon (ref (AbstractStatics a)) in
+	{(mk_typedef a.a_module path a.a_pos null_pos t) with t_private = true}
+
+let class_field_of_enum_field ef = {
+	(mk_field ef.ef_name ef.ef_type ef.ef_pos ef.ef_name_pos) with
+	cf_kind = (match follow ef.ef_type with
+		| TFun _ -> Method MethNormal
+		| _ -> Var { v_read = AccNormal; v_write = AccNo }
+	);
+	cf_doc = ef.ef_doc;
+	cf_params = ef.ef_params;
+}

+ 88 - 14
src/core/tOther.ml

@@ -2,7 +2,6 @@ open Globals
 open Ast
 open TType
 open TFunctions
-open TPrinting
 
 module TExprToExpr = struct
 	let tpath path module_path params =
@@ -263,20 +262,95 @@ end
 
 let no_meta = []
 
-let class_module_type c =
-	let path = ([],"Class<" ^ (s_type_path c.cl_path) ^ ">") in
-	let t = mk_anon ~fields:c.cl_statics (ref (ClassStatics c)) in
-	{ (mk_typedef c.cl_module path c.cl_pos null_pos t) with t_private = true}
+let mk_enum m path pos name_pos =
+	{
+		e_path = path;
+		e_module = m;
+		e_pos = pos;
+		e_name_pos = name_pos;
+		e_doc = None;
+		e_meta = [];
+		e_params = [];
+		e_using = [];
+		e_restore = (fun () -> ());
+		e_private = false;
+		e_extern = false;
+		e_constrs = PMap.empty;
+		e_names = [];
+		e_type = mk_mono();
+	}
 
-let enum_module_type m path p  =
-	let path = ([], "Enum<" ^ (s_type_path path) ^ ">") in
-	let t = mk_mono() in
-	{(mk_typedef m path p null_pos t) with t_private = true}
+let mk_abstract m path pos name_pos =
+	{
+		a_path = path;
+		a_private = false;
+		a_module = m;
+		a_pos = pos;
+		a_name_pos = name_pos;
+		a_doc = None;
+		a_params = [];
+		a_using = [];
+		a_restore = (fun () -> ());
+		a_meta = [];
+		a_from = [];
+		a_to = [];
+		a_from_field = [];
+		a_to_field = [];
+		a_ops = [];
+		a_unops = [];
+		a_impl = None;
+		a_array = [];
+		a_this = mk_mono();
+		a_read = None;
+		a_write = None;
+		a_enum = false;
+		a_call = None;
+	}
 
-let abstract_module_type a tl =
-	let path = ([],Printf.sprintf "Abstract<%s%s>" (s_type_path a.a_path) (s_type_params (ref []) tl)) in
-	let t = mk_anon (ref (AbstractStatics a)) in
-	{(mk_typedef a.a_module path a.a_pos null_pos t) with t_private = true}
+let mk_enum m path pos name_pos =
+	{
+		e_path = path;
+		e_module = m;
+		e_pos = pos;
+		e_name_pos = name_pos;
+		e_doc = None;
+		e_meta = [];
+		e_params = [];
+		e_using = [];
+		e_restore = (fun () -> ());
+		e_private = false;
+		e_extern = false;
+		e_constrs = PMap.empty;
+		e_names = [];
+		e_type = mk_mono();
+	}
+
+let mk_abstract m path pos name_pos =
+	{
+		a_path = path;
+		a_private = false;
+		a_module = m;
+		a_pos = pos;
+		a_name_pos = name_pos;
+		a_doc = None;
+		a_params = [];
+		a_using = [];
+		a_restore = (fun () -> ());
+		a_meta = [];
+		a_from = [];
+		a_to = [];
+		a_from_field = [];
+		a_to_field = [];
+		a_ops = [];
+		a_unops = [];
+		a_impl = None;
+		a_array = [];
+		a_this = mk_mono();
+		a_read = None;
+		a_write = None;
+		a_enum = false;
+		a_call = None;
+	}
 
 module TClass = struct
 	let get_member_fields' self_too c0 tl =
@@ -345,4 +419,4 @@ let s_class_path c =
 		| KAbstractImpl a -> a.a_path
 		| _ -> c.cl_path
 	in
-	s_type_path path
+	s_type_path path

+ 49 - 27
src/core/tPrinting.ml

@@ -128,6 +128,18 @@ and s_constraint = function
 	| MOpenStructure -> "MOpenStructure"
 	| MEmptyStructure -> "MEmptyStructure"
 
+let s_type_param s_type ttp =
+	let s = match (get_constraints ttp) with
+		| [] -> ttp.ttp_name
+		| tl1 -> Printf.sprintf "%s:%s" ttp.ttp_name (String.concat " & " (List.map s_type tl1))
+	in
+	begin match ttp.ttp_default with
+	| None ->
+		s
+	| Some t ->
+		Printf.sprintf "%s = %s" s (s_type t)
+	end
+
 let s_access is_read = function
 	| AccNormal -> "default"
 	| AccNo -> "null"
@@ -380,8 +392,8 @@ let s_types ?(sep = ", ") tl =
 let s_class_kind = function
 	| KNormal ->
 		"KNormal"
-	| KTypeParameter tl ->
-		Printf.sprintf "KTypeParameter [%s]" (s_types tl)
+	| KTypeParameter ttp ->
+		Printf.sprintf "KTypeParameter [%s]" (s_types (get_constraints ttp))
 	| KExpr _ ->
 		"KExpr"
 	| KGeneric ->
@@ -441,27 +453,31 @@ module Printer = struct
 	let s_metadata metadata =
 		s_list " " s_metadata_entry metadata
 
-	let s_type_param tp = match follow tp.ttp_type with
-		| TInst({cl_kind = KTypeParameter tl1},tl2) ->
-			let s = match tl1 with
-				| [] -> tp.ttp_name
-				| _ -> Printf.sprintf "%s:%s" tp.ttp_name (String.concat " & " (List.map s_type tl1))
-			in
-			begin match tp.ttp_default with
-			| None ->
-				s
-			| Some t ->
-				Printf.sprintf "%s = %s" s (s_type t)
-			end
-		| _ -> die "" __LOC__
+	let s_ttp_host = function
+		| TPHType -> "TPHType"
+		| TPHConstructor -> "TPHConstructor"
+		| TPHMethod -> "TPHMethod"
+		| TPHEnumConstructor -> "TPHEnumConstructor"
+		| TPHAnonField -> "TPHAnonField"
+		| TPHLocal -> "TPHLocal"
 
-	let s_type_params tl =
-		s_list ", " s_type_param tl
+	let s_type_param tabs ttp =
+		s_record_fields tabs [
+			"name",ttp.ttp_name;
+			"class",s_type_path ttp.ttp_class.cl_path;
+			"host",s_ttp_host ttp.ttp_host;
+			"type",s_type_kind ttp.ttp_type;
+			"constraints",s_list ", " s_type_kind (get_constraints ttp)	;
+			"default",s_opt s_type_kind ttp.ttp_default;
+		]
+
+	let s_type_params tabs tl =
+		s_list ", " (s_type_param tabs) tl
 
 	let s_tclass_field_flags flags =
 		s_flags flags flag_tclass_field_names
 
-	let s_tclass_field tabs cf =
+	let rec s_tclass_field tabs cf =
 		s_record_fields tabs [
 			"cf_name",cf.cf_name;
 			"cf_doc",s_doc cf.cf_doc;
@@ -470,9 +486,10 @@ module Printer = struct
 			"cf_name_pos",s_pos cf.cf_name_pos;
 			"cf_meta",s_metadata cf.cf_meta;
 			"cf_kind",s_kind cf.cf_kind;
-			"cf_params",s_type_params cf.cf_params;
+			"cf_params",s_type_params (tabs ^ "\t") cf.cf_params;
 			"cf_expr",s_opt (s_expr_ast true "\t\t" s_type) cf.cf_expr;
 			"cf_flags",s_tclass_field_flags cf.cf_flags;
+			"cf_overloads",s_list "\n" (s_tclass_field (tabs ^ "\t")) cf.cf_overloads
 		]
 
 	let s_tclass tabs c =
@@ -484,7 +501,7 @@ module Printer = struct
 			"cl_private",string_of_bool c.cl_private;
 			"cl_doc",s_doc c.cl_doc;
 			"cl_meta",s_metadata c.cl_meta;
-			"cl_params",s_type_params c.cl_params;
+			"cl_params",s_type_params (tabs ^ "\t") c.cl_params;
 			"cl_kind",s_class_kind c.cl_kind;
 			"cl_super",s_opt (fun (c,tl) -> s_type (TInst(c,tl))) c.cl_super;
 			"cl_implements",s_list ", " (fun (c,tl) -> s_type (TInst(c,tl))) c.cl_implements;
@@ -504,7 +521,7 @@ module Printer = struct
 			"t_private",string_of_bool t.t_private;
 			"t_doc",s_doc t.t_doc;
 			"t_meta",s_metadata t.t_meta;
-			"t_params",s_type_params t.t_params;
+			"t_params",s_type_params (tabs ^ "\t") t.t_params;
 			"t_type",s_type_kind t.t_type
 		]
 
@@ -516,7 +533,7 @@ module Printer = struct
 			"ef_name_pos",s_pos ef.ef_name_pos;
 			"ef_type",s_type_kind ef.ef_type;
 			"ef_index",string_of_int ef.ef_index;
-			"ef_params",s_type_params ef.ef_params;
+			"ef_params",s_type_params (tabs ^ "\t") ef.ef_params;
 			"ef_meta",s_metadata ef.ef_meta
 		]
 
@@ -529,8 +546,8 @@ module Printer = struct
 			"e_private",string_of_bool en.e_private;
 			"d_doc",s_doc en.e_doc;
 			"e_meta",s_metadata en.e_meta;
-			"e_params",s_type_params en.e_params;
-			"e_type",s_tdef "\t" en.e_type;
+			"e_params",s_type_params (tabs ^ "\t") en.e_params;
+			"e_type",s_type_kind en.e_type;
 			"e_extern",string_of_bool en.e_extern;
 			"e_constrs",s_list "\n\t" (s_tenum_field (tabs ^ "\t")) (PMap.fold (fun ef acc -> ef :: acc) en.e_constrs []);
 			"e_names",String.concat ", " en.e_names
@@ -545,7 +562,7 @@ module Printer = struct
 			"a_private",string_of_bool a.a_private;
 			"a_doc",s_doc a.a_doc;
 			"a_meta",s_metadata a.a_meta;
-			"a_params",s_type_params a.a_params;
+			"a_params",s_type_params (tabs ^ "\t") a.a_params;
 			"a_ops",s_list ", " (fun (op,cf) -> Printf.sprintf "%s: %s" (s_binop op) cf.cf_name) a.a_ops;
 			"a_unops",s_list ", " (fun (op,flag,cf) -> Printf.sprintf "%s (%s): %s" (s_unop op) (if flag = Postfix then "postfix" else "prefix") cf.cf_name) a.a_unops;
 			"a_impl",s_opt (fun c -> s_type_path c.cl_path) a.a_impl;
@@ -560,7 +577,7 @@ module Printer = struct
 		]
 
 	let s_tvar_extra ve =
-		Printf.sprintf "Some(%s, %s)" (s_type_params ve.v_params) (s_opt (s_expr_ast true "" s_type) ve.v_expr)
+		Printf.sprintf "Some(%s, %s)" (s_type_params "" ve.v_params) (s_opt (s_expr_ast true "" s_type) ve.v_expr)
 
 	let s_tvar v =
 		s_record_fields "" [
@@ -594,11 +611,16 @@ module Printer = struct
 		| MExtern -> "MExtern"
 		| MImport -> "MImport"
 
+	let s_module_tainting_reason = function
+		| CheckDisplayFile -> "check_display_file"
+		| ServerInvalidate -> "server/invalidate"
+		| ServerInvalidateFiles -> "server_invalidate_files"
+
 	let s_module_skip_reason reason =
 		let rec loop stack = function
 			| DependencyDirty(path,reason) ->
 				(Printf.sprintf "%s%s - %s" (if stack = [] then "DependencyDirty " else "") (s_type_path path) (if List.mem path stack then "rec" else loop (path :: stack) reason))
-			| Tainted cause -> "Tainted " ^ cause
+			| Tainted cause -> "Tainted " ^ (s_module_tainting_reason cause)
 			| FileChanged file -> "FileChanged " ^ file
 			| Shadowed file -> "Shadowed " ^ file
 			| LibraryChanged -> "LibraryChanged"

+ 37 - 16
src/core/tType.ml

@@ -32,9 +32,14 @@ type module_check_policy =
 	| NoCheckShadowing
 	| Retype
 
+type module_tainting_reason =
+	| CheckDisplayFile
+	| ServerInvalidate
+	| ServerInvalidateFiles
+
 type module_skip_reason =
 	| DependencyDirty of path * module_skip_reason
-	| Tainted of string
+	| Tainted of module_tainting_reason
 	| FileChanged of string
 	| Shadowed of string
 	| LibraryChanged
@@ -44,6 +49,19 @@ type module_cache_state =
 	| MSBad of module_skip_reason
 	| MSUnknown
 
+type type_param_host =
+	| TPHType
+	| TPHConstructor
+	| TPHMethod
+	| TPHEnumConstructor
+	| TPHAnonField
+	| TPHLocal
+
+type cache_bound_object =
+	| Resource of string * string
+	| IncludeFile of string * string
+	| Warning of WarningList.warning * string * pos
+
 type t =
 	| TMono of tmono
 	| TEnum of tenum * tparams
@@ -92,8 +110,11 @@ and tparams = t list
 
 and typed_type_param = {
 	ttp_name : string;
-	ttp_type : t;
-	ttp_default : t option;
+	ttp_class : tclass;
+	ttp_host : type_param_host;
+	mutable ttp_type : t;
+	mutable ttp_constraints : t list Lazy.t option;
+	mutable ttp_default : t option;
 }
 
 and type_params = typed_type_param list
@@ -232,7 +253,7 @@ and tclass_field = {
 
 and tclass_kind =
 	| KNormal
-	| KTypeParameter of t list
+	| KTypeParameter of typed_type_param
 	| KExpr of Ast.expr
 	| KGeneric
 	| KGenericInstance of tclass * tparams
@@ -248,10 +269,10 @@ and tinfos = {
 	mt_module : module_def;
 	mt_pos : pos;
 	mt_name_pos : pos;
-	mt_private : bool;
-	mt_doc : Ast.documentation;
+	mutable mt_private : bool;
+	mutable mt_doc : Ast.documentation;
 	mutable mt_meta : metadata;
-	mt_params : type_params;
+	mutable mt_params : type_params;
 	mutable mt_using : (tclass * pos) list;
 	mutable mt_restore : unit -> unit;
 }
@@ -305,14 +326,14 @@ and tenum = {
 	e_module : module_def;
 	e_pos : pos;
 	e_name_pos : pos;
-	e_private : bool;
+	mutable e_private : bool;
 	mutable e_doc : Ast.documentation;
 	mutable e_meta : metadata;
 	mutable e_params : type_params;
 	mutable e_using : (tclass * pos) list;
 	mutable e_restore : unit -> unit;
 	(* do not insert any fields above *)
-	e_type : tdef;
+	mutable e_type : t;
 	mutable e_extern : bool;
 	mutable e_constrs : (string , tenum_field) PMap.t;
 	mutable e_names : string list;
@@ -323,8 +344,8 @@ and tdef = {
 	t_module : module_def;
 	t_pos : pos;
 	t_name_pos : pos;
-	t_private : bool;
-	t_doc : Ast.documentation;
+	mutable t_private : bool;
+	mutable t_doc : Ast.documentation;
 	mutable t_meta : metadata;
 	mutable t_params : type_params;
 	mutable t_using : (tclass * pos) list;
@@ -338,7 +359,7 @@ and tabstract = {
 	a_module : module_def;
 	a_pos : pos;
 	a_name_pos : pos;
-	a_private : bool;
+	mutable a_private : bool;
 	mutable a_doc : Ast.documentation;
 	mutable a_meta : metadata;
 	mutable a_params : type_params;
@@ -357,7 +378,7 @@ and tabstract = {
 	mutable a_read : tclass_field option;
 	mutable a_write : tclass_field option;
 	mutable a_call : tclass_field option;
-	a_enum : bool;
+	mutable a_enum : bool;
 }
 
 and module_type =
@@ -382,7 +403,7 @@ and module_def_display = {
 
 and module_def_extra = {
 	m_file : Path.UniqueKey.lazy_t;
-	m_sign : string;
+	m_sign : Digest.t;
 	m_display : module_def_display;
 	mutable m_check_policy : module_check_policy list;
 	mutable m_time : float;
@@ -390,9 +411,9 @@ and module_def_extra = {
 	mutable m_added : int;
 	mutable m_checked : int;
 	mutable m_processed : int;
-	mutable m_deps : (int,(string (* sign *) * path)) PMap.t;
+	mutable m_deps : (int,(Digest.t (* sign *) * path)) PMap.t;
 	mutable m_kind : module_kind;
-	mutable m_binded_res : (string, string) PMap.t;
+	mutable m_cache_bound_objects : cache_bound_object DynArray.t;
 	mutable m_if_feature : (string * class_field_ref) list;
 	mutable m_features : (string,bool) Hashtbl.t;
 }

+ 19 - 18
src/core/tUnification.ml

@@ -260,13 +260,13 @@ module Monomorph = struct
 
 	let spawn_constrained_monos map params =
 		let checks = DynArray.create () in
-		let monos = List.map (fun tp ->
+		let monos = List.map (fun ttp ->
 			let mono = create () in
-			begin match follow tp.ttp_type with
-				| TInst ({ cl_kind = KTypeParameter constr; cl_path = path },_) when constr <> [] ->
-					DynArray.add checks (mono,constr,s_type_path path)
-				| _ ->
+			begin match get_constraints ttp with
+				| [] ->
 					()
+				| constr ->
+					DynArray.add checks (mono,constr,s_type_path ttp.ttp_class.cl_path)
 			end;
 			TMono mono
 		) params in
@@ -695,12 +695,13 @@ let rec unify (uctx : unification_context) a b =
 				loop cs (List.map (apply_params c.cl_params tl) tls)
 			) c.cl_implements
 			|| (match c.cl_kind with
-			| KTypeParameter pl -> List.exists (fun t ->
-				match follow t with
-				| TInst (cs,tls) -> loop cs (List.map (apply_params c.cl_params tl) tls)
-				| TAbstract(aa,tl) -> unifies_to uctx a b aa tl
-				| _ -> false
-			) pl
+			| KTypeParameter ttp ->
+				List.exists (fun t ->
+					match follow t with
+					| TInst (cs,tls) -> loop cs (List.map (apply_params c.cl_params tl) tls)
+					| TAbstract(aa,tl) -> unifies_to uctx a b aa tl
+					| _ -> false
+				) (get_constraints ttp)
 			| _ -> false)
 		in
 		if not (loop c1 tl1) then error [cannot_unify a b]
@@ -722,9 +723,9 @@ let rec unify (uctx : unification_context) a b =
 				error (cannot_unify a b :: msg :: l))
 	| TInst (c,tl) , TAnon an ->
 		if PMap.is_empty an.a_fields then (match c.cl_kind with
-			| KTypeParameter pl ->
+			| KTypeParameter ttp ->
 				(* one of the constraints must unify with { } *)
-				if not (List.exists (fun t -> match follow t with TInst _ | TAnon _ -> true | _ -> false) pl) then error [cannot_unify a b]
+				if not (List.exists (fun t -> match follow t with TInst _ | TAnon _ -> true | _ -> false) (get_constraints ttp)) then error [cannot_unify a b]
 			| _ -> ());
 		ignore(c.cl_build());
 		(try
@@ -824,9 +825,9 @@ let rec unify (uctx : unification_context) a b =
 	| TInst(c,tl),TAbstract({a_path = ["haxe"],"Constructible"},[t1]) ->
 		begin try
 			begin match c.cl_kind with
-				| KTypeParameter tl ->
+				| KTypeParameter ttp ->
 					(* type parameters require an equal Constructible constraint *)
-					if not (List.exists (fun t -> match follow t with TAbstract({a_path = ["haxe"],"Constructible"},[t2]) -> type_iseq uctx t1 t2 | _ -> false) tl) then error [cannot_unify a b]
+					if not (List.exists (fun t -> match follow t with TAbstract({a_path = ["haxe"],"Constructible"},[t2]) -> type_iseq uctx t1 t2 | _ -> false) (get_constraints ttp)) then error [cannot_unify a b]
 				| _ ->
 					let _,t,cf = class_field c tl "new" in
 					if not (has_class_field_flag cf CfPublic) then error [invalid_visibility "new"];
@@ -884,12 +885,12 @@ let rec unify (uctx : unification_context) a b =
 		end
 	| TAbstract (aa,tl), _  ->
 		unify_to uctx a b aa tl
-	| TInst ({ cl_kind = KTypeParameter ctl } as c,pl), TAbstract (bb,tl) ->
+	| TInst ({ cl_kind = KTypeParameter ttp } as c,pl), TAbstract (bb,tl) ->
 		(* one of the constraints must satisfy the abstract *)
 		if not (List.exists (fun t ->
 			let t = apply_params c.cl_params pl t in
 			try unify uctx t b; true with Unify_error _ -> false
-		) ctl) then unify_from uctx a b bb tl
+		) (get_constraints ttp)) then unify_from uctx a b bb tl
 	| _, TAbstract (bb,tl) ->
 		unify_from uctx a b bb tl
 	| _ , _ ->
@@ -1136,7 +1137,7 @@ module UnifyMinT = struct
 		let rec loop t = (match t with
 			| TInst(cl, params) ->
 				(match cl.cl_kind with
-				| KTypeParameter tl -> List.iter loop tl
+				| KTypeParameter ttp -> List.iter loop (get_constraints ttp)
 				| _ -> ());
 				List.iter (fun (ic, ip) ->
 					let t = apply_params cl.cl_params params (TInst (ic,ip)) in

+ 4 - 5
src/core/texpr.ml

@@ -486,15 +486,14 @@ let foldmap f acc e =
 (* Collection of functions that return expressions *)
 module Builder = struct
 	let make_static_this c p =
-		let ta = mk_anon ~fields:c.cl_statics (ref (ClassStatics c)) in
-		mk (TTypeExpr (TClassDecl c)) ta p
+		mk (TTypeExpr (TClassDecl c)) (TType(TFunctions.class_module_type c,[])) p
 
 	let make_typeexpr mt pos =
 		let t =
 			match resolve_typedef mt with
-			| TClassDecl c -> mk_anon ~fields:c.cl_statics (ref (ClassStatics c))
-			| TEnumDecl e -> mk_anon (ref (EnumStatics e))
-			| TAbstractDecl a -> mk_anon (ref (AbstractStatics a))
+			| TClassDecl c -> TType(class_module_type c,[])
+			| TEnumDecl e -> e.e_type
+			| TAbstractDecl a -> TType(abstract_module_type a [],[])
 			| _ -> die "" __LOC__
 		in
 		mk (TTypeExpr mt) t pos

+ 68 - 0
src/filters/addFieldInits.ml

@@ -0,0 +1,68 @@
+open Globals
+open Common
+open Type
+
+
+let add_field_inits cl_path locals com t =
+	let apply c =
+		let ethis = mk (TConst TThis) (TInst (c,extract_param_types c.cl_params)) c.cl_pos in
+		(* TODO: we have to find a variable name which is not used in any of the functions *)
+		let v = alloc_var VGenerated "_g" ethis.etype ethis.epos in
+		let need_this = ref false in
+		let inits,fields = List.fold_left (fun (inits,fields) cf ->
+			match cf.cf_kind,cf.cf_expr with
+			| Var _, Some _ -> (cf :: inits, cf :: fields)
+			| _ -> (inits, cf :: fields)
+		) ([],[]) c.cl_ordered_fields in
+		c.cl_ordered_fields <- (List.rev fields);
+		match inits with
+		| [] -> ()
+		| _ ->
+			let el = List.map (fun cf ->
+				match cf.cf_expr with
+				| None -> die "" __LOC__
+				| Some e ->
+					let lhs = mk (TField({ ethis with epos = cf.cf_pos },FInstance (c,extract_param_types c.cl_params,cf))) cf.cf_type cf.cf_pos in
+					cf.cf_expr <- None;
+					mk (TBinop(OpAssign,lhs,e)) cf.cf_type e.epos
+			) inits in
+			let el = if !need_this then (mk (TVar((v, Some ethis))) ethis.etype ethis.epos) :: el else el in
+			let cf = match c.cl_constructor with
+			| None ->
+				let ct = TFun([],com.basic.tvoid) in
+				let ce = mk (TFunction {
+					tf_args = [];
+					tf_type = com.basic.tvoid;
+					tf_expr = mk (TBlock el) com.basic.tvoid c.cl_pos;
+				}) ct c.cl_pos in
+				let ctor = mk_field "new" ct c.cl_pos null_pos in
+				ctor.cf_kind <- Method MethNormal;
+				{ ctor with cf_expr = Some ce }
+			| Some cf ->
+				match cf.cf_expr with
+				| Some { eexpr = TFunction f } ->
+					let bl = match f.tf_expr with {eexpr = TBlock b } -> b | x -> [x] in
+					let ce = mk (TFunction {f with tf_expr = mk (TBlock (el @ bl)) com.basic.tvoid c.cl_pos }) cf.cf_type cf.cf_pos in
+					{cf with cf_expr = Some ce };
+				| _ ->
+					die "" __LOC__
+			in
+			let config = AnalyzerConfig.get_field_config com c cf in
+			remove_class_field_flag cf CfPostProcessed;
+			Analyzer.Run.run_on_field com config c cf;
+			add_class_field_flag cf CfPostProcessed;
+			(match cf.cf_expr with
+			| Some e ->
+				(* This seems a bit expensive, but hopefully constructor expressions aren't that massive. *)
+				let e = RenameVars.run cl_path locals e in
+				let e = Optimizer.sanitize com e in
+				cf.cf_expr <- Some e
+			| _ ->
+				());
+			c.cl_constructor <- Some cf
+	in
+	match t with
+	| TClassDecl c ->
+		apply c
+	| _ ->
+		()

+ 22 - 0
src/filters/exceptionFunctions.ml

@@ -0,0 +1,22 @@
+open Type
+
+let haxe_exception_type_path = (["haxe"],"Exception")
+let value_exception_type_path = (["haxe"],"ValueException")
+
+(**
+	Check if `cls` is or extends (if `check_parent=true`) `haxe.Exception`
+*)
+	let rec is_haxe_exception_class ?(check_parent=true) cls =
+		cls.cl_path = haxe_exception_type_path
+		|| (check_parent && match cls.cl_super with
+			| None -> false
+			| Some (cls, _) -> is_haxe_exception_class ~check_parent cls
+		)
+	
+	(**
+		Check if `t` is or extends `haxe.Exception`
+	*)
+	let is_haxe_exception ?(check_parent=true) (t:Type.t) =
+		match Abstract.follow_with_abstracts t with
+			| TInst (cls, _) -> is_haxe_exception_class ~check_parent cls
+			| _ -> false

+ 2 - 25
src/filters/exceptions.ml

@@ -4,9 +4,7 @@ open Type
 open Common
 open Typecore
 open Error
-
-let haxe_exception_type_path = (["haxe"],"Exception")
-let value_exception_type_path = (["haxe"],"ValueException")
+open ExceptionFunctions
 
 type context = {
 	typer : typer;
@@ -65,11 +63,7 @@ let haxe_exception_instance_call ctx haxe_exception method_name args p =
 *)
 let std_is ctx e t p =
 	let t = follow t in
-	let std_cls =
-		match Typeload.load_type_raise ctx.typer ([],"Std") "Std" p with
-		| TClassDecl cls -> cls
-		| _ -> raise_typing_error "Std is expected to be a class" p
-	in
+	let std_cls = ctx.typer.g.std in
 	let isOfType_field =
 		try PMap.find "isOfType" std_cls.cl_statics
 		with Not_found -> raise_typing_error ("Std has no field isOfType") p
@@ -122,23 +116,6 @@ let is_haxe_wildcard_catch ctx t =
 	let t = Abstract.follow_with_abstracts t in
 	t == t_dynamic || fast_eq ctx.haxe_exception_type t
 
-(**
-	Check if `cls` is or extends (if `check_parent=true`) `haxe.Exception`
-*)
-let rec is_haxe_exception_class ?(check_parent=true) cls =
-	cls.cl_path = haxe_exception_type_path
-	|| (check_parent && match cls.cl_super with
-		| None -> false
-		| Some (cls, _) -> is_haxe_exception_class ~check_parent cls
-	)
-
-(**
-	Check if `t` is or extends `haxe.Exception`
-*)
-let is_haxe_exception ?(check_parent=true) (t:Type.t) =
-	match Abstract.follow_with_abstracts t with
-		| TInst (cls, _) -> is_haxe_exception_class ~check_parent cls
-		| _ -> false
 
 (**
 	Check if `v` variable is used in `e` expression

+ 5 - 209
src/filters/filters.ml

@@ -25,7 +25,7 @@ open Error
 open Globals
 open FiltersCommon
 
-let get_native_name = TypeloadCheck.get_native_name
+let get_native_name = Naming.get_native_name
 
 (* PASS 1 begin *)
 
@@ -66,66 +66,6 @@ let rec add_final_return e =
 			{ e with eexpr = TFunction f }
 		| _ -> e
 
-module LocalStatic = struct
-	let promote_local_static ctx lut v eo =
-		let name = Printf.sprintf "%s_%s" ctx.curfield.cf_name v.v_name in
-		begin try
-			let cf = PMap.find name ctx.curclass.cl_statics in
-			display_error ctx.com (Printf.sprintf "The expanded name of this local (%s) conflicts with another static field" name) v.v_pos;
-			raise_typing_error ~depth:1 "Conflicting field was found here" cf.cf_name_pos;
-		with Not_found ->
-			let cf = mk_field name ~static:true v.v_type v.v_pos v.v_pos in
-			cf.cf_meta <- v.v_meta;
-			begin match eo with
-			| None ->
-				()
-			| Some e ->
-				let rec loop e = match e.eexpr with
-					| TLocal _ | TFunction _ ->
-						raise_typing_error "Accessing local variables in static initialization is not allowed" e.epos
-					| TConst (TThis | TSuper) ->
-						raise_typing_error "Accessing `this` in static initialization is not allowed" e.epos
-					| TReturn _ | TBreak | TContinue ->
-						raise_typing_error "This kind of control flow in static initialization is not allowed" e.epos
-					| _ ->
-						iter loop e
-				in
-				loop e;
-				cf.cf_expr <- Some e
-			end;
-			TClass.add_field ctx.curclass cf;
-			Hashtbl.add lut v.v_id cf
-		end
-
-	let find_local_static lut v =
-		Hashtbl.find lut v.v_id
-
-	let run ctx e =
-		let local_static_lut = Hashtbl.create 0 in
-		let c = ctx.curclass in
-		let rec run e = match e.eexpr with
-			| TBlock el ->
-				let el = ExtList.List.filter_map (fun e -> match e.eexpr with
-					| TVar(v,eo) when has_var_flag v VStatic ->
-						promote_local_static ctx local_static_lut v eo;
-						None
-					| _ ->
-						Some (run e)
-				) el in
-				{ e with eexpr = TBlock el }
-			| TLocal v when has_var_flag v VStatic ->
-				begin try
-					let cf = find_local_static local_static_lut v in
-					Texpr.Builder.make_static_field c cf e.epos
-				with Not_found ->
-					raise_typing_error (Printf.sprintf "Could not find local static %s (id %i)" v.v_name v.v_id) e.epos
-				end
-			| _ ->
-				Type.map_expr run e
-		in
-		run e
-end
-
 (* -------------------------------------------------------------------------- *)
 (* CHECK LOCAL VARS INIT *)
 
@@ -356,12 +296,6 @@ let check_abstract_as_value e =
 
 (* PASS 2 begin *)
 
-let remove_generic_base t = match t with
-	| TClassDecl c when is_removable_class c ->
-		add_class_flag c CExtern;
-	| _ ->
-		()
-
 (* Removes extern and macro fields, also checks for Void fields *)
 
 let remove_extern_fields com t = match t with
@@ -389,75 +323,10 @@ let remove_extern_fields com t = match t with
 let check_private_path com t = match t with
 	| TClassDecl c when c.cl_private ->
 		let rpath = (fst c.cl_module.m_path,"_" ^ snd c.cl_module.m_path) in
-		if com.type_to_module#mem rpath then raise_typing_error ("This private class name will clash with " ^ s_type_path rpath) c.cl_pos;
+		if com.module_lut#get_type_lut#mem rpath then raise_typing_error ("This private class name will clash with " ^ s_type_path rpath) c.cl_pos;
 	| _ ->
 		()
 
-(* Rewrites class or enum paths if @:native metadata is set *)
-let apply_native_paths t =
-	let get_real_name meta name =
-		let name',p = get_native_name meta in
-		(Meta.RealPath,[Ast.EConst (Ast.String (name,SDoubleQuotes)), p], p), name'
-	in
-	let get_real_path meta path =
-		let name,p = get_native_name meta in
-		(Meta.RealPath,[Ast.EConst (Ast.String (s_type_path path,SDoubleQuotes)), p], p), parse_path name
-	in
-	try
-		(match t with
-		| TClassDecl c ->
-			let did_change = ref false in
-			let field cf = try
-				let meta,name = get_real_name cf.cf_meta cf.cf_name in
-				cf.cf_name <- name;
-				cf.cf_meta <- meta :: cf.cf_meta;
-				List.iter (fun cf -> cf.cf_name <- name) cf.cf_overloads;
-				did_change := true
-			with Not_found ->
-				()
-			in
-			let fields cfs old_map =
-				did_change := false;
-				List.iter field cfs;
-				if !did_change then
-					List.fold_left (fun map f -> PMap.add f.cf_name f map) PMap.empty cfs
-				else
-					old_map
-			in
-			c.cl_fields <- fields c.cl_ordered_fields c.cl_fields;
-			c.cl_statics <- fields c.cl_ordered_statics c.cl_statics;
-			let meta,path = get_real_path c.cl_meta c.cl_path in
-			c.cl_meta <- meta :: c.cl_meta;
-			c.cl_path <- path;
-		| TEnumDecl e ->
-			let did_change = ref false in
-			let field _ ef = try
-				let meta,name = get_real_name ef.ef_meta ef.ef_name in
-				ef.ef_name <- name;
-				ef.ef_meta <- meta :: ef.ef_meta;
-				did_change := true;
-			with Not_found ->
-				()
-			in
-			PMap.iter field e.e_constrs;
-			if !did_change then begin
-				let names = ref [] in
-				e.e_constrs <- PMap.fold
-					(fun ef map ->
-						names := ef.ef_name :: !names;
-						PMap.add ef.ef_name ef map
-					)
-					e.e_constrs PMap.empty;
-				e.e_names <- !names;
-			end;
-			let meta,path = get_real_path e.e_meta e.e_path in
-			e.e_meta <- meta :: e.e_meta;
-			e.e_path <- path;
-		| _ ->
-			())
-	with Not_found ->
-		()
-
 (* Adds the __rtti field if required *)
 let add_rtti com t =
 	let rec has_rtti c =
@@ -473,71 +342,6 @@ let add_rtti com t =
 	| _ ->
 		()
 
-(* Adds member field initializations as assignments to the constructor *)
-let add_field_inits cl_path locals com t =
-	let apply c =
-		let ethis = mk (TConst TThis) (TInst (c,extract_param_types c.cl_params)) c.cl_pos in
-		(* TODO: we have to find a variable name which is not used in any of the functions *)
-		let v = alloc_var VGenerated "_g" ethis.etype ethis.epos in
-		let need_this = ref false in
-		let inits,fields = List.fold_left (fun (inits,fields) cf ->
-			match cf.cf_kind,cf.cf_expr with
-			| Var _, Some _ -> (cf :: inits, cf :: fields)
-			| _ -> (inits, cf :: fields)
-		) ([],[]) c.cl_ordered_fields in
-		c.cl_ordered_fields <- (List.rev fields);
-		match inits with
-		| [] -> ()
-		| _ ->
-			let el = List.map (fun cf ->
-				match cf.cf_expr with
-				| None -> die "" __LOC__
-				| Some e ->
-					let lhs = mk (TField({ ethis with epos = cf.cf_pos },FInstance (c,extract_param_types c.cl_params,cf))) cf.cf_type cf.cf_pos in
-					cf.cf_expr <- None;
-					mk (TBinop(OpAssign,lhs,e)) cf.cf_type e.epos
-			) inits in
-			let el = if !need_this then (mk (TVar((v, Some ethis))) ethis.etype ethis.epos) :: el else el in
-			let cf = match c.cl_constructor with
-			| None ->
-				let ct = TFun([],com.basic.tvoid) in
-				let ce = mk (TFunction {
-					tf_args = [];
-					tf_type = com.basic.tvoid;
-					tf_expr = mk (TBlock el) com.basic.tvoid c.cl_pos;
-				}) ct c.cl_pos in
-				let ctor = mk_field "new" ct c.cl_pos null_pos in
-				ctor.cf_kind <- Method MethNormal;
-				{ ctor with cf_expr = Some ce }
-			| Some cf ->
-				match cf.cf_expr with
-				| Some { eexpr = TFunction f } ->
-					let bl = match f.tf_expr with {eexpr = TBlock b } -> b | x -> [x] in
-					let ce = mk (TFunction {f with tf_expr = mk (TBlock (el @ bl)) com.basic.tvoid c.cl_pos }) cf.cf_type cf.cf_pos in
-					{cf with cf_expr = Some ce };
-				| _ ->
-					die "" __LOC__
-			in
-			let config = AnalyzerConfig.get_field_config com c cf in
-			remove_class_field_flag cf CfPostProcessed;
-			Analyzer.Run.run_on_field com config c cf;
-			add_class_field_flag cf CfPostProcessed;
-			(match cf.cf_expr with
-			| Some e ->
-				(* This seems a bit expensive, but hopefully constructor expressions aren't that massive. *)
-				let e = RenameVars.run cl_path locals e in
-				let e = Optimizer.sanitize com e in
-				cf.cf_expr <- Some e
-			| _ ->
-				());
-			c.cl_constructor <- Some cf
-	in
-	match t with
-	| TClassDecl c ->
-		apply c
-	| _ ->
-		()
-
 (* Adds the __meta__ field if required *)
 let add_meta_field com t = match t with
 	| TClassDecl c ->
@@ -618,14 +422,6 @@ let check_reserved_type_paths com t =
 
 (* PASS 3 end *)
 
-let is_cached com t =
-	let m = (t_infos t).mt_module.m_extra in
-	m.m_processed <> 0 && m.m_processed < com.compilation_step
-
-let apply_filters_once ctx filters t =
-	let detail_times = (try int_of_string (Common.defined_value_safe ctx.com ~default:"0" Define.FilterTimes) with _ -> 0) in
-	if not (is_cached ctx.com t) then run_expression_filters ctx detail_times filters t
-
 let iter_expressions fl mt =
 	match mt with
 	| TClassDecl c ->
@@ -666,7 +462,7 @@ let destruction tctx detail_times main locals =
 	with_timer detail_times "type 2" None (fun () ->
 		(* PASS 2: type filters pre-DCE *)
 		List.iter (fun t ->
-			remove_generic_base t;
+			FiltersCommon.remove_generic_base t;
 			remove_extern_fields com t;
 			(* check @:remove metadata before DCE so it is ignored there (issue #2923) *)
 			check_remove_metadata t;
@@ -698,9 +494,9 @@ let destruction tctx detail_times main locals =
 	let type_filters = [
 		Exceptions.patch_constructors tctx; (* TODO: I don't believe this should load_instance anything at this point... *)
 		check_private_path com;
-		apply_native_paths;
+		Naming.apply_native_paths;
 		add_rtti com;
-		(match com.platform with | Jvm -> (fun _ -> ()) | _ -> (fun mt -> add_field_inits tctx.curclass.cl_path locals com mt));
+		(match com.platform with | Jvm -> (fun _ -> ()) | _ -> (fun mt -> AddFieldInits.add_field_inits tctx.curclass.cl_path locals com mt));
 		(match com.platform with Hl -> (fun _ -> ()) | _ -> add_meta_field com);
 		check_void_field;
 		(match com.platform with | Cpp -> promote_first_interface_to_super | _ -> (fun _ -> ()));

+ 17 - 5
src/filters/filtersCommon.ml

@@ -18,6 +18,7 @@
 *)
 open Globals
 open Type
+open Common
 open Typecore
 
 let rec is_removable_class c =
@@ -27,11 +28,8 @@ let rec is_removable_class c =
 		(match c.cl_super with
 			| Some (c,_) -> is_removable_class c
 			| _ -> false) ||
-		List.exists (fun tp -> match follow tp.ttp_type with
-			| TInst(c,_) ->
-				has_ctor_constraint c || Meta.has Meta.Const c.cl_meta
-			| _ ->
-				false
+		List.exists (fun tp ->
+			has_ctor_constraint tp.ttp_class || Meta.has Meta.Const tp.ttp_class.cl_meta
 		) c.cl_params)
 	| KTypeParameter _ ->
 		(* this shouldn't happen, have to investigate (see #4092) *)
@@ -39,6 +37,12 @@ let rec is_removable_class c =
 	| _ ->
 		false
 
+let remove_generic_base t = match t with
+	| TClassDecl c when is_removable_class c ->
+		add_class_flag c CExtern;
+	| _ ->
+		()
+
 (**
 	Check if `field` is overridden in subclasses
 *)
@@ -85,3 +89,11 @@ let run_expression_filters ?(ignore_processed_status=false) ctx detail_times fil
 	| TEnumDecl _ -> ()
 	| TTypeDecl _ -> ()
 	| TAbstractDecl _ -> ()
+
+let is_cached com t =
+	let m = (t_infos t).mt_module.m_extra in
+	m.m_processed <> 0 && m.m_processed < com.compilation_step
+
+let apply_filters_once ctx filters t =
+	let detail_times = (try int_of_string (Common.defined_value_safe ctx.com ~default:"0" Define.FilterTimes) with _ -> 0) in
+	if not (is_cached ctx.com t) then run_expression_filters ctx detail_times filters t

+ 62 - 0
src/filters/localStatic.ml

@@ -0,0 +1,62 @@
+open Common
+open Type
+open Typecore
+open Error
+
+let promote_local_static ctx lut v eo =
+	let name = Printf.sprintf "%s_%s" ctx.curfield.cf_name v.v_name in
+	begin try
+		let cf = PMap.find name ctx.curclass.cl_statics in
+		display_error ctx.com (Printf.sprintf "The expanded name of this local (%s) conflicts with another static field" name) v.v_pos;
+		raise_typing_error ~depth:1 "Conflicting field was found here" cf.cf_name_pos;
+	with Not_found ->
+		let cf = mk_field name ~static:true v.v_type v.v_pos v.v_pos in
+		cf.cf_meta <- v.v_meta;
+		begin match eo with
+		| None ->
+			()
+		| Some e ->
+			let rec loop e = match e.eexpr with
+				| TLocal _ | TFunction _ ->
+					raise_typing_error "Accessing local variables in static initialization is not allowed" e.epos
+				| TConst (TThis | TSuper) ->
+					raise_typing_error "Accessing `this` in static initialization is not allowed" e.epos
+				| TReturn _ | TBreak | TContinue ->
+					raise_typing_error "This kind of control flow in static initialization is not allowed" e.epos
+				| _ ->
+					iter loop e
+			in
+			loop e;
+			cf.cf_expr <- Some e
+		end;
+		TClass.add_field ctx.curclass cf;
+		Hashtbl.add lut v.v_id cf
+	end
+
+let find_local_static lut v =
+	Hashtbl.find lut v.v_id
+
+let run ctx e =
+	let local_static_lut = Hashtbl.create 0 in
+	let c = ctx.curclass in
+	let rec run e = match e.eexpr with
+		| TBlock el ->
+			let el = ExtList.List.filter_map (fun e -> match e.eexpr with
+				| TVar(v,eo) when has_var_flag v VStatic ->
+					promote_local_static ctx local_static_lut v eo;
+					None
+				| _ ->
+					Some (run e)
+			) el in
+			{ e with eexpr = TBlock el }
+		| TLocal v when has_var_flag v VStatic ->
+			begin try
+				let cf = find_local_static local_static_lut v in
+				Texpr.Builder.make_static_field c cf e.epos
+			with Not_found ->
+				raise_typing_error (Printf.sprintf "Could not find local static %s (id %i)" v.v_name v.v_id) e.epos
+			end
+		| _ ->
+			Type.map_expr run e
+	in
+	run e

+ 3 - 3
src/filters/renameVars.ml

@@ -28,17 +28,17 @@ let reserve_init ri name =
 let reserve_all_types ri com path_to_name =
 	List.iter (fun mt ->
 		let tinfos = t_infos mt in
-		let native_name = try fst (TypeloadCheck.get_native_name tinfos.mt_meta) with Not_found -> path_to_name tinfos.mt_path in
+		let native_name = try fst (Naming.get_native_name tinfos.mt_meta) with Not_found -> path_to_name tinfos.mt_path in
 		match mt with
 		| TClassDecl c when native_name = "" ->
 			List.iter (fun cf ->
-				let native_name = try fst (TypeloadCheck.get_native_name cf.cf_meta) with Not_found -> cf.cf_name in
+				let native_name = try fst (Naming.get_native_name cf.cf_meta) with Not_found -> cf.cf_name in
 				reserve_init ri native_name
 			) c.cl_ordered_statics
 		| TClassDecl { cl_kind = KModuleFields m; cl_ordered_statics = fl } ->
 			let prefix = Path.flat_path m.m_path ^ "_" in
 			List.iter (fun cf ->
-				let name = try fst (TypeloadCheck.get_native_name cf.cf_meta) with Not_found -> prefix ^ cf.cf_name in
+				let name = try fst (Naming.get_native_name cf.cf_meta) with Not_found -> prefix ^ cf.cf_name in
 				reserve_init ri name
 			) fl
 		| _ ->

+ 23 - 3
src/generators/gencpp.ml

@@ -3442,7 +3442,7 @@ let cpp_class_hash interface =
 let rec is_constant_zero expr =
   match expr.cppexpr with
   | CppFloat x when (float_of_string x) = 0.0 -> true
-  | CppInt i when i = Int32.of_int 0 -> true
+  | CppInt i when i = Int32.zero -> true
   | CppCastScalar(expr,_) -> is_constant_zero(expr)
   | _ -> false
 ;;
@@ -5238,6 +5238,9 @@ let generate_enum_files baseCtx enum_def super_deps meta =
    let ctx = file_context baseCtx cpp_file debug false in
    let strq = strq ctx.ctx_common in
 
+   let classId = try Hashtbl.find baseCtx.ctx_type_ids (class_text enum_def.e_path) with Not_found -> Int32.zero in
+   let classIdTxt = Printf.sprintf "0x%08lx" classId in
+
    if (debug>1) then
       print_endline ("Found enum definition:" ^ (join_class_path  class_path "::" ));
 
@@ -5279,6 +5282,10 @@ let generate_enum_files baseCtx enum_def super_deps meta =
 
    output_cpp ("HX_DEFINE_CREATE_ENUM(" ^ class_name ^ ")\n\n");
 
+   output_cpp ("bool " ^ class_name ^ "::_hx_isInstanceOf(int inClassId) {\n");
+   output_cpp ("\treturn inClassId == (int)0x00000001 || inClassId == ::hx::EnumBase_obj::_hx_ClassId || inClassId == _hx_ClassId;\n");
+   output_cpp ("}\n");
+
    output_cpp ("int " ^ class_name ^ "::__FindIndex(::String inName)\n{\n");
    PMap.iter (fun _ constructor ->
       let name = constructor.ef_name in
@@ -5390,13 +5397,15 @@ let generate_enum_files baseCtx enum_def super_deps meta =
    output_h ("{\n\ttypedef " ^ super ^ " super;\n");
    output_h ("\t\ttypedef " ^ class_name ^ " OBJ_;\n");
    output_h "\n\tpublic:\n";
+   output_h ("\t\tenum { _hx_ClassId = " ^ classIdTxt ^ " };\n\n");
    output_h ("\t\t" ^ class_name ^ "() {};\n");
    output_h ("\t\tHX_DO_ENUM_RTTI;\n");
    output_h ("\t\tstatic void __boot();\n");
    output_h ("\t\tstatic void __register();\n");
    output_h ("\t\tstatic bool __GetStatic(const ::String &inName, Dynamic &outValue, ::hx::PropertyAccess inCallProp);\n");
    output_h ("\t\t::String GetEnumName( ) const { return " ^ (strq (join_class_path class_path "."))  ^ "; }\n" );
-   output_h ("\t\t::String __ToString() const { return " ^ (strq (just_class_name ^ ".") )^ " + _hx_tag; }\n\n");
+   output_h ("\t\t::String __ToString() const { return " ^ (strq (just_class_name ^ ".") )^ " + _hx_tag; }\n");
+   output_h ("\t\tbool _hx_isInstanceOf(int inClassId);\n\n");
 
 
    PMap.iter (fun _ constructor ->
@@ -5761,7 +5770,7 @@ let generate_class_files baseCtx super_deps constructor_deps class_def inScripta
       then 0 else 1 in
    let scriptable = inScriptable && not class_def.cl_private in
 
-   let classId = try Hashtbl.find baseCtx.ctx_type_ids (class_text class_def.cl_path) with Not_found -> Int32.of_int 0 in
+   let classId = try Hashtbl.find baseCtx.ctx_type_ids (class_text class_def.cl_path) with Not_found -> Int32.zero in
    let classIdTxt = Printf.sprintf "0x%08lx" classId in
 
    (* Config *)
@@ -8564,6 +8573,17 @@ let generate_source ctx =
          if (is_internal) then
             (if (debug>1) then print_endline (" internal enum " ^ name ))
          else begin
+            let rec makeId enum_name seed =
+               let id = gen_hash32 seed enum_name in
+               (* reserve first 100 ids for runtime *)
+               if id < Int32.of_int 100 || Hashtbl.mem existingIds id then
+                  makeId enum_name (seed+100)
+               else begin
+                  Hashtbl.add existingIds id true;
+                  Hashtbl.add ctx.ctx_type_ids enum_name id;
+               end in
+            makeId name 0;
+
             let meta = Texpr.build_metadata common_ctx.basic object_def in
             if (enum_def.e_extern) then
                (if (debug>1) then print_endline ("external enum " ^ name ));

+ 41 - 7
src/generators/genhl.ml

@@ -361,7 +361,7 @@ let make_debug ctx arr =
 let fake_tnull =
 	{null_abstract with
 		a_path = [],"Null";
-		a_params = [{ttp_name = "T"; ttp_type = t_dynamic; ttp_default = None}];
+		a_params = [mk_type_param null_class TPHType None None];
 	}
 
 let get_rec_cache ctx t none_callback not_found_callback =
@@ -435,7 +435,7 @@ let rec to_type ?tref ctx t =
 		HAbstract (name, alloc_string ctx name)
 	| TInst (c,pl) ->
 		(match c.cl_kind with
-		| KTypeParameter tl ->
+		| KTypeParameter ttp ->
 			let rec loop = function
 				| [] -> HDyn
 				| t :: tl ->
@@ -443,7 +443,7 @@ let rec to_type ?tref ctx t =
 					| TInst (c,_) as t when not (has_class_flag c CInterface) -> to_type ?tref ctx t
 					| _ -> loop tl
 			in
-			loop tl
+			loop (get_constraints ttp)
 		| _ -> class_type ~tref ctx c pl false)
 	| TAbstract ({a_path = [],"Null"},[t1]) ->
 		let t = to_type ?tref ctx t1 in
@@ -1384,7 +1384,7 @@ and get_access ctx e =
 				let t = to_type ctx t in
 				AArray (a,(t,t),i)
 			| TInst ({ cl_path = ["hl"],"Abstract" },[TInst({ cl_kind = KExpr (EConst (String("hl_carray",_)),_) },_)]) ->
-				let a = eval_null_check ctx a in
+				let a = eval_expr ctx a in
 				hold ctx a;
 				let i = eval_to ctx i HI32 in
 				free ctx a;
@@ -2082,6 +2082,32 @@ and eval_expr ctx e =
 			| AInstanceField (f, index) -> op ctx (OPrefetch (eval_expr ctx f, index + 1, mode))
 			| _ -> op ctx (OPrefetch (eval_expr ctx value, 0, mode)));
 			alloc_tmp ctx HVoid
+        | "$unsafecast", [value] ->
+			let r = alloc_tmp ctx (to_type ctx e.etype) in
+            op ctx (OUnsafeCast (r, eval_expr ctx value));
+			r
+		| "$asm", [mode; value] ->
+			let mode = (match get_const mode with
+				| TInt m -> Int32.to_int m
+				| _ -> abort "Constant mode required" e.epos
+			) in
+			let value = (match get_const value with
+				| TInt m -> Int32.to_int m
+				| _ -> abort "Constant value required" e.epos
+			) in
+			op ctx (OAsm (mode, value, 0));
+			alloc_tmp ctx HVoid
+		| "$asm", [mode; value; reg] ->
+			let mode = (match get_const mode with
+				| TInt m -> Int32.to_int m
+				| _ -> abort "Constant mode required" e.epos
+			) in
+			let value = (match get_const value with
+				| TInt m -> Int32.to_int m
+				| _ -> abort "Constant value required" e.epos
+			) in
+			op ctx (OAsm (mode, value, (eval_expr ctx reg) + 1));
+			alloc_tmp ctx HVoid
 		| _ ->
 			abort ("Unknown native call " ^ s) e.epos)
 	| TEnumIndex v ->
@@ -2169,9 +2195,9 @@ and eval_expr ctx e =
 				match follow t with
 				| TFun (_,rt) ->
 					(match follow rt with
-					| TInst({ cl_kind = KTypeParameter tl },_) ->
+					| TInst({ cl_kind = KTypeParameter ttp },_) ->
 						(* don't allow if we have a constraint virtual, see hxbit.Serializer.getRef *)
-						not (List.exists (fun t -> match to_type ctx t with HVirtual _ -> true | _ -> false) tl)
+						not (List.exists (fun t -> match to_type ctx t with HVirtual _ -> true | _ -> false) (get_constraints ttp))
 					| _ -> false)
 				| _ ->
 					false
@@ -2469,6 +2495,14 @@ and eval_expr ctx e =
 				free ctx ra;
 				free ctx ridx;
 				v
+            | ACArray (ra, _, ridx) ->
+				hold ctx ra;
+				hold ctx ridx;
+                let v = value() in
+                op ctx (OSetArray (ra,ridx,v));
+                free ctx ridx;
+                free ctx ra;
+                v
 			| ADynamic (ethis,f) ->
 				let obj = eval_null_check ctx ethis in
 				hold ctx obj;
@@ -2480,7 +2514,7 @@ and eval_expr ctx e =
 				let r = value() in
 				op ctx (OSetEnumField (ctx.m.mcaptreg,index,r));
 				r
-			| AEnum _ | ANone | AInstanceFun _ | AInstanceProto _ | AStaticFun _ | AVirtualMethod _ | ACArray _ ->
+			| AEnum _ | ANone | AInstanceFun _ | AInstanceProto _ | AStaticFun _ | AVirtualMethod _ ->
 				die "" __LOC__)
 		| OpBoolOr ->
 			let r = alloc_tmp ctx HBool in

+ 11 - 144
src/generators/genjs.ml

@@ -21,24 +21,7 @@ open Globals
 open Ast
 open Type
 open Common
-
-type sourcemap = {
-	sources : (string) DynArray.t;
-	sources_hash : (string, int) Hashtbl.t;
-	mappings : Rbuffer.t;
-
-	mutable source_last_pos : sourcemap_pos;
-	mutable print_comma : bool;
-	mutable output_last_col : int;
-	mutable output_current_col : int;
-	mutable current_expr : sourcemap_pos option;
-}
-
-and sourcemap_pos = {
-	file : int;
-	line : int;
-	col : int;
-}
+open JsSourcemap
 
 type ctx = {
 	com : Common.context;
@@ -154,13 +137,13 @@ let static_field ctx c f =
 
 let module_field m f =
 	try
-		fst (TypeloadCheck.get_native_name f.cf_meta)
+		fst (Naming.get_native_name f.cf_meta)
 	with Not_found ->
 		Path.flat_path m.m_path ^ "_" ^ f.cf_name
 
 let module_field_expose_path mpath f =
 	try
-		fst (TypeloadCheck.get_native_name f.cf_meta)
+		fst (Naming.get_native_name f.cf_meta)
 	with Not_found ->
 		(dot_path mpath) ^ "." ^ f.cf_name
 
@@ -169,98 +152,6 @@ let add_feature ctx = Common.add_feature ctx.com
 
 let unsupported p = abort "This expression cannot be compiled to Javascript" p
 
-let encode_mapping smap pos =
-	if smap.print_comma then
-		Rbuffer.add_char smap.mappings ','
-	else
-		smap.print_comma <- true;
-
-	let base64_vlq number =
-		let encode_digit digit =
-			let chars = [|
-				'A';'B';'C';'D';'E';'F';'G';'H';'I';'J';'K';'L';'M';'N';'O';'P';
-				'Q';'R';'S';'T';'U';'V';'W';'X';'Y';'Z';'a';'b';'c';'d';'e';'f';
-				'g';'h';'i';'j';'k';'l';'m';'n';'o';'p';'q';'r';'s';'t';'u';'v';
-				'w';'x';'y';'z';'0';'1';'2';'3';'4';'5';'6';'7';'8';'9';'+';'/'
-			|] in
-			Array.unsafe_get chars digit
-		in
-		let to_vlq number =
-			if number < 0 then
-				((-number) lsl 1) + 1
-			else
-				number lsl 1
-		in
-		let rec loop vlq =
-			let shift = 5 in
-			let base = 1 lsl shift in
-			let mask = base - 1 in
-			let continuation_bit = base in
-			let digit = vlq land mask in
-			let next = vlq asr shift in
-			Rbuffer.add_char smap.mappings (encode_digit (
-				if next > 0 then digit lor continuation_bit else digit));
-			if next > 0 then loop next else ()
-		in
-		loop (to_vlq number)
-	in
-
-	base64_vlq (smap.output_current_col - smap.output_last_col);
-	base64_vlq (pos.file - smap.source_last_pos.file);
-	base64_vlq (pos.line - smap.source_last_pos.line);
-	base64_vlq (pos.col - smap.source_last_pos.col);
-
-	smap.source_last_pos <- pos;
-	smap.output_last_col <- smap.output_current_col
-
-let noop () = ()
-
-let add_mapping smap pos =
-	if pos.pmin < 0 then noop else
-
-	let file = try
-		Hashtbl.find smap.sources_hash pos.pfile
-	with Not_found ->
-		let length = DynArray.length smap.sources in
-		Hashtbl.replace smap.sources_hash pos.pfile length;
-		DynArray.add smap.sources pos.pfile;
-		length
-	in
-
-	let pos =
-		let line, col = Lexer.find_pos pos in
-		let line = line - 1 in
-		{ file = file; line = line; col = col }
-	in
-
-	if smap.source_last_pos <> pos then begin
-		let old_current_expr = smap.current_expr in
-		smap.current_expr <- Some pos;
-		encode_mapping smap pos;
-		(fun () -> smap.current_expr <- old_current_expr)
-	end else
-		noop
-
-let add_mapping ctx e =
-	Option.map_default (fun smap -> add_mapping smap e.epos) noop ctx.smap
-
-let handle_newlines ctx str =
-	Option.may (fun smap ->
-		let rec loop from =
-			try begin
-				let next = String.index_from str from '\n' + 1 in
-				Rbuffer.add_char smap.mappings ';';
-				smap.output_last_col <- 0;
-				smap.output_current_col <- 0;
-				smap.print_comma <- false;
-				Option.may (encode_mapping smap) smap.current_expr;
-				loop next
-			end with Not_found ->
-				smap.output_current_col <- smap.output_current_col + (String.length str - from);
-		in
-		loop 0
-	) ctx.smap
-
 let flush ctx =
 	let chan =
 		match ctx.chan with
@@ -275,43 +166,16 @@ let flush ctx =
 
 let spr ctx s =
 	ctx.separator <- false;
-	handle_newlines ctx s;
+	handle_newlines ctx.smap s;
 	Rbuffer.add_string ctx.buf s
 
 let print ctx =
 	ctx.separator <- false;
 	Printf.kprintf (fun s -> begin
-		handle_newlines ctx s;
+		handle_newlines ctx.smap s;
 		Rbuffer.add_string ctx.buf s
 	end)
 
-let write_mappings ctx smap =
-	let basefile = Filename.basename ctx.com.file in
-	print ctx "\n//# sourceMappingURL=%s.map" (url_encode_s basefile);
-	let channel = open_out_bin (ctx.com.file ^ ".map") in
-	let sources = DynArray.to_list smap.sources in
-	let to_url file =
-		ExtString.String.map (fun c -> if c == '\\' then '/' else c) (Path.get_full_path file)
-	in
-	output_string channel "{\n";
-	output_string channel "\"version\":3,\n";
-	output_string channel ("\"file\":\"" ^ (String.concat "\\\\" (ExtString.String.nsplit basefile "\\")) ^ "\",\n");
-	output_string channel ("\"sourceRoot\":\"\",\n");
-	output_string channel ("\"sources\":[" ^
-		(String.concat "," (List.map (fun s -> "\"file:///" ^ to_url s ^ "\"") sources)) ^
-		"],\n");
-	if Common.defined ctx.com Define.SourceMapContent then begin
-		output_string channel ("\"sourcesContent\":[" ^
-			(String.concat "," (List.map (fun s -> try "\"" ^ StringHelper.s_escape (Std.input_file ~bin:true s) ^ "\"" with _ -> "null") sources)) ^
-			"],\n");
-	end;
-	output_string channel "\"names\":[],\n";
-	output_string channel "\"mappings\":\"";
-	Rbuffer.output_buffer channel smap.mappings;
-	output_string channel "\"\n";
-	output_string channel "}";
-	close_out channel
-
 let newline ctx =
 	match Rbuffer.nth ctx.buf (Rbuffer.length ctx.buf - 1) with
 	| '}' | '{' | ':' | ';' when not ctx.separator -> print ctx "\n%s" ctx.tabs
@@ -613,7 +477,7 @@ and add_objectdecl_parens e =
 	loop e
 
 and gen_expr ctx e =
-	let clear_mapping = add_mapping ctx e in
+	let clear_mapping = add_mapping ctx.smap e in
 	(match e.eexpr with
 	| TConst c -> gen_constant ctx e.epos c
 	| TLocal v -> spr ctx (ident v.v_name)
@@ -978,7 +842,7 @@ and gen_block_element ?(newline_after=false) ?(keep_blocks=false) ctx e =
 		if newline_after then newline ctx
 
 and gen_value ctx e =
-	let clear_mapping = add_mapping ctx e in
+	let clear_mapping = add_mapping ctx.smap e in
 	let assign e =
 		mk (TBinop (Ast.OpAssign,
 			mk (TLocal (match ctx.in_value with None -> die "" __LOC__ | Some v -> v)) t_dynamic e.epos,
@@ -2138,7 +2002,10 @@ let generate com =
 	);
 
 	(match ctx.smap with
-	| Some smap -> write_mappings ctx smap
+	| Some smap ->
+		write_mappings ctx.com smap "file:///";
+		let basefile = Filename.basename com.file in
+		print ctx "\n//# sourceMappingURL=%s.map" (url_encode_s basefile);
 	| None -> try Sys.remove (com.file ^ ".map") with _ -> ());
 	flush ctx;
 	Option.may (fun chan -> close_out chan) ctx.chan

+ 17 - 15
src/generators/genjvm.ml

@@ -202,8 +202,11 @@ let rec jsignature_of_type gctx stack t =
 		TObject((["haxe";"root"],"Array"),[TType(WNone,t)])
 	| TInst({cl_path = (["java"],"NativeArray")},[t]) ->
 		TArray(jsignature_of_type t,None)
-	| TInst({cl_kind = KTypeParameter [t]},_) when t != t_dynamic -> jsignature_of_type t
-	| TInst({cl_kind = KTypeParameter _; cl_path = (_,name)},_) -> TTypeParameter name
+	| TInst({cl_kind = KTypeParameter ttp; cl_path = (_,name)},_) ->
+		begin match get_constraints ttp with
+			| [t] when t != t_dynamic -> jsignature_of_type t
+			| _ -> TTypeParameter name
+		end
 	| TInst({cl_path = ["_Class"],"Class_Impl_"},_) -> java_class_sig
 	| TInst({cl_path = ["_Enum"],"Enum_Impl_"},_) -> java_class_sig
 	| TInst(c,tl) -> TObject(c.cl_path,List.map jtype_argument_of_type tl)
@@ -392,7 +395,7 @@ let is_interface_var_access c cf =
 let follow = Abstract.follow_with_abstracts
 
 class haxe_exception gctx (t : Type.t) =
-	let is_haxe_exception = Exceptions.is_haxe_exception t
+	let is_haxe_exception = ExceptionFunctions.is_haxe_exception t
 	and native_type = jsignature_of_type gctx t in
 object(self)
 	val native_path = (match native_type with TObject(path,_) -> path | _ -> die "" __LOC__)
@@ -2113,7 +2116,11 @@ class texpr_to_jvm
 		| TEnumParameter(e1,ef,i) ->
 			self#texpr rvalue_any e1;
 			let path,name,jsig_arg = match follow ef.ef_type with
-				| TFun(tl,TEnum(en,_)) ->
+				| TFun(tl,tr) ->
+					let en = match follow tr with
+						| TEnum(en,_) -> en
+						| _ -> die "" __LOC__
+					in
 					let n,_,t = List.nth tl i in
 					en.e_path,n,self#vtype t
 				| _ -> die "" __LOC__
@@ -2127,7 +2134,7 @@ class texpr_to_jvm
 			self#texpr rvalue_any e1;
 			(* There could be something like `throw throw`, so we should only throw if we aren't terminated (issue #10363) *)
 			if not (jm#is_terminated) then begin
-				if not (Exceptions.is_haxe_exception e1.etype) && not (does_unify e1.etype gctx.t_runtime_exception) then begin
+				if not (ExceptionFunctions.is_haxe_exception e1.etype) && not (does_unify e1.etype gctx.t_runtime_exception) then begin
 					let exc = new haxe_exception gctx e1.etype in
 					if not (List.exists (fun exc' -> exc#is_assignable_to exc') caught_exceptions) then
 						jm#add_thrown_exception exc#get_native_path;
@@ -2640,16 +2647,11 @@ class tclass_to_jvm gctx c = object(self)
 		end
 
 	method private generate_signature =
-		jc#set_type_parameters (List.map (fun tp ->
-			let jsigs = match follow tp.ttp_type with
-			| TInst({cl_kind = KTypeParameter tl},_) ->
-				List.map (fun t ->
-					get_boxed_type (jsignature_of_type gctx t)
-				 ) tl
-			| _ ->
-				[]
-			in
-			(tp.ttp_name,jsigs)
+		jc#set_type_parameters (List.map (fun ttp ->
+			let jsigs = List.map (fun t ->
+				get_boxed_type (jsignature_of_type gctx t)
+			) (get_constraints ttp) in
+			(ttp.ttp_name,jsigs)
 		) c.cl_params);
 		match c.cl_super with
 			| Some(c,tl) -> jc#set_super_parameters (List.map (jtype_argument_of_type gctx []) tl)

+ 40 - 5
src/generators/genlua.ml

@@ -20,11 +20,13 @@
  * DEALINGS IN THE SOFTWARE.
  *)
 
+open Extlib_leftovers
 open Ast
 open Type
 open Common
 open ExtList
 open Error
+open JsSourcemap
 
 type pos = Globals.pos
 
@@ -32,6 +34,7 @@ type ctx = {
     com : Common.context;
     buf : Buffer.t;
     packages : (string list,unit) Hashtbl.t;
+    smap : sourcemap option;
     mutable current : tclass;
     mutable statics : (tclass * tclass_field * texpr) list;
     mutable inits : texpr list;
@@ -143,11 +146,15 @@ let temp ctx =
 
 let spr ctx s =
     ctx.separator <- false;
+	handle_newlines ctx.smap s;
     Buffer.add_string ctx.buf s
 
 let print ctx =
     ctx.separator <- false;
-    Printf.kprintf (fun s -> Buffer.add_string ctx.buf s)
+    Printf.kprintf (fun s -> begin
+        handle_newlines ctx.smap s;
+        Buffer.add_string ctx.buf s
+    end)
 
 let newline ctx = print ctx "\n%s" ctx.tabs
 
@@ -281,7 +288,7 @@ let mk_mr_select com e ecall name =
 (* from genphp *)
 let rec is_string_type t =
     match follow t with
-    | TInst ({cl_kind = KTypeParameter constraints}, _) -> List.exists is_string_type constraints
+    | TInst ({cl_kind = KTypeParameter ttp}, _) -> List.exists is_string_type (get_constraints ttp)
     | TInst ({cl_path = ([], "String")}, _) -> true
     | TAnon a ->
         (match !(a.a_status) with
@@ -582,9 +589,10 @@ and gen_loop ctx cond do_while e =
     if do_while then
         print ctx " or _hx_do_first_%i" ctx.break_depth;
     print ctx " do ";
-    if do_while then
+    if do_while then begin
         newline ctx;
         println ctx "_hx_do_first_%i = false;" ctx.break_depth;
+    end;
     if will_continue then print ctx "repeat ";
     gen_block_element ctx e;
     if will_continue then begin
@@ -661,6 +669,7 @@ and lua_arg_name(a,_) =
         | _, _, _ ->  ident a.v_name;
 
 and gen_expr ?(local=true) ctx e = begin
+    let clear_mapping = add_mapping ctx.smap e in
     match e.eexpr with
       TConst c ->
         gen_constant ctx e.epos c;
@@ -1042,13 +1051,16 @@ and gen_expr ?(local=true) ctx e = begin
     | TCast (e1,None) ->
         gen_value ctx e1;
     | TIdent s ->
-        spr ctx s
+        spr ctx s;
+
+    clear_mapping ()
 end;
 
     (* gen_block_element handles expressions that map to "statements" in lua. *)
     (* It handles no-op situations, and ensures that expressions are formatted with newlines *)
 and gen_block_element ctx e  =
     ctx.iife_assign <- false;
+    let clear_mapping = add_mapping ctx.smap e in
     begin match e.eexpr with
         | TTypeExpr _ | TConst _ | TLocal _ | TFunction _ ->
             ()
@@ -1108,6 +1120,7 @@ and gen_block_element ctx e  =
             gen_expr ctx e;
             semicolon ctx;
     end;
+    clear_mapping ()
 
 and is_const_null e =
     match e.eexpr with
@@ -1146,6 +1159,7 @@ and gen_anon_value ctx e =
         gen_value ctx e
 
 and gen_value ctx e =
+    let clear_mapping = add_mapping ctx.smap e in
     let assign e =
         mk (TBinop (Ast.OpAssign,
                     mk (TLocal (match ctx.in_value with None -> Globals.die "" __LOC__ | Some v -> v)) t_dynamic e.epos,
@@ -1279,7 +1293,8 @@ and gen_value ctx e =
         gen_block_element ctx (mk (TTry (block (assign b),
                                          List.map (fun (v,e) -> v, block (assign e)) catchs
                                         )) e.etype e.epos);
-        v()
+        v();
+    clear_mapping ()
 
 and gen_tbinop ctx op e1 e2 =
     (match op, e1.eexpr, e2.eexpr with
@@ -1865,10 +1880,26 @@ let generate_type_forward ctx = function
     | TTypeDecl _ | TAbstractDecl _ -> ()
 
 let alloc_ctx com =
+    let smap =
+		if com.debug || Common.defined com Define.SourceMap then
+			Some {
+				source_last_pos = { file = 0; line = 0; col = 0};
+				print_comma = false;
+				output_last_col = 0;
+				output_current_col = 0;
+				sources = DynArray.create();
+				sources_hash = Hashtbl.create 0;
+				mappings = Rbuffer.create 16;
+				current_expr = None;
+			}
+		else
+			None
+	in
     let ctx = {
         com = com;
         buf = Buffer.create 16000;
         packages = Hashtbl.create 0;
+        smap = smap;
         statics = [];
         inits = [];
         current = null_class;
@@ -2174,6 +2205,10 @@ let generate com =
     if anyExposed then
         println ctx "return _hx_exports";
 
+    (match ctx.smap with
+    | Some smap -> write_mappings ctx.com smap ""
+    | None -> try Sys.remove (com.file ^ ".map") with _ -> ());
+
     let ch = open_out_bin com.file in
     output_string ch (Buffer.contents ctx.buf);
     close_out ch

+ 1 - 2
src/generators/genpy.ml

@@ -38,8 +38,7 @@ module Utils = struct
 			abort (Printf.sprintf "Could not find type %s\n" (s_type_path path)) null_pos
 
 	let mk_static_field c cf p =
-			let ta = mk_anon ~fields:c.cl_statics (ref (ClassStatics c)) in
-			let ethis = mk (TTypeExpr (TClassDecl c)) ta p in
+			let ethis = Texpr.Builder.make_static_this c p in
 			let t = monomorphs cf.cf_params cf.cf_type in
 			mk (TField (ethis,(FStatic (c,cf)))) t p
 

+ 1 - 3
src/generators/genswf.ml

@@ -149,9 +149,7 @@ let build_dependencies t =
 		| Some x -> add_inherit x);
 		List.iter (fun tp ->
 			(* add type-parameters constraints dependencies *)
-			match follow tp.ttp_type with
-			| TInst (c,_) -> List.iter add_inherit c.cl_implements
-			| _ -> ()
+			List.iter add_inherit tp.ttp_class.cl_implements
 		) c.cl_params;
 		List.iter add_inherit c.cl_implements;
 	| TEnumDecl e when not e.e_extern ->

+ 4 - 4
src/generators/genswf9.ml

@@ -238,8 +238,8 @@ let rec type_id ctx t =
 		| _ -> def())
 	| TInst (c,_) ->
 		(match c.cl_kind with
-		| KTypeParameter l ->
-			(match l with
+		| KTypeParameter ttp ->
+			(match get_constraints ttp with
 			| [t] -> type_id ctx t
 			| _ -> type_path ctx ([],"Object"))
 		| _ ->
@@ -1066,7 +1066,7 @@ let rec gen_expr_content ctx retval e =
 		gen_constant ctx c e.etype e.epos
 	| TThrow e ->
 		ctx.infos.icond <- true;
-		if has_feature ctx.com "haxe.CallStack.exceptionStack" && not (Exceptions.is_haxe_exception e.etype) then begin
+		if has_feature ctx.com "haxe.CallStack.exceptionStack" && not (ExceptionFunctions.is_haxe_exception e.etype) then begin
 			getvar ctx (VGlobal (type_path ctx (["flash"],"Boot")));
 			let id = type_path ctx (["flash";"errors"],"Error") in
 			write ctx (HFindPropStrict id);
@@ -1240,7 +1240,7 @@ let rec gen_expr_content ctx retval e =
 					| _ -> Type.iter call_loop e
 				in
 				let has_call = (try call_loop e; false with Exit -> true) in
-				if has_call && has_feature ctx.com "haxe.CallStack.exceptionStack" && not (Exceptions.is_haxe_exception v.v_type) then begin
+				if has_call && has_feature ctx.com "haxe.CallStack.exceptionStack" && not (ExceptionFunctions.is_haxe_exception v.v_type) then begin
 					getvar ctx (gen_local_access ctx v e.epos Read);
 					write ctx (HAsType (type_path ctx (["flash";"errors"],"Error")));
 					let j = jump ctx J3False in

+ 16 - 2
src/generators/hl2c.ml

@@ -990,7 +990,15 @@ let generate_function ctx f =
 		| OGetMem (r,b,idx) ->
 			sexpr "%s = *(%s*)(%s + %s)" (reg r) (ctype (rtype r)) (reg b) (reg idx)
 		| OGetArray (r, arr, idx) ->
-			sexpr "%s = ((%s*)(%s + 1))[%s]" (reg r) (ctype (rtype r)) (reg arr) (reg idx)
+            (match rtype arr with
+            | HAbstract _ ->
+                (match rtype r with
+                | HStruct _ | HObj _ ->
+			        sexpr "%s = ((%s)%s) + %s" (reg r) (ctype (rtype r)) (reg arr) (reg idx)
+                | _ ->
+			        sexpr "%s = ((%s*)%s)[%s]" (reg r) (ctype (rtype r)) (reg arr) (reg idx))
+            | _ ->
+			    sexpr "%s = ((%s*)(%s + 1))[%s]" (reg r) (ctype (rtype r)) (reg arr) (reg idx))
 		| OSetUI8 (b,idx,r) ->
 			sexpr "*(unsigned char*)(%s + %s) = (unsigned char)%s" (reg b) (reg idx) (reg r)
 		| OSetUI16 (b,idx,r) ->
@@ -998,7 +1006,11 @@ let generate_function ctx f =
 		| OSetMem (b,idx,r) ->
 			sexpr "*(%s*)(%s + %s) = %s" (ctype (rtype r)) (reg b) (reg idx) (reg r)
 		| OSetArray (arr,idx,v) ->
-			sexpr "((%s*)(%s + 1))[%s] = %s" (ctype (rtype v)) (reg arr) (reg idx) (reg v)
+            (match rtype arr with
+            | HAbstract _ ->
+			    sexpr "((%s*)%s)[%s] = %s" (ctype (rtype v)) (reg arr) (reg idx) (reg v)
+            | _ ->
+			    sexpr "((%s*)(%s + 1))[%s] = %s" (ctype (rtype v)) (reg arr) (reg idx) (reg v))
 		| OSafeCast (r,v) ->
 			let tsrc = rtype v in
 			let t = rtype r in
@@ -1098,6 +1110,8 @@ let generate_function ctx f =
 				Globals.die "" __LOC__
 			)) in
 			sexpr "__hl_prefetch_m%d(%s)" mode expr
+		| OAsm _ ->
+			sexpr "UNSUPPORTED ASM OPCODE";
 	) f.code;
 	flush_options (Array.length f.code);
 	unblock();

+ 13 - 0
src/generators/hlcode.ml

@@ -202,6 +202,7 @@ type opcode =
 	| ORefOffset of reg * reg * reg
 	| ONop of string
 	| OPrefetch of reg * field index * int
+    | OAsm of int * int * reg
 
 type fundecl = {
 	fpath : string * string;
@@ -574,6 +575,18 @@ let ostr fstr o =
 	| ORefOffset (r,r2,off) -> Printf.sprintf "refoffset %d, %d, %d" r r2 off
 	| ONop s -> if s = "" then "nop" else "nop " ^ s
 	| OPrefetch (r,f,mode) -> Printf.sprintf "prefetch %d[%d] %d" r f mode
+	| OAsm (mode, value, reg) ->
+		match mode with
+		| 0 when reg = 0 ->
+			Printf.sprintf "asm %.2X" value
+		| 1 when reg = 0 ->
+			Printf.sprintf "asm scratch R%d" value
+		| 2 ->
+			Printf.sprintf "asm R%d := %d" value (reg - 1)
+		| 3 ->
+			Printf.sprintf "asm %d := R%d" (reg - 1) value
+		| _ ->
+			Printf.sprintf "asm[%d] %d%s" mode value (if reg = 0 then "" else ", " ^ string_of_int (reg-1))
 
 let fundecl_name f = if snd f.fpath = "" then "fun$" ^ (string_of_int f.findex) else (fst f.fpath) ^ "." ^ (snd f.fpath)
 

+ 6 - 6
src/generators/hlinterp.ml

@@ -1154,6 +1154,8 @@ let interp ctx f args =
 			(match get r2, get off with
 			| VRef (RArray (a,pos),t), VInt i -> set r (VRef (RArray (a,pos + Int32.to_int i),t))
 			| _ -> Globals.die "" __LOC__)
+		| OAsm _ ->
+			throw_msg ctx "Unsupported ASM"
 		| ONop _ | OPrefetch _ ->
 			()
 		);
@@ -2456,17 +2458,13 @@ let check code macros =
 				reg p HI32;
 				(match rtype v with HI32 | HI64 | HF32 | HF64 -> () | _ -> error (reg_inf r ^ " should be numeric"));
 			| OSetArray (a,i,v) ->
-				reg a HArray;
+				(match rtype a with HAbstract ("hl_carray",_) -> () | _ -> reg a HArray);
 				reg i HI32;
 				ignore(rtype v);
-			| OUnsafeCast (a,b) ->
-				is_dyn a;
-				is_dyn b;
-			| OSafeCast (a,b) ->
+            | OUnsafeCast (a,b) | OSafeCast (a,b) ->
 				ignore(rtype a);
 				ignore(rtype b);
 			| OArraySize (r,a) ->
-				(match rtype a with HAbstract ("hl_carray",_) -> () | _ -> reg a HArray);
 				reg r HI32
 			| OType (r,_) ->
 				reg r HType
@@ -2549,6 +2547,8 @@ let check code macros =
 				();
 			| OPrefetch (r,f,_) ->
 				if f = 0 then ignore(rtype r) else ignore(tfield r (f - 1) false)
+			| OAsm (_,_,r) ->
+				if r > 0 then ignore(rtype (r - 1))
 		) f.code
 		(* TODO : check that all path correctly initialize NULL values and reach a return *)
 	in

+ 11 - 0
src/generators/hlopt.ml

@@ -166,6 +166,12 @@ let opcode_fx frw op =
 		()
 	| OPrefetch (r,_,_) ->
 		read r
+    | OAsm (_,_,r) ->
+        if r > 0 then begin
+            (* assume both *)
+            read (r - 1);
+            write (r - 1);
+        end
 
 let opcode_eq a b =
 	match a, b with
@@ -437,6 +443,11 @@ let opcode_map read write op =
 	| OPrefetch (r, fid, mode) ->
 		let r2 = read r in
 		OPrefetch (r2, fid, mode)
+	| OAsm (_, _, 0) ->
+		op
+	| OAsm (mode, value, r) ->
+		let r2 = read (r - 1) in
+		OAsm (mode, value, (write r2) + 1)
 
 (* build code graph *)
 

+ 158 - 0
src/generators/jsSourcemap.ml

@@ -0,0 +1,158 @@
+(*
+	The Haxe Compiler
+	Copyright (C) 2005-2019  Haxe Foundation
+
+	This program is free software; you can redistribute it and/or
+	modify it under the terms of the GNU General Public License
+	as published by the Free Software Foundation; either version 2
+	of the License, or (at your option) any later version.
+
+	This program is distributed in the hope that it will be useful,
+	but WITHOUT ANY WARRANTY; without even the implied warranty of
+	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+	GNU General Public License for more details.
+
+	You should have received a copy of the GNU General Public License
+	along with this program; if not, write to the Free Software
+	Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *)
+open Extlib_leftovers
+open Globals
+open Type
+open Common
+
+type sourcemap = {
+	sources : (string) DynArray.t;
+	sources_hash : (string, int) Hashtbl.t;
+	mappings : Rbuffer.t;
+
+	mutable source_last_pos : sourcemap_pos;
+	mutable print_comma : bool;
+	mutable output_last_col : int;
+	mutable output_current_col : int;
+	mutable current_expr : sourcemap_pos option;
+}
+
+and sourcemap_pos = {
+	file : int;
+	line : int;
+	col : int;
+}
+
+let encode_mapping smap pos =
+	if smap.print_comma then
+		Rbuffer.add_char smap.mappings ','
+	else
+		smap.print_comma <- true;
+
+	let base64_vlq number =
+		let encode_digit digit =
+			let chars = [|
+				'A';'B';'C';'D';'E';'F';'G';'H';'I';'J';'K';'L';'M';'N';'O';'P';
+				'Q';'R';'S';'T';'U';'V';'W';'X';'Y';'Z';'a';'b';'c';'d';'e';'f';
+				'g';'h';'i';'j';'k';'l';'m';'n';'o';'p';'q';'r';'s';'t';'u';'v';
+				'w';'x';'y';'z';'0';'1';'2';'3';'4';'5';'6';'7';'8';'9';'+';'/'
+			|] in
+			Array.unsafe_get chars digit
+		in
+		let to_vlq number =
+			if number < 0 then
+				((-number) lsl 1) + 1
+			else
+				number lsl 1
+		in
+		let rec loop vlq =
+			let shift = 5 in
+			let base = 1 lsl shift in
+			let mask = base - 1 in
+			let continuation_bit = base in
+			let digit = vlq land mask in
+			let next = vlq asr shift in
+			Rbuffer.add_char smap.mappings (encode_digit (
+				if next > 0 then digit lor continuation_bit else digit));
+			if next > 0 then loop next else ()
+		in
+		loop (to_vlq number)
+	in
+
+	base64_vlq (smap.output_current_col - smap.output_last_col);
+	base64_vlq (pos.file - smap.source_last_pos.file);
+	base64_vlq (pos.line - smap.source_last_pos.line);
+	base64_vlq (pos.col - smap.source_last_pos.col);
+
+	smap.source_last_pos <- pos;
+	smap.output_last_col <- smap.output_current_col
+
+let noop () = ()
+
+let add_mapping smap pos =
+	if pos.pmin < 0 then noop else
+
+	let file = try
+		Hashtbl.find smap.sources_hash pos.pfile
+	with Not_found ->
+		let length = DynArray.length smap.sources in
+		Hashtbl.replace smap.sources_hash pos.pfile length;
+		DynArray.add smap.sources pos.pfile;
+		length
+	in
+
+	let pos =
+		let line, col = Lexer.find_pos pos in
+		let line = line - 1 in
+		{ file = file; line = line; col = col }
+	in
+
+	if smap.source_last_pos <> pos then begin
+		let old_current_expr = smap.current_expr in
+		smap.current_expr <- Some pos;
+		encode_mapping smap pos;
+		(fun () -> smap.current_expr <- old_current_expr)
+	end else
+		noop
+
+let add_mapping smap e =
+	Option.map_default (fun smap -> add_mapping smap e.epos) noop smap
+
+let handle_newlines smap str =
+	Option.may (fun smap ->
+		let rec loop from =
+			try begin
+				let next = String.index_from str from '\n' + 1 in
+				Rbuffer.add_char smap.mappings ';';
+				smap.output_last_col <- 0;
+				smap.output_current_col <- 0;
+				smap.print_comma <- false;
+				Option.may (encode_mapping smap) smap.current_expr;
+				loop next
+			end with Not_found ->
+				smap.output_current_col <- smap.output_current_col + (String.length str - from);
+		in
+		loop 0
+	) smap
+
+let write_mappings (com : Common.context) smap source_path_prefix =
+	let basefile = Filename.basename com.file in
+	let channel = open_out_bin (com.file ^ ".map") in
+	let sources = DynArray.to_list smap.sources in
+	let to_url file =
+		ExtString.String.map (fun c -> if c == '\\' then '/' else c) (Path.get_full_path file)
+	in
+	output_string channel "{\n";
+	output_string channel "\"version\":3,\n";
+	output_string channel ("\"file\":\"" ^ (String.concat "\\\\" (ExtString.String.nsplit basefile "\\")) ^ "\",\n");
+	output_string channel ("\"sourceRoot\":\"\",\n");
+	output_string channel ("\"sources\":[" ^
+		(String.concat "," (List.map (fun s -> "\"" ^ source_path_prefix ^ to_url s ^ "\"") sources)) ^
+		"],\n");
+	if Common.defined com Define.SourceMapContent then begin
+		output_string channel ("\"sourcesContent\":[" ^
+			(String.concat "," (List.map (fun s -> try "\"" ^ StringHelper.s_escape (Std.input_file ~bin:true s) ^ "\"" with _ -> "null") sources)) ^
+			"],\n");
+	end;
+	output_string channel "\"names\":[],\n";
+	output_string channel "\"mappings\":\"";
+	Rbuffer.output_buffer channel smap.mappings;
+	output_string channel "\"\n";
+	output_string channel "}";
+	close_out channel

+ 5 - 0
src/macro/eval/eval.ml

@@ -0,0 +1,5 @@
+include EvalEncode
+include EvalDecode
+include EvalValue
+include EvalContext
+include EvalMain

+ 0 - 5
src/macro/eval/evalContext.ml

@@ -302,11 +302,6 @@ module GlobalState = struct
 
 	let stdlib : builtins option ref = ref None
 	let macro_lib : (string,value) Hashtbl.t = Hashtbl.create 0
-
-	let cleanup ctx =
-		(* curapi holds a reference to the typing context which we don't want to persist. Let's unset it so the
-		   context can be collected. *)
-		ctx.curapi <- Obj.magic ""
 end
 
 let get_ctx () = (!GlobalState.get_ctx_ref)()

+ 1 - 1
src/macro/eval/evalDebugSocket.ml

@@ -486,7 +486,7 @@ module ValueCompletion = struct
 		DisplayPosition.display_position#set {p with pmin = offset; pmax = offset};
 		begin try
 			let e = parse_expr ctx text p in
-			let e = Display.ExprPreprocessing.find_before_pos DMDefault e in
+			let e = ExprPreprocessing.find_before_pos DMDefault e in
 			save();
 			let rec loop e = match fst e with
 			| EDisplay(e1,DKDot) ->

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

@@ -27,7 +27,6 @@ open EvalField
 exception Break
 exception Continue
 exception Return of value
-exception Sys_exit of int
 
 let s_value_kind = function
 	| VNull -> "VNull"

+ 2 - 1
src/macro/eval/evalLuv.ml

@@ -554,7 +554,8 @@ let uv_error_fields = [
 						let messages = ref [] in
 						HaxeError.recurse_error (fun depth err ->
 							let cm = make_compiler_message ~from_macro:err.err_from_macro (HaxeError.error_msg err.err_message) err.err_pos depth DKCompilerMessage Error in
-							match MessageReporting.compiler_message_string cm with
+							let ectx = MessageReporting.create_error_context false in
+							match MessageReporting.compiler_message_string ectx cm with
 								| None -> ()
 								| Some str -> messages := str :: !messages
 						) err;

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

@@ -145,7 +145,8 @@ let create com api is_macro =
 		Which is printing an error to stderr and exiting with code 2 *)
 	Luv.Error.set_on_unhandled_exception (fun ex ->
 		match ex with
-		| Sys_exit _ -> raise ex
+		| EvalTypes.Sys_exit _ ->
+			raise ex
 		| _ ->
 			let msg = match ex with
 				| Error.Error err ->

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

@@ -2590,7 +2590,7 @@ module StdSys = struct
 	)
 
 	let exit = vfun1 (fun code ->
-		raise (Sys_exit(decode_int code));
+		raise (EvalTypes.Sys_exit(decode_int code));
 	)
 
 	let getChar = vfun1 (fun echo ->

+ 1 - 1
src/macro/eval/evalThread.ml

@@ -100,7 +100,7 @@ let run ctx f thread =
 		let msg = get_exc_error_message ctx v stack p in
 		prerr_endline msg;
 		close();
-	| Sys_exit i ->
+	| EvalTypes.Sys_exit i ->
 		close();
 		exit i;
 	| exc ->

+ 1 - 0
src/macro/eval/evalTypes.ml

@@ -0,0 +1 @@
+exception Sys_exit of int

+ 10 - 38
src/macro/macroApi.ml

@@ -1142,7 +1142,7 @@ and encode_method_kind m =
 and encode_class_kind k =
 	let tag, pl = (match k with
 		| KNormal -> 0, []
-		| KTypeParameter pl -> 1, [encode_tparams pl]
+		| KTypeParameter ttp -> 1, [encode_tparams (get_constraints ttp)] (* TTPTODO *)
 		| KModuleFields m -> 2, [encode_string (s_type_path m.m_path)]
 		| KExpr e -> 3, [encode_expr e]
 		| KGeneric -> 4, []
@@ -1442,14 +1442,6 @@ let decode_tconst c =
 	| 6, [] -> TSuper
 	| _ -> raise Invalid_expr
 
-let decode_type_params v =
-	List.map (fun v ->
-		let name = decode_string (field v "name") in
-		let t = decode_type (field v "t") in
-		let default = opt decode_type (field v "defaultType") in
-		mk_type_param name t default
-	) (decode_array v)
-
 let decode_tvar v =
 	(Obj.obj (decode_unsafe (field v "$")) : tvar)
 
@@ -1478,31 +1470,6 @@ let decode_field_kind v =
 	| 1, [m] -> Method (decode_method_kind m)
 	| _ -> raise Invalid_expr
 
-let decode_cfield v =
-	let public = decode_bool (field v "isPublic") in
-	let extern = decode_bool (field v "isExtern") in
-	let final = decode_bool (field v "isFinal") in
-	let abstract = decode_bool (field v "isAbstract") in
-	let cf = {
-		cf_name = decode_string (field v "name");
-		cf_type = decode_type (field v "type");
-		cf_pos = decode_pos (field v "pos");
-		cf_name_pos = decode_pos (field v "namePos");
-		cf_doc = decode_doc (field v "doc");
-		cf_meta = []; (* TODO *)
-		cf_kind = decode_field_kind (field v "kind");
-		cf_params = decode_type_params (field v "params");
-		cf_expr = None;
-		cf_expr_unoptimized = None;
-		cf_overloads = decode_ref (field v "overloads");
-		cf_flags = 0;
-	} in
-	if public then add_class_field_flag cf CfPublic;
-	if extern then add_class_field_flag cf CfExtern;
-	if final then add_class_field_flag cf CfFinal;
-	if abstract then add_class_field_flag cf CfAbstract;
-	cf
-
 let decode_efield v =
 	let rec get_enum t =
 		match follow t with
@@ -2120,7 +2087,7 @@ let macro_api ccom get_api =
 			if name = "" then failwith "Empty resource name";
 			Hashtbl.replace (ccom()).resources name data;
 			let m = (get_api()).current_module() in
-			m.m_extra.m_binded_res <- PMap.add name data m.m_extra.m_binded_res;
+			DynArray.add m.m_extra.m_cache_bound_objects (Resource(name,data));
 			vnull
 		);
 		"get_resources", vfun0 (fun() ->
@@ -2303,10 +2270,13 @@ let macro_api ccom get_api =
 		"apply_params", vfun3 (fun tpl tl t ->
 			let tl = List.map decode_type (decode_array tl) in
 			let tpl = List.map (fun v ->
-				let name = decode_string (field v "name") in
 				let t = decode_type (field v "t") in
 				let default = None in (* we don't care here *)
-				mk_type_param  name t default
+				let c = match t with
+					| TInst(c,_) -> c
+					| _ -> die "" __LOC__
+				in
+				mk_type_param c TPHType default None
 			) (decode_array tpl) in
 			let rec map t = match t with
 				| TInst({cl_kind = KTypeParameter _},_) ->
@@ -2330,6 +2300,8 @@ let macro_api ccom get_api =
 					failwith ("unable to find file for inclusion: " ^ file)
 			in
 			(ccom()).include_files <- (file, position) :: (ccom()).include_files;
+			let m = (get_api()).current_module() in
+			DynArray.add m.m_extra.m_cache_bound_objects (IncludeFile(file,position));
 			vnull
 		);
 		(* Compilation server *)
@@ -2345,7 +2317,7 @@ let macro_api ccom get_api =
 			List.iter (fun v ->
 				let s = decode_string v in
 				let s = com.file_keys#get s in
-				cs#taint_modules s "server_invalidate_files";
+				cs#taint_modules s ServerInvalidateFiles;
 				cs#remove_files s;
 			) (decode_array a);
 			vnull

+ 2 - 2
src/optimization/analyzer.ml

@@ -375,11 +375,11 @@ module ConstPropagation = DataFlow(struct
 	let top = Top
 	let bottom = Bottom
 
-	let rec equals lat1 lat2 = match lat1,lat2 with
+	let equals lat1 lat2 = match lat1,lat2 with
 		| Top,Top | Bottom,Bottom -> true
 		| Const ct1,Const ct2 -> ct1 = ct2
 		| Null t1,Null t2 -> t1 == t2
-		| EnumValue(i1,tl1),EnumValue(i2,tl2) -> i1 = i2 && safe_for_all2 equals tl1 tl2
+		| EnumValue(i1,[]),EnumValue(i2,[]) -> i1 = i2
 		| ModuleType(mt1,_),ModuleType (mt2,_) -> mt1 == mt2
 		| _ -> false
 

+ 26 - 23
src/optimization/dce.ml

@@ -50,19 +50,9 @@ let push_class dce c =
 		dce.curclass <- old
 	)
 
-let find_field c name kind =
-	match kind with
-	| CfrConstructor ->
-		begin match c.cl_constructor with Some cf -> cf | None -> raise Not_found end
-	| CfrStatic ->
-		PMap.find name c.cl_statics
-	| CfrMember ->
-		PMap.find name c.cl_fields
-
 let resolve_class_field_ref ctx cfr =
 	let ctx = if cfr.cfr_is_macro && not ctx.is_macro_context then Option.get (ctx.get_macros()) else ctx in
-	let path = ctx.type_to_module#find cfr.cfr_path in
-	let m = ctx.module_lut#find path in
+	let m = ctx.module_lut#find_by_type cfr.cfr_path in
 
 	Option.get (ExtList.List.find_map (fun mt -> match mt with
 		| TClassDecl c when c.cl_path = cfr.cfr_path ->
@@ -247,10 +237,10 @@ and mark_t dce p t =
 	if not (List.exists (fun t2 -> Type.fast_eq t t2) dce.t_stack) then begin
 		dce.t_stack <- t :: dce.t_stack;
 		begin match follow t with
-		| TInst({cl_kind = KTypeParameter tl} as c,pl) ->
+		| TInst({cl_kind = KTypeParameter ttp} as c,pl) ->
 			if not (Meta.has Meta.Used c.cl_meta) then begin
 				c.cl_meta <- (mk_used_meta c.cl_pos) :: c.cl_meta;
-				List.iter (mark_t dce p) tl;
+				List.iter (mark_t dce p) (get_constraints ttp);
 			end;
 			List.iter (mark_t dce p) pl
 		| TInst(c,pl) ->
@@ -358,7 +348,7 @@ and field dce c n kind =
 		end else match c.cl_super with Some (csup,_) -> field dce csup n kind | None -> raise Not_found
 	with Not_found -> try
 		match c.cl_kind with
-		| KTypeParameter tl ->
+		| KTypeParameter ttp ->
 			let rec loop tl = match tl with
 				| [] -> raise Not_found
 				| TInst(c,_) :: cl ->
@@ -366,7 +356,7 @@ and field dce c n kind =
 				| t :: tl ->
 					loop tl
 			in
-			loop tl
+			loop (get_constraints ttp)
 		| _ -> raise Not_found
 	with Not_found ->
 		if dce.debug then prerr_endline ("[DCE] Field " ^ n ^ " not found on " ^ (s_type_path c.cl_path)) else ())
@@ -511,6 +501,15 @@ and expr_field dce e fa is_call_expr =
 	end;
 	expr dce e;
 
+and check_op dce op = match op with
+	| OpMod ->
+		check_and_add_feature dce "binop_%";
+	| OpUShr ->
+		check_and_add_feature dce "binop_>>>";
+	| OpAssignOp op ->
+		check_op dce op
+	| _ ->
+		()
 
 and expr dce e =
 	mark_t dce e.epos e.etype;
@@ -605,7 +604,12 @@ and expr dce e =
 		check_and_add_feature dce "dynamic_array_read";
 		expr dce e1;
 		expr dce e2;
-	| TBinop( (OpAssign | OpAssignOp _), ({eexpr = TArray({etype = TDynamic None},_)} as e1), e2) ->
+	| TBinop(OpAssign, ({eexpr = TArray({etype = TDynamic None},_)} as e1), e2) ->
+		check_and_add_feature dce "dynamic_array_write";
+		expr dce e1;
+		expr dce e2;
+	| TBinop(OpAssignOp op, ({eexpr = TArray({etype = TDynamic None},_)} as e1), e2) ->
+		check_op dce op;
 		check_and_add_feature dce "dynamic_array_write";
 		expr dce e1;
 		expr dce e2;
@@ -629,10 +633,12 @@ and expr dce e =
 		expr dce e1;
 		expr dce e2;
 	| TBinop(OpAssignOp op,({eexpr = TField(_,(FDynamic _ as fa) )} as e1),e2) ->
+		check_op dce op;
 		check_dynamic_write dce fa;
 		expr dce e1;
 		expr dce e2;
 	| TBinop(OpAssignOp op,({eexpr = TField(_,(FAnon cf as fa) )} as e1),e2) ->
+		check_op dce op;
 		if Meta.has Meta.Optional cf.cf_meta then
 			check_anon_optional_write dce fa
 		else
@@ -655,12 +661,8 @@ and expr dce e =
 		check_and_add_feature dce "type_param_binop_!=";
 		expr dce e1;
 		expr dce e2;
-	| TBinop(OpMod,e1,e2) ->
-		check_and_add_feature dce "binop_%";
-		expr dce e1;
-		expr dce e2;
-	| TBinop((OpUShr | OpAssignOp OpUShr),e1,e2) ->
-		check_and_add_feature dce "binop_>>>";
+	| TBinop(op,e1,e2) ->
+		check_op dce op;
 		expr dce e1;
 		expr dce e2;
 	| TCall(({ eexpr = TField(ef, fa) } as e2), el ) ->
@@ -721,8 +723,9 @@ let collect_entry_points dce com =
 		match t with
 		| TClassDecl c ->
 			let keep_class = keep_whole_class dce c && (not (has_class_flag c CExtern) || (has_class_flag c CInterface)) in
+			let is_struct = dce.com.platform = Hl && Meta.has Meta.Struct c.cl_meta in
 			let loop kind cf =
-				if keep_class || keep_field dce cf c kind then mark_field dce c cf kind
+				if keep_class || is_struct || keep_field dce cf c kind then mark_field dce c cf kind
 			in
 			List.iter (loop CfrStatic) c.cl_ordered_statics;
 			List.iter (loop CfrMember) c.cl_ordered_fields;

+ 6 - 4
src/optimization/inline.ml

@@ -6,6 +6,8 @@ open Common
 open Typecore
 open Error
 
+let maybe_reapply_overload_call_ref = ref (fun _ _ -> assert false)
+
 let mk_untyped_call name p params =
 	{
 		eexpr = TCall({ eexpr = TIdent name; etype = t_dynamic; epos = p }, params);
@@ -100,7 +102,7 @@ let api_inline ctx c field params p =
 		let m = (try ctx.com.module_lut#find path with Not_found -> die "" __LOC__) in
 		add_dependency ctx.m.curmod m;
 		Option.get (ExtList.List.find_map (function
-			| TClassDecl cl when cl.cl_path = path -> Some (make_static_this cl p)
+			| TClassDecl cl when cl.cl_path = path -> Some (Texpr.Builder.make_static_this cl p)
 			| _ -> None
 		) m.m_types)
 	in
@@ -160,7 +162,7 @@ let api_inline ctx c field params p =
 			None)
 	| (["js"],"Boot"),"__downcastCheck",[o; {eexpr = TTypeExpr (TClassDecl cls) } as t] when ctx.com.platform = Js ->
 		if (has_class_flag cls CInterface) then
-			Some (Texpr.Builder.fcall (make_static_this c p) "__implements" [o;t] tbool p)
+			Some (Texpr.Builder.fcall (Texpr.Builder.make_static_this c p) "__implements" [o;t] tbool p)
 		else
 			Some (Texpr.Builder.fcall (eJsSyntax()) "instanceof" [o;t] tbool p)
 	| (["haxe";"ds";"_Vector"],"Vector_Impl_"),("fromArrayCopy"),[{ eexpr = TArrayDecl args } as edecl] -> (try
@@ -221,7 +223,7 @@ let inline_default_config cf t =
 			c.cl_params @ ct, pl @ cpl
 	in
 	let rec loop t = match follow t with
-		| TInst({cl_kind = KTypeParameter tl},_) -> List.fold_left (fun (params',tl') (params,tl) -> (params @ params',tl @ tl')) ([],[]) (List.map loop tl)
+		| TInst({cl_kind = KTypeParameter ttp},_) -> List.fold_left (fun (params',tl') (params,tl) -> (params @ params',tl @ tl')) ([],[]) (List.map loop (get_constraints ttp))
 		| TInst (c,pl) -> get_params c pl
 		| _ -> ([],[])
 	in
@@ -614,7 +616,7 @@ class inline_state ctx ethis params cf f p = object(self)
 				else map_type
 			in
 			let e = Type.map_expr_type (map_expr_type map_type) map_type (map_var map_type) e in
-			CallUnification.maybe_reapply_overload_call ctx e
+			(!maybe_reapply_overload_call_ref) ctx e
 		in
 		let e = map_expr_type map_type e in
 		let rec drop_unused_vars e =

+ 18 - 2
src/syntax/grammar.mly

@@ -1715,8 +1715,24 @@ and parse_call_params f p1 s =
 				let e = check_signature_mark e p1 p2 in
 				f (List.rev (e :: acc)) p2
 			| [< '(Comma,p2); '(PClose,p3) >] ->
-				let e = check_signature_mark e p1 p3 in
-				f (List.rev (e :: acc)) p3
+				if (is_signature_display()) then begin
+					let prev_arg_pos = punion p1 p2 in
+					let comma_paren_pos = punion p2 p3 in
+					(* first check wether the display position is within the previous argument *)
+					if encloses_position_gt display_position#get prev_arg_pos then begin
+						(* wrap the argument that was just parsed *)
+						let e = mk_display_expr e DKMarked in
+						f (List.rev (e :: acc)) p3
+					(* then check wether the display position is between the comma and the closing parenthesis *)
+					end else if encloses_position_gt display_position#get comma_paren_pos then begin
+						(* add a dummy final argument *)
+						let e2 = mk_display_expr (mk_null_expr comma_paren_pos) DKMarked in
+						f (List.rev (e2 :: e :: acc)) p3
+					end else f (List.rev (e :: acc)) p3
+				end else begin
+				(* if not in signature display mode don't check anything *)
+					f (List.rev (e :: acc)) p3
+				end
 			| [< '(Comma,p2) >] ->
 				let e = check_signature_mark e p1 p2 in
 				parse_next_param (e :: acc) p2

+ 26 - 10
src/typing/callUnification.ml

@@ -5,6 +5,7 @@ open Common
 open Typecore
 open Error
 open FieldAccess
+open FieldCallCandidate
 
 let unify_call_args ctx el args r callp inline force_inline in_overload =
 	let call_error err p = raise_error_msg (Call_error err) p in
@@ -350,14 +351,6 @@ let unify_field_call ctx fa el_typed el p inline =
 		in
 		loop candidates
 	in
-	let fail_fun () =
-		let tf = TFun(List.map (fun _ -> ("",false,t_dynamic)) el,t_dynamic) in
-		let call () =
-			let ef = mk (TField(fa.fa_on,FieldAccess.apply_fa fa.fa_field fa.fa_host)) tf fa.fa_pos in
-			mk (TCall(ef,[])) t_dynamic p
-		in
-		make_field_call_candidate [] t_dynamic [] tf fa.fa_field call
-	in
 	let maybe_check_access cf =
 		(* type_field doesn't check access for overloads, so let's check it here *)
 		begin match co with
@@ -367,13 +360,34 @@ let unify_field_call ctx fa el_typed el p inline =
 			()
 		end;
 	in
+	(* There's always a chance that we never even came across the EDisplay in an argument, so let's look for it (issue #11422). *)
+	let check_display_args () =
+		if ctx.is_display_file then begin
+			let rec loop el = match el with
+				| [] ->
+					()
+				| e :: el ->
+					if Ast.exists (function EDisplay _ -> true | _ -> false) e then
+						ignore(type_expr ctx e WithType.value)
+					else
+						loop el
+			in
+			loop el
+		end;
+	in
 	match candidates with
 	| [cf] ->
 		if overload_kind = OverloadProper then maybe_check_access cf;
 		begin try
 			commit_delayed_display (attempt_call cf false)
 		with Error _ when Common.ignore_error ctx.com ->
-			fail_fun();
+			check_display_args();
+			let tf = TFun(List.map (fun _ -> ("",false,t_dynamic)) el,t_dynamic) in
+			let call () =
+				let ef = mk (TField(fa.fa_on,FieldAccess.apply_fa fa.fa_field fa.fa_host)) tf fa.fa_pos in
+				mk (TCall(ef,[])) t_dynamic p
+			in
+			make_field_call_candidate [] t_dynamic [] tf fa.fa_field call
 		end
 	| _ ->
 		let candidates,failures = attempt_calls candidates in
@@ -385,6 +399,7 @@ let unify_field_call ctx fa el_typed el p inline =
 				) delayed_display;
 				cf,err
 			) failures in
+			check_display_args();
 			let failures = remove_duplicates (fun (_,e1) (_,e2) -> (MessageReporting.print_error e1) <> (MessageReporting.print_error e2)) failures in
 			begin match failures with
 			| [_,err] ->
@@ -408,7 +423,8 @@ let unify_field_call ctx fa el_typed el p inline =
 			end
 		in
 		if overload_kind = OverloadProper then begin match Overloads.Resolution.reduce_compatible candidates with
-			| [] -> fail()
+			| [] ->
+				fail()
 			| [fcc] ->
 				maybe_check_access fcc.fc_field;
 				commit_delayed_display fcc

+ 39 - 0
src/typing/fieldCallCandidate.ml

@@ -0,0 +1,39 @@
+
+open Type
+
+(* This record holds transient information about an (attempted) call on a field. It is created when resolving
+   field calls and is passed to overload filters. *)
+   type 'a field_call_candidate = {
+	(* The argument expressions for this call and whether or not the argument is optional on the
+	   target function. *)
+	fc_args  : texpr list;
+	(* The applied return type. *)
+	fc_ret   : Type.t;
+	(* The applied function type. *)
+	fc_type  : Type.t;
+	(* The class field being called. *)
+	fc_field : tclass_field;
+	(* The field monomorphs that were created for this call. *)
+	fc_monos : Type.t list;
+	(* The custom data associated with this call. *)
+	fc_data  : 'a;
+}
+
+let make_field_call_candidate args ret monos t cf data = {
+	fc_args  = args;
+	fc_type  = t;
+	fc_field = cf;
+	fc_data  = data;
+	fc_ret   = ret;
+	fc_monos = monos;
+}
+
+let s_field_call_candidate fcc =
+	let pctx = print_context() in
+	let se = s_expr_pretty false "" false (s_type pctx) in
+	let sl_args = List.map se fcc.fc_args in
+	Printer.s_record_fields "" [
+		"fc_args",String.concat ", " sl_args;
+		"fc_type",s_type pctx fcc.fc_type;
+		"fc_field",Printf.sprintf "%s: %s" fcc.fc_field.cf_name (s_type pctx fcc.fc_field.cf_type)
+	]

+ 2 - 2
src/typing/fields.ml

@@ -319,11 +319,11 @@ let type_field cfg ctx e i p mode (with_type : WithType.t) =
 				snd (class_field_with_access e c tl)
 			with Not_found -> try
 				match c.cl_kind with
-				| KTypeParameter tl ->
+				| KTypeParameter ttp ->
 					type_field_by_list (fun t -> match follow t with
 						| TAbstract _ -> type_field_by_e type_field_by_type (mk_cast e t p);
 						| _ -> raise Not_found
-					) tl
+					) (get_constraints ttp)
 				| _ -> raise Not_found
 			with Not_found ->
 				type_field_by_interfaces e c

+ 4 - 4
src/typing/finalization.ml

@@ -42,14 +42,14 @@ let get_main ctx types =
 			| _ -> raise_typing_error ("Invalid -main : " ^ s_type_path path ^ " has invalid main function") c.cl_pos
 		in
 		if not (ExtType.is_void (follow r)) then raise_typing_error (Printf.sprintf "Return type of main function should be Void (found %s)" (s_type (print_context()) r)) f.cf_name_pos;
-		f.cf_meta <- (Dce.mk_keep_meta f.cf_pos) :: f.cf_meta;
+		if not (Meta.has Meta.Keep f.cf_meta) then f.cf_meta <- (Dce.mk_keep_meta f.cf_pos) :: f.cf_meta;
 		let emain = type_module_type ctx (TClassDecl c) null_pos in
 		let main = mk (TCall (mk (TField (emain,fmode)) ft null_pos,[])) r null_pos in
 		let call_static path method_name =
 			let et = List.find (fun t -> t_path t = path) types in
 			let ec = (match et with TClassDecl c -> c | _ -> die "" __LOC__) in
 			let ef = PMap.find method_name ec.cl_statics in
-			let et = mk (TTypeExpr et) (mk_anon (ref (ClassStatics ec))) null_pos in
+			let et = Texpr.Builder.make_typeexpr et null_pos in
 			mk (TCall (mk (TField (et,FStatic (ec,ef))) ef.cf_type null_pos,[])) ctx.t.tvoid null_pos
 		in
 		(* add haxe.EntryPoint.run() call *)
@@ -101,7 +101,7 @@ type state =
 	| Done
 	| NotYet
 
-let sort_types com (modules : (path,module_def) lookup) =
+let sort_types com (modules : module_lut) =
 	let types = ref [] in
 	let states = Hashtbl.create 0 in
 	let state p = try Hashtbl.find states p with Not_found -> NotYet in
@@ -112,7 +112,7 @@ let sort_types com (modules : (path,module_def) lookup) =
 		match state p with
 		| Done -> ()
 		| Generating ->
-			com.warning WStaticInitOrder [] ("Warning : maybe loop in static generation of " ^ s_type_path p) (t_infos t).mt_pos;
+			module_warning com (t_infos t).mt_module WStaticInitOrder [] ("Warning : maybe loop in static generation of " ^ s_type_path p) (t_infos t).mt_pos;
 		| NotYet ->
 			Hashtbl.add states p Generating;
 			let t = (match t with

+ 1 - 1
src/typing/forLoop.ml

@@ -267,7 +267,7 @@ module IterationKind = struct
 		let t_void = ctx.t.tvoid in
 		let t_int = ctx.t.tint in
 		let mk_field e n =
-			TField (e,try quick_field e.etype n with Not_found -> die "" __LOC__)
+			TField (e,try quick_field e.etype n with Not_found -> Error.raise_msg (Printf.sprintf "Could not find field %s on %s" n (s_type_kind e.etype)) e.epos)
 		in
 		let get_array_length arr p =
 			mk (mk_field arr "length") ctx.com.basic.tint p

+ 1 - 1
src/typing/functionArguments.ml

@@ -22,7 +22,7 @@ let type_function_arg_value ctx t c do_display =
 		| None -> None
 		| Some e ->
 			let p = pos e in
-			let e = if do_display then Display.ExprPreprocessing.process_expr ctx.com e else e in
+			let e = if do_display then Display.preprocess_expr ctx.com e else e in
 			let e = Optimizer.reduce_expression ctx (type_expr ctx e (WithType.with_type t)) in
 			unify ctx e.etype t p;
 			let rec loop e = match e.eexpr with

+ 22 - 23
src/typing/generic.ml

@@ -5,6 +5,7 @@ open Ast
 open Type
 open Typecore
 open Error
+open FieldCallCandidate
 
 type generic_context = {
 	ctx : typer;
@@ -62,7 +63,7 @@ let make_generic ctx ps pt debug p =
 	let rec loop acc_name acc_subst ttpl tl = match ttpl,tl with
 		| ttp :: ttpl,t :: tl ->
 			let name,t = try process t with Exit -> raise_typing_error ("Could not determine type for parameter " ^ ttp.ttp_name) p in
-			loop (name :: acc_name) ((follow ttp.ttp_type,t) :: acc_subst) ttpl tl
+			loop (name :: acc_name) ((ttp.ttp_type,t) :: acc_subst) ttpl tl
 		| [],[] ->
 			let name = String.concat "_" (List.rev acc_name) in
 			name,acc_subst
@@ -174,13 +175,13 @@ let static_method_container gctx c cf p =
 		| TInst(cg,_) -> cg
 		| _ -> raise_typing_error ("Cannot specialize @:generic static method because the generated type name is already used: " ^ name) p
 	with Error { err_message = Module_not_found path } when path = (pack,name) ->
-		let m = (try ctx.com.module_lut#find (ctx.com.type_to_module#find c.cl_path) with Not_found -> die "" __LOC__) in
+		let m = c.cl_module in
 		let mg = {
 			m_id = alloc_mid();
 			m_path = (pack,name);
 			m_types = [];
 			m_statics = None;
-			m_extra = module_extra (s_type_path (pack,name)) m.m_extra.m_sign 0. MFake m.m_extra.m_check_policy;
+			m_extra = module_extra (s_type_path (pack,name)) m.m_extra.m_sign 0. MFake gctx.ctx.com.compilation_step m.m_extra.m_check_policy;
 		} in
 		gctx.mg <- Some mg;
 		let cg = mk_class mg (pack,name) c.cl_pos c.cl_name_pos in
@@ -239,8 +240,9 @@ let build_generic_class ctx c p tl =
 		| TInst (c2,tl) ->
 			(match c2.cl_kind with
 			| KTypeParameter tl ->
-				if not (TypeloadCheck.is_generic_parameter ctx c2) && has_ctor_constraint c2 then
-					raise_typing_error "Type parameters with a constructor cannot be used non-generically" p;
+				(* TPTODO *)
+				(* if not (TypeloadCheck.is_generic_parameter ctx c2) && has_ctor_constraint c2 then
+					raise_typing_error "Type parameters with a constructor cannot be used non-generically" p; *)
 				recurse := true
 			| _ -> ());
 			List.iter check_recursive tl;
@@ -259,7 +261,7 @@ let build_generic_class ctx c p tl =
 		| TInst({ cl_kind = KGenericInstance (csup,_) },_) when c == csup -> t
 		| _ -> raise_typing_error ("Cannot specialize @:generic because the generated type name is already used: " ^ name) p
 	with Error { err_message = Module_not_found path } when path = (pack,name) ->
-		let m = (try ctx.com.module_lut#find (ctx.com.type_to_module#find c.cl_path) with Not_found -> die "" __LOC__) in
+		let m = c.cl_module in
 		if gctx.generic_debug then begin
 			print_endline (Printf.sprintf "[GENERIC] Building @:generic class %s as %s with:" (s_type_path c.cl_path) name);
 			List.iter (fun (t1,(t2,eo)) ->
@@ -280,7 +282,7 @@ let build_generic_class ctx c p tl =
 			m_path = (pack,name);
 			m_types = [];
 			m_statics = None;
-			m_extra = module_extra (s_type_path (pack,name)) m.m_extra.m_sign 0. MFake m.m_extra.m_check_policy;
+			m_extra = module_extra (s_type_path (pack,name)) m.m_extra.m_sign 0. MFake gctx.ctx.com.compilation_step m.m_extra.m_check_policy;
 		} in
 		gctx.mg <- Some mg;
 		let cg = mk_class mg (pack,name) c.cl_pos c.cl_name_pos in
@@ -305,24 +307,21 @@ let build_generic_class ctx c p tl =
 		add_dependency ctx.m.curmod mg;
 		set_type_parameter_dependencies mg tl;
 		let build_field cf_old =
-			(* We have to clone the type parameters (issue #4672). We cannot substitute the constraints immediately because
-			   we need the full substitution list first. *)
-			let param_subst,params = List.fold_left (fun (subst,params) tp -> match follow tp.ttp_type with
-				| TInst(c,tl) as t ->
-					let t2 = TInst({c with cl_module = mg;},tl) in
-					(t,(t2,None)) :: subst,({tp with ttp_type=t2}) :: params
-				| _ -> die "" __LOC__
-			) ([],[]) cf_old.cf_params in
+			let params = List.map (fun ttp ->
+				let c = {ttp.ttp_class with cl_module = mg} in
+				let def = Option.map (generic_substitute_type gctx) ttp.ttp_default in
+				let constraints = match ttp.ttp_constraints with
+					| None -> None
+					| Some constraints -> Some (lazy (List.map (generic_substitute_type gctx) (Lazy.force constraints)))
+				in
+				let ttp' = mk_type_param c ttp.ttp_host def constraints in
+				c.cl_kind <- KTypeParameter ttp';
+				(ttp.ttp_type,ttp')
+			) cf_old.cf_params in
+			let param_subst = List.map (fun (t,ttp) -> t,(ttp.ttp_type,None)) params in
 			let gctx = {gctx with subst = param_subst @ gctx.subst} in
 			let cf_new = {cf_old with cf_pos = cf_old.cf_pos; cf_expr_unoptimized = None} in (* copy *)
-			(* Type parameter constraints are substituted here. *)
-			cf_new.cf_params <- List.rev_map (fun tp -> match follow tp.ttp_type with
-				| TInst({cl_kind = KTypeParameter tl1} as c,_) ->
-					let tl1 = List.map (generic_substitute_type gctx) tl1 in
-					c.cl_kind <- KTypeParameter tl1;
-					tp (* TPTODO: weird mapping *)
-				| _ -> die "" __LOC__
-			) params;
+			cf_new.cf_params <- List.map (fun (_,ttp) -> ttp) params;
 			let f () =
 				ignore(follow cf_old.cf_type);
 				(* We update here because the follow could resolve some TLazy things that end up modifying flags, such as

+ 9 - 17
src/typing/macroContext.ml

@@ -26,14 +26,6 @@ open Resolution
 open Error
 open Globals
 
-module Eval = struct
-	include EvalEncode
-	include EvalDecode
-	include EvalValue
-	include EvalContext
-	include EvalMain
-end
-
 module InterpImpl = Eval (* Hlmacro *)
 
 module Interp = struct
@@ -48,7 +40,7 @@ let macro_interp_cache = ref None
 let safe_decode com v expected t p f =
 	try
 		f ()
-	with MacroApi.Invalid_expr | EvalContext.RunTimeException _ ->
+	with MacroApi.Invalid_expr ->
 		let path = [dump_path com;"decoding_error"] in
 		let ch = Path.create_file false ".txt" [] path  in
 		let errors = Interp.handle_decoding_error (output_string ch) v t in
@@ -282,7 +274,7 @@ let make_macro_com_api com mcom p =
 			!macro_enable_cache
 		);
 		format_string = (fun s p ->
-			Common.format_string com s p (fun e p -> (e,p))
+			FormatString.format_string com.defines s p (fun e p -> (e,p))
 		);
 		cast_or_unify = (fun t e p ->
 			Interp.exc_string "unsupported"
@@ -632,7 +624,7 @@ and flush_macro_context mint mctx =
 	(* we should maybe ensure that all filters in Main are applied. Not urgent atm *)
 	let expr_filters = [
 		"handle_abstract_casts",AbstractCast.handle_abstract_casts mctx;
-		"local_statics",Filters.LocalStatic.run mctx;
+		"local_statics",LocalStatic.run mctx;
 		"Exceptions",Exceptions.filter mctx;
 		"captured_vars",CapturedVars.captured_vars mctx.com;
 	] in
@@ -668,14 +660,14 @@ and flush_macro_context mint mctx =
 			()
 	in
 	let type_filters = [
-		Filters.remove_generic_base;
+		FiltersCommon.remove_generic_base;
 		Exceptions.patch_constructors mctx;
-		(fun mt -> Filters.add_field_inits mctx.curclass.cl_path (RenameVars.init mctx.com) mctx.com mt);
+		(fun mt -> AddFieldInits.add_field_inits mctx.curclass.cl_path (RenameVars.init mctx.com) mctx.com mt);
 		minimal_restore;
-		Filters.apply_native_paths
+		Naming.apply_native_paths
 	] in
 	let ready = fun t ->
-		Filters.apply_filters_once mctx expr_filters t;
+		FiltersCommon.apply_filters_once mctx expr_filters t;
 		List.iter (fun f -> f t) type_filters
 	in
 	(try Interp.add_types mint types ready
@@ -747,7 +739,7 @@ let get_macro_context ctx =
 		mctx
 
 let load_macro_module mctx com cpath display p =
-	let m = (try com.type_to_module#find cpath with Not_found -> cpath) in
+	let m = (try com.module_lut#get_type_lut#find cpath with Not_found -> cpath) in
 	(* Temporarily enter display mode while typing the macro. *)
 	let old = mctx.com.display in
 	if display then mctx.com.display <- com.display;
@@ -996,7 +988,7 @@ let type_macro ctx mode cpath f (el:Ast.expr list) p =
 						else try
 							let ct = Interp.decode_ctype v in
 							Typeload.load_complex_type ctx false ct;
-						with MacroApi.Invalid_expr | EvalContext.RunTimeException _ ->
+						with MacroApi.Invalid_expr  | EvalContext.RunTimeException _ ->
 							Interp.decode_type v
 						in
 						ctx.ret <- t;

+ 6 - 2
src/typing/matcher/exprToPattern.ml

@@ -252,7 +252,11 @@ let rec make pctx toplevel t e =
 		| ECall(e1,el) ->
 			let e1 = type_expr ctx e1 (WithType.with_type t) in
 			begin match e1.eexpr,follow e1.etype with
-				| TField(_, FEnum(en,ef)),TFun(_,TEnum(_,tl)) ->
+				| TField(_, FEnum(en,ef)),TFun(_,tr) ->
+					let tl = match follow tr with
+						| TEnum(_,tl) -> tl
+						| _ -> fail()
+					in
 					let map = apply_params en.e_params tl in
 					let monos = Monomorph.spawn_constrained_monos map ef.ef_params in
 					let map t = map (apply_params ef.ef_params monos t) in
@@ -442,4 +446,4 @@ let rec make pctx toplevel t e =
 			fail()
 	in
 	let pat = loop e in
-	pat,p
+	pat,p

+ 6 - 2
src/typing/operators.ml

@@ -118,9 +118,9 @@ let rec classify t =
 	| TAbstract ({ a_path = [],"Int" },[]) -> KInt
 	| TAbstract ({ a_path = [],"Float" },[]) -> KFloat
 	| TAbstract (a,[]) when List.exists (fun t -> match classify t with KInt | KFloat -> true | _ -> false) a.a_to -> KNumParam t
-	| TInst ({ cl_kind = KTypeParameter ctl },_) when List.exists (fun t -> match classify t with KInt | KFloat -> true | _ -> false) ctl -> KNumParam t
+	| TInst ({ cl_kind = KTypeParameter ttp },_) when List.exists (fun t -> match classify t with KInt | KFloat -> true | _ -> false) (get_constraints ttp) -> KNumParam t
 	| TAbstract (a,[]) when List.exists (fun t -> match classify t with KString -> true | _ -> false) a.a_to -> KStrParam t
-	| TInst ({ cl_kind = KTypeParameter ctl },_) when List.exists (fun t -> match classify t with KString -> true | _ -> false) ctl -> KStrParam t
+	| TInst ({ cl_kind = KTypeParameter ttp },_) when List.exists (fun t -> match classify t with KString -> true | _ -> false) (get_constraints ttp) -> KStrParam t
 	| TMono r when r.tm_type = None -> KUnk
 	| TDynamic _ -> KDyn
 	| _ -> KOther
@@ -630,6 +630,10 @@ let type_non_assign_op ctx op e1 e2 is_assign_op abstract_overload_only with_typ
 			WithType.value
 	in
 	let e1 = type_expr ctx e1 wt in
+	let e1 = match wt with
+		| WithType.WithType(t,_) -> AbstractCast.cast_or_unify ctx t e1 e1.epos
+		| _ -> e1
+	in
 	let result = if abstract_overload_only then begin
 		let e2 = type_binop_rhs ctx op e1 e2 is_assign_op with_type p in
 		try_abstract_binop_overloads ctx op e1 e2 is_assign_op p

+ 1 - 1
src/typing/overloadResolution.ml

@@ -1,7 +1,7 @@
-open Typecore
 open TType
 open TUnification
 open TFunctions
+open FieldCallCandidate
 
 let unify_cf map_type c cf el =
 	let monos = List.map (fun _ -> mk_mono()) cf.cf_params in

+ 36 - 16
src/typing/tanon_identification.ml

@@ -135,29 +135,30 @@ object(self)
 		in
 		loop td.t_type
 
-	method identify (accept_anons : bool) (t : Type.t) =
-		match t with
-		| TType(td,tl) ->
+	method identity_anon (an : tanon) =
+		let make_pfm path = {
+			pfm_path = path;
+			pfm_params = [];
+			pfm_fields = an.a_fields;
+			pfm_converted = None;
+			pfm_arity = count_fields an.a_fields;
+		} in
+		match !(an.a_status) with
+		| ClassStatics {cl_path = path} | EnumStatics {e_path = path} | AbstractStatics {a_path = path} ->
 			begin try
-				Some (Hashtbl.find pfms td.t_path)
+				Some (Hashtbl.find pfms path)			
 			with Not_found ->
-				self#identify accept_anons (apply_typedef td tl)
+				let pfm = make_pfm path in
+				self#add_pfm path pfm;
+				Some pfm
 			end
-		| TMono {tm_type = Some t} ->
-			self#identify accept_anons t
-		| TAbstract(a,tl) when not (Meta.has Meta.CoreType a.a_meta) ->
-			self#identify accept_anons (Abstract.get_underlying_type a tl)
-		| TAbstract({a_path=([],"Null")},[t]) ->
-			self#identify accept_anons t
-		| TLazy f ->
-			self#identify accept_anons (lazy_type f)
-		| TAnon an when accept_anons && not (PMap.is_empty an.a_fields) ->
+		| _ ->
 			let arity = PMap.fold (fun cf i ->
 				replace_mono cf.cf_type;
 				i + 1
 			) an.a_fields 0 in
 			begin try
-				Some (self#find_compatible arity t)
+				Some (self#find_compatible arity (TAnon an))
 			with Not_found ->
 				let id = num in
 				num <- num + 1;
@@ -171,7 +172,26 @@ object(self)
 				} in
 				self#add_pfm path pfm;
 				Some pfm
-			end;
+			end
+
+	method identify (accept_anons : bool) (t : Type.t) =
+		match t with
+		| TType(td,tl) ->
+			begin try
+				Some (Hashtbl.find pfms td.t_path)
+			with Not_found ->
+				self#identify accept_anons (apply_typedef td tl)
+			end
+		| TMono {tm_type = Some t} ->
+			self#identify accept_anons t
+		| TAbstract(a,tl) when not (Meta.has Meta.CoreType a.a_meta) ->
+			self#identify accept_anons (Abstract.get_underlying_type a tl)
+		| TAbstract({a_path=([],"Null")},[t]) ->
+			self#identify accept_anons t
+		| TLazy f ->
+			self#identify accept_anons (lazy_type f)
+		| TAnon an when accept_anons && not (PMap.is_empty an.a_fields) ->
+			self#identity_anon an
 		| _ ->
 			None
 end

+ 76 - 96
src/typing/typeload.ml

@@ -35,7 +35,7 @@ open Globals
 
 let build_count = ref 0
 
-let type_function_params_rec = ref (fun _ _ _ _ -> die "" __LOC__)
+let type_function_params_ref = ref (fun _ _ _ _ _ -> die "" __LOC__)
 
 let check_field_access ctx cff =
 	let display_access = ref None in
@@ -102,17 +102,6 @@ let find_type_in_module_raise ctx m tname p =
 	with Not_found ->
 		raise_typing_error_ext (make_error (Type_not_found (m.m_path,tname,Not_defined)) p)
 
-(* raises Module_not_found or Type_not_found *)
-let load_type_raise ctx mpath tname p =
-	let m = ctx.g.do_load_module ctx mpath p in
-	find_type_in_module_raise ctx m tname p
-
-(* raises Not_found *)
-let load_type ctx mpath tname p = try
-	load_type_raise ctx mpath tname p
-with Error { err_message = (Module_not_found _ | Type_not_found _); err_pos = p2 } when p = p2 ->
-	raise Not_found
-
 (** since load_type_def and load_instance are used in PASS2, they should not access the structure of a type **)
 
 let find_type_in_current_module_context ctx pack name =
@@ -286,28 +275,24 @@ let make_extension_type ctx tl =
 	let ta = mk_anon ~fields (ref (Extend tl)) in
 	ta
 
-let check_param_constraints ctx t map c p =
-	match follow t with
-	| TMono _ -> ()
-	| _ ->
-		let ctl = (match c.cl_kind with KTypeParameter l -> l | _ -> []) in
-		List.iter (fun ti ->
-			let ti = map ti in
-			try
-				unify_raise t ti p
-			with Error ({ err_message = Unify l } as err) ->
-				let fail() =
-					if not ctx.untyped then display_error_ext ctx.com { err with err_message = (Unify (Constraint_failure (s_type_path c.cl_path) :: l)) }
-				in
-				match follow t with
-				| TInst({cl_kind = KExpr e},_) ->
-					let e = type_expr {ctx with locals = PMap.empty} e (WithType.with_type ti) in
-					begin try unify_raise e.etype ti p
-					with Error { err_message = Unify _ } -> fail() end
-				| _ ->
-					fail()
+let check_param_constraints ctx t map ttp p =
+	List.iter (fun ti ->
+		let ti = map ti in
+		try
+			unify_raise t ti p
+		with Error ({ err_message = Unify l } as err) ->
+			let fail() =
+				if not ctx.untyped then display_error_ext ctx.com { err with err_message = (Unify (Constraint_failure (s_type_path ttp.ttp_class.cl_path) :: l)) }
+			in
+			match follow t with
+			| TInst({cl_kind = KExpr e},_) ->
+				let e = type_expr {ctx with locals = PMap.empty} e (WithType.with_type ti) in
+				begin try unify_raise e.etype ti p
+				with Error { err_message = Unify _ } -> fail() end
+			| _ ->
+				fail()
 
-		) ctl
+	) (get_constraints ttp)
 
 type load_instance_param_mode =
 	| ParamNormal
@@ -357,7 +342,8 @@ let rec load_params ctx info params p =
 	in
 	let checks = DynArray.create () in
 	let rec loop tl1 tl2 is_rest = match tl1,tl2 with
-		| t :: tl1,({ttp_name=name;ttp_type=t2}) :: tl2 ->
+		| t :: tl1,ttp:: tl2 ->
+			let name = ttp.ttp_name in
 			let t,pt = load_param t in
 			let check_const c =
 				let is_expression = (match t with TInst ({ cl_kind = KExpr _ },_) -> true | _ -> false) in
@@ -370,15 +356,14 @@ let rec load_params ctx info params p =
 					raise_typing_error "Type parameter is expected to be a constant value" p
 			in
 			let is_rest = is_rest || name = "Rest" && info.build_kind = BuildGenericBuild in
-			let t = match follow t2 with
-				| TInst ({ cl_kind = KTypeParameter [] } as c, []) when (match info.build_kind with BuildGeneric _ -> false | _ -> true) ->
-					check_const c;
+			let t = match ttp.ttp_constraints with
+				| None when (match info.build_kind with BuildGeneric _ -> false | _ -> true) ->
+					check_const ttp.ttp_class;
 					t
-				| TInst (c,[]) ->
-					check_const c;
-					DynArray.add checks (t,c,pt);
+				| _ ->
+					check_const ttp.ttp_class;
+					DynArray.add checks (t,ttp,pt);
 					t
-				| _ -> die "" __LOC__
 			in
 			t :: loop tl1 tl2 is_rest
 		| [],[] ->
@@ -429,7 +414,7 @@ and load_instance' ctx ptp get_params =
 		if t.tparams <> [] then raise_typing_error ("Class type parameter " ^ t.tname ^ " can't have parameters") ptp.pos_full;
 		pt
 	with Not_found ->
-		let mt = load_type_def ctx ptp.pos_path t in
+		let mt = load_type_def ctx (if ptp.pos_path == null_pos then ptp.pos_full else ptp.pos_path) t in
 		let info = ctx.g.get_build_info ctx mt ptp.pos_full in
 		if info.build_path = ([],"Dynamic") then match t.tparams with
 			| [] -> t_dynamic
@@ -591,7 +576,7 @@ and load_complex_type' ctx allow_display (t,p) =
 					no_expr e;
 					topt t, Var { v_read = AccNormal; v_write = AccNormal }
 				| FFun fd ->
-					params := (!type_function_params_rec) ctx fd (fst f.cff_name) p;
+					params := (!type_function_params_ref) ctx fd TPHAnonField (fst f.cff_name) p;
 					no_expr fd.f_expr;
 					let old = ctx.type_params in
 					ctx.type_params <- !params @ old;
@@ -684,11 +669,11 @@ and init_meta_overloads ctx co cf =
 				| [] ->
 					()
 				| l ->
-					ctx.type_params <- List.filter (fun t ->
-						not (List.mem t l) (* TODO: this still looks suspicious *)
+					ctx.type_params <- List.filter (fun ttp ->
+						ttp.ttp_host <> TPHMethod
 					) ctx.type_params
 			end;
-			let params : type_params = (!type_function_params_rec) ctx f cf.cf_name p in
+			let params : type_params = (!type_function_params_ref) ctx f TPHMethod cf.cf_name p in
 			ctx.type_params <- params @ ctx.type_params;
 			let topt = function None -> raise_typing_error "Explicit type required" p | Some t -> load_complex_type ctx true t in
 			let args =
@@ -743,17 +728,10 @@ let load_type_hint ?(opt=false) ctx pcur t =
 (* ---------------------------------------------------------------------- *)
 (* PASS 1 & 2 : Module and Class Structure *)
 
-type type_param_host =
-	| TPHType
-	| TPHConstructor
-	| TPHMethod
-	| TPHEnumConstructor
-
 let rec type_type_param ctx host path get_params p tp =
 	let n = fst tp.tp_name in
 	let c = mk_class ctx.m.curmod (fst path @ [snd path],n) (pos tp.tp_name) (pos tp.tp_name) in
 	c.cl_params <- type_type_params ctx host c.cl_path get_params p tp.tp_params;
-	c.cl_kind <- KTypeParameter [];
 	c.cl_meta <- tp.Ast.tp_meta;
 	if host = TPHEnumConstructor then c.cl_meta <- (Meta.EnumConstructorParam,[],null_pos) :: c.cl_meta;
 	let t = TInst (c,extract_param_types c.cl_params) in
@@ -770,39 +748,46 @@ let rec type_type_param ctx host path get_params p tp =
 					()
 				| TPHConstructor
 				| TPHMethod
-				| TPHEnumConstructor ->
+				| TPHEnumConstructor
+				| TPHAnonField
+				| TPHLocal ->
 					display_error ctx.com "Default type parameters are only supported on types" (pos ct)
 				end;
 				t
 			) "default" in
 			Some (TLazy r)
 	in
-	match tp.tp_constraints with
-	| None ->
-		mk_type_param n t default
-	| Some th ->
-		let r = make_lazy ctx t (fun r ->
-			let ctx = { ctx with type_params = ctx.type_params @ get_params() } in
-			let rec loop th = match fst th with
-				| CTIntersection tl -> List.map (load_complex_type ctx true) tl
-				| CTParent ct -> loop ct
-				| _ -> [load_complex_type ctx true th]
-			in
-			let constr = loop th in
-			(* check against direct recursion *)
-			let rec loop t =
-				match follow t with
-				| TInst (c2,_) when c == c2 -> raise_typing_error "Recursive constraint parameter is not allowed" p
-				| TInst ({ cl_kind = KTypeParameter cl },_) ->
-					List.iter loop cl
-				| _ ->
-					()
-			in
-			List.iter loop constr;
-			c.cl_kind <- KTypeParameter constr;
-			t
-		) "constraint" in
-		mk_type_param n (TLazy r) default
+	let ttp = match tp.tp_constraints with
+		| None ->
+			mk_type_param c host default None
+		| Some th ->
+			let current_type_params = ctx.type_params in
+			let constraints = lazy (
+				let ctx = { ctx with type_params = get_params() @ current_type_params } in
+				let rec loop th = match fst th with
+					| CTIntersection tl -> List.map (load_complex_type ctx true) tl
+					| CTParent ct -> loop ct
+					| _ -> [load_complex_type ctx true th]
+				in
+				let constr = loop th in
+				(* check against direct recursion *)
+				let rec loop t =
+					match follow t with
+					| TInst (c2,_) when c == c2 ->
+						raise_typing_error "Recursive constraint parameter is not allowed" p
+					| TInst ({ cl_kind = KTypeParameter ttp },_) ->
+						List.iter loop (get_constraints ttp)
+					| _ ->
+						()
+				in
+				List.iter loop constr;
+				constr
+			) in
+			delay ctx PConnectField (fun () -> ignore (Lazy.force constraints));
+			mk_type_param c host default (Some constraints)
+	in
+	c.cl_kind <- KTypeParameter ttp;
+	ttp
 
 and type_type_params ctx host path get_params p tpl =
 	let names = ref [] in
@@ -845,21 +830,16 @@ let load_core_class ctx c =
 let init_core_api ctx c =
 	let ccore = load_core_class ctx c in
 	begin try
-		List.iter2 (fun tp1 tp2 -> match follow tp1.ttp_type, follow tp2.ttp_type with
-			| TInst({cl_kind = KTypeParameter l1},_),TInst({cl_kind = KTypeParameter l2},_) ->
-				begin try
-					List.iter2 (fun t1 t2 -> type_eq EqCoreType t2 t1) l1 l2
-				with
-					| Invalid_argument _ ->
-						raise_typing_error "Type parameters must have the same number of constraints as core type" c.cl_pos
-					| Unify_error l ->
-						(* TODO send as one call with sub errors *)
-						display_error ctx.com ("Type parameter " ^ tp2.ttp_name ^ " has different constraint than in core type") c.cl_pos;
-						display_error ctx.com (error_msg (Unify l)) c.cl_pos;
-				end
-			| t1,t2 ->
-				Printf.printf "%s %s" (s_type (print_context()) t1) (s_type (print_context()) t2);
-				die "" __LOC__
+		List.iter2 (fun ttp1 ttp2 ->
+			try
+				List.iter2 (fun t1 t2 -> type_eq EqCoreType t2 t1) (get_constraints ttp1) (get_constraints ttp2)
+			with
+				| Invalid_argument _ ->
+					raise_typing_error "Type parameters must have the same number of constraints as core type" c.cl_pos
+				| Unify_error l ->
+					(* TODO send as one call with sub errors *)
+					display_error ctx.com ("Type parameter " ^ ttp2.ttp_name ^ " has different constraint than in core type") c.cl_pos;
+					display_error ctx.com (error_msg (Unify l)) c.cl_pos;
 		) ccore.cl_params c.cl_params;
 	with Invalid_argument _ ->
 		raise_typing_error "Class must have the same number of type parameters as core type" c.cl_pos
@@ -912,4 +892,4 @@ let init_core_api ctx c =
 	| Some cf, _ when not (has_class_field_flag cf CfPublic) -> ()
 	| Some f, Some f2 -> compare_fields f f2
 	| None, Some cf when not (has_class_field_flag cf CfPublic) -> ()
-	| _ -> raise_typing_error "Constructor differs from core type" c.cl_pos)
+	| _ -> raise_typing_error "Constructor differs from core type" c.cl_pos)

+ 23 - 56
src/typing/typeloadCheck.ml

@@ -62,28 +62,27 @@ let valid_redefinition ctx map1 map2 f1 t1 f2 t2 = (* child, parent *)
 		| l1, l2 when List.length l1 = List.length l2 ->
 			let to_check = ref [] in
 			(* TPTODO: defaults *)
-			let monos = List.map2 (fun tp1 tp2 ->
-				(match follow tp1.ttp_type, follow tp2.ttp_type with
-				| TInst ({ cl_kind = KTypeParameter ct1 } as c1,pl1), TInst ({ cl_kind = KTypeParameter ct2 } as c2,pl2) ->
-					(match ct1, ct2 with
-					| [], [] -> ()
-					| _, _ when List.length ct1 = List.length ct2 ->
-						(* if same constraints, they are the same type *)
-						let check monos =
-							List.iter2 (fun t1 t2  ->
-								try
-									let t1 = apply_params l1 monos (apply_params c1.cl_params pl1 (map2 t1)) in
-									let t2 = apply_params l2 monos (apply_params c2.cl_params pl2 (map1 t2)) in
-									type_eq EqStrict t1 t2
-								with Unify_error l ->
-									raise (Unify_error (Unify_custom "Constraints differ" :: l))
-							) ct1 ct2
-						in
-						to_check := check :: !to_check;
-					| _ ->
-						raise (Unify_error [Unify_custom "Different number of constraints"]))
-				| _ -> ());
-				TInst (mk_class null_module ([],tp1.ttp_name) null_pos null_pos,[])
+			let monos = List.map2 (fun ttp1 ttp2 ->
+				let ct1 = get_constraints ttp1 in
+				let ct2 = get_constraints ttp2 in
+				(match ct1, ct2 with
+				| [], [] -> ()
+				| _, _ when List.length ct1 = List.length ct2 ->
+					(* if same constraints, they are the same type *)
+					let check monos =
+						List.iter2 (fun t1 t2  ->
+							try
+								let t1 = apply_params l1 monos (map2 t1) in
+								let t2 = apply_params l2 monos (map1 t2) in
+								type_eq EqStrict t1 t2
+							with Unify_error l ->
+								raise (Unify_error (Unify_custom "Constraints differ" :: l))
+						) ct1 ct2
+					in
+					to_check := check :: !to_check;
+				| _ ->
+					raise (Unify_error [Unify_custom "Different number of constraints"]));
+				TInst (mk_class null_module ([],ttp1.ttp_name) null_pos null_pos,[])
 			) l1 l2 in
 			List.iter (fun f -> f monos) !to_check;
 			apply_params l1 monos t1, apply_params l2 monos t2
@@ -131,24 +130,6 @@ let copy_meta meta_src meta_target sl =
 	) meta_src;
 	!meta
 
-(** retrieve string from @:native metadata or raise Not_found *)
-let get_native_name meta =
-	let rec get_native meta = match meta with
-		| [] -> raise Not_found
-		| (Meta.Native,[v],p as meta) :: _ ->
-			meta
-		| _ :: meta ->
-			get_native meta
-	in
-	let (_,e,mp) = get_native meta in
-	match e with
-	| [Ast.EConst (Ast.String(name,_)),p] ->
-		name,p
-	| [] ->
-		raise Not_found
-	| _ ->
-		raise_typing_error "String expected" mp
-
 let check_native_name_override ctx child base =
 	let error base_pos child_pos =
 		(* TODO construct error *)
@@ -156,9 +137,9 @@ let check_native_name_override ctx child base =
 		display_error ~depth:1 ctx.com (compl_msg "Base field is defined here") base_pos
 	in
 	try
-		let child_name, child_pos = get_native_name child.cf_meta in
+		let child_name, child_pos = Naming.get_native_name child.cf_meta in
 		try
-			let base_name, base_pos = get_native_name base.cf_meta in
+			let base_name, base_pos = Naming.get_native_name base.cf_meta in
 			if base_name <> child_name then
 				error base_pos child_pos
 		with Not_found ->
@@ -351,20 +332,6 @@ let check_global_metadata ctx meta f_add mpath tpath so =
 	) ctx.com.global_metadata;
 	if ctx.is_display_file then delay ctx PCheckConstraint (fun () -> DisplayEmitter.check_display_metadata ctx meta)
 
-let check_module_types ctx m p t =
-	let t = t_infos t in
-	try
-		let path2 = ctx.com.type_to_module#find t.mt_path in
-		if m.m_path <> path2 && String.lowercase_ascii (s_type_path path2) = String.lowercase_ascii (s_type_path m.m_path) then raise_typing_error ("Module " ^ s_type_path path2 ^ " is loaded with a different case than " ^ s_type_path m.m_path) p;
-		let m2 = ctx.com.module_lut#find path2 in
-		let hex1 = Digest.to_hex m.m_extra.m_sign in
-		let hex2 = Digest.to_hex m2.m_extra.m_sign in
-		let s = if hex1 = hex2 then hex1 else Printf.sprintf "was %s, is %s" hex2 hex1 in
-		raise_typing_error (Printf.sprintf "Type name %s is redefined from module %s (%s)" (s_type_path t.mt_path)  (s_type_path path2) s) p
-	with
-		Not_found ->
-			ctx.com.type_to_module#add t.mt_path m.m_path
-
 module Inheritance = struct
 	let is_basic_class_path path = match path with
 		| ([],("Array" | "String" | "Date" | "Xml")) -> true

+ 10 - 14
src/typing/typeloadFields.ml

@@ -633,7 +633,7 @@ let create_field_context ctx cctx cff is_display_file display_modifier =
 	fctx
 
 let create_typer_context_for_field ctx cctx fctx cff =
-	DeprecationCheck.check_is ctx.com ctx.curclass.cl_meta cff.cff_meta (fst cff.cff_name) cff.cff_meta (snd cff.cff_name);
+	DeprecationCheck.check_is ctx.com ctx.m.curmod ctx.curclass.cl_meta cff.cff_meta (fst cff.cff_name) cff.cff_meta (snd cff.cff_name);
 	let ctx = {
 		ctx with
 		pass = PBuildClass; (* will be set later to PTypeExpr *)
@@ -692,7 +692,7 @@ let transform_field (ctx,cctx) c f fields p =
 	in
 	if List.mem_assoc AMacro f.cff_access then
 		(match ctx.g.macros with
-		| Some (_,mctx) when mctx.com.type_to_module#mem c.cl_path ->
+		| Some (_,mctx) when mctx.com.module_lut#get_type_lut#mem c.cl_path ->
 			(* assume that if we had already a macro with the same name, it has not been changed during the @:build operation *)
 			if not (List.exists (fun f2 -> f2.cff_name = f.cff_name && List.mem_assoc AMacro f2.cff_access) (!fields)) then
 				raise_typing_error "Class build macro cannot return a macro function when the class has already been compiled into the macro context" p
@@ -701,7 +701,7 @@ let transform_field (ctx,cctx) c f fields p =
 
 let type_var_field ctx t e stat do_display p =
 	if stat then ctx.curfun <- FunStatic else ctx.curfun <- FunMember;
-	let e = if do_display then Display.ExprPreprocessing.process_expr ctx.com e else e in
+	let e = if do_display then Display.preprocess_expr ctx.com e else e in
 	let e = type_expr ctx e (WithType.with_type t) in
 	let e = AbstractCast.cast_or_unify ctx t e p in
 	match t with
@@ -950,7 +950,7 @@ module TypeBinding = struct
 							| NothingToDo ->
 								(fun () -> ())
 							| NormalOverride rctx ->
-								(fun () -> 
+								(fun () ->
 									TypeloadCheck.check_override_field ctx cf.cf_name_pos rctx
 								)
 							| OverloadOverride f ->
@@ -958,7 +958,7 @@ module TypeBinding = struct
 							end
 						| _ ->
 							(fun () -> ())
-					in					
+					in
 					let e = TypeloadFunction.type_function ctx args ret fmode e fctx.is_display_field p in
 					f_check();
 					(* Disabled for now, see https://github.com/HaxeFoundation/haxe/issues/3033 *)
@@ -1288,7 +1288,7 @@ let setup_args_ret ctx cctx fctx name fd p =
 
 let create_method (ctx,cctx,fctx) c f fd p =
 	let name = fst f.cff_name in
-	let params = TypeloadFunction.type_function_params ctx fd name p in
+	let params = TypeloadFunction.type_function_params ctx fd TPHMethod name p in
 	if fctx.is_generic then begin
 		if params = [] then raise_typing_error "Generic functions must have type parameters" p;
 	end;
@@ -1775,12 +1775,7 @@ let init_class ctx c p herits fields =
 		| _ :: l ->
 			check_require l
 	in
-	let rec check_if_feature = function
-		| [] -> []
-		| (Meta.IfFeature,el,_) :: _ -> List.map (fun (e,p) -> match e with EConst (String(s,_)) -> s | _ -> raise_typing_error "String expected" p) el
-		| _ :: l -> check_if_feature l
-	in
-	let cl_if_feature = check_if_feature c.cl_meta in
+	let cl_if_feature = Feature.check_if_feature c.cl_meta in
 	let cl_req = check_require c.cl_meta in
 	let has_init = ref false in
 	List.iter (fun f ->
@@ -1805,10 +1800,11 @@ let init_class ctx c p herits fields =
 					| FKConstructor -> CfrConstructor
 					| _ -> if fctx.is_static then CfrStatic else CfrMember
 				in
-				ctx.m.curmod.m_extra.m_if_feature <- (s, (mk_class_field_ref c cf ref_kind fctx.is_macro)) :: ctx.m.curmod.m_extra.m_if_feature;
+				let cf_ref = mk_class_field_ref c cf ref_kind fctx.is_macro in
+				Feature.set_feature ctx.m.curmod cf_ref s;
 			in
 			List.iter set_feature cl_if_feature;
-			List.iter set_feature (check_if_feature cf.cf_meta);
+			List.iter set_feature (Feature.check_if_feature cf.cf_meta);
 			let req = check_require f.cff_meta in
 			let req = (match req with None -> if fctx.is_static || fctx.field_kind = FKConstructor then cl_req else None | _ -> req) in
 			(match req with

+ 4 - 4
src/typing/typeloadFunction.ml

@@ -43,9 +43,9 @@ let save_field_state ctx =
 		ctx.in_function <- old_in_function;
 	)
 
-let type_function_params ctx fd fname p =
+let type_function_params ctx fd host fname p =
 	let params = ref [] in
-	params := Typeload.type_type_params ctx TPHMethod ([],fname) (fun() -> !params) p fd.f_params;
+	params := Typeload.type_type_params ctx host ([],fname) (fun() -> !params) p fd.f_params;
 	!params
 
 let type_function ctx (args : function_arguments) ret fmode e do_display p =
@@ -78,7 +78,7 @@ let type_function ctx (args : function_arguments) ret fmode e do_display p =
 	end else begin
 		let is_display_debug = Meta.has (Meta.Custom ":debug.display") ctx.curfield.cf_meta in
 		if is_display_debug then print_endline ("before processing:\n" ^ (Expr.dump_with_pos e));
-		let e = if !Parser.had_resume then e else Display.ExprPreprocessing.process_expr ctx.com e in
+		let e = if !Parser.had_resume then e else Display.preprocess_expr ctx.com e in
 		if is_display_debug then print_endline ("after processing:\n" ^ (Expr.dump_with_pos e));
 		type_expr ctx e NoValue
 	end in
@@ -257,4 +257,4 @@ let add_constructor ctx c force_constructor p =
 		(* nothing to do *)
 		()
 ;;
-Typeload.type_function_params_rec := type_function_params
+Typeload.type_function_params_ref := type_function_params

+ 15 - 31
src/typing/typeloadModule.ml

@@ -50,12 +50,11 @@ module ModuleLevel = struct
 			m_path = mpath;
 			m_types = [];
 			m_statics = None;
-			m_extra = module_extra (Path.get_full_path file) (Define.get_signature ctx.com.defines) (file_time file) (if ctx.com.is_macro_context then MMacro else MCode) (get_policy ctx.g mpath);
+			m_extra = module_extra (Path.get_full_path file) (Define.get_signature ctx.com.defines) (file_time file) (if ctx.com.is_macro_context then MMacro else MCode) ctx.com.compilation_step (get_policy ctx.g mpath);
 		} in
 		m
 
 	let add_module ctx m p =
-		List.iter (TypeloadCheck.check_module_types ctx m p) m.m_types;
 		ctx.com.module_lut#add m.m_path m
 
 	(*
@@ -66,7 +65,7 @@ module ModuleLevel = struct
 		let decls = ref [] in
 		let statics = ref [] in
 		let check_name name meta also_statics p =
-			DeprecationCheck.check_is com meta [] name meta p;
+			DeprecationCheck.check_is com ctx.m.curmod meta [] name meta p;
 			let error prev_pos =
 				display_error ctx.com ("Name " ^ name ^ " is already defined in this module") p;
 				raise_typing_error ~depth:1 (compl_msg "Previous declaration here") prev_pos;
@@ -132,20 +131,11 @@ module ModuleLevel = struct
 				let path = make_path name priv d.d_meta p in
 				if Meta.has (Meta.Custom ":fakeEnum") d.d_meta then raise_typing_error "@:fakeEnum enums is no longer supported in Haxe 4, use extern enum abstract instead" p;
 				let e = {
-					e_path = path;
-					e_module = m;
-					e_pos = p;
-					e_name_pos = (pos d.d_name);
+					(mk_enum m path p (pos d.d_name)) with
 					e_doc = d.d_doc;
 					e_meta = d.d_meta;
-					e_params = [];
-					e_using = [];
-					e_restore = (fun () -> ());
 					e_private = priv;
 					e_extern = List.mem EExtern d.d_flags;
-					e_constrs = PMap.empty;
-					e_names = [];
-					e_type = enum_module_type m path p;
 				} in
 				if not e.e_extern then check_type_name name d.d_meta;
 				decls := (TEnumDecl e, decl) :: !decls;
@@ -205,7 +195,7 @@ module ModuleLevel = struct
 					| None -> ()
 					| Some p ->
 						let options = Warning.from_meta d.d_meta in
-						ctx.com.warning WDeprecatedEnumAbstract options "`@:enum abstract` is deprecated in favor of `enum abstract`" p
+						module_warning ctx.com ctx.m.curmod WDeprecatedEnumAbstract options "`@:enum abstract` is deprecated in favor of `enum abstract`" p
 				end;
 				decls := (TAbstractDecl a, decl) :: !decls;
 				match d.d_data with
@@ -388,16 +378,8 @@ module TypeLevel = struct
 			ef_params = params;
 			ef_meta = c.ec_meta;
 		} in
-		DeprecationCheck.check_is ctx.com e.e_meta f.ef_meta f.ef_name f.ef_meta f.ef_name_pos;
-		let cf = {
-			(mk_field f.ef_name f.ef_type p f.ef_name_pos) with
-			cf_kind = (match follow f.ef_type with
-				| TFun _ -> Method MethNormal
-				| _ -> Var { v_read = AccNormal; v_write = AccNo }
-			);
-			cf_doc = f.ef_doc;
-			cf_params = f.ef_params;
-		} in
+		DeprecationCheck.check_is ctx.com ctx.m.curmod e.e_meta f.ef_meta f.ef_name f.ef_meta f.ef_name_pos;
+		let cf = class_field_of_enum_field f in
 		if ctx.is_display_file && DisplayPosition.display_position#enclosed_in f.ef_name_pos then
 			DisplayEmitter.display_enum_field ctx e f p;
 		f,cf
@@ -535,8 +517,7 @@ module TypeLevel = struct
 		) (!constructs);
 		e.e_names <- List.rev !names;
 		e.e_extern <- e.e_extern;
-		e.e_type.t_params <- e.e_params;
-		e.e_type.t_type <- mk_anon ~fields:!fields (ref (EnumStatics e));
+		unify ctx (TType(enum_module_type e !fields,[])) e.e_type p;
 		if !is_flat then e.e_meta <- (Meta.FlatEnum,[],null_pos) :: e.e_meta;
 		if Meta.has Meta.InheritDoc e.e_meta then
 			delay ctx PConnectField (fun() -> InheritDoc.build_enum_doc ctx e);
@@ -592,7 +573,7 @@ module TypeLevel = struct
 		| TMono r ->
 			(match r.tm_type with
 			| None -> Monomorph.bind r tt;
-			| Some _ -> die "" __LOC__);
+			| Some t' -> die (Printf.sprintf "typedef %s is already initialized to %s, but new init to %s was attempted" (s_type_path t.t_path) (s_type_kind t') (s_type_kind tt)) __LOC__);
 		| _ -> die "" __LOC__);
 		TypeloadFields.build_module_def ctx (TTypeDecl t) t.t_meta (fun _ -> []) (fun _ -> ())
 
@@ -702,7 +683,7 @@ let make_curmod ctx m =
 	let rl = new resolution_list ["import";s_type_path m.m_path] in
 	List.iter (fun mt ->
 		rl#add (module_type_resolution mt None null_pos))
-	(List.rev ctx.g.std.m_types);
+	(List.rev ctx.g.std_types.m_types);
 	{
 		curmod = m;
 		import_resolution = rl;
@@ -756,11 +737,14 @@ let type_types_into_module ctx m tdecls p =
 	let ctx = create_typer_context_for_module ctx m in
 	let decls,tdecls = ModuleLevel.create_module_types ctx m tdecls p in
 	let types = List.map fst decls in
-	List.iter (TypeloadCheck.check_module_types ctx m p) types;
+	(* During the initial module_lut#add in type_module, m has no m_types yet by design.
+	   We manually add them here. This and module_lut#add itself should be the only places
+	   in the compiler that call add_module_type. *)
+	List.iter (fun mt -> ctx.com.module_lut#add_module_type m mt) types;
 	m.m_types <- m.m_types @ types;
 	(* define the per-module context for the next pass *)
-	if ctx.g.std != null_module then begin
-		add_dependency m ctx.g.std;
+	if ctx.g.std_types != null_module then begin
+		add_dependency m ctx.g.std_types;
 		(* this will ensure both String and (indirectly) Array which are basic types which might be referenced *)
 		ignore(load_instance ctx (make_ptp (mk_type_path (["std"],"String")) null_pos) ParamNormal)
 	end;

+ 26 - 172
src/typing/typer.ml

@@ -702,7 +702,7 @@ and type_vars ctx vl p =
 	let vl = List.map (fun ev ->
 		let n = fst ev.ev_name
 		and pv = snd ev.ev_name in
-		DeprecationCheck.check_is ctx.com ctx.curclass.cl_meta ctx.curfield.cf_meta n ev.ev_meta pv;
+		DeprecationCheck.check_is ctx.com ctx.m.curmod ctx.curclass.cl_meta ctx.curfield.cf_meta n ev.ev_meta pv;
 		try
 			let t = Typeload.load_type_hint ctx p ev.ev_type in
 			let e = (match ev.ev_expr with
@@ -745,9 +745,9 @@ and type_vars ctx vl p =
 		mk (TMeta((Meta.MergeBlock,[],p), e)) e.etype e.epos
 
 and format_string ctx s p =
-	Common.format_string ctx.com s p (fun enext p ->
+	FormatString.format_string ctx.com.defines s p (fun enext p ->
 		if ctx.in_display && DisplayPosition.display_position#enclosed_in p then
-			Display.ExprPreprocessing.process_expr ctx.com (enext,p)
+			Display.preprocess_expr ctx.com (enext,p)
 		else
 			enext,p
 	)
@@ -1041,9 +1041,9 @@ and type_new ctx ptp el with_type force_inline p =
 		unify_constructor_call c fa
 	in
 	try begin match Abstract.follow_with_forward_ctor t with
-	| TInst ({cl_kind = KTypeParameter tl} as c,params) ->
+	| TInst ({cl_kind = KTypeParameter ttp} as c,params) ->
 		if not (TypeloadCheck.is_generic_parameter ctx c) then raise_typing_error "Only generic type parameters can be constructed" p;
- 		begin match get_constructible_constraint ctx tl p with
+ 		begin match get_constructible_constraint ctx (get_constraints ttp) p with
 		| None ->
 			raise_typing_error_ext (make_error (No_constructor (TClassDecl c)) p)
 		| Some(tl,tr) ->
@@ -1213,7 +1213,7 @@ and type_map_declaration ctx e1 el with_type p =
 
 and type_local_function ctx kind f with_type p =
 	let name,inline = match kind with FKNamed (name,inline) -> Some name,inline | _ -> None,false in
-	let params = TypeloadFunction.type_function_params ctx f (match name with None -> "localfun" | Some (n,_) -> n) p in
+	let params = TypeloadFunction.type_function_params ctx f TPHLocal (match name with None -> "localfun" | Some (n,_) -> n) p in
 	if params <> [] then begin
 		if name = None then display_error ctx.com "Type parameters not supported in unnamed local functions" p;
 		if with_type <> WithType.NoValue then raise_typing_error "Type parameters are not supported for rvalue functions" p
@@ -1557,8 +1557,7 @@ and type_cast ctx e t p =
 	let texpr = loop t in
 	mk (TCast (type_expr ctx e WithType.value,Some texpr)) t p
 
-and make_if_then_else ctx e0 e1 e2 with_type p =
-	let e1,e2,t = match with_type with
+and get_if_then_else_operands ctx e1 e2 with_type = match with_type with
 	| WithType.NoValue -> e1,e2,ctx.t.tvoid
 	| WithType.Value _ -> e1,e2,unify_min ctx [e1; e2]
 	| WithType.WithType(t,src) when (match follow t with TMono _ -> true | t -> ExtType.is_void t) ->
@@ -1567,7 +1566,9 @@ and make_if_then_else ctx e0 e1 e2 with_type p =
 		let e1 = AbstractCast.cast_or_unify ctx t e1 e1.epos in
 		let e2 = AbstractCast.cast_or_unify ctx t e2 e2.epos in
 		e1,e2,t
-	in
+
+and make_if_then_else ctx e0 e1 e2 with_type p =
+	let e1,e2,t = get_if_then_else_operands ctx e1 e2 with_type in
 	mk (TIf (e0,e1,Some e2)) t p
 
 and type_if ctx e e1 e2 with_type is_ternary p =
@@ -1842,26 +1843,22 @@ and type_expr ?(mode=MGet) ctx (e,p) (with_type:WithType.t) =
 		let vr = new value_reference ctx in
 		let e1 = type_expr ctx (Expr.ensure_block e1) with_type in
 		let e2 = type_expr ctx (Expr.ensure_block e2) (WithType.with_type e1.etype) in
-		let tmin = unify_min ctx [e1; e2] in
-		let e1 = vr#as_var "tmp" {e1 with etype = ctx.t.tnull tmin} in
-		let e_null = Builder.make_null e1.etype e1.epos in
-		let e_cond = mk (TBinop(OpNotEq,e1,e_null)) ctx.t.tbool e1.epos in
-
+		let e1,e2,tmin = get_if_then_else_operands ctx e1 e2 with_type in
 		let rec follow_null t =
 			match t with
 			| TAbstract({a_path = [],"Null"},[t]) -> follow_null t
 			| _ -> t
 		in
 		let iftype = if DeadEnd.has_dead_end e2 then
-			WithType.with_type (follow_null e1.etype)
-		else
-			let t = match e2.etype with
-				| TAbstract({a_path = [],"Null"},[t]) -> tmin
-				| _ -> follow_null tmin
-			in
-			WithType.with_type t
+			follow_null e1.etype
+		else match e2.etype with
+			| TAbstract({a_path = [],"Null"},[t]) -> tmin
+			| _ -> follow_null tmin
 		in
-		let e_if = make_if_then_else ctx e_cond e1 e2 iftype p in
+		let e1 = vr#as_var "tmp" {e1 with etype = ctx.t.tnull tmin} in
+		let e_null = Builder.make_null e1.etype e1.epos in
+		let e_cond = mk (TBinop(OpNotEq,e1,e_null)) ctx.t.tbool e1.epos in
+		let e_if = mk (TIf(e_cond,e1,Some e2)) iftype p in
 		vr#to_texpr e_if
 	| EBinop (OpAssignOp OpNullCoal,e1,e2) ->
 		let e_cond = EBinop(OpNotEq,e1,(EConst(Ident "null"), p)) in
@@ -2013,160 +2010,18 @@ and type_expr ?(mode=MGet) ctx (e,p) (with_type:WithType.t) =
 				DisplayEmitter.display_module_type ctx mt p_t;
 			let e_t = type_module_type ctx mt p_t in
 			let e_Std_isOfType =
-				match Typeload.load_type_raise ctx ([],"Std") "Std" p with
-				| TClassDecl c ->
-					let cf =
-						try PMap.find "isOfType" c.cl_statics
-						with Not_found -> die "" __LOC__
-					in
-					Texpr.Builder.make_static_field c cf (mk_zero_range_pos p)
-				| _ -> die "" __LOC__
+				ignore(ctx.g.std.cl_build());
+				let cf = try
+					PMap.find "isOfType" ctx.g.std.cl_statics
+				with Not_found ->
+					die "" __LOC__
+				in
+				Texpr.Builder.make_static_field ctx.g.std cf (mk_zero_range_pos p)
 			in
 			mk (TCall (e_Std_isOfType, [e; e_t])) ctx.com.basic.tbool p
 		| _ ->
 			display_error ctx.com "Unsupported type for `is` operator" p_t;
 			Texpr.Builder.make_bool ctx.com.basic false p
-
-(* ---------------------------------------------------------------------- *)
-(* TYPER INITIALIZATION *)
-
-let create com macros =
-	let ctx = {
-		com = com;
-		t = com.basic;
-		g = {
-			core_api = None;
-			macros = macros;
-			type_patches = Hashtbl.create 0;
-			module_check_policies = [];
-			delayed = [];
-			debug_delayed = [];
-			doinline = com.display.dms_inline && not (Common.defined com Define.NoInline);
-			retain_meta = Common.defined com Define.RetainUntypedMeta;
-			std = null_module;
-			global_using = [];
-			complete = false;
-			type_hints = [];
-			load_only_cached_modules = false;
-			functional_interface_lut = new pmap_lookup;
-			do_macro = MacroContext.type_macro;
-			do_load_macro = MacroContext.load_macro';
-			do_load_module = TypeloadModule.load_module;
-			do_load_type_def = Typeload.load_type_def;
-			get_build_info = InstanceBuilder.get_build_info;
-			do_format_string = format_string;
-			do_load_core_class = Typeload.load_core_class;
-		};
-		m = {
-			curmod = null_module;
-			import_resolution = new resolution_list ["import";"typer"];
-			own_resolution = None;
-			enum_with_type = None;
-			module_using = [];
-			import_statements = [];
-		};
-		is_display_file = false;
-		bypass_accessor = 0;
-		meta = [];
-		with_type_stack = [];
-		call_argument_stack = [];
-		pass = PBuildModule;
-		macro_depth = 0;
-		untyped = false;
-		curfun = FunStatic;
-		in_function = false;
-		in_loop = false;
-		in_display = false;
-		allow_inline = true;
-		allow_transform = true;
-		get_build_infos = (fun() -> None);
-		ret = mk_mono();
-		locals = PMap.empty;
-		type_params = [];
-		curclass = null_class;
-		curfield = null_field;
-		tthis = mk_mono();
-		opened = [];
-		vthis = None;
-		in_call_args = false;
-		in_overload_call_args = false;
-		delayed_display = None;
-		monomorphs = {
-			perfunction = [];
-		};
-		memory_marker = Typecore.memory_marker;
-	} in
-	ctx.g.std <- (try
-		TypeloadModule.load_module ctx ([],"StdTypes") null_pos
-	with
-		Error { err_message = Module_not_found ([],"StdTypes") } ->
-			try
-				let std_path = Sys.getenv "HAXE_STD_PATH" in
-				raise_typing_error ("Standard library not found. Please check your `HAXE_STD_PATH` environment variable (current value: \"" ^ std_path ^ "\")") null_pos
-			with Not_found ->
-				raise_typing_error "Standard library not found. You may need to set your `HAXE_STD_PATH` environment variable" null_pos
-	);
-	(* We always want core types to be available so we add them as default imports (issue #1904 and #3131). *)
-	List.iter (fun mt ->
-		ctx.m.import_resolution#add (module_type_resolution mt None null_pos))
-	(List.rev ctx.g.std.m_types);
-	List.iter (fun t ->
-		match t with
-		| TAbstractDecl a ->
-			(match snd a.a_path with
-			| "Void" -> ctx.t.tvoid <- TAbstract (a,[]);
-			| "Float" -> ctx.t.tfloat <- TAbstract (a,[]);
-			| "Int" -> ctx.t.tint <- TAbstract (a,[])
-			| "Bool" -> ctx.t.tbool <- TAbstract (a,[])
-			| "Dynamic" -> t_dynamic_def := TAbstract(a,extract_param_types a.a_params);
-			| "Null" ->
-				let mk_null t =
-					try
-						if not (is_null ~no_lazy:true t || is_explicit_null t) then TAbstract (a,[t]) else t
-					with Exit ->
-						(* don't force lazy evaluation *)
-						let r = ref (lazy_available t_dynamic) in
-						r := lazy_wait (fun() ->
-							let t = (if not (is_null t) then TAbstract (a,[t]) else t) in
-							r := lazy_available t;
-							t
-						);
-						TLazy r
-				in
-				ctx.t.tnull <- mk_null;
-			| _ -> ())
-		| TEnumDecl _ | TClassDecl _ | TTypeDecl _ ->
-			()
-	) ctx.g.std.m_types;
-	let m = TypeloadModule.load_module ctx ([],"String") null_pos in
-	List.iter (fun mt -> match mt with
-		| TClassDecl c -> ctx.t.tstring <- TInst (c,[])
-		| _ -> ()
-	) m.m_types;
-	let m = TypeloadModule.load_module ctx ([],"Array") null_pos in
-	(try
-		List.iter (fun t -> (
-			match t with
-			| TClassDecl ({cl_path = ([],"Array")} as c) ->
-				ctx.t.tarray <- (fun t -> TInst (c,[t]));
-				raise Exit
-			| _ -> ()
-		)) m.m_types;
-		die "" __LOC__
-	with Exit -> ());
-	let m = TypeloadModule.load_module ctx (["haxe"],"EnumTools") null_pos in
-	(match m.m_types with
-	| [TClassDecl c1;TClassDecl c2] -> ctx.g.global_using <- (c1,c1.cl_pos) :: (c2,c2.cl_pos) :: ctx.g.global_using
-	| [TClassDecl c1] ->
-		let m = TypeloadModule.load_module ctx (["haxe"],"EnumWithType.valueTools") null_pos in
-		(match m.m_types with
-		| [TClassDecl c2 ] -> ctx.g.global_using <- (c1,c1.cl_pos) :: (c2,c2.cl_pos) :: ctx.g.global_using
-		| _ -> die "" __LOC__);
-	| _ -> die "" __LOC__);
-	ignore(TypeloadModule.load_module ctx (["haxe"],"Exception") null_pos);
-	ctx.g.complete <- true;
-	ctx
-
 ;;
 unify_min_ref := unify_min;
 unify_min_for_type_source_ref := unify_min_for_type_source;
@@ -2174,5 +2029,4 @@ make_call_ref := make_call;
 type_call_target_ref := type_call_target;
 type_access_ref := type_access;
 type_block_ref := type_block;
-create_context_ref := create;
 type_expr_ref := (fun ?(mode=MGet) ctx e with_type -> type_expr ~mode ctx e with_type);

+ 3 - 4
src/typing/typerBase.ml

@@ -210,8 +210,7 @@ let type_module_type ctx t p =
 			let t_tmp = class_module_type c in
 			mk (TTypeExpr (TClassDecl c)) (TType (t_tmp,[])) p
 		| TEnumDecl e ->
-			let types = (match tparams with None -> Monomorph.spawn_constrained_monos (fun t -> t) e.e_params | Some l -> l) in
-			mk (TTypeExpr (TEnumDecl e)) (TType (e.e_type,types)) p
+			mk (TTypeExpr (TEnumDecl e)) e.e_type p
 		| TTypeDecl s ->
 			let t = apply_typedef s (List.map (fun _ -> spawn_monomorph ctx p) s.t_params) in
 			DeprecationCheck.check_typedef (create_deprecation_context ctx) s p;
@@ -309,8 +308,8 @@ let get_constructible_constraint ctx tl p =
 				end;
 			| TAbstract({a_path = ["haxe"],"Constructible"},[t1]) ->
 				Some (extract_function t1)
-			| TInst({cl_kind = KTypeParameter tl1},_) ->
-				begin match loop tl1 with
+			| TInst({cl_kind = KTypeParameter ttp},_) ->
+				begin match loop (get_constraints ttp) with
 				| None -> loop tl
 				| Some _ as t -> t
 				end

+ 3 - 3
src/typing/typerDisplay.ml

@@ -251,14 +251,14 @@ let rec handle_signature_display ctx e_ast with_type =
 		l
 	in
 	let find_constructor_types t = match follow t with
-		| TInst ({cl_kind = KTypeParameter tl} as c,_) ->
+		| TInst ({cl_kind = KTypeParameter ttp} as c,_) ->
 			let rec loop tl = match tl with
 				| [] -> raise_typing_error_ext (make_error (No_constructor (TClassDecl c)) p)
 				| t :: tl -> match follow t with
 					| TAbstract({a_path = ["haxe"],"Constructible"},[t]) -> t
 					| _ -> loop tl
 			in
-			[loop tl,None,PMap.empty]
+			[loop (get_constraints ttp),None,PMap.empty]
 		| TInst (c,tl) | TAbstract({a_impl = Some c},tl) ->
 			Display.merge_core_doc ctx (TClassDecl c);
 			let fa = get_constructor_access c tl p in
@@ -628,7 +628,7 @@ let handle_display ctx e_ast dk mode with_type =
 						false
 					end
 				end
-			| ITTypeParameter {cl_kind = KTypeParameter tl} when get_constructible_constraint ctx tl null_pos <> None ->
+			| ITTypeParameter {cl_kind = KTypeParameter ttp} when get_constructible_constraint ctx (get_constraints ttp) null_pos <> None ->
 				true
 			| _ -> false
 		) r.fitems in

+ 167 - 0
src/typing/typerEntry.ml

@@ -0,0 +1,167 @@
+open Globals
+open Common
+open Type
+open Typecore
+open Typer
+open Resolution
+open Error
+
+let create com macros =
+	let ctx = {
+		com = com;
+		t = com.basic;
+		g = {
+			core_api = None;
+			macros = macros;
+			type_patches = Hashtbl.create 0;
+			module_check_policies = [];
+			delayed = [];
+			debug_delayed = [];
+			doinline = com.display.dms_inline && not (Common.defined com Define.NoInline);
+			retain_meta = Common.defined com Define.RetainUntypedMeta;
+			std_types = null_module;
+			std = null_class;
+			global_using = [];
+			complete = false;
+			type_hints = [];
+			load_only_cached_modules = false;
+			functional_interface_lut = new Lookup.pmap_lookup;
+			do_macro = MacroContext.type_macro;
+			do_load_macro = MacroContext.load_macro';
+			do_load_module = TypeloadModule.load_module;
+			do_load_type_def = Typeload.load_type_def;
+			get_build_info = InstanceBuilder.get_build_info;
+			do_format_string = format_string;
+			do_load_core_class = Typeload.load_core_class;
+		};
+		m = {
+			curmod = null_module;
+			import_resolution = new resolution_list ["import";"typer"];
+			own_resolution = None;
+			enum_with_type = None;
+			module_using = [];
+			import_statements = [];
+		};
+		is_display_file = false;
+		bypass_accessor = 0;
+		meta = [];
+		with_type_stack = [];
+		call_argument_stack = [];
+		pass = PBuildModule;
+		macro_depth = 0;
+		untyped = false;
+		curfun = FunStatic;
+		in_function = false;
+		in_loop = false;
+		in_display = false;
+		allow_inline = true;
+		allow_transform = true;
+		get_build_infos = (fun() -> None);
+		ret = mk_mono();
+		locals = PMap.empty;
+		type_params = [];
+		curclass = null_class;
+		curfield = null_field;
+		tthis = mk_mono();
+		opened = [];
+		vthis = None;
+		in_call_args = false;
+		in_overload_call_args = false;
+		delayed_display = None;
+		monomorphs = {
+			perfunction = [];
+		};
+		memory_marker = Typecore.memory_marker;
+	} in
+	ctx.g.std_types <- (try
+		TypeloadModule.load_module ctx ([],"StdTypes") null_pos
+	with
+		Error { err_message = Module_not_found ([],"StdTypes") } ->
+			try
+				let std_path = Sys.getenv "HAXE_STD_PATH" in
+				raise_typing_error ("Standard library not found. Please check your `HAXE_STD_PATH` environment variable (current value: \"" ^ std_path ^ "\")") null_pos
+			with Not_found ->
+				raise_typing_error "Standard library not found. You may need to set your `HAXE_STD_PATH` environment variable" null_pos
+	);
+	(* We always want core types to be available so we add them as default imports (issue #1904 and #3131). *)
+	List.iter (fun mt ->
+		ctx.m.import_resolution#add (module_type_resolution mt None null_pos))
+	(List.rev ctx.g.std_types.m_types);
+	List.iter (fun t ->
+		match t with
+		| TAbstractDecl a ->
+			(match snd a.a_path with
+			| "Void" -> ctx.t.tvoid <- TAbstract (a,[]);
+			| "Float" ->
+				let t = (TAbstract (a,[])) in
+				Type.unify t ctx.t.tfloat;
+				ctx.t.tfloat <- t
+			| "Int" ->
+				let t = (TAbstract (a,[])) in
+				Type.unify t ctx.t.tint;
+				ctx.t.tint <- t
+			| "Bool" ->
+				let t = (TAbstract (a,[])) in
+				Type.unify t ctx.t.tbool;
+				ctx.t.tbool <- t
+			| "Dynamic" ->
+				t_dynamic_def := TAbstract(a,extract_param_types a.a_params);
+			| "Null" ->
+				let mk_null t =
+					try
+						if not (is_null ~no_lazy:true t || is_explicit_null t) then TAbstract (a,[t]) else t
+					with Exit ->
+						(* don't force lazy evaluation *)
+						let r = ref (lazy_available t_dynamic) in
+						r := lazy_wait (fun() ->
+							let t = (if not (is_null t) then TAbstract (a,[t]) else t) in
+							r := lazy_available t;
+							t
+						);
+						TLazy r
+				in
+				ctx.t.tnull <- mk_null;
+			| _ -> ())
+		| TEnumDecl _ | TClassDecl _ | TTypeDecl _ ->
+			()
+	) ctx.g.std_types.m_types;
+	let m = TypeloadModule.load_module ctx ([],"String") null_pos in
+	List.iter (fun mt -> match mt with
+		| TClassDecl c ->
+			let t = (TInst (c,[])) in
+			Type.unify t ctx.t.tstring;
+			ctx.t.tstring <- t
+		| _ -> ()
+	) m.m_types;
+	let m = TypeloadModule.load_module ctx ([],"Std") null_pos in
+	List.iter (fun mt -> match mt with
+		| TClassDecl c -> ctx.g.std <- c;
+		| _ -> ()
+	) m.m_types;
+	let m = TypeloadModule.load_module ctx ([],"Array") null_pos in
+	(try
+		List.iter (fun t -> (
+			match t with
+			| TClassDecl ({cl_path = ([],"Array")} as c) ->
+				ctx.t.tarray <- (fun t -> TInst (c,[t]));
+				raise Exit
+			| _ -> ()
+		)) m.m_types;
+		die "" __LOC__
+	with Exit -> ());
+	let m = TypeloadModule.load_module ctx (["haxe"],"EnumTools") null_pos in
+	(match m.m_types with
+	| [TClassDecl c1;TClassDecl c2] -> ctx.g.global_using <- (c1,c1.cl_pos) :: (c2,c2.cl_pos) :: ctx.g.global_using
+	| [TClassDecl c1] ->
+		let m = TypeloadModule.load_module ctx (["haxe"],"EnumWithType.valueTools") null_pos in
+		(match m.m_types with
+		| [TClassDecl c2 ] -> ctx.g.global_using <- (c1,c1.cl_pos) :: (c2,c2.cl_pos) :: ctx.g.global_using
+		| _ -> die "" __LOC__);
+	| _ -> die "" __LOC__);
+	ignore(TypeloadModule.load_module ctx (["haxe"],"Exception") null_pos);
+	ctx.g.complete <- true;
+	ctx
+
+;;
+create_context_ref := create;
+Inline.maybe_reapply_overload_call_ref := CallUnification.maybe_reapply_overload_call;

+ 3 - 0
std/hl/Api.hx

@@ -26,6 +26,9 @@ extern class Api {
 	static inline function rethrow(v:Dynamic):Void {
 		untyped $rethrow(v);
 	}
+	static inline function unsafeCast<From,To>(v:From):To {
+		return untyped $unsafecast(v);
+	}
 	@:hlNative("std", "obj_get_field") static function getField(obj:Dynamic, hash:Int):Dynamic;
 	@:hlNative("std", "obj_set_field") static function setField(obj:Dynamic, hash:Int, value:Dynamic):Void;
 	@:hlNative("std", "obj_has_field") static function hasField(obj:Dynamic, hash:Int):Bool;

+ 4 - 21
std/hl/CArray.hx

@@ -1,35 +1,18 @@
 package hl;
 
-#if (hl_ver >= version("1.13.0"))
+#if (hl_ver >= version("1.14.0"))
 /**
 	CArray is a compact array where all objects are memory aligned and stored as a single GC block.
 	You must hold a reference to the CArray while any of the objects it contains is still referenced somewhere.
  **/
 abstract CArray<T>(Abstract<"hl_carray">) {
 
-	public var length(get,never) : Int;
-
-
-	#if (hl_ver >= version("1.14.0"))
-	inline function get_length() return untyped $asize(this);
 	@:arrayAccess inline function get( index : Int ) : T return untyped this[index];
-	#else
-	inline function get_length() return getLen(cast this);
-	@:arrayAccess inline function get( index : Int ) : T return getIndex(cast this, index);
-	#end
-
-	public static function alloc<T>( cl : Class<T>, size : Int ) : CArray<T> {
-		return cast alloc_carray( (cast cl:BaseType).__type__ , size );
-	}
 
-	@:hlNative("?std","carray_get")
-	static function getIndex( arr : CArray<Dynamic>, index : Int ) : Dynamic {
-		return null;
-	}
+	public inline function unsafeSet( index : Int, v : T ) return untyped this[index] = v;
 
-	@:hlNative("?std","carray_length")
-	static function getLen( arr : CArray<Dynamic> ) : Int {
-		return 0;
+	public static inline function alloc<T>( cl : Class<T>, size : Int ) : CArray<T> {
+		return cast alloc_carray( (cast cl:BaseType).__type__ , size );
 	}
 
 	@:hlNative("?std","alloc_carray")

+ 1 - 1
std/js/Object.hx

@@ -24,4 +24,4 @@ package js;
 
 @:deprecated typedef Object = js.lib.Object;
 @:deprecated typedef ObjectPrototype = js.lib.Object.ObjectPrototype;
-@:deprecated typedef ObjectPropertyDescriptor = js.lib.Object.ObjectPropertyDescriptor;
+@:deprecated typedef ObjectPropertyDescriptor<TProp> = js.lib.Object.ObjectPropertyDescriptor<TProp>;

+ 43 - 1
std/js/html/Navigator.hx

@@ -106,6 +106,11 @@ extern class Navigator {
 	var onLine(default,null) : Bool;
 	var storage(default,null) : StorageManager;
 
+	/**
+		Returns a `WakeLock` object which allows a document to acquire a screen wake lock.
+	**/
+	var wakeLock(default,null) : WakeLock;
+
 	@:overload( function( duration : Int ) : Bool {} )
 	function vibrate( pattern : Array<Int> ) : Bool;
 	function javaEnabled() : Bool;
@@ -122,4 +127,41 @@ extern class Navigator {
 	function sendBeacon( url : String, ?data : Blob ) : Bool;
 	function requestMediaKeySystemAccess( keySystem : String, supportedConfigurations : Array<js.html.eme.MediaKeySystemConfiguration> ) : Promise<js.html.eme.MediaKeySystemAccess>;
 	function taintEnabled() : Bool;
-}
+
+	/**
+		Returns `true` if the equivalent call to `share()` would succeed.
+		Returns `false` if the data cannot be validated.
+	**/
+	function canShare(?data: NavigatorShareData): Bool;
+
+	/**
+		Invokes the native sharing mechanism of the device to share data such as text, URLs, or files.
+	**/
+	function share(data: NavigatorShareData): Promise<Void>;
+}
+
+/**
+	An object containing data to share.
+**/
+typedef NavigatorShareData = {
+
+	/**
+		An array of `File` objects representing files to be shared.
+	**/
+	var ?files: Array<File>;
+
+	/**
+		A string representing text to be shared.
+	**/
+	var ?text: String;
+
+	/**
+		A string representing the title to be shared.
+	**/
+	var ?title: String;
+
+	/**
+		A string representing a URL to be shared
+	**/
+	var ?url: String;
+}

+ 74 - 0
std/js/html/WakeLock.hx

@@ -0,0 +1,74 @@
+/*
+ * Copyright (C)2005-2023 Haxe Foundation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+package js.html;
+
+import js.lib.Promise;
+
+/**
+	Prevents device screens from dimming or locking when an application needs to keep running.
+
+	Documentation [WakeLock](https://developer.mozilla.org/en-US/docs/Web/API/WakeLock) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/WakeLock/contributors.txt), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/).
+
+	@see <https://developer.mozilla.org/en-US/docs/Web/API/WakeLock>
+**/
+@:native("WakeLock")
+extern class WakeLock {
+
+	/**
+		Returns a `Promise` that resolves with a `WakeLockSentinel` object, which allows control over screen dimming and locking.
+	**/
+	function request(?type: WakeLockType): Promise<WakeLockSentinel>;
+}
+
+/**
+	Provides a handle to the underlying platform wake lock and can be manually released and reacquired.
+
+	Documentation [WakeLockSentinel](https://developer.mozilla.org/en-US/docs/Web/API/WakeLockSentinel) by [Mozilla Contributors](https://developer.mozilla.org/en-US/docs/Web/API/WakeLockSentinel/contributors.txt), licensed under [CC-BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/).
+
+	@see <https://developer.mozilla.org/en-US/docs/Web/API/WakeLockSentinel>
+**/
+@:native("WakeLockSentinel")
+extern class WakeLockSentinel  extends EventTarget {
+
+	/**
+		A boolean a that indicates whether a `WakeLockSentinel` has been released yet.
+	**/
+	final released: Bool;
+
+	/**
+		A string representation of the currently acquired `WakeLockSentinel` type.
+	**/
+	final type: WakeLockType;
+
+	/**
+		Releases the `WakeLockSentinel`, returning a `Promise` that is resolved once the sentinel has been successfully released.
+	**/
+	function release(): Promise<Void>;
+}
+
+/**
+	Indicates the type of `WakeLockSentinel` to be acquired.
+**/
+enum abstract WakeLockType(String) from String to String {
+	var Screen = "screen";
+}

+ 151 - 53
std/js/lib/Object.hx

@@ -33,35 +33,64 @@ import haxe.DynamicAccess;
 @:native("Object")
 extern class Object {
 	/**
-		Copies the values of all enumerable own properties from one or more
-		source objects to a target object.
+		The Object.assign() method is used to copy the values of all enumerable
+		own properties from one or more source objects to a target object. It
+		will return the target object.
+
+		Note: this is an ES2015 feature
+
+		See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/assign
 	**/
-	static function assign<T:{}>(target:T, sources:Rest<{}>):T;
+	static function assign<TSource:{}, TDest:{}>(target:TSource, sources:Rest<{}>):TDest;
 
 	/**
-		Creates a new object with the specified prototype object and properties.
+		The Object.create() method create a new object, using an existing object
+		to provide the newly created object's __proto__ . (see browser console
+		for visual evidence.)
+
+		See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/create
 	**/
-	@:pure static function create<T>(proto:{}, ?propertiesObject:DynamicAccess<ObjectPropertyDescriptor>):T;
+	@:pure static function create<T>(proto:Null<{}>, ?propertiesObject:DynamicAccess<ObjectPropertyDescriptor<Any>>):T;
 
 	/**
-		Adds the named properties described by the given descriptors to an object.
+		The Object.defineProperties() method defines new or modifies existing
+		properties directly on an object, returning the object.
+
+		See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/defineProperties
 	**/
-	static function defineProperties<T:{}>(obj:T, props:DynamicAccess<ObjectPropertyDescriptor>):T;
+	static function defineProperties<T:{}>(obj:T, props:DynamicAccess<ObjectPropertyDescriptor<Any>>):T;
 
 	/**
-		Adds the named property described by a given descriptor to an object.
+		The static method Object.defineProperty() defines a new property directly
+		on an object, or modifies an existing property on an object, and returns
+		the object.
+
+		See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/defineProperty
 	**/
-	@:overload(function<T:{}>(obj:T, prop:Symbol, descriptor:ObjectPropertyDescriptor):T {})
-	static function defineProperty<T:{}>(obj:T, prop:String, descriptor:ObjectPropertyDescriptor):T;
+	@:overload(function<T:{}, TProp>(obj:T, prop:Symbol, descriptor:ObjectPropertyDescriptor<TProp>):T {})
+	static function defineProperty<T:{}, TProp>(obj:T, prop:String, descriptor:ObjectPropertyDescriptor<TProp>):T;
 
 	/**
-		Returns an array containing all of the [key, value] pairs of a given
-		object's own enumerable string properties.
+		The Object.entries() method returns an array of a given object's own
+		enumerable property [key, value] pairs, in the same order as that
+		provided by a for...in loop (the difference being that a for-in loop
+		enumerates properties in the prototype chain as well).
+
+		Note: this is an ES2017 feature
+
+		See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/entries
 	**/
-	@:pure static function entries(obj:{}):Array<ObjectEntry>;
+	@:pure static function entries<T:{}>(obj:T):Array<ObjectEntry>;
 
 	/**
-		Freezes an object: other code can't delete or change any properties.
+		The Object.freeze() method freezes an object: that is, prevents new
+		properties from being added to it; prevents existing properties from
+		being removed; and prevents existing properties, or their enumerability,
+		configurability, or writability, from being changed, it also prevents the
+		prototype from being changed.
+		The method returns the passed object.
+
+		See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/freeze
 	**/
 	static function freeze<T:{}>(obj:T):T;
 
@@ -72,76 +101,149 @@ extern class Object {
 	@:pure static function fromEntries<T:{}>(iterable:Any):T;
 
 	/**
-		Returns a property descriptor for a named property on an object.
+		The Object.getOwnPropertyDescriptor() method returns a property
+		descriptor for an own property (that is, one directly present on an
+		object and not in the object's prototype chain) of a given object.
+
+		In ES5, if the first argument to this method is not an object (a
+		primitive), then it will cause a TypeError. In ES2015, a non-object
+		first argument will be coerced to an object at first.
+
+		See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/getOwnPropertyDescriptor
 	**/
-	@:overload(function<T>(target:Array<T>, propertyKey:Int):Null<ObjectPropertyDescriptor> {})
-	@:overload(function(obj:{}, prop:Symbol):Null<ObjectPropertyDescriptor> {})
-	@:pure static function getOwnPropertyDescriptor(obj:{}, prop:String):Null<ObjectPropertyDescriptor>;
+	@:overload(function(obj:String, prop:Symbol):Null<ObjectPropertyDescriptor<String>> {})
+	@:overload(function(obj:String, prop:String):Null<ObjectPropertyDescriptor<String>> {})
+	@:overload(function<T>(target:Array<T>, propertyKey:Int):Null<ObjectPropertyDescriptor<T>> {})
+	@:overload(function<T, TProp>(obj:T, prop:Symbol):Null<ObjectPropertyDescriptor<TProp>> {})
+	@:pure static function getOwnPropertyDescriptor<T, TProp>(obj:T, prop:String):Null<ObjectPropertyDescriptor<TProp>>;
 
 	/**
-		Returns an array containing the names of all of the given object's own
-		enumerable and non-enumerable properties.
+		The Object.getOwnPropertyDescriptors() method returns all own property
+		descriptors of a given object.
+
+		See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/getOwnPropertyDescriptors
 	**/
-	@:pure static function getOwnPropertyNames(obj:{}):Array<String>;
+	@:overload(function(target:String):DynamicAccess<ObjectPropertyDescriptor<String>> {})
+	@:overload(function<T>(target:Array<T>):DynamicAccess<ObjectPropertyDescriptor<T>> {})
+	@:pure static function getOwnPropertyDescriptors<T>(obj:T):DynamicAccess<ObjectPropertyDescriptor<Any>>;
 
 	/**
-		Returns an array of all symbol properties found directly upon a given object.
+		The Object.getOwnPropertyNames() method returns an array of all
+		properties (including non-enumerable properties except for those which
+		use Symbol) found directly upon a given object.
+
+		See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/getOwnPropertyNames
 	**/
-	@:pure static function getOwnPropertySymbols(obj:{}):Array<Symbol>;
+	@:pure static function getOwnPropertyNames<T:{}>(obj:T):Array<String>;
 
 	/**
-		Returns the prototype of the specified object.
+		The Object.getOwnPropertySymbols() method returns an array of all symbol
+		properties found directly upon a given object.
+
+		Note: this is an ES2015 feature
+
+		See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/getOwnPropertySymbols
 	**/
-	@:pure static function getPrototypeOf<TProto:{}>(obj:{}):Null<TProto>;
+	@:pure static function getOwnPropertySymbols<T:{}>(obj:T):Array<Symbol>;
 
 	/**
-		Compares if two values are the same value. Equates all NaN values
-		(which differs from both Abstract Equality Comparison and
-		Strict Equality Comparison).
+		The Object.getPrototypeOf() method returns the prototype (i.e. the value
+		of the internal [[Prototype]] property) of the specified object.
+
+		See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/getPrototypeOf
 	**/
-	@:pure static function is<T>(value1:T, value2:T):Bool;
+	@:pure static function getPrototypeOf<T:{}, TProto>(obj:T):TProto;
 
 	/**
-		Determines if extending of an object is allowed.
+		The Object.is() method determines whether two values are the same value.
+
+		Note: this is an ES2015 feature
+
+		See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/is
 	**/
-	@:pure static function isExtensible(obj:{}):Bool;
+	@:native("is") @:pure static function isSame<T:{}>(obj1:T, obj2:T):Bool;
 
 	/**
-		Determines if an object was frozen.
+		The Object.is() method determines whether two values are the same value.
+
+		Note: this is an ES2015 feature
+
+		See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/is
 	**/
-	@:pure static function isFrozen(obj:{}):Bool;
+	@:deprecated("Use Object.isSame()")
+	@:pure static function is<T:{}>(obj1:T, obj2:T):Bool;
 
 	/**
-		Determines if an object is sealed.
+		The Object.isExtensible() method determines if an object is extensible
+		(whether it can have new properties added to it).
+
+		See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/isExtensible
 	**/
-	@:pure static function isSealed(obj:{}):Bool;
+	@:pure static function isExtensible<T:{}>(obj:T):Bool;
 
 	/**
-		Returns an array containing the names of all of the given object's own
-		enumerable string properties.
+		The Object.isFrozen() determines if an object is frozen.
+
+		See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/isFrozen
+	**/
+	@:pure static function isFrozen<T:{}>(obj:T):Bool;
+
+	/**
+		The Object.isSealed() method determines if an object is sealed.
+
+		See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/isSealed
 	**/
-	@:pure static function keys(obj:{}):Array<String>;
+	@:pure static function isSealed<T:{}>(obj:T):Bool;
 
 	/**
-		Prevents any extensions of an object.
+		The Object.keys() method returns an array of a given object's own
+		enumerable properties, in the same order as that provided by a for...in
+		loop (the difference being that a for-in loop enumerates properties in
+		the prototype chain as well).
+
+		See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/keys
+	**/
+	@:pure static function keys<T:{}>(obj:T):Array<String>;
+
+	/**
+		The Object.preventExtensions() method prevents new properties from ever
+		being added to an object (i.e. prevents future extensions to the object).
+
+		See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/preventExtensions
 	**/
 	static function preventExtensions<T:{}>(obj:T):T;
 
 	/**
-		Prevents other code from deleting properties of an object.
+		The Object.seal() method seals an object, preventing new properties from
+		being added to it and marking all existing properties as
+		non-configurable. Values of present properties can still be changed as
+		long as they are writable.
+
+		See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/seal
 	**/
 	static function seal<T:{}>(obj:T):T;
 
 	/**
-		Sets the prototype (i.e., the internal Prototype property).
+		The Object.setPrototypeOf() method sets the prototype (i.e., the internal
+		[[Prototype]] property) of a specified object to another object or null.
+
+		Note: this is an ES2015 feature
+
+		See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/setPrototypeOf
 	**/
-	static function setPrototypeOf<T:{}>(obj:T, prototype:Null<{}>):T;
+	static function setPrototypeOf<T:{}, TProto:{}>(obj:T, proto:Null<TProto>):T;
 
 	/**
-		Returns an array containing the values that correspond to all of
-		a given object's own enumerable string properties.
+		The Object.values() method returns an array of a given object's own
+		enumerable property values, in the same order as that provided by a
+		for...in loop (the difference being that a for-in loop enumerates
+		properties in the prototype chain as well).
+
+		Note: this is an ES2017 feature
+
+		See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/values
 	**/
-	@:pure static function values(obj:{}):Array<Any>;
+	@:pure static function values<T:{}>(obj:T):Array<Any>;
 
 	/**
 		Allows the addition of properties to all objects of type Object.
@@ -196,11 +298,10 @@ typedef ObjectPrototype = {
 /**
 	@see <https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/defineProperty>
 **/
-typedef ObjectPropertyDescriptor = {
+typedef ObjectPropertyDescriptor<TProp> = {
 	/**
 		`true` if and only if the type of this property descriptor may be
 		changed and if the property may be deleted from the corresponding object.
-
 		Defaults to `false`.
 	**/
 	var ?configurable:Bool;
@@ -208,7 +309,6 @@ typedef ObjectPropertyDescriptor = {
 	/**
 		`true` if and only if this property shows up during enumeration of the
 		properties on the corresponding object.
-
 		Defaults to `false`.
 	**/
 	var ?enumerable:Bool;
@@ -217,12 +317,11 @@ typedef ObjectPropertyDescriptor = {
 		The value associated with the property.
 		Can be any valid JavaScript value (number, object, function, etc).
 	**/
-	var ?value:Any;
+	var ?value:TProp;
 
 	/**
 		`true` if and only if the value associated with the property may be
 		changed with an assignment operator.
-
 		Defaults to `false`.
 	**/
 	var ?writable:Bool;
@@ -235,7 +334,7 @@ typedef ObjectPropertyDescriptor = {
 		property is defined due to inheritance).
 		The return value will be used as the value of the property.
 	**/
-	var ?get:Void->Any;
+	var ?get:Void->TProp;
 
 	/**
 		A function which serves as a setter for the property, or undefined if
@@ -243,7 +342,7 @@ typedef ObjectPropertyDescriptor = {
 		is called with one argument (the value being assigned to the property)
 		and with `this` set to the object through which the property is assigned.
 	**/
-	var ?set:Any->Void;
+	var ?set:TProp->Void;
 }
 
 /**
@@ -252,7 +351,6 @@ typedef ObjectPropertyDescriptor = {
 abstract ObjectEntry(Array<Any>) {
 	public var key(get, never):String;
 	public var value(get, never):Any;
-
 	inline function get_key():String
 		return this[0];
 

+ 2 - 2
std/js/lib/Proxy.hx

@@ -65,12 +65,12 @@ typedef ProxyHandler<T:{}> = {
 	/**
 		A trap for `Object.getOwnPropertyDescriptor`.
 	**/
-	var ?getOwnPropertyDescriptor:(target:T, prop:EitherType<String, Symbol>) -> Null<ObjectPropertyDescriptor>;
+	var ?getOwnPropertyDescriptor:(target:T, prop:EitherType<String, Symbol>) -> Null<ObjectPropertyDescriptor<Any>>;
 
 	/**
 		A trap for `Object.defineProperty`.
 	**/
-	var ?defineProperty:(target:T, property:EitherType<String, Symbol>, descriptor:ObjectPropertyDescriptor) -> Bool;
+	var ?defineProperty:(target:T, property:EitherType<String, Symbol>, descriptor:ObjectPropertyDescriptor<Any>) -> Bool;
 
 	/**
 		A trap for the `in` operator.

部分文件因为文件数量过多而无法显示