Pārlūkot izejas kodu

[typer] split up `init_module_type`

Simon Krajewski 3 gadi atpakaļ
vecāks
revīzija
d4b8b730d3
1 mainītis faili ar 268 papildinājumiem un 256 dzēšanām
  1. 268 256
      src/typing/typeloadModule.ml

+ 268 - 256
src/typing/typeloadModule.ml

@@ -393,6 +393,270 @@ module TypeLevel = struct
 			DisplayEmitter.display_enum_field ctx e f p;
 			DisplayEmitter.display_enum_field ctx e f p;
 		f,cf
 		f,cf
 
 
+	let init_class ctx context_init c d p =
+		if ctx.is_display_file && DisplayPosition.display_position#enclosed_in (pos d.d_name) then
+			DisplayEmitter.display_module_type ctx (match c.cl_kind with KAbstractImpl a -> TAbstractDecl a | _ -> TClassDecl c) (pos d.d_name);
+		TypeloadCheck.check_global_metadata ctx c.cl_meta (fun m -> c.cl_meta <- m :: c.cl_meta) c.cl_module.m_path c.cl_path None;
+		let herits = d.d_flags in
+		List.iter (fun (m,_,p) ->
+			if m = Meta.Final then begin
+				add_class_flag c CFinal;
+			end
+		) d.d_meta;
+		let prev_build_count = ref (!build_count - 1) in
+		let build() =
+			c.cl_build <- (fun()-> Building [c]);
+			let fl = TypeloadCheck.Inheritance.set_heritance ctx c herits p in
+			let rec build() =
+				c.cl_build <- (fun()-> Building [c]);
+				try
+					List.iter (fun f -> f()) fl;
+					TypeloadFields.init_class ctx c p context_init d.d_flags d.d_data;
+					c.cl_build <- (fun()-> Built);
+					incr build_count;
+					List.iter (fun tp -> ignore(follow tp.ttp_type)) c.cl_params;
+					Built;
+				with TypeloadCheck.Build_canceled state ->
+					c.cl_build <- make_pass ctx build;
+					let rebuild() =
+						delay_late ctx PBuildClass (fun() -> ignore(c.cl_build()));
+					in
+					(match state with
+					| Built -> die "" __LOC__
+					| Building cl ->
+						if !build_count = !prev_build_count then typing_error ("Loop in class building prevent compiler termination (" ^ String.concat "," (List.map (fun c -> s_type_path c.cl_path) cl) ^ ")") c.cl_pos;
+						prev_build_count := !build_count;
+						rebuild();
+						Building (c :: cl)
+					| BuildMacro f ->
+						f := rebuild :: !f;
+						state);
+				| exn ->
+					c.cl_build <- (fun()-> Built);
+					raise exn
+			in
+			build()
+		in
+		ctx.pass <- PBuildClass;
+		ctx.curclass <- c;
+		c.cl_build <- make_pass ctx build;
+		ctx.pass <- PBuildModule;
+		ctx.curclass <- null_class;
+		delay ctx PBuildClass (fun() -> ignore(c.cl_build()));
+		if Meta.has Meta.InheritDoc c.cl_meta then
+				delay ctx PConnectField (fun() -> InheritDoc.build_class_doc ctx c);
+		if (ctx.com.platform = Java || ctx.com.platform = Cs) && not (has_class_flag c CExtern) then
+			delay ctx PTypeField (fun () ->
+				let metas = StrictMeta.check_strict_meta ctx c.cl_meta in
+				if metas <> [] then c.cl_meta <- metas @ c.cl_meta;
+				let rec run_field cf =
+					let metas = StrictMeta.check_strict_meta ctx cf.cf_meta in
+					if metas <> [] then cf.cf_meta <- metas @ cf.cf_meta;
+					List.iter run_field cf.cf_overloads
+				in
+				List.iter run_field c.cl_ordered_statics;
+				List.iter run_field c.cl_ordered_fields;
+				match c.cl_constructor with
+					| Some f -> run_field f
+					| _ -> ()
+			)
+
+	let init_enum ctx context_init e d p =
+		if ctx.is_display_file && DisplayPosition.display_position#enclosed_in (pos d.d_name) then
+			DisplayEmitter.display_module_type ctx (TEnumDecl e) (pos d.d_name);
+		let ctx = { ctx with type_params = e.e_params } in
+		let h = (try Some (Hashtbl.find ctx.g.type_patches e.e_path) with Not_found -> None) in
+		TypeloadCheck.check_global_metadata ctx e.e_meta (fun m -> e.e_meta <- m :: e.e_meta) e.e_module.m_path e.e_path None;
+		(match h with
+		| None -> ()
+		| Some (h,hcl) ->
+			Hashtbl.iter (fun _ _ -> typing_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 ->
+				{
+					cff_name = c.ec_name;
+					cff_doc = c.ec_doc;
+					cff_meta = c.ec_meta;
+					cff_pos = c.ec_pos;
+					cff_access = [];
+					cff_kind = (match c.ec_args, c.ec_params with
+						| [], [] -> FVar (c.ec_type,None)
+						| _ -> FFun { f_params = c.ec_params; f_type = c.ec_type; f_expr = None; f_args = List.map (fun (n,o,t) -> (n,null_pos),o,[],Some t,None) c.ec_args });
+				}
+			) (!constructs)
+		in
+		TypeloadFields.build_module_def ctx (TEnumDecl e) e.e_meta get_constructs context_init (fun (e,p) ->
+			match e with
+			| EVars [{ ev_type = Some (CTAnonymous fields,p); ev_expr = None }] ->
+				constructs := List.map (fun f ->
+					let args, params, t = (match f.cff_kind with
+					| FVar (t,None) -> [], [], t
+					| FFun { f_params = pl; f_type = t; f_expr = (None|Some (EBlock [],_)); f_args = al } ->
+						let al = List.map (fun ((n,_),o,_,t,_) -> match t with None -> typing_error "Missing function parameter type" f.cff_pos | Some t -> n,o,t) al in
+						al, pl, t
+					| _ ->
+						typing_error "Invalid enum constructor in @:build result" p
+					) in
+					{
+						ec_name = f.cff_name;
+						ec_doc = f.cff_doc;
+						ec_meta = f.cff_meta;
+						ec_pos = f.cff_pos;
+						ec_args = args;
+						ec_params = params;
+						ec_type = t;
+					}
+				) fields
+			| _ -> typing_error "Enum build macro must return a single variable with anonymous object fields" p
+		);
+		let et = TEnum (e,extract_param_types e.e_params) in
+		let names = ref [] in
+		let index = ref 0 in
+		let is_flat = ref true in
+		let fields = ref PMap.empty in
+		List.iter (fun c ->
+			if PMap.mem (fst c.ec_name) e.e_constrs then typing_error ("Duplicate constructor " ^ fst c.ec_name) (pos c.ec_name);
+			let f,cf = load_enum_field ctx e et is_flat index c in
+			e.e_constrs <- PMap.add f.ef_name f e.e_constrs;
+			fields := PMap.add cf.cf_name cf !fields;
+			incr index;
+			names := (fst c.ec_name) :: !names;
+			if Meta.has Meta.InheritDoc f.ef_meta then
+				delay ctx PConnectField (fun() -> InheritDoc.build_enum_field_doc ctx f);
+		) (!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));
+		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);
+		if (ctx.com.platform = Java || ctx.com.platform = Cs) && not e.e_extern then
+			delay ctx PTypeField (fun () ->
+				let metas = StrictMeta.check_strict_meta ctx e.e_meta in
+				e.e_meta <- metas @ e.e_meta;
+				PMap.iter (fun _ ef ->
+					let metas = StrictMeta.check_strict_meta ctx ef.ef_meta in
+					if metas <> [] then ef.ef_meta <- metas @ ef.ef_meta
+				) e.e_constrs
+			)
+
+	let init_typedef ctx context_init t d p =
+		if ctx.is_display_file && DisplayPosition.display_position#enclosed_in (pos d.d_name) then
+			DisplayEmitter.display_module_type ctx (TTypeDecl t) (pos d.d_name);
+		TypeloadCheck.check_global_metadata ctx t.t_meta (fun m -> t.t_meta <- m :: t.t_meta) t.t_module.m_path t.t_path None;
+		let ctx = { ctx with type_params = t.t_params } in
+		let tt = load_complex_type ctx true d.d_data in
+		let tt = (match fst d.d_data with
+		| CTExtend _ -> tt
+		| CTPath { tpackage = ["haxe";"macro"]; tname = "MacroType" } ->
+			(* we need to follow MacroType immediately since it might define other module types that we will load afterwards *)
+			if t.t_type == follow tt then typing_error "Recursive typedef is not allowed" p;
+			tt
+		| _ ->
+			if (Meta.has Meta.Eager d.d_meta) then
+				follow tt
+			else begin
+				let rec check_rec tt =
+					if tt == t.t_type then typing_error "Recursive typedef is not allowed" p;
+					match tt with
+					| TMono r ->
+						(match r.tm_type with
+						| None -> ()
+						| Some t -> check_rec t)
+					| TLazy f ->
+						check_rec (lazy_type f);
+					| TType (td,tl) ->
+						if td == t then typing_error "Recursive typedef is not allowed" p;
+						check_rec (apply_typedef td tl)
+					| _ ->
+						()
+				in
+				let r = exc_protect ctx (fun r ->
+					r := lazy_processing (fun() -> tt);
+					check_rec tt;
+					tt
+				) "typedef_rec_check" in
+				TLazy r
+			end
+		) in
+		(match t.t_type with
+		| TMono r ->
+			(match r.tm_type with
+			| None -> Monomorph.bind r tt;
+			| Some _ -> die "" __LOC__);
+		| _ -> die "" __LOC__);
+		TypeloadFields.build_module_def ctx (TTypeDecl t) t.t_meta (fun _ -> []) context_init (fun _ -> ());
+		if ctx.com.platform = Cs && t.t_meta <> [] then
+			delay ctx PTypeField (fun () ->
+				let metas = StrictMeta.check_strict_meta ctx t.t_meta in
+				if metas <> [] then t.t_meta <- metas @ t.t_meta;
+			)
+
+	let init_abstract ctx context_init a d p =
+		if ctx.is_display_file && DisplayPosition.display_position#enclosed_in (pos d.d_name) then
+			DisplayEmitter.display_module_type ctx (TAbstractDecl a) (pos d.d_name);
+		TypeloadCheck.check_global_metadata ctx a.a_meta (fun m -> a.a_meta <- m :: a.a_meta) a.a_module.m_path a.a_path None;
+		let ctx = { ctx with type_params = a.a_params } in
+		let is_type = ref false in
+		let load_type t from =
+			let _, pos = t in
+			let t = load_complex_type ctx true t in
+			let t = if not (Meta.has Meta.CoreType a.a_meta) then begin
+				if !is_type then begin
+					let r = exc_protect ctx (fun r ->
+						r := lazy_processing (fun() -> t);
+						(try (if from then Type.unify t a.a_this else Type.unify a.a_this t) with Unify_error _ -> typing_error "You can only declare from/to with compatible types" pos);
+						t
+					) "constraint" in
+					TLazy r
+				end else
+					typing_error "Missing underlying type declaration or @:coreType declaration" p;
+			end else begin
+				if Meta.has Meta.Callable a.a_meta then
+					typing_error "@:coreType abstracts cannot be @:callable" p;
+				t
+			end in
+			t
+		in
+		List.iter (function
+			| AbFrom t -> a.a_from <- (load_type t true) :: a.a_from
+			| AbTo t -> a.a_to <- (load_type t false) :: a.a_to
+			| AbOver t ->
+				if a.a_impl = None then typing_error "Abstracts with underlying type must have an implementation" a.a_pos;
+				if Meta.has Meta.CoreType a.a_meta then typing_error "@:coreType abstracts cannot have an underlying type" p;
+				let at = load_complex_type ctx true t in
+				delay ctx PForce (fun () ->
+					let rec loop stack t =
+						match follow t with
+						| TAbstract(a,_) when not (Meta.has Meta.CoreType a.a_meta) ->
+							if List.memq a stack then
+								typing_error "Abstract underlying type cannot be recursive" a.a_pos
+							else
+								loop (a :: stack) a.a_this
+						| _ -> ()
+					in
+					loop [] at
+				);
+				a.a_this <- at;
+				is_type := true;
+			| AbExtern ->
+				(match a.a_impl with Some c -> add_class_flag c CExtern | None -> (* Hmmmm.... *) ())
+			| AbPrivate | AbEnum -> ()
+		) d.d_flags;
+		a.a_from <- List.rev a.a_from;
+		a.a_to <- List.rev a.a_to;
+		if not !is_type then begin
+			if Meta.has Meta.CoreType a.a_meta then
+				a.a_this <- TAbstract(a,extract_param_types a.a_params)
+			else
+				typing_error "Abstract is missing underlying type declaration" a.a_pos
+		end;
+		if Meta.has Meta.InheritDoc a.a_meta then
+			delay ctx PConnectField (fun() -> InheritDoc.build_abstract_doc ctx a)
+
 	(*
 	(*
 		In this pass, we can access load and access other modules types, but we cannot follow them or access their structure
 		In this pass, we can access load and access other modules types, but we cannot follow them or access their structure
 		since they have not been setup. We also build a context_init list that will be evaluated the first time we evaluate
 		since they have not been setup. We also build a context_init list that will be evaluated the first time we evaluate
@@ -419,268 +683,16 @@ module TypeLevel = struct
 			ImportHandling.init_using ctx context_init path p
 			ImportHandling.init_using ctx context_init path p
 		| EClass d ->
 		| EClass d ->
 			let c = (match get_type (fst d.d_name) with TClassDecl c -> c | _ -> die "" __LOC__) in
 			let c = (match get_type (fst d.d_name) with TClassDecl c -> c | _ -> die "" __LOC__) in
-			if ctx.is_display_file && DisplayPosition.display_position#enclosed_in (pos d.d_name) then
-				DisplayEmitter.display_module_type ctx (match c.cl_kind with KAbstractImpl a -> TAbstractDecl a | _ -> TClassDecl c) (pos d.d_name);
-			TypeloadCheck.check_global_metadata ctx c.cl_meta (fun m -> c.cl_meta <- m :: c.cl_meta) c.cl_module.m_path c.cl_path None;
-			let herits = d.d_flags in
-			List.iter (fun (m,_,p) ->
-				if m = Meta.Final then begin
-					add_class_flag c CFinal;
-				end
-			) d.d_meta;
-			let prev_build_count = ref (!build_count - 1) in
-			let build() =
-				c.cl_build <- (fun()-> Building [c]);
-				let fl = TypeloadCheck.Inheritance.set_heritance ctx c herits p in
-				let rec build() =
-					c.cl_build <- (fun()-> Building [c]);
-					try
-						List.iter (fun f -> f()) fl;
-						TypeloadFields.init_class ctx c p context_init d.d_flags d.d_data;
-						c.cl_build <- (fun()-> Built);
-						incr build_count;
-						List.iter (fun tp -> ignore(follow tp.ttp_type)) c.cl_params;
-						Built;
-					with TypeloadCheck.Build_canceled state ->
-						c.cl_build <- make_pass ctx build;
-						let rebuild() =
-							delay_late ctx PBuildClass (fun() -> ignore(c.cl_build()));
-						in
-						(match state with
-						| Built -> die "" __LOC__
-						| Building cl ->
-							if !build_count = !prev_build_count then typing_error ("Loop in class building prevent compiler termination (" ^ String.concat "," (List.map (fun c -> s_type_path c.cl_path) cl) ^ ")") c.cl_pos;
-							prev_build_count := !build_count;
-							rebuild();
-							Building (c :: cl)
-						| BuildMacro f ->
-							f := rebuild :: !f;
-							state);
-					| exn ->
-						c.cl_build <- (fun()-> Built);
-						raise exn
-				in
-				build()
-			in
-			ctx.pass <- PBuildClass;
-			ctx.curclass <- c;
-			c.cl_build <- make_pass ctx build;
-			ctx.pass <- PBuildModule;
-			ctx.curclass <- null_class;
-			delay ctx PBuildClass (fun() -> ignore(c.cl_build()));
-			if Meta.has Meta.InheritDoc c.cl_meta then
-					delay ctx PConnectField (fun() -> InheritDoc.build_class_doc ctx c);
-			if (ctx.com.platform = Java || ctx.com.platform = Cs) && not (has_class_flag c CExtern) then
-				delay ctx PTypeField (fun () ->
-					let metas = StrictMeta.check_strict_meta ctx c.cl_meta in
-					if metas <> [] then c.cl_meta <- metas @ c.cl_meta;
-					let rec run_field cf =
-						let metas = StrictMeta.check_strict_meta ctx cf.cf_meta in
-						if metas <> [] then cf.cf_meta <- metas @ cf.cf_meta;
-						List.iter run_field cf.cf_overloads
-					in
-					List.iter run_field c.cl_ordered_statics;
-					List.iter run_field c.cl_ordered_fields;
-					match c.cl_constructor with
-						| Some f -> run_field f
-						| _ -> ()
-				);
+			init_class ctx context_init c d p
 		| EEnum d ->
 		| EEnum d ->
 			let e = (match get_type (fst d.d_name) with TEnumDecl e -> e | _ -> die "" __LOC__) in
 			let e = (match get_type (fst d.d_name) with TEnumDecl e -> e | _ -> die "" __LOC__) in
-			if ctx.is_display_file && DisplayPosition.display_position#enclosed_in (pos d.d_name) then
-				DisplayEmitter.display_module_type ctx (TEnumDecl e) (pos d.d_name);
-			let ctx = { ctx with type_params = e.e_params } in
-			let h = (try Some (Hashtbl.find ctx.g.type_patches e.e_path) with Not_found -> None) in
-			TypeloadCheck.check_global_metadata ctx e.e_meta (fun m -> e.e_meta <- m :: e.e_meta) e.e_module.m_path e.e_path None;
-			(match h with
-			| None -> ()
-			| Some (h,hcl) ->
-				Hashtbl.iter (fun _ _ -> typing_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 ->
-					{
-						cff_name = c.ec_name;
-						cff_doc = c.ec_doc;
-						cff_meta = c.ec_meta;
-						cff_pos = c.ec_pos;
-						cff_access = [];
-						cff_kind = (match c.ec_args, c.ec_params with
-							| [], [] -> FVar (c.ec_type,None)
-							| _ -> FFun { f_params = c.ec_params; f_type = c.ec_type; f_expr = None; f_args = List.map (fun (n,o,t) -> (n,null_pos),o,[],Some t,None) c.ec_args });
-					}
-				) (!constructs)
-			in
-			TypeloadFields.build_module_def ctx (TEnumDecl e) e.e_meta get_constructs context_init (fun (e,p) ->
-				match e with
-				| EVars [{ ev_type = Some (CTAnonymous fields,p); ev_expr = None }] ->
-					constructs := List.map (fun f ->
-						let args, params, t = (match f.cff_kind with
-						| FVar (t,None) -> [], [], t
-						| FFun { f_params = pl; f_type = t; f_expr = (None|Some (EBlock [],_)); f_args = al } ->
-							let al = List.map (fun ((n,_),o,_,t,_) -> match t with None -> typing_error "Missing function parameter type" f.cff_pos | Some t -> n,o,t) al in
-							al, pl, t
-						| _ ->
-							typing_error "Invalid enum constructor in @:build result" p
-						) in
-						{
-							ec_name = f.cff_name;
-							ec_doc = f.cff_doc;
-							ec_meta = f.cff_meta;
-							ec_pos = f.cff_pos;
-							ec_args = args;
-							ec_params = params;
-							ec_type = t;
-						}
-					) fields
-				| _ -> typing_error "Enum build macro must return a single variable with anonymous object fields" p
-			);
-			let et = TEnum (e,extract_param_types e.e_params) in
-			let names = ref [] in
-			let index = ref 0 in
-			let is_flat = ref true in
-			let fields = ref PMap.empty in
-			List.iter (fun c ->
-				if PMap.mem (fst c.ec_name) e.e_constrs then typing_error ("Duplicate constructor " ^ fst c.ec_name) (pos c.ec_name);
-				let f,cf = load_enum_field ctx e et is_flat index c in
-				e.e_constrs <- PMap.add f.ef_name f e.e_constrs;
-				fields := PMap.add cf.cf_name cf !fields;
-				incr index;
-				names := (fst c.ec_name) :: !names;
-				if Meta.has Meta.InheritDoc f.ef_meta then
-					delay ctx PConnectField (fun() -> InheritDoc.build_enum_field_doc ctx f);
-			) (!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));
-			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);
-			if (ctx.com.platform = Java || ctx.com.platform = Cs) && not e.e_extern then
-				delay ctx PTypeField (fun () ->
-					let metas = StrictMeta.check_strict_meta ctx e.e_meta in
-					e.e_meta <- metas @ e.e_meta;
-					PMap.iter (fun _ ef ->
-						let metas = StrictMeta.check_strict_meta ctx ef.ef_meta in
-						if metas <> [] then ef.ef_meta <- metas @ ef.ef_meta
-					) e.e_constrs
-				);
+			init_enum ctx context_init e d p
 		| ETypedef d ->
 		| ETypedef d ->
 			let t = (match get_type (fst d.d_name) with TTypeDecl t -> t | _ -> die "" __LOC__) in
 			let t = (match get_type (fst d.d_name) with TTypeDecl t -> t | _ -> die "" __LOC__) in
-			if ctx.is_display_file && DisplayPosition.display_position#enclosed_in (pos d.d_name) then
-				DisplayEmitter.display_module_type ctx (TTypeDecl t) (pos d.d_name);
-			TypeloadCheck.check_global_metadata ctx t.t_meta (fun m -> t.t_meta <- m :: t.t_meta) t.t_module.m_path t.t_path None;
-			let ctx = { ctx with type_params = t.t_params } in
-			let tt = load_complex_type ctx true d.d_data in
-			let tt = (match fst d.d_data with
-			| CTExtend _ -> tt
-			| CTPath { tpackage = ["haxe";"macro"]; tname = "MacroType" } ->
-				(* we need to follow MacroType immediately since it might define other module types that we will load afterwards *)
-				if t.t_type == follow tt then typing_error "Recursive typedef is not allowed" p;
-				tt
-			| _ ->
-				if (Meta.has Meta.Eager d.d_meta) then
-					follow tt
-				else begin
-					let rec check_rec tt =
-						if tt == t.t_type then typing_error "Recursive typedef is not allowed" p;
-						match tt with
-						| TMono r ->
-							(match r.tm_type with
-							| None -> ()
-							| Some t -> check_rec t)
-						| TLazy f ->
-							check_rec (lazy_type f);
-						| TType (td,tl) ->
-							if td == t then typing_error "Recursive typedef is not allowed" p;
-							check_rec (apply_typedef td tl)
-						| _ ->
-							()
-					in
-					let r = exc_protect ctx (fun r ->
-						r := lazy_processing (fun() -> tt);
-						check_rec tt;
-						tt
-					) "typedef_rec_check" in
-					TLazy r
-				end
-			) in
-			(match t.t_type with
-			| TMono r ->
-				(match r.tm_type with
-				| None -> Monomorph.bind r tt;
-				| Some _ -> die "" __LOC__);
-			| _ -> die "" __LOC__);
-			TypeloadFields.build_module_def ctx (TTypeDecl t) t.t_meta (fun _ -> []) context_init (fun _ -> ());
-			if ctx.com.platform = Cs && t.t_meta <> [] then
-				delay ctx PTypeField (fun () ->
-					let metas = StrictMeta.check_strict_meta ctx t.t_meta in
-					if metas <> [] then t.t_meta <- metas @ t.t_meta;
-				);
+			init_typedef ctx context_init t d p
 		| EAbstract d ->
 		| EAbstract d ->
 			let a = (match get_type (fst d.d_name) with TAbstractDecl a -> a | _ -> die "" __LOC__) in
 			let a = (match get_type (fst d.d_name) with TAbstractDecl a -> a | _ -> die "" __LOC__) in
-			if ctx.is_display_file && DisplayPosition.display_position#enclosed_in (pos d.d_name) then
-				DisplayEmitter.display_module_type ctx (TAbstractDecl a) (pos d.d_name);
-			TypeloadCheck.check_global_metadata ctx a.a_meta (fun m -> a.a_meta <- m :: a.a_meta) a.a_module.m_path a.a_path None;
-			let ctx = { ctx with type_params = a.a_params } in
-			let is_type = ref false in
-			let load_type t from =
-				let _, pos = t in
-				let t = load_complex_type ctx true t in
-				let t = if not (Meta.has Meta.CoreType a.a_meta) then begin
-					if !is_type then begin
-						let r = exc_protect ctx (fun r ->
-							r := lazy_processing (fun() -> t);
-							(try (if from then Type.unify t a.a_this else Type.unify a.a_this t) with Unify_error _ -> typing_error "You can only declare from/to with compatible types" pos);
-							t
-						) "constraint" in
-						TLazy r
-					end else
-						typing_error "Missing underlying type declaration or @:coreType declaration" p;
-				end else begin
-					if Meta.has Meta.Callable a.a_meta then
-						typing_error "@:coreType abstracts cannot be @:callable" p;
-					t
-				end in
-				t
-			in
-			List.iter (function
-				| AbFrom t -> a.a_from <- (load_type t true) :: a.a_from
-				| AbTo t -> a.a_to <- (load_type t false) :: a.a_to
-				| AbOver t ->
-					if a.a_impl = None then typing_error "Abstracts with underlying type must have an implementation" a.a_pos;
-					if Meta.has Meta.CoreType a.a_meta then typing_error "@:coreType abstracts cannot have an underlying type" p;
-					let at = load_complex_type ctx true t in
-					delay ctx PForce (fun () ->
-						let rec loop stack t =
-							match follow t with
-							| TAbstract(a,_) when not (Meta.has Meta.CoreType a.a_meta) ->
-								if List.memq a stack then
-									typing_error "Abstract underlying type cannot be recursive" a.a_pos
-								else
-									loop (a :: stack) a.a_this
-							| _ -> ()
-						in
-						loop [] at
-					);
-					a.a_this <- at;
-					is_type := true;
-				| AbExtern ->
-					(match a.a_impl with Some c -> add_class_flag c CExtern | None -> (* Hmmmm.... *) ())
-				| AbPrivate | AbEnum -> ()
-			) d.d_flags;
-			a.a_from <- List.rev a.a_from;
-			a.a_to <- List.rev a.a_to;
-			if not !is_type then begin
-				if Meta.has Meta.CoreType a.a_meta then
-					a.a_this <- TAbstract(a,extract_param_types a.a_params)
-				else
-					typing_error "Abstract is missing underlying type declaration" a.a_pos
-			end;
-			if Meta.has Meta.InheritDoc a.a_meta then
-				delay ctx PConnectField (fun() -> InheritDoc.build_abstract_doc ctx a);
+			init_abstract ctx context_init a d p
 		| EStatic _ ->
 		| EStatic _ ->
 			(* nothing to do here as module fields are collected into a special EClass *)
 			(* nothing to do here as module fields are collected into a special EClass *)
 			()
 			()