Sfoglia il codice sorgente

completely rewrote compiler priority passes system

Nicolas Cannasse 13 anni fa
parent
commit
52434b48dd
5 ha cambiato i file con 455 aggiunte e 314 eliminazioni
  1. 9 9
      codegen.ml
  2. 26 10
      type.ml
  3. 152 25
      typecore.ml
  4. 227 221
      typeload.ml
  5. 41 49
      typer.ml

+ 9 - 9
codegen.ml

@@ -218,7 +218,7 @@ let make_generic ctx ps pt p =
 	in
 	in
 	let name =
 	let name =
 		String.concat "_" (List.map2 (fun (s,_) t ->
 		String.concat "_" (List.map2 (fun (s,_) t ->
-			let path = (match follow t with		
+			let path = (match follow t with
 				| TInst (ct,_) -> ct.cl_path
 				| TInst (ct,_) -> ct.cl_path
 				| TEnum (e,_) -> e.e_path
 				| TEnum (e,_) -> e.e_path
 				| TAbstract (a,_) when has_meta ":runtime_value" a.a_meta -> a.a_path
 				| TAbstract (a,_) when has_meta ":runtime_value" a.a_meta -> a.a_path
@@ -489,8 +489,8 @@ let build_instance ctx mtype p =
 					r := (fun() -> t);
 					r := (fun() -> t);
 					unify_raise ctx (build_generic ctx c p pl) t p;
 					unify_raise ctx (build_generic ctx c p pl) t p;
 					t
 					t
-				) in
-				delay ctx (fun() -> ignore ((!r)()));
+				) "build_generic" in
+				delay ctx PForce (fun() -> ignore ((!r)()));
 				TLazy r
 				TLazy r
 			| KMacroType ->
 			| KMacroType ->
 				let r = exc_protect ctx (fun r ->
 				let r = exc_protect ctx (fun r ->
@@ -498,8 +498,8 @@ let build_instance ctx mtype p =
 					r := (fun() -> t);
 					r := (fun() -> t);
 					unify_raise ctx (build_macro_type ctx pl p) t p;
 					unify_raise ctx (build_macro_type ctx pl p) t p;
 					t
 					t
-				) in
-				delay ctx (fun() -> ignore ((!r)()));
+				) "macro_type" in
+				delay ctx PForce (fun() -> ignore ((!r)()));
 				TLazy r
 				TLazy r
 			| _ ->
 			| _ ->
 				TInst (c,pl)
 				TInst (c,pl)
@@ -567,7 +567,7 @@ let remove_generic_base ctx t = match t with
 		(try
 		(try
 			let (_,_,prec) = get_meta ":?genericRec" c.cl_meta in
 			let (_,_,prec) = get_meta ":?genericRec" c.cl_meta in
 			(try
 			(try
-				let (_,_,pnew) = get_meta ":?genericT" c.cl_meta in			
+				let (_,_,pnew) = get_meta ":?genericT" c.cl_meta in
 				display_error ctx ("Class " ^ (s_type_path c.cl_path) ^ " was used recursively and cannot use its type parameter") prec;
 				display_error ctx ("Class " ^ (s_type_path c.cl_path) ^ " was used recursively and cannot use its type parameter") prec;
 				error "Type parameter usage was here" pnew
 				error "Type parameter usage was here" pnew
 			with Not_found _ ->
 			with Not_found _ ->
@@ -603,7 +603,7 @@ let apply_native_paths ctx t =
 		()
 		()
 
 
 (* Adds the __rtti field if required *)
 (* Adds the __rtti field if required *)
-let add_rtti ctx t = 
+let add_rtti ctx t =
 	let has_rtti c =
 	let has_rtti c =
 		let rec has_rtti_new c =
 		let rec has_rtti_new c =
 			has_meta ":rttiInfos" c.cl_meta || match c.cl_super with None -> false | Some (csup,_) -> has_rtti_new csup
 			has_meta ":rttiInfos" c.cl_meta || match c.cl_super with None -> false | Some (csup,_) -> has_rtti_new csup
@@ -1563,10 +1563,10 @@ let rec create_dumpfile acc = function
 	| [] -> assert false
 	| [] -> assert false
 	| d :: [] ->
 	| d :: [] ->
 		let ch = open_out (String.concat "/" (List.rev (d :: acc)) ^ ".dump") in
 		let ch = open_out (String.concat "/" (List.rev (d :: acc)) ^ ".dump") in
-		let buf = Buffer.create 0 in		
+		let buf = Buffer.create 0 in
 		buf, (fun () ->
 		buf, (fun () ->
 			output_string ch (Buffer.contents buf);
 			output_string ch (Buffer.contents buf);
-			close_out ch)		
+			close_out ch)
 	| d :: l ->
 	| d :: l ->
 		let dir = String.concat "/" (List.rev (d :: acc)) in
 		let dir = String.concat "/" (List.rev (d :: acc)) in
 		if not (Sys.file_exists dir) then Unix.mkdir dir 0o755;
 		if not (Sys.file_exists dir) then Unix.mkdir dir 0o755;

+ 26 - 10
type.ml

@@ -273,7 +273,7 @@ let alloc_var =
 	let uid = ref 0 in
 	let uid = ref 0 in
 	(fun n t -> incr uid; { v_name = n; v_type = t; v_id = !uid; v_capture = false; v_extra = None })
 	(fun n t -> incr uid; { v_name = n; v_type = t; v_id = !uid; v_capture = false; v_extra = None })
 
 
-let alloc_mid = 
+let alloc_mid =
 	let mid = ref 0 in
 	let mid = ref 0 in
 	(fun() -> incr mid; !mid)
 	(fun() -> incr mid; !mid)
 
 
@@ -320,7 +320,7 @@ let mk_class m path pos =
 		cl_restore = (fun() -> ());
 		cl_restore = (fun() -> ());
 	}
 	}
 
 
-let module_extra file sign time kind = 
+let module_extra file sign time kind =
 	{
 	{
 		m_file = file;
 		m_file = file;
 		m_sign = sign;
 		m_sign = sign;
@@ -335,6 +335,20 @@ let module_extra file sign time kind =
 		m_macro_calls = [];
 		m_macro_calls = [];
 	}
 	}
 
 
+
+let mk_field name t p = {
+	cf_name = name;
+	cf_type = t;
+	cf_pos = p;
+	cf_doc = None;
+	cf_meta = [];
+	cf_public = true;
+	cf_kind = Var { v_read = AccNormal; v_write = AccNormal };
+	cf_expr = None;
+	cf_params = [];
+	cf_overloads = [];
+}
+
 let null_module = {
 let null_module = {
 		m_id = alloc_mid();
 		m_id = alloc_mid();
 		m_path = [] , "";
 		m_path = [] , "";
@@ -347,6 +361,8 @@ let null_class =
 	c.cl_private <- true;
 	c.cl_private <- true;
 	c
 	c
 
 
+let null_field = mk_field "" t_dynamic Ast.null_pos
+
 let add_dependency m mdep =
 let add_dependency m mdep =
 	if m != null_module && m != mdep then m.m_extra.m_deps <- PMap.add mdep.m_id mdep m.m_extra.m_deps
 	if m != null_module && m != mdep then m.m_extra.m_deps <- PMap.add mdep.m_id mdep m.m_extra.m_deps
 
 
@@ -567,7 +583,7 @@ let rec is_nullable ?(no_lazy=false) = function
 (*
 (*
 	Type parameters will most of the time be nullable objects, so we don't want to make it hard for users
 	Type parameters will most of the time be nullable objects, so we don't want to make it hard for users
 	to have to specify Null<T> all over the place, so while they could be a basic type, let's assume they will not.
 	to have to specify Null<T> all over the place, so while they could be a basic type, let's assume they will not.
-	
+
 	This will still cause issues with inlining and haxe.rtti.Generic. In that case proper explicit Null<T> is required to
 	This will still cause issues with inlining and haxe.rtti.Generic. In that case proper explicit Null<T> is required to
 	work correctly with basic types. This could still be fixed by redoing a nullability inference on the typed AST.
 	work correctly with basic types. This could still be fixed by redoing a nullability inference on the typed AST.
 
 
@@ -854,10 +870,10 @@ let rec raw_class_field build_type c i =
 					| _ ->
 					| _ ->
 						loop ctl
 						loop ctl
 			in
 			in
-			loop tl		
+			loop tl
 		| _ ->
 		| _ ->
 			if not c.cl_interface then raise Not_found;
 			if not c.cl_interface then raise Not_found;
-			(* 
+			(*
 				an interface can implements other interfaces without
 				an interface can implements other interfaces without
 				having to redeclare its fields
 				having to redeclare its fields
 			*)
 			*)
@@ -924,14 +940,14 @@ let rec unify a b =
 		unify_types a b tl1 tl2
 		unify_types a b tl1 tl2
 	| TAbstract (a1,tl1) , TAbstract (a2,tl2) when a1 == a2 ->
 	| TAbstract (a1,tl1) , TAbstract (a2,tl2) when a1 == a2 ->
 		unify_types a b tl1 tl2
 		unify_types a b tl1 tl2
-	| TAbstract (a1,tl1) , TAbstract (a2,tl2) ->		
+	| TAbstract (a1,tl1) , TAbstract (a2,tl2) ->
 		if not (List.exists (fun t ->
 		if not (List.exists (fun t ->
 			let t = apply_params a1.a_types tl1 t in
 			let t = apply_params a1.a_types tl1 t in
 			try unify t b; true with Unify_error _ -> false
 			try unify t b; true with Unify_error _ -> false
 		) a1.a_super) && not (List.exists (fun t ->
 		) a1.a_super) && not (List.exists (fun t ->
 			let t = apply_params a2.a_types tl2 t in
 			let t = apply_params a2.a_types tl2 t in
 			try unify a t; true with Unify_error _ -> false
 			try unify a t; true with Unify_error _ -> false
-		) a2.a_sub) then error [cannot_unify a b]		
+		) a2.a_sub) then error [cannot_unify a b]
 	| TInst (c1,tl1) , TInst (c2,tl2) ->
 	| TInst (c1,tl1) , TInst (c2,tl2) ->
 		let rec loop c tl =
 		let rec loop c tl =
 			if c == c2 then begin
 			if c == c2 then begin
@@ -943,7 +959,7 @@ let rec unify a b =
 					loop cs (List.map (apply_params c.cl_types tl) tls)
 					loop cs (List.map (apply_params c.cl_types tl) tls)
 			) || List.exists (fun (cs,tls) ->
 			) || List.exists (fun (cs,tls) ->
 				loop cs (List.map (apply_params c.cl_types tl) tls)
 				loop cs (List.map (apply_params c.cl_types tl) tls)
-			) c.cl_implements 
+			) c.cl_implements
 			|| (match c.cl_kind with
 			|| (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_types tl) tls) | _ -> false) pl
 			| KTypeParameter pl -> List.exists (fun t -> match follow t with TInst (cs,tls) -> loop cs (List.map (apply_params c.cl_types tl) tls) | _ -> false) pl
 			| _ -> false)
 			| _ -> false)
@@ -987,7 +1003,7 @@ let rec unify a b =
 			PMap.iter (fun n f2 ->
 			PMap.iter (fun n f2 ->
 			try
 			try
 				let f1 = PMap.find n a1.a_fields in
 				let f1 = PMap.find n a1.a_fields in
-				if not (unify_kind f1.cf_kind f2.cf_kind) then 
+				if not (unify_kind f1.cf_kind f2.cf_kind) then
 					(match !(a1.a_status), f1.cf_kind, f2.cf_kind with
 					(match !(a1.a_status), f1.cf_kind, f2.cf_kind with
 					| Opened, Var { v_read = AccNormal; v_write = AccNo }, Var { v_read = AccNormal; v_write = AccNormal } ->
 					| Opened, Var { v_read = AccNormal; v_write = AccNo }, Var { v_read = AccNormal; v_write = AccNormal } ->
 						f1.cf_kind <- f2.cf_kind;
 						f1.cf_kind <- f2.cf_kind;
@@ -1088,7 +1104,7 @@ let rec unify a b =
 and unify_types a b tl1 tl2 =
 and unify_types a b tl1 tl2 =
 	List.iter2 (fun t1 t2 ->
 	List.iter2 (fun t1 t2 ->
 		try
 		try
-			type_eq EqRightDynamic t1 t2 
+			type_eq EqRightDynamic t1 t2
 		with Unify_error l ->
 		with Unify_error l ->
 			let err = cannot_unify a b in
 			let err = cannot_unify a b in
 			error (try unify t1 t2; (err :: (Invariant_parameter (t1,t2)) :: l) with _ -> err :: l)
 			error (try unify t1 t2; (err :: (Invariant_parameter (t1,t2)) :: l) with _ -> err :: l)

+ 152 - 25
typecore.ml

@@ -36,15 +36,23 @@ type macro_mode =
 	| MBuild
 	| MBuild
 	| MMacroType
 	| MMacroType
 
 
-type delayed_functions = {
-	mutable df_normal : (unit -> unit) list;
-	mutable df_late : (unit -> unit) list;
-}
+
+type typer_pass =
+	| PBuildModule			(* build the module structure and setup module type parameters *)
+	| PInitModuleTypes		(* resolve imports and typedefs : dont follow types ! *)
+	| PResolveTypedefs		(* using and other functions that need to follow typededs *)
+	| PBuildClass			(* build the class structure *)
+	| PDefineConstructor	(* add an inherited constructor *)
+	| PTypeField			(* type the class field, allow access to types structures *)
+	| PCheckConstraint		(* perform late constraint checks with inferred types *)
+	| PForce				(* usually ensure that lazy have been evaluated *)
+	| PFinal				(* not used, only mark for finalize *)
 
 
 type typer_globals = {
 type typer_globals = {
 	types_module : (path, path) Hashtbl.t;
 	types_module : (path, path) Hashtbl.t;
 	modules : (path , module_def) Hashtbl.t;
 	modules : (path , module_def) Hashtbl.t;
-	mutable delayed : delayed_functions;
+	mutable delayed : (typer_pass * (unit -> unit) list) list;
+	mutable debug_delayed : (typer_pass * ((unit -> unit) * string * typer) list) list;
 	doinline : bool;
 	doinline : bool;
 	mutable core_api : typer option;
 	mutable core_api : typer option;
 	mutable macros : ((unit -> unit) * typer) option;
 	mutable macros : ((unit -> unit) * typer) option;
@@ -64,6 +72,7 @@ type typer_globals = {
 and typer = {
 and typer = {
 	(* shared *)
 	(* shared *)
 	com : context;
 	com : context;
+	mutable pass : typer_pass;
 	mutable t : basic_types;
 	mutable t : basic_types;
 	g : typer_globals;
 	g : typer_globals;
 	mutable in_macro : bool;
 	mutable in_macro : bool;
@@ -78,7 +87,7 @@ and typer = {
 	mutable tthis : t;
 	mutable tthis : t;
 	mutable type_params : (string * t) list;
 	mutable type_params : (string * t) list;
 	(* per-function *)
 	(* per-function *)
-	mutable curmethod : string;
+	mutable curfield : tclass_field;
 	mutable untyped : bool;
 	mutable untyped : bool;
 	mutable in_super_call : bool;
 	mutable in_super_call : bool;
 	mutable in_loop : bool;
 	mutable in_loop : bool;
@@ -162,6 +171,17 @@ let rec error_msg = function
 	| Custom s -> s
 	| Custom s -> s
 	| Stack (m1,m2) -> error_msg m1 ^ "\n" ^ error_msg m2
 	| Stack (m1,m2) -> error_msg m1 ^ "\n" ^ error_msg m2
 
 
+let pass_name = function
+	| PBuildModule -> "build-module"
+	| PInitModuleTypes -> "init-types"
+	| PResolveTypedefs -> "resolve-types"
+	| PBuildClass -> "build-class"
+	| PDefineConstructor -> "define-constructor"
+	| PTypeField -> "type-field"
+	| PCheckConstraint -> "check-constraint"
+	| PForce -> "force"
+	| PFinal -> "final"
+
 let display_error ctx msg p = ctx.on_error ctx msg p
 let display_error ctx msg p = ctx.on_error ctx msg p
 
 
 let error msg p = raise (Error (Custom msg,p))
 let error msg p = raise (Error (Custom msg,p))
@@ -187,7 +207,7 @@ let unify_raise ctx t1 t2 p =
 			(* no untyped check *)
 			(* no untyped check *)
 			raise (Error (Unify l,p))
 			raise (Error (Unify l,p))
 
 
-let exc_protect ctx f =
+let exc_protect ctx f (where:string) =
 	let rec r = ref (fun() ->
 	let rec r = ref (fun() ->
 		try
 		try
 			f r
 			f r
@@ -223,24 +243,31 @@ let gen_local ctx t =
 let not_opened = ref Closed
 let not_opened = ref Closed
 let mk_anon fl = TAnon { a_fields = fl; a_status = not_opened; }
 let mk_anon fl = TAnon { a_fields = fl; a_status = not_opened; }
 
 
-let delay ctx f =
-	ctx.g.delayed.df_normal <- f :: ctx.g.delayed.df_normal
-
-let delay_late ctx f =
-	ctx.g.delayed.df_late <- f :: ctx.g.delayed.df_late
-
-let mk_field name t p = {
-	cf_name = name;
-	cf_type = t;
-	cf_pos = p;
-	cf_doc = None;
-	cf_meta = no_meta;
-	cf_public = true;
-	cf_kind = Var { v_read = AccNormal; v_write = AccNormal };
-	cf_expr = None;
-	cf_params = [];
-	cf_overloads = [];
-}
+let delay ctx p f =
+	let rec loop = function
+		| [] -> [p,[f]]
+		| (p2,l) :: rest ->
+			if p2 = p then
+				(p, f :: l) :: rest
+			else if p2 < p then
+				(p2,l) :: loop rest
+			else
+				(p,[f]) :: (p2,l) :: rest
+	in
+	ctx.g.delayed <- loop ctx.g.delayed
+
+let rec flush_pass ctx p (where:string) =
+	match ctx.g.delayed with
+	| (p2,l) :: rest when p2 <= p ->
+		(match l with
+		| [] ->
+			ctx.g.delayed <- rest;
+		| f :: l ->
+			ctx.g.delayed <- (p2,l) :: rest;
+			f());
+		flush_pass ctx p where
+	| _ ->
+		()
 
 
 let fake_modules = Hashtbl.create 0
 let fake_modules = Hashtbl.create 0
 let create_fake_module ctx file =
 let create_fake_module ctx file =
@@ -258,3 +285,103 @@ let create_fake_module ctx file =
 	Hashtbl.replace ctx.g.modules mdep.m_path mdep;
 	Hashtbl.replace ctx.g.modules mdep.m_path mdep;
 	mdep
 	mdep
 
 
+(* -------------- debug functions to activate when debugging typer passes ------------------------------- *)
+(*/*
+
+let delay_tabs = ref ""
+
+let context_ident ctx =
+	if Common.defined ctx.com "core_api" then
+		" core "
+	else if Common.defined ctx.com "macro" then
+		"macro "
+	else
+		"  out "
+
+let debug ctx str =
+	if Common.defined ctx.com "cdebug" then prerr_endline (context_ident ctx ^ !delay_tabs ^ str)
+
+let pass_infos ctx p =
+	let inf = Ast.s_type_path ctx.current.m_path in
+	let inf = (match snd ctx.curclass.cl_path with "" -> inf | n when n = snd ctx.current.m_path -> inf | n -> inf ^ "." ^ n) in
+	let inf = (match ctx.curfield.cf_name with "" -> inf | n -> inf ^ ":" ^ n) in
+	let inf = pass_name p ^ " ("  ^ inf ^ ")" in
+	let inf = if ctx.pass > p then inf ^ " ??CURPASS=" ^ pass_name ctx.pass else inf in
+	inf
+
+let delay ctx p f =
+	let inf = pass_infos ctx p in
+	let rec loop = function
+		| [] -> [p,[f,inf,ctx]]
+		| (p2,l) :: rest ->
+			if p2 = p then
+				(p, (f,inf,ctx) :: l) :: rest
+			else if p2 < p then
+				(p2,l) :: loop rest
+			else
+				(p,[f,inf,ctx]) :: (p2,l) :: rest
+	in
+	ctx.g.debug_delayed <- loop ctx.g.debug_delayed;
+	if p <> PForce then debug ctx ("add " ^ inf)
+
+let pending_passes ctx =
+	let rec loop acc = function
+		| (PDefineConstructor,_) :: pl -> loop acc pl (* SKIP SINCE HAVE SPECIAL BEHAVIOR *)
+		| (p,l) :: pl when p < ctx.pass -> loop (acc @ l) pl
+		| _ -> acc
+	in
+	match loop [] ctx.g.debug_delayed with
+	| [] -> ""
+	| l -> " ??PENDING[" ^ String.concat ";" (List.map (fun (_,i,_) -> i) l) ^ "]"
+
+let display_error ctx msg p =
+	debug ctx ("ERROR " ^ msg);
+	display_error ctx msg p
+
+let rec flush_pass ctx p where =
+	let rec loop() =
+		match ctx.g.debug_delayed with
+		| (p2,l) :: rest when p2 <= p ->
+			(match l with
+			| [] ->
+				ctx.g.debug_delayed <- rest
+			| (f,inf,ctx2) :: l ->
+				ctx.g.debug_delayed <- (p2,l) :: rest;
+				let old = !delay_tabs in
+				(match p2 with
+				| PForce | PTypeField -> ()
+				| _ ->
+					debug ctx ("run " ^ inf ^ pending_passes ctx2);
+					delay_tabs := !delay_tabs ^ "\t");
+				(try f() with Fatal_error -> delay_tabs := old; raise Fatal_error | exc when not (Common.defined ctx.com "stack") -> debug ctx ("FATAL " ^ Printexc.to_string exc); delay_tabs := old; raise exc);
+				delay_tabs := old);
+			loop()
+		| _ ->
+			()
+	in
+	match ctx.g.debug_delayed with
+	| (p2,_) :: _ when p2 <= p ->
+		let old = !delay_tabs in
+		debug ctx ("flush " ^ pass_name p ^ "(" ^ where ^ ")");
+		delay_tabs := !delay_tabs ^ "\t";
+		loop();
+		delay_tabs := old;
+		debug ctx "flush-done";
+	| _ ->
+		()
+
+let exc_protect ctx f where =
+	let inf = pass_infos ctx ctx.pass in
+	exc_protect ctx (fun r ->
+		flush_pass ctx PBuildClass where;
+		debug ctx ("run " ^ inf ^ pending_passes ctx);
+		let old = !delay_tabs in
+		delay_tabs := !delay_tabs ^ "\t";
+		let t = f r in
+		delay_tabs := old;
+		t
+	) where
+
+*/*)
+(* --------------------------------------------------- *)
+

+ 227 - 221
typeload.ml

@@ -78,7 +78,7 @@ let rec load_type_def ctx p t =
 			let next() =
 			let next() =
 				let t, m = (try
 				let t, m = (try
 					t, ctx.g.do_load_module ctx (t.tpackage,t.tname) p
 					t, ctx.g.do_load_module ctx (t.tpackage,t.tname) p
-				with Error (Module_not_found _,p2) as e when p == p2 -> 
+				with Error (Module_not_found _,p2) as e when p == p2 ->
 					match t.tpackage with
 					match t.tpackage with
 					| "std" :: l ->
 					| "std" :: l ->
 						let t = { t with tpackage = l } in
 						let t = { t with tpackage = l } in
@@ -139,7 +139,7 @@ let rec load_instance ctx t p allow_no_params =
 		if t.tparams <> [] then error ("Class type parameter " ^ t.tname ^ " can't have parameters") p;
 		if t.tparams <> [] then error ("Class type parameter " ^ t.tname ^ " can't have parameters") p;
 		pt
 		pt
 	with Not_found ->
 	with Not_found ->
-		let mt = (load_type_def ctx p t) in
+		let mt = load_type_def ctx p t in
 		let is_generic = match mt with TClassDecl {cl_kind = KGeneric} -> true | _ -> false in
 		let is_generic = match mt with TClassDecl {cl_kind = KGeneric} -> true | _ -> false in
 		let types , path , f = ctx.g.do_build_instance ctx mt p in
 		let types , path , f = ctx.g.do_build_instance ctx mt p in
 		if allow_no_params && t.tparams = [] then begin
 		if allow_no_params && t.tparams = [] then begin
@@ -148,7 +148,7 @@ let rec load_instance ctx t p allow_no_params =
 				match follow t with
 				match follow t with
 				| TInst (c,_) ->
 				| TInst (c,_) ->
 					let t = mk_mono() in
 					let t = mk_mono() in
-					if c.cl_kind <> KTypeParameter [] || is_generic then delay_late ctx (fun() -> check_param_constraints ctx types t (!pl) c p);
+					if c.cl_kind <> KTypeParameter [] || is_generic then delay ctx PCheckConstraint (fun() -> check_param_constraints ctx types t (!pl) c p);
 					t;
 					t;
 				| _ -> assert false
 				| _ -> assert false
 			) types;
 			) types;
@@ -183,10 +183,10 @@ let rec load_instance ctx t p allow_no_params =
 				| TInst (c,[]) ->
 				| TInst (c,[]) ->
 					let r = exc_protect ctx (fun r ->
 					let r = exc_protect ctx (fun r ->
 						r := (fun() -> t);
 						r := (fun() -> t);
-						delay_late ctx (fun() -> check_param_constraints ctx types t tparams c p);
+						delay ctx PCheckConstraint (fun() -> check_param_constraints ctx types t tparams c p);
 						t
 						t
-					) in
-					delay ctx (fun () -> ignore(!r()));
+					) "constraint" in
+					delay ctx PForce (fun () -> ignore(!r()));
 					TLazy r
 					TLazy r
 				| _ -> assert false
 				| _ -> assert false
 			) tparams types in
 			) tparams types in
@@ -372,17 +372,17 @@ let valid_redefinition ctx f1 t1 f2 t2 =
 	let t1, t2 = (match f1.cf_params, f2.cf_params with
 	let t1, t2 = (match f1.cf_params, f2.cf_params with
 		| [], [] -> t1, t2
 		| [], [] -> t1, t2
 		| l1, l2 when List.length l1 = List.length l2 ->
 		| l1, l2 when List.length l1 = List.length l2 ->
-			let monos = List.map2 (fun (_,p1) (_,p2) -> 
+			let monos = List.map2 (fun (_,p1) (_,p2) ->
 				match follow p1, follow p2 with
 				match follow p1, follow p2 with
 				| TInst ({ cl_kind = KTypeParameter ct1 } as c1,pl1), TInst ({ cl_kind = KTypeParameter ct2 } as c2,pl2) ->
 				| TInst ({ cl_kind = KTypeParameter ct1 } as c1,pl1), TInst ({ cl_kind = KTypeParameter ct2 } as c2,pl2) ->
 					(match ct1, ct2 with
 					(match ct1, ct2 with
-					| [], [] -> 
+					| [], [] ->
 						let m = mk_mono() in
 						let m = mk_mono() in
 						m,m
 						m,m
 					| _, _ when List.length ct1 = List.length ct2 ->
 					| _, _ when List.length ct1 = List.length ct2 ->
 						(* if same constraints, they are the same type *)
 						(* if same constraints, they are the same type *)
 						List.iter2 (fun t1 t2  ->
 						List.iter2 (fun t1 t2  ->
-							try 
+							try
 								type_eq EqStrict (apply_params c1.cl_types pl1 t1) (apply_params c2.cl_types pl2 t2)
 								type_eq EqStrict (apply_params c1.cl_types pl1 t1) (apply_params c2.cl_types pl2 t2)
 							with Unify_error l ->
 							with Unify_error l ->
 								raise (Unify_error (Unify_custom "Constraints differ" :: l))
 								raise (Unify_error (Unify_custom "Constraints differ" :: l))
@@ -418,7 +418,7 @@ let copy_meta meta_src meta_target sl =
 	) meta_src;
 	) meta_src;
 	!meta
 	!meta
 
 
-let check_overriding ctx c p () =
+let check_overriding ctx c p =
 	match c.cl_super with
 	match c.cl_super with
 	| None ->
 	| None ->
 		(match c.cl_overrides with
 		(match c.cl_overrides with
@@ -500,7 +500,7 @@ let rec check_interface ctx c p intf params =
 		check_interface ctx c p i2 (List.map (apply_params intf.cl_types params) p2)
 		check_interface ctx c p i2 (List.map (apply_params intf.cl_types params) p2)
 	) intf.cl_implements
 	) intf.cl_implements
 
 
-let check_interfaces ctx c p () =
+let check_interfaces ctx c p =
 	match c.cl_path with
 	match c.cl_path with
 	| "Proxy" :: _ , _ -> ()
 	| "Proxy" :: _ , _ -> ()
 	| _ ->
 	| _ ->
@@ -612,15 +612,16 @@ let set_heritance ctx c herits p =
 		| HImplements t -> HImplements (resolve_imports t)
 		| HImplements t -> HImplements (resolve_imports t)
 		| h -> h
 		| h -> h
 	) herits in
 	) herits in
+	flush_pass ctx PBuildClass "init_class"; (* make sure super classes are fully initialized *)
 	List.iter loop (List.filter (ctx.g.do_inherit ctx c p) herits)
 	List.iter loop (List.filter (ctx.g.do_inherit ctx c p) herits)
 
 
 let rec type_type_params ctx path get_params p tp =
 let rec type_type_params ctx path get_params p tp =
 	let n = tp.tp_name in
 	let n = tp.tp_name in
 	let c = mk_class ctx.current (fst path @ [snd path],n) p in
 	let c = mk_class ctx.current (fst path @ [snd path],n) p in
 	c.cl_types <- List.map (type_type_params ctx c.cl_path get_params p) tp.tp_params;
 	c.cl_types <- List.map (type_type_params ctx c.cl_path get_params p) tp.tp_params;
-	let t = TInst (c,List.map snd c.cl_types) in	
+	let t = TInst (c,List.map snd c.cl_types) in
 	match tp.tp_constraints with
 	match tp.tp_constraints with
-	| [] -> 
+	| [] ->
 		c.cl_kind <- KTypeParameter [];
 		c.cl_kind <- KTypeParameter [];
 		n, t
 		n, t
 	| _ ->
 	| _ ->
@@ -629,8 +630,8 @@ let rec type_type_params ctx path get_params p tp =
 			let ctx = { ctx with type_params = ctx.type_params @ get_params() } in
 			let ctx = { ctx with type_params = ctx.type_params @ get_params() } in
 			c.cl_kind <- KTypeParameter (List.map (load_complex_type ctx p) tp.tp_constraints);
 			c.cl_kind <- KTypeParameter (List.map (load_complex_type ctx p) tp.tp_constraints);
 			t
 			t
-		) in
-		delay ctx (fun () -> ignore(!r()));
+		) "constraint" in
+		delay ctx PForce (fun () -> ignore(!r()));
 		n, TLazy r
 		n, TLazy r
 
 
 let type_function_params ctx fd fname p =
 let type_function_params ctx fd fname p =
@@ -721,6 +722,7 @@ let init_core_api ctx c =
 			c
 			c
 	) in
 	) in
 	let t = load_instance ctx2 { tpackage = fst c.cl_path; tname = snd c.cl_path; tparams = []; tsub = None; } c.cl_pos true in
 	let t = load_instance ctx2 { tpackage = fst c.cl_path; tname = snd c.cl_path; tparams = []; tsub = None; } c.cl_pos true in
+	flush_pass ctx2 PFinal "core_final";
 	match t with
 	match t with
 	| TInst (ccore,_) ->
 	| TInst (ccore,_) ->
 		(match c.cl_doc with
 		(match c.cl_doc with
@@ -741,7 +743,7 @@ let init_core_api ctx c =
 				match f2.cf_kind, f.cf_kind with
 				match f2.cf_kind, f.cf_kind with
 				| Method MethInline, Method MethNormal -> () (* allow to add 'inline' *)
 				| Method MethInline, Method MethNormal -> () (* allow to add 'inline' *)
 				| Method MethNormal, Method MethInline -> () (* allow to disable 'inline' *)
 				| Method MethNormal, Method MethInline -> () (* allow to disable 'inline' *)
-				| _ ->					
+				| _ ->
 					error ("Field " ^ f.cf_name ^ " has different property access than core type") p;
 					error ("Field " ^ f.cf_name ^ " has different property access than core type") p;
 			end;
 			end;
 			(match follow f.cf_type, follow f2.cf_type with
 			(match follow f.cf_type, follow f2.cf_type with
@@ -811,7 +813,7 @@ let patch_class ctx c fields =
 		in
 		in
 		List.rev (loop [] fields)
 		List.rev (loop [] fields)
 
 
-let rec string_list_of_expr_path (e,p) = 
+let rec string_list_of_expr_path (e,p) =
 	match e with
 	match e with
 	| EConst (Ident i) -> [i]
 	| EConst (Ident i) -> [i]
 	| EField (e,f) -> f :: string_list_of_expr_path e
 	| EField (e,f) -> f :: string_list_of_expr_path e
@@ -842,13 +844,11 @@ let build_module_def ctx mt meta fvars fbuild =
 		display_error ctx msg p
 		display_error ctx msg p
 
 
 let init_class ctx c p herits fields =
 let init_class ctx c p herits fields =
+	let ctx = { ctx with curclass = c; type_params = c.cl_types; pass = PBuildClass } in
 	incr stats.s_classes_built;
 	incr stats.s_classes_built;
 	let fields = patch_class ctx c fields in
 	let fields = patch_class ctx c fields in
-	let ctx = { ctx with type_params = c.cl_types } in
 	c.cl_extern <- List.mem HExtern herits;
 	c.cl_extern <- List.mem HExtern herits;
 	c.cl_interface <- List.mem HInterface herits;
 	c.cl_interface <- List.mem HInterface herits;
-	if has_meta ":generic" c.cl_meta && c.cl_types <> [] then c.cl_kind <- KGeneric;
-	if c.cl_path = (["haxe";"macro"],"MacroType") then c.cl_kind <- KMacroType;
 	set_heritance ctx c herits p;
 	set_heritance ctx c herits p;
 	let fields = ref fields in
 	let fields = ref fields in
 	let get_fields() = !fields in
 	let get_fields() = !fields in
@@ -864,7 +864,7 @@ let init_class ctx c p herits fields =
 		c.cl_extern <- true;
 		c.cl_extern <- true;
 		List.filter (fun f -> List.mem AStatic f.cff_access) fields, []
 		List.filter (fun f -> List.mem AStatic f.cff_access) fields, []
 	end else fields, herits in
 	end else fields, herits in
-	if core_api && not (ctx.com.display || Common.defined ctx.com "dce") then delay ctx (fun() -> init_core_api ctx c);
+	if core_api && not (ctx.com.display || Common.defined ctx.com "dce") then delay ctx PForce (fun() -> init_core_api ctx c);
 	let tthis = TInst (c,List.map snd c.cl_types) in
 	let tthis = TInst (c,List.map snd c.cl_types) in
 	let rec extends_public c =
 	let rec extends_public c =
 		List.exists (fun (c,_) -> c.cl_path = (["haxe"],"Public") || extends_public c) c.cl_implements ||
 		List.exists (fun (c,_) -> c.cl_path = (["haxe"],"Public") || extends_public c) c.cl_implements ||
@@ -914,32 +914,33 @@ let init_class ctx c p herits fields =
 
 
 	let fields = if not display_file || Common.defined ctx.com "no-copt" then fields else Optimizer.optimize_completion c fields in
 	let fields = if not display_file || Common.defined ctx.com "no-copt" then fields else Optimizer.optimize_completion c fields in
 
 
+	let delayed_expr = ref [] in
+
 	let rec is_full_type t =
 	let rec is_full_type t =
 		match t with
 		match t with
 		| TFun (args,ret) -> is_full_type ret && List.for_all (fun (_,_,t) -> is_full_type t) args
 		| TFun (args,ret) -> is_full_type ret && List.for_all (fun (_,_,t) -> is_full_type t) args
 		| TMono r -> (match !r with None -> false | Some t -> is_full_type t)
 		| TMono r -> (match !r with None -> false | Some t -> is_full_type t)
 		| TAbstract _ | TInst _ | TEnum _ | TLazy _ | TDynamic _ | TAnon _ | TType _ -> true
 		| TAbstract _ | TInst _ | TEnum _ | TLazy _ | TDynamic _ | TAnon _ | TType _ -> true
 	in
 	in
-	let bind_type cf r p macro =
+	let bind_type ctx cf r p macro =
 		if ctx.com.display then begin
 		if ctx.com.display then begin
 			let cp = !Parser.resume_display in
 			let cp = !Parser.resume_display in
 			if display_file && (cp.pmin = 0 || (p.pmin <= cp.pmin && p.pmax >= cp.pmax)) then begin
 			if display_file && (cp.pmin = 0 || (p.pmin <= cp.pmin && p.pmax >= cp.pmax)) then begin
 				if macro && not ctx.in_macro then
 				if macro && not ctx.in_macro then
 					(* force macro system loading of this class in order to get completion *)
 					(* force macro system loading of this class in order to get completion *)
-					(fun() -> ignore(ctx.g.do_macro ctx MExpr c.cl_path cf.cf_name [] p))
+					delay ctx PTypeField (fun() -> ignore(ctx.g.do_macro ctx MExpr c.cl_path cf.cf_name [] p))
 				else begin
 				else begin
 					cf.cf_type <- TLazy r;
 					cf.cf_type <- TLazy r;
-					(fun() -> ignore((!r)()))
+					delayed_expr := (ctx,r) :: !delayed_expr;
 				end
 				end
 			end else begin
 			end else begin
 				if not (is_full_type cf.cf_type) then cf.cf_type <- TLazy r;
 				if not (is_full_type cf.cf_type) then cf.cf_type <- TLazy r;
-				(fun() -> ())
 			end
 			end
 		end else if macro && not ctx.in_macro then
 		end else if macro && not ctx.in_macro then
-			(fun () -> ())
+			()
 		else begin
 		else begin
 			cf.cf_type <- TLazy r;
 			cf.cf_type <- TLazy r;
-			(fun () -> ignore(!r()))
+			delayed_expr := (ctx,r) :: !delayed_expr;
 		end
 		end
 	in
 	in
 
 
@@ -948,8 +949,7 @@ let init_class ctx c p herits fields =
 		if not stat && has_field cf.cf_name c.cl_super then error ("Redefinition of variable " ^ cf.cf_name ^ " in subclass is not allowed") p;
 		if not stat && has_field cf.cf_name c.cl_super then error ("Redefinition of variable " ^ cf.cf_name ^ " in subclass is not allowed") p;
 		let t = cf.cf_type in
 		let t = cf.cf_type in
 		match e with
 		match e with
-		| None ->
-			(fun() -> ())
+		| None -> ()
 		| Some e ->
 		| Some e ->
 			let r = exc_protect ctx (fun r ->
 			let r = exc_protect ctx (fun r ->
 				if not !return_partial_type then begin
 				if not !return_partial_type then begin
@@ -989,8 +989,8 @@ let init_class ctx c p herits fields =
 					cf.cf_type <- t;
 					cf.cf_type <- t;
 				end;
 				end;
 				t
 				t
-			) in
-			bind_type cf r (snd e) false
+			) "bind_var" in
+			bind_type ctx cf r (snd e) false
 	in
 	in
 
 
 	(* ----------------------- FIELD INIT ----------------------------- *)
 	(* ----------------------- FIELD INIT ----------------------------- *)
@@ -1001,9 +1001,9 @@ let init_class ctx c p herits fields =
 		let stat = List.mem AStatic f.cff_access in
 		let stat = List.mem AStatic f.cff_access in
 		let inline = List.mem AInline f.cff_access in
 		let inline = List.mem AInline f.cff_access in
 		let override = List.mem AOverride f.cff_access in
 		let override = List.mem AOverride f.cff_access in
-		let ctx = { ctx with 
-			curclass = c;
+		let ctx = { ctx with
 			tthis = tthis;
 			tthis = tthis;
+			pass = PTypeField;
 			on_error = (fun ctx msg ep ->
 			on_error = (fun ctx msg ep ->
 				ctx.com.error msg ep;
 				ctx.com.error msg ep;
 				(* macros expressions might reference other code, let's recall which class we are actually compiling *)
 				(* macros expressions might reference other code, let's recall which class we are actually compiling *)
@@ -1040,8 +1040,9 @@ let init_class ctx c p herits fields =
 				cf_params = [];
 				cf_params = [];
 				cf_overloads = [];
 				cf_overloads = [];
 			} in
 			} in
-			let delay = bind_var ctx cf e stat inline in
-			f, false, cf, delay
+			ctx.curfield <- cf;
+			bind_var ctx cf e stat inline;
+			f, false, cf
 		| FFun fd ->
 		| FFun fd ->
 			let params = type_function_params ctx fd f.cff_name p in
 			let params = type_function_params ctx fd f.cff_name p in
 			if inline && c.cl_interface then error "You can't declare inline methods in interfaces" p;
 			if inline && c.cl_interface then error "You can't declare inline methods in interfaces" p;
@@ -1083,7 +1084,6 @@ let init_class ctx c p herits fields =
 			let parent = (if not stat then get_parent c name else None) in
 			let parent = (if not stat then get_parent c name else None) in
 			let dynamic = List.mem ADynamic f.cff_access || (match parent with Some { cf_kind = Method MethDynamic } -> true | _ -> false) in
 			let dynamic = List.mem ADynamic f.cff_access || (match parent with Some { cf_kind = Method MethDynamic } -> true | _ -> false) in
 			if inline && dynamic then error "You can't have both 'inline' and 'dynamic'" p;
 			if inline && dynamic then error "You can't have both 'inline' and 'dynamic'" p;
-			ctx.curmethod <- name;
 			ctx.type_params <- if stat then params else params @ ctx.type_params;
 			ctx.type_params <- if stat then params else params @ ctx.type_params;
 			let constr = (name = "new") in
 			let constr = (name = "new") in
 			let ret = if constr then ctx.t.tvoid else type_opt ctx p fd.f_type in
 			let ret = if constr then ctx.t.tvoid else type_opt ctx p fd.f_type in
@@ -1110,6 +1110,7 @@ let init_class ctx c p herits fields =
 				cf_params = params;
 				cf_params = params;
 				cf_overloads = [];
 				cf_overloads = [];
 			} in
 			} in
+			ctx.curfield <- cf;
 			init_meta_overloads ctx cf;
 			init_meta_overloads ctx cf;
 			let r = exc_protect ctx (fun r ->
 			let r = exc_protect ctx (fun r ->
 				if not !return_partial_type then begin
 				if not !return_partial_type then begin
@@ -1131,13 +1132,9 @@ let init_class ctx c p herits fields =
 					cf.cf_type <- t;
 					cf.cf_type <- t;
 				end;
 				end;
 				t
 				t
-			) in
-			let delay = if ((c.cl_extern && not inline) || c.cl_interface) && cf.cf_name <> "__init__" then
-				(fun() -> ())
-			else
-				bind_type cf r (match fd.f_expr with Some e -> snd e | None -> f.cff_pos) is_macro
-			in
-			f, constr, cf, delay
+			) "type_fun" in
+			if not (((c.cl_extern && not inline) || c.cl_interface) && cf.cf_name <> "__init__") then bind_type ctx cf r (match fd.f_expr with Some e -> snd e | None -> f.cff_pos) is_macro;
+			f, constr, cf
 		| FProp (get,set,t,eo) ->
 		| FProp (get,set,t,eo) ->
 			if override then error "You cannot override properties" p;
 			if override then error "You cannot override properties" p;
 			let ret = (match t, eo with
 			let ret = (match t, eo with
@@ -1192,8 +1189,11 @@ let init_class ctx c p herits fields =
 				cf_params = [];
 				cf_params = [];
 				cf_overloads = [];
 				cf_overloads = [];
 			} in
 			} in
-			let delay = bind_var ctx cf eo stat inline in
-			f, false, cf, (fun() -> delay(); (!check_get)(); (!check_set)())
+			ctx.curfield <- cf;
+			bind_var ctx cf eo stat inline;
+			delay ctx PForce (fun() -> (!check_get)());
+			delay ctx PForce (fun() -> (!check_set)());
+			f, false, cf
 	in
 	in
 	let rec check_require = function
 	let rec check_require = function
 		| [] -> None
 		| [] -> None
@@ -1212,10 +1212,10 @@ let init_class ctx c p herits fields =
 			check_require l
 			check_require l
 	in
 	in
 	let cl_req = check_require c.cl_meta in
 	let cl_req = check_require c.cl_meta in
-	let fl = List.fold_left (fun acc f ->
+	List.iter (fun f ->
 		try
 		try
 			let p = f.cff_pos in
 			let p = f.cff_pos in
-			let fd , constr, f , delayed = loop_cf f in
+			let fd , constr, f = loop_cf f in
 			let is_static = List.mem AStatic fd.cff_access in
 			let is_static = List.mem AStatic fd.cff_access in
 			if is_static && f.cf_name = "name" && Common.defined ctx.com "js" then error "This identifier cannot be used in Javascript for statics" p;
 			if is_static && f.cf_name = "name" && Common.defined ctx.com "js" then error "This identifier cannot be used in Javascript for statics" p;
 			if (is_static || constr) && c.cl_interface && f.cf_name <> "__init__" then error "You can't declare static fields in interfaces" p;
 			if (is_static || constr) && c.cl_interface && f.cf_name <> "__init__" then error "You can't declare static fields in interfaces" p;
@@ -1238,12 +1238,10 @@ let init_class ctx c p herits fields =
 					c.cl_ordered_fields <- f :: c.cl_ordered_fields;
 					c.cl_ordered_fields <- f :: c.cl_ordered_fields;
 					if List.mem AOverride fd.cff_access then c.cl_overrides <- f.cf_name :: c.cl_overrides;
 					if List.mem AOverride fd.cff_access then c.cl_overrides <- f.cf_name :: c.cl_overrides;
 				end;
 				end;
-			end;
-			delayed :: acc
+			end
 		with Error (Custom str,p) ->
 		with Error (Custom str,p) ->
-			display_error ctx str p;
-			acc
-	) [] fields in
+			display_error ctx str p
+	) fields;
 	c.cl_ordered_statics <- List.rev c.cl_ordered_statics;
 	c.cl_ordered_statics <- List.rev c.cl_ordered_statics;
 	c.cl_ordered_fields <- List.rev c.cl_ordered_fields;
 	c.cl_ordered_fields <- List.rev c.cl_ordered_fields;
 	(*
 	(*
@@ -1258,10 +1256,10 @@ let init_class ctx c p herits fields =
 			| Some cf ->
 			| Some cf ->
 				ignore (follow cf.cf_type); (* make sure it's typed *)
 				ignore (follow cf.cf_type); (* make sure it's typed *)
 				let args = (match cf.cf_expr with
 				let args = (match cf.cf_expr with
-					| Some { eexpr = TFunction f } -> 
-						List.map (fun (v,def) -> 
+					| Some { eexpr = TFunction f } ->
+						List.map (fun (v,def) ->
 							(*
 							(*
-								let's optimize a bit the output by not always copying the default value 
+								let's optimize a bit the output by not always copying the default value
 								into the inherited constructor when it's not necessary for the platform
 								into the inherited constructor when it's not necessary for the platform
 							*)
 							*)
 							match ctx.com.platform, def with
 							match ctx.com.platform, def with
@@ -1289,8 +1287,9 @@ let init_class ctx c p herits fields =
 			(* nothing to do *)
 			(* nothing to do *)
 			()
 			()
 	in
 	in
-	delay ctx (fun() -> add_constructor c);
-	List.rev fl
+	if c.cl_constructor = None & c.cl_super <> None then delay ctx PDefineConstructor (fun() -> add_constructor c);
+	(* push delays in reverse order so they will be run in correct order *)
+	List.iter (fun (ctx,r) -> delay ctx PTypeField (fun() -> ignore((!r)()))) !delayed_expr
 
 
 let resolve_typedef t =
 let resolve_typedef t =
 	match t with
 	match t with
@@ -1316,11 +1315,153 @@ let add_module ctx m p =
 	List.iter decl_type m.m_types;
 	List.iter decl_type m.m_types;
 	Hashtbl.add ctx.g.modules m.m_path m
 	Hashtbl.add ctx.g.modules m.m_path m
 
 
+let init_module_type ctx usings (decl,p) =
+	let get_type name =
+		try List.find (fun t -> snd (t_infos t).mt_path = name) ctx.current.m_types with Not_found -> assert false
+	in
+	match decl with
+	| EImport t ->
+		(match t.tsub with
+		| None ->
+			let md = ctx.g.do_load_module ctx (t.tpackage,t.tname) p in
+			let types = List.filter (fun t -> not (t_infos t).mt_private) md.m_types in
+			ctx.local_types <- ctx.local_types @ types
+		| Some _ ->
+			let t = load_type_def ctx p t in
+			ctx.local_types <- ctx.local_types @ [t]
+		)
+	| EUsing t ->
+		let filter_classes types =
+			let rec loop acc types = match List.rev types with
+				| td :: l ->
+					(match resolve_typedef td with
+					| TClassDecl c ->
+						loop (c :: acc) l
+					| td ->
+						loop acc l)
+				| [] ->
+					acc
+			in
+			loop [] types
+		in
+		(* make sure using are processed in the declaration order *)
+		if !usings = [] then delay ctx PResolveTypedefs (fun() -> List.iter (fun f -> f()) (List.rev !usings));
+		usings := (fun() ->
+			match t.tsub with
+			| None ->
+				let md = ctx.g.do_load_module ctx (t.tpackage,t.tname) p in
+				let types = List.filter (fun t -> not (t_infos t).mt_private) md.m_types in
+				flush_pass ctx PInitModuleTypes "using";
+				ctx.local_using <- ctx.local_using @ (filter_classes types);
+				ctx.local_types <- ctx.local_types @ types
+			| Some _ ->
+				let t = load_type_def ctx p t in
+				flush_pass ctx PInitModuleTypes "using";
+				ctx.local_using <- ctx.local_using @ (filter_classes [t]);
+				ctx.local_types <- ctx.local_types @ [t]
+		) :: !usings
+	| EClass d ->
+		let c = (match get_type d.d_name with TClassDecl c -> c | _ -> assert false) in
+		if has_meta ":generic" c.cl_meta && c.cl_types <> [] then c.cl_kind <- KGeneric;
+		if c.cl_path = (["haxe";"macro"],"MacroType") then c.cl_kind <- KMacroType;
+		(* for debug only - we can't shadow ctx since it will get injected 'using' *)
+		ctx.curclass <- c;
+		delay ctx PForce (fun() -> check_overriding ctx c p);
+		delay ctx PForce (fun() -> check_interfaces ctx c p);
+		delay ctx PBuildClass (fun() -> init_class ctx c p d.d_flags d.d_data);
+		ctx.curclass <- null_class;
+	| EEnum d ->
+		let e = (match get_type d.d_name with TEnumDecl e -> e | _ -> assert false) in
+		let ctx = { ctx with type_params = e.e_types } in
+		let h = (try Some (Hashtbl.find ctx.g.type_patches e.e_path) with Not_found -> None) in
+		(match h with
+		| None -> ()
+		| Some (h,hcl) ->
+			Hashtbl.iter (fun _ _ -> error "Field type patch not supported for enums" e.e_pos) h;
+			e.e_meta <- e.e_meta @ hcl.tp_meta);
+		let constructs = ref d.d_data in
+		let get_constructs() =
+			List.map (fun (c,doc,meta,pl,p) ->
+				{
+					cff_name = c;
+					cff_doc = doc;
+					cff_meta = meta;
+					cff_pos = p;
+					cff_access = [];
+					cff_kind = (match pl with
+						| [] -> FVar (None,None)
+						| _ -> FFun { f_params = []; f_type = None; f_expr = None; f_args = List.map (fun (n,o,t) -> n,o,Some t,None) pl });
+				}
+			) (!constructs)
+		in
+		build_module_def ctx (TEnumDecl e) e.e_meta get_constructs (fun (e,p) ->
+			match e with
+			| EVars [_,Some (CTAnonymous fields),None] ->
+				constructs := List.map (fun f ->
+					(f.cff_name,f.cff_doc,f.cff_meta,(match f.cff_kind with
+					| FVar (None,None) -> []
+					| FFun { f_params = []; f_type = None; f_expr = (None|Some (EBlock [],_)); f_args = pl } -> List.map (fun (n,o,t,_) -> match t with None -> error "Missing function parameter type" f.cff_pos | Some t -> n,o,t) pl
+					| _ -> error "Invalid enum constructor in @:build result" p
+					),f.cff_pos)
+				) fields
+			| _ -> error "Enum build macro must return a single variable with anonymous object fields" p
+		);
+		let et = TEnum (e,List.map snd e.e_types) in
+		let names = ref [] in
+		let index = ref 0 in
+		List.iter (fun (c,doc,meta,t,p) ->
+			let t = (match t with
+				| [] -> et
+				| l ->
+					let pnames = ref PMap.empty in
+					TFun (List.map (fun (s,opt,t) ->
+						if PMap.mem s (!pnames) then error ("Duplicate parameter '" ^ s ^ "' in enum constructor " ^ c) p;
+						pnames := PMap.add s () (!pnames);
+						s, opt, load_type_opt ~opt ctx p (Some t)
+					) l, et)
+			) in
+			if PMap.mem c e.e_constrs then error ("Duplicate constructor " ^ c) p;
+			e.e_constrs <- PMap.add c {
+				ef_name = c;
+				ef_type = t;
+				ef_pos = p;
+				ef_doc = doc;
+				ef_index = !index;
+				ef_meta = meta;
+			} e.e_constrs;
+			incr index;
+			names := c :: !names;
+		) (!constructs);
+		e.e_names <- List.rev !names;
+		e.e_extern <- e.e_extern || e.e_names = [];
+	| ETypedef d ->
+		let t = (match get_type d.d_name with TTypeDecl t -> t | _ -> assert false) in
+		let ctx = { ctx with type_params = t.t_types } in
+		let tt = load_complex_type ctx p d.d_data in
+		(*
+			we exceptionnaly allow follow here because we don't care the type we get as long as it's not our own
+		*)
+		if t.t_type == follow tt then error "Recursive typedef is not allowed" p;
+		(match t.t_type with
+		| TMono r ->
+			(match !r with
+			| None -> r := Some tt;
+			| Some _ -> assert false);
+		| _ -> assert false);
+	| EAbstract d ->
+		let a = (match get_type d.d_name with TAbstractDecl a -> a | _ -> assert false) in
+		let ctx = { ctx with type_params = a.a_types } in
+		List.iter (function
+			| APrivAbstract -> ()
+			| ASubType t -> a.a_sub <- load_complex_type ctx p t :: a.a_sub
+			| ASuperType t -> a.a_super <- load_complex_type ctx p t :: a.a_super
+		) d.d_flags
+
 let type_module ctx m file tdecls loadp =
 let type_module ctx m file tdecls loadp =
 	(* PASS 1 : build module structure - does not load any module or type - should be atomic ! *)
 	(* PASS 1 : build module structure - does not load any module or type - should be atomic ! *)
 	let decls = ref [] in
 	let decls = ref [] in
 	let make_path name priv =
 	let make_path name priv =
-		if List.exists (fun t -> snd (t_path t) = name) (!decls) then error ("Type name " ^ name ^ " is already defined in this module") loadp;
+		if List.exists (fun (t,_) -> snd (t_path t) = name) !decls then error ("Type name " ^ name ^ " is already defined in this module") loadp;
 		if priv then (fst m @ ["_" ^ snd m], name) else (fst m, name)
 		if priv then (fst m @ ["_" ^ snd m], name) else (fst m, name)
 	in
 	in
 	let m = {
 	let m = {
@@ -1329,8 +1470,9 @@ let type_module ctx m file tdecls loadp =
 		m_types = [];
 		m_types = [];
 		m_extra = module_extra (Common.unique_full_path file) (Common.get_signature ctx.com) (file_time file) (if ctx.in_macro then MMacro else MCode);
 		m_extra = module_extra (Common.unique_full_path file) (Common.get_signature ctx.com) (file_time file) (if ctx.in_macro then MMacro else MCode);
 	} in
 	} in
-	List.iter (fun (d,p) ->
-		match d with
+	List.iter (fun decl ->
+		let p = snd decl in
+		match fst decl with
 		| EImport _ | EUsing _ -> ()
 		| EImport _ | EUsing _ -> ()
 		| EClass d ->
 		| EClass d ->
 			let priv = List.mem HPrivate d.d_flags in
 			let priv = List.mem HPrivate d.d_flags in
@@ -1340,7 +1482,7 @@ let type_module ctx m file tdecls loadp =
 			c.cl_private <- priv;
 			c.cl_private <- priv;
 			c.cl_doc <- d.d_doc;
 			c.cl_doc <- d.d_doc;
 			c.cl_meta <- d.d_meta;
 			c.cl_meta <- d.d_meta;
-			decls := TClassDecl c :: !decls
+			decls := (TClassDecl c, decl) :: !decls
 		| EEnum d ->
 		| EEnum d ->
 			let priv = List.mem EPrivate d.d_flags in
 			let priv = List.mem EPrivate d.d_flags in
 			let path = make_path d.d_name priv in
 			let path = make_path d.d_name priv in
@@ -1356,7 +1498,7 @@ let type_module ctx m file tdecls loadp =
 				e_constrs = PMap.empty;
 				e_constrs = PMap.empty;
 				e_names = [];
 				e_names = [];
 			} in
 			} in
-			decls := TEnumDecl e :: !decls
+			decls := (TEnumDecl e, decl) :: !decls
 		| ETypedef d ->
 		| ETypedef d ->
 			let priv = List.mem EPrivate d.d_flags in
 			let priv = List.mem EPrivate d.d_flags in
 			let path = make_path d.d_name priv in
 			let path = make_path d.d_name priv in
@@ -1370,7 +1512,7 @@ let type_module ctx m file tdecls loadp =
 				t_type = mk_mono();
 				t_type = mk_mono();
 				t_meta = d.d_meta;
 				t_meta = d.d_meta;
 			} in
 			} in
-			decls := TTypeDecl t :: !decls
+			decls := (TTypeDecl t, decl) :: !decls
 	   | EAbstract d ->
 	   | EAbstract d ->
 			let priv = List.mem APrivAbstract d.d_flags in
 			let priv = List.mem APrivAbstract d.d_flags in
 			let path = make_path d.d_name priv in
 			let path = make_path d.d_name priv in
@@ -1385,18 +1527,21 @@ let type_module ctx m file tdecls loadp =
 				a_sub = [];
 				a_sub = [];
 				a_super = [];
 				a_super = [];
 			} in
 			} in
-			decls := TAbstractDecl a :: !decls
+			decls := (TAbstractDecl a, decl) :: !decls
 	) tdecls;
 	) tdecls;
-	m.m_types <- List.rev !decls;
+	let decls = List.rev !decls in
+	m.m_types <- List.map fst decls;
 	add_module ctx m loadp;
 	add_module ctx m loadp;
-	(* PASS 2 : build types structure - does not type any expression ! *)
+	(* define the per-module context for the next pass *)
 	let ctx = {
 	let ctx = {
 		com = ctx.com;
 		com = ctx.com;
 		g = ctx.g;
 		g = ctx.g;
 		t = ctx.t;
 		t = ctx.t;
+		pass = PInitModuleTypes;
 		on_error = (fun ctx msg p -> ctx.com.error msg p);
 		on_error = (fun ctx msg p -> ctx.com.error msg p);
 		macro_depth = ctx.macro_depth;
 		macro_depth = ctx.macro_depth;
-		curclass = ctx.curclass;
+		curclass = null_class;
+		curfield = null_field;
 		tthis = ctx.tthis;
 		tthis = ctx.tthis;
 		ret = ctx.ret;
 		ret = ctx.ret;
 		current = m;
 		current = m;
@@ -1404,7 +1549,6 @@ let type_module ctx m file tdecls loadp =
 		local_types = ctx.g.std.m_types @ m.m_types;
 		local_types = ctx.g.std.m_types @ m.m_types;
 		local_using = [];
 		local_using = [];
 		type_params = [];
 		type_params = [];
-		curmethod = "";
 		curfun = FStatic;
 		curfun = FStatic;
 		untyped = false;
 		untyped = false;
 		in_super_call = false;
 		in_super_call = false;
@@ -1415,164 +1559,25 @@ let type_module ctx m file tdecls loadp =
 		param_type = None;
 		param_type = None;
 		vthis = None;
 		vthis = None;
 	} in
 	} in
-	let delays = ref [] in
-	let get_class name =
-		let c = List.find (fun d -> match d with TClassDecl { cl_path = _ , n } -> n = name | _ -> false) m.m_types in
-		match c with TClassDecl c -> c | _ -> assert false
-	in
-	let get_enum name =
-		let e = List.find (fun d -> match d with TEnumDecl { e_path = _ , n } -> n = name | _ -> false) m.m_types in
-		match e with TEnumDecl e -> e | _ -> assert false
-	in
-	let get_tdef name =
-		let s = List.find (fun d -> match d with TTypeDecl { t_path = _ , n } -> n = name | _ -> false) m.m_types in
-		match s with TTypeDecl s -> s | _ -> assert false
-	in
-	let get_abstract name =
-		let s = List.find (fun d -> match d with TAbstractDecl { a_path = _ , n } -> n = name | _ -> false) m.m_types in
-		match s with TAbstractDecl a -> a | _ -> assert false
-	in
-	let filter_classes types =
-		let rec loop acc types = match List.rev types with
-			| t :: l ->
-				(match resolve_typedef t with TClassDecl c -> loop (c :: acc) l | _ -> loop acc l)
-			| [] ->
-				acc
-		in
-		loop [] types
-	in
-	(* here is an additional PASS 1 phase, which handle the type parameters declaration, with lazy contraints *)
-	List.iter (fun (d,p) ->
+	(* here is an additional PASS 1 phase, which define the type parameters for all module types.
+	   Constraints are handled lazily (no other type is loaded) because they might be recursive anyway *)
+	List.iter (fun d ->
 		match d with
 		match d with
-		| EImport _ | EUsing _ -> ()
-		| EClass d ->
-			let c = get_class d.d_name in
+		| (TClassDecl c, (EClass d, p)) ->
 			c.cl_types <- List.map (type_type_params ctx c.cl_path (fun() -> c.cl_types) p) d.d_params;
 			c.cl_types <- List.map (type_type_params ctx c.cl_path (fun() -> c.cl_types) p) d.d_params;
-		| EEnum d ->
-			let e = get_enum d.d_name in
+		| (TEnumDecl e, (EEnum d, p)) ->
 			e.e_types <- List.map (type_type_params ctx e.e_path (fun() -> e.e_types) p) d.d_params;
 			e.e_types <- List.map (type_type_params ctx e.e_path (fun() -> e.e_types) p) d.d_params;
-		| ETypedef d ->
-			let t = get_tdef d.d_name in
+		| (TTypeDecl t, (ETypedef d, p)) ->
 			t.t_types <- List.map (type_type_params ctx t.t_path (fun() -> t.t_types) p) d.d_params;
 			t.t_types <- List.map (type_type_params ctx t.t_path (fun() -> t.t_types) p) d.d_params;
-		| EAbstract d ->
-			let a = get_abstract d.d_name in
+		| (TAbstractDecl a, (EAbstract d, p)) ->
 			a.a_types <- List.map (type_type_params ctx a.a_path (fun() -> a.a_types) p) d.d_params;
 			a.a_types <- List.map (type_type_params ctx a.a_path (fun() -> a.a_types) p) d.d_params;
-	) tdecls;
-	(* back to PASS2 *)
-	List.iter (fun (d,p) ->
-		match d with
-		| EImport t ->
-			(match t.tsub with
-			| None ->
-				let md = ctx.g.do_load_module ctx (t.tpackage,t.tname) p in
-				let types = List.filter (fun t -> not (t_infos t).mt_private) md.m_types in
-				ctx.local_types <- ctx.local_types @ types
-			| Some _ ->
-				let t = load_type_def ctx p t in
-				ctx.local_types <- ctx.local_types @ [t]
-			)
-		| EUsing t ->
-			(match t.tsub with
-			| None ->
-				let md = ctx.g.do_load_module ctx (t.tpackage,t.tname) p in
-				let types = List.filter (fun t -> not (t_infos t).mt_private) md.m_types in
-				ctx.local_using <- ctx.local_using @ (filter_classes types);
-				ctx.local_types <- ctx.local_types @ types
-			| Some _ ->
-				let t = load_type_def ctx p t in
-				ctx.local_using <- ctx.local_using @ (filter_classes [t]);
-				ctx.local_types <- ctx.local_types @ [t])
-		| EClass d ->
-			let c = get_class d.d_name in
-			let checks = if not ctx.com.display then [check_overriding ctx c p; check_interfaces ctx c p] else [] in
-			delays := !delays @ (checks @ init_class ctx c p d.d_flags d.d_data)
-		| EEnum d ->
-			let e = get_enum d.d_name in
-			let ctx = { ctx with type_params = e.e_types } in
-			let h = (try Some (Hashtbl.find ctx.g.type_patches e.e_path) with Not_found -> None) in
-			(match h with
-			| None -> ()
-			| Some (h,hcl) ->
-				Hashtbl.iter (fun _ _ -> error "Field type patch not supported for enums" e.e_pos) h;
-				e.e_meta <- e.e_meta @ hcl.tp_meta);
-			let constructs = ref d.d_data in
-			let get_constructs() =
-				List.map (fun (c,doc,meta,pl,p) ->
-					{
-						cff_name = c;
-						cff_doc = doc;
-						cff_meta = meta;
-						cff_pos = p;
-						cff_access = [];
-						cff_kind = (match pl with
-							| [] -> FVar (None,None)
-							| _ -> FFun { f_params = []; f_type = None; f_expr = None; f_args = List.map (fun (n,o,t) -> n,o,Some t,None) pl });
-					}
-				) (!constructs)
-			in
-			build_module_def ctx (TEnumDecl e) e.e_meta get_constructs (fun (e,p) ->
-				match e with
-				| EVars [_,Some (CTAnonymous fields),None] ->
-					constructs := List.map (fun f ->
-						(f.cff_name,f.cff_doc,f.cff_meta,(match f.cff_kind with
-						| FVar (None,None) -> []
-						| FFun { f_params = []; f_type = None; f_expr = (None|Some (EBlock [],_)); f_args = pl } -> List.map (fun (n,o,t,_) -> match t with None -> error "Missing function parameter type" f.cff_pos | Some t -> n,o,t) pl
-						| _ -> error "Invalid enum constructor in @:build result" p
-						),f.cff_pos)
-					) fields
-				| _ -> error "Enum build macro must return a single variable with anonymous object fields" p
-			);
-			let et = TEnum (e,List.map snd e.e_types) in
-			let names = ref [] in
-			let index = ref 0 in
-			List.iter (fun (c,doc,meta,t,p) ->
-				if c = "name" && Common.defined ctx.com "js" then error "This identifier cannot be used in Javascript" p;
-				let t = (match t with
-					| [] -> et
-					| l ->
-						let pnames = ref PMap.empty in
-						TFun (List.map (fun (s,opt,t) ->
-							if PMap.mem s (!pnames) then error ("Duplicate parameter '" ^ s ^ "' in enum constructor " ^ c) p;
-							pnames := PMap.add s () (!pnames);
-							s, opt, load_type_opt ~opt ctx p (Some t)
-						) l, et)
-				) in
-				if PMap.mem c e.e_constrs then error ("Duplicate constructor " ^ c) p;
-				e.e_constrs <- PMap.add c {
-					ef_name = c;
-					ef_type = t;
-					ef_pos = p;
-					ef_doc = doc;
-					ef_index = !index;
-					ef_meta = meta;
-				} e.e_constrs;
-				incr index;
-				names := c :: !names;
-			) (!constructs);
-			e.e_names <- List.rev !names;
-			e.e_extern <- e.e_extern || e.e_names = [];
-		| ETypedef d ->
-			let t = get_tdef d.d_name in
-			let ctx = { ctx with type_params = t.t_types } in
-			let tt = load_complex_type ctx p d.d_data in
-			if t.t_type == follow tt then error "Recursive typedef is not allowed" p;
-			(match t.t_type with
-			| TMono r ->
-				(match !r with
-				| None -> r := Some tt;
-				| Some _ -> assert false);
-			| _ -> assert false);
-		| EAbstract d ->
-			let a = get_abstract d.d_name in
-			let ctx = { ctx with type_params = a.a_types } in
-			List.iter (function
-				| APrivAbstract -> ()
-				| ASubType t -> a.a_sub <- load_complex_type ctx p t :: a.a_sub
-				| ASuperType t -> a.a_super <- load_complex_type ctx p t :: a.a_super
-			) d.d_flags
-	) tdecls;
-	(* PASS 3 : type checking, delayed until all modules and types are built *)
-	List.iter (delay ctx) (List.rev (!delays));
+		| _ ->
+			assert false
+	) decls;
+	(* enter the next pass *)
+	let usings = ref [] in
+	delay ctx PInitModuleTypes (fun() -> List.iter (init_module_type ctx usings) tdecls);
+	flush_pass ctx (if ctx.pass < PBuildClass then ctx.pass else PBuildClass) "type_module";
 	m
 	m
 
 
 let resolve_module_file com m remap p =
 let resolve_module_file com m remap p =
@@ -1665,6 +1670,7 @@ let load_module ctx m p =
 				raise (Forbid_package (inf,p::pl))
 				raise (Forbid_package (inf,p::pl))
 	) in
 	) in
 	add_dependency ctx.current m2;
 	add_dependency ctx.current m2;
+	flush_pass ctx (if ctx.pass < PBuildClass then ctx.pass else PBuildClass) "load_module";
 	m2
 	m2
 
 
 ;;
 ;;

+ 41 - 49
typer.ml

@@ -51,10 +51,10 @@ let mk_infos ctx p params =
 		("fileName" , (EConst (String file) , p)) ::
 		("fileName" , (EConst (String file) , p)) ::
 		("lineNumber" , (EConst (Int (string_of_int (Lexer.get_error_line p))),p)) ::
 		("lineNumber" , (EConst (Int (string_of_int (Lexer.get_error_line p))),p)) ::
 		("className" , (EConst (String (s_type_path ctx.curclass.cl_path)),p)) ::
 		("className" , (EConst (String (s_type_path ctx.curclass.cl_path)),p)) ::
-		if ctx.curmethod = "" then
+		if ctx.curfield.cf_name = "" then
 			params
 			params
 		else
 		else
-			("methodName", (EConst (String ctx.curmethod),p)) :: params
+			("methodName", (EConst (String ctx.curfield.cf_name),p)) :: params
 	) ,p)
 	) ,p)
 
 
 let check_assign ctx e =
 let check_assign ctx e =
@@ -81,7 +81,7 @@ let rec classify t =
 	| TInst ({ cl_path = ([],"Float") },[]) -> KFloat
 	| TInst ({ cl_path = ([],"Float") },[]) -> KFloat
 	| TInst ({ cl_path = ([],"String") },[]) -> KString
 	| TInst ({ cl_path = ([],"String") },[]) -> KString
 	| TAbstract ({ a_path = [],"Int" },[]) -> KInt
 	| TAbstract ({ a_path = [],"Int" },[]) -> KInt
-	| TAbstract ({ a_path = [],"Float" },[]) -> KFloat	
+	| TAbstract ({ a_path = [],"Float" },[]) -> KFloat
 	| TInst ({ cl_kind = KTypeParameter ctl },_) when List.exists (fun t -> match classify t with KInt | KFloat -> true | _ -> false) ctl -> KParam t
 	| TInst ({ cl_kind = KTypeParameter ctl },_) when List.exists (fun t -> match classify t with KInt | KFloat -> true | _ -> false) ctl -> KParam t
 	| TMono r when !r = None -> KUnk
 	| TMono r when !r = None -> KUnk
 	| TDynamic _ -> KDyn
 	| TDynamic _ -> KDyn
@@ -107,16 +107,16 @@ let rec is_pos_infos = function
 		false
 		false
 
 
 let add_constraint_checks ctx c pl f tl p =
 let add_constraint_checks ctx c pl f tl p =
-	List.iter2 (fun m (name,t) -> 
+	List.iter2 (fun m (name,t) ->
 		match follow t with
 		match follow t with
 		| TInst ({ cl_kind = KTypeParameter constr },_) when constr <> [] ->
 		| TInst ({ cl_kind = KTypeParameter constr },_) when constr <> [] ->
-			let constr = List.map (fun t -> 
+			let constr = List.map (fun t ->
 				let t = apply_params f.cf_params tl t in
 				let t = apply_params f.cf_params tl t in
 				(* only apply params if not static : in that case no param is passed *)
 				(* only apply params if not static : in that case no param is passed *)
 				let t = (if pl = [] then t else apply_params c.cl_types pl t) in
 				let t = (if pl = [] then t else apply_params c.cl_types pl t) in
 				t
 				t
 			) constr in
 			) constr in
-			delay_late ctx (fun() ->
+			delay ctx PCheckConstraint (fun() ->
 				List.iter (fun ct ->
 				List.iter (fun ct ->
 					try
 					try
 						Type.unify m ct
 						Type.unify m ct
@@ -140,7 +140,7 @@ let class_field ctx c pl name p =
 
 
 (* checks if class cs(ource) can access field cf of class ct(arget) *)
 (* checks if class cs(ource) can access field cf of class ct(arget) *)
 let can_access cs ct cf stat =
 let can_access cs ct cf stat =
-	let rec loop ct = 
+	let rec loop ct =
 		((is_parent ct cs) && (PMap.mem cf.cf_name (if stat then ct.cl_statics else ct.cl_fields)))
 		((is_parent ct cs) && (PMap.mem cf.cf_name (if stat then ct.cl_statics else ct.cl_fields)))
 	 	|| match ct.cl_super with
 	 	|| match ct.cl_super with
 	 	   | Some (ct,_) -> loop ct
 	 	   | Some (ct,_) -> loop ct
@@ -298,7 +298,7 @@ let rec unify_call_params ctx cf el args r p inline =
 			let args, ret = (match Type.field_type o with
 			let args, ret = (match Type.field_type o with
 				| TFun (tl,t) -> tl, t
 				| TFun (tl,t) -> tl, t
 				| _ -> assert false
 				| _ -> assert false
-			) in		
+			) in
 			Some (unify_call_params ctx (Some (t, { o with cf_overloads = l })) el args ret p inline)
 			Some (unify_call_params ctx (Some (t, { o with cf_overloads = l })) el args ret p inline)
 		| _ ->
 		| _ ->
 			None
 			None
@@ -438,7 +438,7 @@ let rec type_module_type ctx t tparams p =
 			t_types = [];
 			t_types = [];
 			t_meta = no_meta;
 			t_meta = no_meta;
 		} in
 		} in
-		mk (TTypeExpr (TAbstractDecl a)) (TType (t_tmp,[])) p		
+		mk (TTypeExpr (TAbstractDecl a)) (TType (t_tmp,[])) p
 
 
 let type_type ctx tpath p =
 let type_type ctx tpath p =
 	type_module_type ctx (Typeload.load_type_def ctx p { tpackage = fst tpath; tname = snd tpath; tparams = []; tsub = None }) None p
 	type_module_type ctx (Typeload.load_type_def ctx p { tpackage = fst tpath; tname = snd tpath; tparams = []; tsub = None }) None p
@@ -539,9 +539,9 @@ let field_access ctx mode f t e p =
 	let fnormal() = AKField ((mk (TField (e,f.cf_name)) t p),f) in
 	let fnormal() = AKField ((mk (TField (e,f.cf_name)) t p),f) in
 	let normal() =
 	let normal() =
 		match follow e.etype with
 		match follow e.etype with
-		| TAnon a -> 
+		| TAnon a ->
 			(match !(a.a_status) with
 			(match !(a.a_status) with
-			| EnumStatics e -> 
+			| EnumStatics e ->
 				AKField ((mk (TEnumField (e,f.cf_name)) t p),f)
 				AKField ((mk (TEnumField (e,f.cf_name)) t p),f)
 			| _ -> fnormal())
 			| _ -> fnormal())
 		| _ -> fnormal()
 		| _ -> fnormal()
@@ -587,7 +587,7 @@ let field_access ctx mode f t e p =
 			else
 			else
 				normal()
 				normal()
 		| AccCall m ->
 		| AccCall m ->
-			if m = ctx.curmethod && (match e.eexpr with TConst TThis -> true | TTypeExpr (TClassDecl c) when c == ctx.curclass -> true | _ -> false) then
+			if m = ctx.curfield.cf_name && (match e.eexpr with TConst TThis -> true | TTypeExpr (TClassDecl c) when c == ctx.curclass -> true | _ -> false) then
 				let prefix = (match ctx.com.platform with Flash when Common.defined ctx.com "as3" -> "$" | _ -> "") in
 				let prefix = (match ctx.com.platform with Flash when Common.defined ctx.com "as3" -> "$" | _ -> "") in
 				AKExpr (mk (TField (e,prefix ^ f.cf_name)) t p)
 				AKExpr (mk (TField (e,prefix ^ f.cf_name)) t p)
 			else if mode = MSet then
 			else if mode = MSet then
@@ -701,13 +701,13 @@ let type_ident_raise ?(imported_enums=true) ctx i p mode =
 			| Some ({ eexpr = TFunction f } as e) ->
 			| Some ({ eexpr = TFunction f } as e) ->
 				(* create a fake class with a fake field to emulate inlining *)
 				(* create a fake class with a fake field to emulate inlining *)
 				let c = mk_class ctx.current (["local"],v.v_name) e.epos in
 				let c = mk_class ctx.current (["local"],v.v_name) e.epos in
-				let cf = { (mk_field v.v_name v.v_type e.epos) with cf_params = params; cf_expr = Some e; cf_kind = Method MethInline } in				
+				let cf = { (mk_field v.v_name v.v_type e.epos) with cf_params = params; cf_expr = Some e; cf_kind = Method MethInline } in
 				c.cl_extern <- true;
 				c.cl_extern <- true;
 				c.cl_fields <- PMap.add cf.cf_name cf PMap.empty;
 				c.cl_fields <- PMap.add cf.cf_name cf PMap.empty;
 				AKInline (mk (TConst TNull) (TInst (c,[])) p, cf, t)
 				AKInline (mk (TConst TNull) (TInst (c,[])) p, cf, t)
-			| _ -> 
+			| _ ->
 				AKExpr (mk (TLocal v) t p))
 				AKExpr (mk (TLocal v) t p))
-		| _ -> 
+		| _ ->
 			AKExpr (mk (TLocal v) v.v_type p))
 			AKExpr (mk (TLocal v) v.v_type p))
 	with Not_found -> try
 	with Not_found -> try
 		(* member variable lookup *)
 		(* member variable lookup *)
@@ -875,7 +875,7 @@ let type_callback ctx e params p =
 					ordered_args @ [type_expr ctx infos true]
 					ordered_args @ [type_expr ctx infos true]
 				else if ctx.com.config.pf_pad_nulls then
 				else if ctx.com.config.pf_pad_nulls then
 					(ordered_args @ [(mk (TConst TNull) t_dynamic p)])
 					(ordered_args @ [(mk (TConst TNull) t_dynamic p)])
-				else 
+				else
 					ordered_args
 					ordered_args
 			in
 			in
 			loop args [] given_args missing_args a
 			loop args [] given_args missing_args a
@@ -1014,7 +1014,7 @@ let type_generic_function ctx (e,cf) el p =
 		(el,ret,e)
 		(el,ret,e)
 	with Codegen.Generic_Exception (msg,p) ->
 	with Codegen.Generic_Exception (msg,p) ->
 		error msg p)
 		error msg p)
-	
+
 let rec type_binop ctx op e1 e2 p =
 let rec type_binop ctx op e1 e2 p =
 	match op with
 	match op with
 	| OpAssign ->
 	| OpAssign ->
@@ -2024,7 +2024,7 @@ and type_expr ctx ?(need_val=true) (e,p) =
 		let el, c , params = (match follow t with
 		let el, c , params = (match follow t with
 		| TInst ({cl_kind = KTypeParameter tl} as c,params) ->
 		| TInst ({cl_kind = KTypeParameter tl} as c,params) ->
 			(* first check field parameters, then class parameters *)
 			(* first check field parameters, then class parameters *)
-			let cf = PMap.find ctx.curmethod (match ctx.curfun with FStatic -> ctx.curclass.cl_statics | _ -> ctx.curclass.cl_fields) in
+			let cf = PMap.find ctx.curfield.cf_name (match ctx.curfun with FStatic -> ctx.curclass.cl_statics | _ -> ctx.curclass.cl_fields) in
 			(try
 			(try
 				let tt = List.assoc (snd c.cl_path) cf.cf_params in
 				let tt = List.assoc (snd c.cl_path) cf.cf_params in
 				if not (type_iseq tt t) then raise Not_found;
 				if not (type_iseq tt t) then raise Not_found;
@@ -2032,7 +2032,7 @@ and type_expr ctx ?(need_val=true) (e,p) =
 				let tt = List.assoc (snd c.cl_path) ctx.type_params in
 				let tt = List.assoc (snd c.cl_path) ctx.type_params in
 				if not (type_iseq tt t) then raise Not_found;
 				if not (type_iseq tt t) then raise Not_found;
 				if not (has_meta ":?genericT" ctx.curclass.cl_meta) then ctx.curclass.cl_meta <- (":?genericT",[],p) :: ctx.curclass.cl_meta;
 				if not (has_meta ":?genericT" ctx.curclass.cl_meta) then ctx.curclass.cl_meta <- (":?genericT",[],p) :: ctx.curclass.cl_meta;
-			with Not_found ->			
+			with Not_found ->
 				error "Only generic type parameters can be constructed" p);
 				error "Only generic type parameters can be constructed" p);
 			let el = List.map (type_expr ctx) el in
 			let el = List.map (type_expr ctx) el in
 			let ctor = mk_field "new" (tfun (List.map (fun e -> e.etype) el) ctx.t.tvoid) p in
 			let ctor = mk_field "new" (tfun (List.map (fun e -> e.etype) el) ctx.t.tvoid) p in
@@ -2061,7 +2061,7 @@ and type_expr ctx ?(need_val=true) (e,p) =
 				(try
 				(try
 					fst (unify_call_params ctx (Some (TInst(c,params),f)) el args r p false)
 					fst (unify_call_params ctx (Some (TInst(c,params),f)) el args r p false)
 				with Error (e,p) ->
 				with Error (e,p) ->
-					display_error ctx (error_msg e) p; 
+					display_error ctx (error_msg e) p;
 					[])
 					[])
 			| _ ->
 			| _ ->
 				error "Constructor is not a function" p
 				error "Constructor is not a function" p
@@ -2190,7 +2190,7 @@ and type_expr ctx ?(need_val=true) (e,p) =
 			| _ ->
 			| _ ->
 				t
 				t
 		in
 		in
-		let rec get_fields t = 
+		let rec get_fields t =
 			match follow t with
 			match follow t with
 			| TInst (c,params) ->
 			| TInst (c,params) ->
 				let priv = is_parent c ctx.curclass in
 				let priv = is_parent c ctx.curclass in
@@ -2400,16 +2400,16 @@ and build_call ctx acc el twith p =
 	| AKExpr e | AKField (e,_) ->
 	| AKExpr e | AKField (e,_) ->
 		let el , t, e = (match follow e.etype with
 		let el , t, e = (match follow e.etype with
 		| TFun (args,r) ->
 		| TFun (args,r) ->
-			let fopts = (match acc with 
+			let fopts = (match acc with
 				| AKField (e,f) ->
 				| AKField (e,f) ->
-					(match e.eexpr with 
+					(match e.eexpr with
 					| TField (e,_) -> fopts e.etype f
 					| TField (e,_) -> fopts e.etype f
 					| _ -> None)
 					| _ -> None)
 				| _ ->
 				| _ ->
 					None
 					None
 			) in
 			) in
 			(match fopts,acc with
 			(match fopts,acc with
-				| Some (_,cf),AKField({eexpr = TField(e,_)},_) when has_meta ":generic" cf.cf_meta -> 
+				| Some (_,cf),AKField({eexpr = TField(e,_)},_) when has_meta ":generic" cf.cf_meta ->
 					type_generic_function ctx (e,cf) el p
 					type_generic_function ctx (e,cf) el p
 				| _ ->
 				| _ ->
 					let el, tfunc = unify_call_params ctx fopts el args r p false in
 					let el, tfunc = unify_call_params ctx fopts el args r p false in
@@ -2464,20 +2464,8 @@ let get_main ctx =
 		let emain = type_type ctx cl null_pos in
 		let emain = type_type ctx cl null_pos in
 		Some (mk (TCall (mk (TField (emain,"main")) ft null_pos,[])) r null_pos)
 		Some (mk (TCall (mk (TField (emain,"main")) ft null_pos,[])) r null_pos)
 
 
-let rec finalize ctx =
-	match ctx.g.delayed.df_normal,ctx.g.delayed.df_late with
-	| [],[] ->
-		(* at last done *)
-		()
-	| [],l ->
-		(* normal done, but late remains *)
-		ctx.g.delayed.df_late <- [];
-		List.iter (fun f -> f()) l;
-		finalize ctx		
-	| l,_ ->
-		ctx.g.delayed.df_normal <- [];
-		List.iter (fun f -> f()) l;
-		finalize ctx
+let finalize ctx =
+	flush_pass ctx PFinal "final"
 
 
 type state =
 type state =
 	| Generating
 	| Generating
@@ -2729,12 +2717,14 @@ let make_macro_api ctx p =
 		Interp.get_display = (fun s ->
 		Interp.get_display = (fun s ->
 			let is_displaying = ctx.com.display in
 			let is_displaying = ctx.com.display in
 			let old_resume = !Parser.resume_display in
 			let old_resume = !Parser.resume_display in
+			let old_error = ctx.on_error in
 			let restore () =
 			let restore () =
 				if not is_displaying then begin
 				if not is_displaying then begin
 					ctx.com.defines <- PMap.remove "display" ctx.com.defines;
 					ctx.com.defines <- PMap.remove "display" ctx.com.defines;
-					ctx.com.display <- false;
+					ctx.com.display <- false
 				end;
 				end;
-				Parser.resume_display := old_resume
+				Parser.resume_display := old_resume;
+				ctx.on_error <- old_error;
 			in
 			in
 			(* temporarily enter display mode with a fake position *)
 			(* temporarily enter display mode with a fake position *)
 			if not is_displaying then begin
 			if not is_displaying then begin
@@ -2746,6 +2736,7 @@ let make_macro_api ctx p =
 				Ast.pmin = 0;
 				Ast.pmin = 0;
 				Ast.pmax = 0;
 				Ast.pmax = 0;
 			};
 			};
+			ctx.on_error <- (fun ctx msg p -> raise (Error(Custom msg,p)));
 			let str = try
 			let str = try
 				let e = parse_expr_string s Ast.null_pos true in
 				let e = parse_expr_string s Ast.null_pos true in
 				let e = Optimizer.optimize_completion_expr e in
 				let e = Optimizer.optimize_completion_expr e in
@@ -2753,7 +2744,7 @@ let make_macro_api ctx p =
 				"NO COMPLETION"
 				"NO COMPLETION"
 			with DisplayFields fields ->
 			with DisplayFields fields ->
 				let pctx = print_context() in
 				let pctx = print_context() in
-				String.concat "," (List.map (fun (f,t,_) -> f ^ ":" ^ s_type pctx t) fields)				
+				String.concat "," (List.map (fun (f,t,_) -> f ^ ":" ^ s_type pctx t) fields)
 			| DisplayTypes tl ->
 			| DisplayTypes tl ->
 				let pctx = print_context() in
 				let pctx = print_context() in
 				String.concat "," (List.map (s_type pctx) tl)
 				String.concat "," (List.map (s_type pctx) tl)
@@ -2855,7 +2846,7 @@ let make_macro_api ctx p =
 					Some (TInst (ctx.curclass,[]))
 					Some (TInst (ctx.curclass,[]))
 		);
 		);
 		Interp.get_local_method = (fun() ->
 		Interp.get_local_method = (fun() ->
-			ctx.curmethod;
+			ctx.curfield.cf_name;
 		);
 		);
 		Interp.get_local_using = (fun() ->
 		Interp.get_local_using = (fun() ->
 			ctx.local_using;
 			ctx.local_using;
@@ -2887,7 +2878,7 @@ let make_macro_api ctx p =
 		);
 		);
 	}
 	}
 
 
-let flush_macro_context mctx ctx = 
+let flush_macro_context mctx ctx =
 	finalize ctx;
 	finalize ctx;
 	let _, types, modules = generate ctx in
 	let _, types, modules = generate ctx in
 	ctx.com.types <- types;
 	ctx.com.types <- types;
@@ -2949,7 +2940,9 @@ let load_macro ctx cpath f p =
 	ctx2.local_types <- mloaded.m_types;
 	ctx2.local_types <- mloaded.m_types;
 	add_dependency ctx.current mloaded;
 	add_dependency ctx.current mloaded;
 	let cl, meth = (match Typeload.load_instance ctx2 { tpackage = fst cpath; tname = snd cpath; tparams = []; tsub = None } p true with
 	let cl, meth = (match Typeload.load_instance ctx2 { tpackage = fst cpath; tname = snd cpath; tparams = []; tsub = None } p true with
-		| TInst (c,_) -> c, (try PMap.find f c.cl_statics with Not_found -> error ("Method " ^ f ^ " not found on class " ^ s_type_path cpath) p)
+		| TInst (c,_) ->
+			finalize ctx2;
+			c, (try PMap.find f c.cl_statics with Not_found -> error ("Method " ^ f ^ " not found on class " ^ s_type_path cpath) p)
 		| _ -> error "Macro should be called on a class" p
 		| _ -> error "Macro should be called on a class" p
 	) in
 	) in
 	let meth = (match follow meth.cf_type with TFun (args,ret) -> args,ret,cl,meth | _ -> error "Macro call should be a method" p) in
 	let meth = (match follow meth.cf_type with TFun (args,ret) -> args,ret,cl,meth | _ -> error "Macro call should be a method" p) in
@@ -3140,10 +3133,8 @@ let rec create com =
 			modules = Hashtbl.create 0;
 			modules = Hashtbl.create 0;
 			types_module = Hashtbl.create 0;
 			types_module = Hashtbl.create 0;
 			type_patches = Hashtbl.create 0;
 			type_patches = Hashtbl.create 0;
-			delayed = {
-				df_normal = [];
-				df_late = [];
-			};
+			delayed = [];
+			debug_delayed = [];
 			doinline = not (Common.defined com "no_inline" || com.display);
 			doinline = not (Common.defined com "no_inline" || com.display);
 			hook_generate = [];
 			hook_generate = [];
 			get_build_infos = (fun() -> None);
 			get_build_infos = (fun() -> None);
@@ -3155,6 +3146,7 @@ let rec create com =
 			do_optimize = Optimizer.reduce_expression;
 			do_optimize = Optimizer.reduce_expression;
 			do_build_instance = Codegen.build_instance;
 			do_build_instance = Codegen.build_instance;
 		};
 		};
+		pass = PBuildModule;
 		macro_depth = 0;
 		macro_depth = 0;
 		untyped = false;
 		untyped = false;
 		curfun = FStatic;
 		curfun = FStatic;
@@ -3167,8 +3159,8 @@ let rec create com =
 		local_types = [];
 		local_types = [];
 		local_using = [];
 		local_using = [];
 		type_params = [];
 		type_params = [];
-		curmethod = "";
 		curclass = null_class;
 		curclass = null_class;
+		curfield = null_field;
 		tthis = mk_mono();
 		tthis = mk_mono();
 		current = null_module;
 		current = null_module;
 		opened = [];
 		opened = [];