Browse Source

added hashlink plugin system (with --macro exclude) requires hl 1.16+

ncannasse 1 month ago
parent
commit
e4b21dbfd8
4 changed files with 235 additions and 206 deletions
  1. 1 1
      src/filters/filters.ml
  2. 212 202
      src/generators/genhl.ml
  3. 4 2
      std/hl/Api.hx
  4. 18 1
      std/hl/_std/Type.hx

+ 1 - 1
src/filters/filters.ml

@@ -181,7 +181,7 @@ open FilterContext
 let destruction_before_dce pool scom all_types_array =
 let destruction_before_dce pool scom all_types_array =
 	let filters = [
 	let filters = [
 		FiltersCommon.remove_generic_base;
 		FiltersCommon.remove_generic_base;
-		apply_macro_exclude;
+		(if scom.platform = Hl then (fun t -> ()) else apply_macro_exclude);
 		remove_extern_fields scom;
 		remove_extern_fields scom;
 		(* check @:remove metadata before DCE so it is ignored there (issue #2923) *)
 		(* check @:remove metadata before DCE so it is ignored there (issue #2923) *)
 		check_remove_metadata;
 		check_remove_metadata;

+ 212 - 202
src/generators/genhl.ml

@@ -366,6 +366,9 @@ let fake_tnull =
 		a_params = [mk_type_param null_class TPHType None None];
 		a_params = [mk_type_param null_class TPHType None None];
 	}
 	}
 
 
+let is_excluded c =
+	has_class_flag c CExcluded
+
 let get_rec_cache ctx t none_callback not_found_callback =
 let get_rec_cache ctx t none_callback not_found_callback =
 	try
 	try
 		match !(List.assq t ctx.rec_cache) with
 		match !(List.assq t ctx.rec_cache) with
@@ -3439,32 +3442,33 @@ and make_fun ?gen_content ctx name fidx f cthis cparent =
 			op ctx (OSetEnumField (ctx.m.mcaptreg, index, alloc_var ctx v false)));
 			op ctx (OSetEnumField (ctx.m.mcaptreg, index, alloc_var ctx v false)));
 	) f.tf_args;
 	) f.tf_args;
 
 
+	let tret = to_type ctx f.tf_type in
 	(match gen_content with
 	(match gen_content with
-	| None -> ()
-	| Some f -> f());
+	| None ->
+		ignore(eval_expr ctx f.tf_expr);
+		let rec has_final_jump e =
+			(* prevents a jump outside function bounds error *)
+			match e.eexpr with
+			| TBlock el -> (match List.rev el with e :: _ -> has_final_jump e | [] -> false)
+			| TParenthesis e -> has_final_jump e
+			| TReturn _ -> false
+			| _ -> true
+		in
+		set_curpos ctx (max_pos f.tf_expr);
+		if tret = HVoid then
+			op ctx (ORet (alloc_tmp ctx HVoid))
+		else if has_final_jump f.tf_expr then begin
+			let r = alloc_tmp ctx tret in
+			(match tret with
+			| HI32 | HUI8 | HUI16 | HI64 -> op ctx (OInt (r,alloc_i32 ctx 0l))
+			| HF32 | HF64 -> op ctx (OFloat (r,alloc_float ctx 0.))
+			| HBool -> op ctx (OBool (r,false))
+			| _ -> op ctx (ONull r));
+			op ctx (ORet r)
+		end;
+	| Some f ->
+		f());
 
 
-	ignore(eval_expr ctx f.tf_expr);
-	let tret = to_type ctx f.tf_type in
-	let rec has_final_jump e =
-		(* prevents a jump outside function bounds error *)
-		match e.eexpr with
-		| TBlock el -> (match List.rev el with e :: _ -> has_final_jump e | [] -> false)
-		| TParenthesis e -> has_final_jump e
-		| TReturn _ -> false
-		| _ -> true
-	in
-	set_curpos ctx (max_pos f.tf_expr);
-	if tret = HVoid then
-		op ctx (ORet (alloc_tmp ctx HVoid))
-	else if has_final_jump f.tf_expr then begin
-		let r = alloc_tmp ctx tret in
-		(match tret with
-		| HI32 | HUI8 | HUI16 | HI64 -> op ctx (OInt (r,alloc_i32 ctx 0l))
-		| HF32 | HF64 -> op ctx (OFloat (r,alloc_float ctx 0.))
-		| HBool -> op ctx (OBool (r,false))
-		| _ -> op ctx (ONull r));
-		op ctx (ORet r)
-	end;
 	let fargs = (match tthis with None -> [] | Some t -> [t]) @ (match rcapt with None -> [] | Some r -> [rtype ctx r]) @ args in
 	let fargs = (match tthis with None -> [] | Some t -> [t]) @ (match rcapt with None -> [] | Some r -> [rtype ctx r]) @ args in
 	let hlf = {
 	let hlf = {
 		fpath = name;
 		fpath = name;
@@ -3516,8 +3520,9 @@ let generate_static ctx c f =
 			| (Meta.HlNative,_ ,p) :: _ ->
 			| (Meta.HlNative,_ ,p) :: _ ->
 				abort "Invalid @:hlNative decl" p
 				abort "Invalid @:hlNative decl" p
 			| [] ->
 			| [] ->
+				let gen_content = if is_excluded c then Some (fun() -> op ctx (OAssert 0)) else None in
 				(match f.cf_expr with
 				(match f.cf_expr with
-				| Some { eexpr = TFunction fn } -> ignore(make_fun ctx (s_type_path c.cl_path,f.cf_name) (alloc_fid ctx c f) fn None None)
+				| Some { eexpr = TFunction fn } -> ignore(make_fun ?gen_content ctx (s_type_path c.cl_path,f.cf_name) (alloc_fid ctx c f) fn None None)
 				| _ -> if not (Meta.has Meta.NoExpr f.cf_meta) then abort "Missing function body" f.cf_pos)
 				| _ -> if not (Meta.has Meta.NoExpr f.cf_meta) then abort "Missing function body" f.cf_pos)
 			| _ :: l ->
 			| _ :: l ->
 				loop l
 				loop l
@@ -3530,7 +3535,25 @@ let generate_member ctx c f =
 	| Var _ -> ()
 	| Var _ -> ()
 	| _ when is_extern_field f -> ()
 	| _ when is_extern_field f -> ()
 	| Method m ->
 	| Method m ->
-		let gen_content = if f.cf_name <> "new" then None else Some (fun() ->
+		let ff = match f.cf_expr with
+			| Some { eexpr = TFunction f } -> f
+			| None when has_class_field_flag f CfAbstract ->
+				let tl,tr = match follow f.cf_type with
+					| TFun(tl,tr) -> tl,tr
+					| _ -> die "" __LOC__
+				in
+				let args = List.map (fun (n,_,t) ->
+					let v = Type.alloc_var VGenerated n t null_pos in
+					(v,None)
+				) tl in
+				{
+					tf_args = args;
+					tf_type = tr;
+					tf_expr = mk (TThrow (mk (TConst TNull) t_dynamic null_pos)) t_dynamic null_pos;
+				}
+			| _ -> abort "Missing function body" f.cf_pos
+		in
+		let gen_content = if is_excluded c then Some (fun() -> op ctx (OAssert 0)) else if f.cf_name <> "new" then None else Some (fun() ->
 
 
 			let o = (match class_type ctx c (extract_param_types c.cl_params) false with
 			let o = (match class_type ctx c (extract_param_types c.cl_params) false with
 				| HObj o | HStruct o -> o
 				| HObj o | HStruct o -> o
@@ -3551,25 +3574,9 @@ let generate_member ctx c f =
 					op ctx (OSetThis (fid,r));
 					op ctx (OSetThis (fid,r));
 				| _ -> ()
 				| _ -> ()
 			) c.cl_ordered_fields;
 			) c.cl_ordered_fields;
+			ignore(eval_expr ctx ff.tf_expr);
+			op ctx (ORet (alloc_tmp ctx HVoid))
 		) in
 		) in
-		let ff = match f.cf_expr with
-			| Some { eexpr = TFunction f } -> f
-			| None when has_class_field_flag f CfAbstract ->
-				let tl,tr = match follow f.cf_type with
-					| TFun(tl,tr) -> tl,tr
-					| _ -> die "" __LOC__
-				in
-				let args = List.map (fun (n,_,t) ->
-					let v = Type.alloc_var VGenerated n t null_pos in
-					(v,None)
-				) tl in
-				{
-					tf_args = args;
-					tf_type = tr;
-					tf_expr = mk (TThrow (mk (TConst TNull) t_dynamic null_pos)) t_dynamic null_pos;
-				}
-			| _ -> abort "Missing function body" f.cf_pos
-		in
 		ignore(make_fun ?gen_content ctx (s_type_path c.cl_path,f.cf_name) (alloc_fid ctx c f) ff (Some c) None);
 		ignore(make_fun ?gen_content ctx (s_type_path c.cl_path,f.cf_name) (alloc_fid ctx c f) ff (Some c) None);
 		if f.cf_name = "toString" && not (has_class_field_flag f CfOverride) && not (PMap.mem "__string" c.cl_fields) && is_to_string f.cf_type then begin
 		if f.cf_name = "toString" && not (has_class_field_flag f CfOverride) && not (PMap.mem "__string" c.cl_fields) && is_to_string f.cf_type then begin
 			let p = {f.cf_pos with pmax = f.cf_pos.pmin} in
 			let p = {f.cf_pos with pmax = f.cf_pos.pmin} in
@@ -3624,200 +3631,201 @@ let generate_type ctx t =
 	| TEnumDecl _ | TTypeDecl _ | TAbstractDecl _ ->
 	| TEnumDecl _ | TTypeDecl _ | TAbstractDecl _ ->
 		()
 		()
 
 
-let generate_static_init ctx types main =
-	let exprs = ref [] in
-	let t_void = ctx.com.basic.tvoid in
+let generate_static_content ctx types f =
+	let is_init = alloc_tmp ctx HBool in
+	op ctx (OCall0 (is_init, alloc_fun_path ctx ([],"Type") "init"));
+	hold ctx is_init;
 
 
-	let gen_content() =
-
-		let is_init = alloc_tmp ctx HBool in
-		op ctx (OCall0 (is_init, alloc_fun_path ctx ([],"Type") "init"));
-		hold ctx is_init;
-
-		(* init class values *)
-		List.iter (fun t ->
-			match t with
-			| TClassDecl c when not (has_class_flag c CExtern) && not (is_array_class (s_type_path c.cl_path) && snd c.cl_path <> "ArrayDyn") && c != ctx.core_type && c != ctx.core_enum ->
+	(* init class values *)
+	List.iter (fun t ->
+		match t with
+		| TClassDecl c when not (has_class_flag c CExtern) && not (is_array_class (s_type_path c.cl_path) && snd c.cl_path <> "ArrayDyn") && c != ctx.core_type && c != ctx.core_enum ->
 
 
-				let path = if c == ctx.array_impl.abase then [],"Array" else if c == ctx.base_class then [],"Class" else c.cl_path in
+			let path = if c == ctx.array_impl.abase then [],"Array" else if c == ctx.base_class then [],"Class" else c.cl_path in
 
 
-				let g, ct = class_global ~resolve:false ctx c in
-				let ctype = if c == ctx.array_impl.abase then ctx.array_impl.aall else c in
-				let t = class_type ctx ctype (extract_param_types ctype.cl_params) false in
+			let g, ct = class_global ~resolve:false ctx c in
+			let ctype = if c == ctx.array_impl.abase then ctx.array_impl.aall else c in
+			let t = class_type ctx ctype (extract_param_types ctype.cl_params) false in
 
 
-				let index name =
-					match ct with
-					| HObj o ->
-						fst (try get_index name o with Not_found -> die "" __LOC__)
-					| _ ->
-						die "" __LOC__
-				in
+			let index name =
+				match ct with
+				| HObj o ->
+					fst (try get_index name o with Not_found -> die "" __LOC__)
+				| _ ->
+					die "" __LOC__
+			in
 
 
-				let rc = (match t with
-				| HObj o when (match o.pclassglobal with None -> -1 | Some i -> i) <> g ->
-					(* manual registration for objects with prototype tricks (Array) *)
+			let rc = (match t with
+			| HObj o when (match o.pclassglobal with None -> -1 | Some i -> i) <> g ->
+				(* manual registration for objects with prototype tricks (Array) *)
 
 
-					let rc = alloc_tmp ctx ct in
-					op ctx (ONew rc);
-					op ctx (OSetGlobal (g,rc));
-					hold ctx rc;
+				let rc = alloc_tmp ctx ct in
+				op ctx (ONew rc);
+				op ctx (OSetGlobal (g,rc));
+				hold ctx rc;
 
 
-					let rt = alloc_tmp ctx HType in
-					op ctx (OType (rt, t));
-					op ctx (OSetField (rc,index "__type__",rt));
-					op ctx (OSetField (rc,index "__name__",eval_expr ctx { eexpr = TConst (TString (s_type_path path)); epos = c.cl_pos; etype = ctx.com.basic.tstring }));
+				let rt = alloc_tmp ctx HType in
+				op ctx (OType (rt, t));
+				op ctx (OSetField (rc,index "__type__",rt));
+				op ctx (OSetField (rc,index "__name__",eval_expr ctx { eexpr = TConst (TString (s_type_path path)); epos = c.cl_pos; etype = ctx.com.basic.tstring }));
 
 
-					let rname = alloc_tmp ctx HBytes in
-					op ctx (OString (rname, alloc_string ctx (s_type_path path)));
-					op ctx (OCall2 (alloc_tmp ctx HVoid, alloc_fun_path ctx ([],"Type") "register",rname,rc));
-					rc
+				let rname = alloc_tmp ctx HBytes in
+				op ctx (OString (rname, alloc_string ctx (s_type_path path)));
+				op ctx (OCall2 (alloc_tmp ctx HVoid, alloc_fun_path ctx ([],"Type") "register",rname,rc));
+				rc
 
 
-				| _ ->
+			| _ ->
 
 
-					let rct = alloc_tmp ctx HType in
-					op ctx (OType (rct, ct));
-					hold ctx rct;
+				let rct = alloc_tmp ctx HType in
+				op ctx (OType (rct, ct));
+				hold ctx rct;
 
 
-					let rt = alloc_tmp ctx HType in
-					op ctx (OType (rt, t));
+				let rt = alloc_tmp ctx HType in
+				op ctx (OType (rt, t));
 
 
-					let rname = alloc_tmp ctx HBytes in
-					op ctx (OString (rname, alloc_string ctx (s_type_path path)));
+				let rname = alloc_tmp ctx HBytes in
+				op ctx (OString (rname, alloc_string ctx (s_type_path path)));
 
 
-					let rc = alloc_tmp ctx (class_type ctx ctx.base_class [] false) in
-					op ctx (OCall3 (rc, alloc_fun_path ctx ([],"Type") "initClass", rct, rt, rname));
-					hold ctx rc;
-					free ctx rct;
-					rc
-				) in
+				let rc = alloc_tmp ctx (class_type ctx ctx.base_class [] false) in
+				op ctx (OCall3 (rc, alloc_fun_path ctx ([],"Type") (if is_excluded c then "loadClass" else "initClass"), rct, rt, rname));
+				hold ctx rc;
+				free ctx rct;
+				rc
+			) in
 
 
-				let gather_implements() =
-					let classes = ref [] in
-					let rec lookup cv =
-						List.exists (fun (i,_) -> i == c || lookup i) cv.cl_implements
-					in
-					let check = function
-						| TClassDecl c when (has_class_flag c CInterface) = false && not (has_class_flag c CExtern) -> if lookup c then classes := c :: !classes
-						| _ -> ()
-					in
-					List.iter check ctx.com.types;
-					!classes
+			let gather_implements() =
+				let classes = ref [] in
+				let rec lookup cv =
+					List.exists (fun (i,_) -> i == c || lookup i) cv.cl_implements
 				in
 				in
-				if (has_class_flag c CInterface) then begin
-					let l = gather_implements() in
-					let rt = alloc_tmp ctx HType in
-					op ctx (OType (rt, HType));
-					let ra = alloc_array ctx (reg_int ctx (List.length l)) HType in
-					list_iteri (fun i intf ->
-						op ctx (OType (rt, to_type ctx (TInst (intf,[]))));
-						op ctx (OSetArray (ra, reg_int ctx i, rt));
-					) l;
-					op ctx (OSetField (rc,index "__implementedBy__",ra));
-
-					(* TODO : use a plain class for interface object since we don't allow statics *)
-					let rt = alloc_tmp ctx ct in
-					op ctx (OSafeCast (rt, rc));
-					op ctx (OSetGlobal (g, rt));
-				end;
+				let check = function
+					| TClassDecl c when (has_class_flag c CInterface) = false && not (has_class_flag c CExtern) -> if lookup c then classes := c :: !classes
+					| _ -> ()
+				in
+				List.iter check ctx.com.types;
+				!classes
+			in
+			if (has_class_flag c CInterface) then begin
+				let l = gather_implements() in
+				let rt = alloc_tmp ctx HType in
+				op ctx (OType (rt, HType));
+				let ra = alloc_array ctx (reg_int ctx (List.length l)) HType in
+				list_iteri (fun i intf ->
+					op ctx (OType (rt, to_type ctx (TInst (intf,[]))));
+					op ctx (OSetArray (ra, reg_int ctx i, rt));
+				) l;
+				op ctx (OSetField (rc,index "__implementedBy__",ra));
+
+				(* TODO : use a plain class for interface object since we don't allow statics *)
+				let rt = alloc_tmp ctx ct in
+				op ctx (OSafeCast (rt, rc));
+				op ctx (OSetGlobal (g, rt));
+			end;
 
 
-				(match Texpr.build_metadata ctx.com.basic (TClassDecl c) with
-				| None -> ()
-				| Some e ->
-					let r = eval_to ctx e HDyn in
-					op ctx (OSetField (rc,index "__meta__",r)));
+			(match Texpr.build_metadata ctx.com.basic (TClassDecl c) with
+			| None -> ()
+			| Some e ->
+				let r = eval_to ctx e HDyn in
+				op ctx (OSetField (rc,index "__meta__",r)));
+
+			free ctx rc;
+
+		| TEnumDecl e when not (has_enum_flag e EnExtern) ->
+
+			let et = enum_class ctx e in
+			let t = enum_type ctx e in
+
+			let ret = alloc_tmp ctx HType in
+			op ctx (OType (ret, et));
+			hold ctx ret;
+			let rt = alloc_tmp ctx HType in
+			op ctx (OType (rt, t));
+			let r = alloc_tmp ctx (class_type ctx ctx.base_enum [] false) in
+			let etr = alloc_tmp ctx et in
+			op ctx (OCall2 (r, alloc_fun_path ctx ([],"Type") "initEnum", ret, rt));
+			free ctx ret;
+			op ctx (OSafeCast (etr, r));
+
+			let index name =
+				match et with
+				| HObj o ->
+					fst (try get_index name o with Not_found -> die "" __LOC__)
+				| _ ->
+					die "" __LOC__
+			in
 
 
-				free ctx rc;
+			let avalues = alloc_tmp ctx (HArray t) in
+			op ctx (OField (avalues, r, index "__evalues__"));
 
 
-			| TEnumDecl e when not (has_enum_flag e EnExtern) ->
+			List.iter (fun n ->
+				let f = PMap.find n e.e_constrs in
+				match follow f.ef_type with
+				| TFun _ -> ()
+				| _ ->
+					let g = alloc_global ctx (efield_name e f) t in
+					let r = alloc_tmp ctx t in
+					let rd = alloc_tmp ctx HDyn in
+					op ctx (OGetArray (rd,avalues, reg_int ctx f.ef_index));
+					op ctx (OSafeCast (r, rd));
+					op ctx (OSetGlobal (g,r));
+					op ctx (OSetField (etr, index f.ef_name ,r));
+			) e.e_names;
 
 
-				let et = enum_class ctx e in
-				let t = enum_type ctx e in
+			(match Texpr.build_metadata ctx.com.basic (TEnumDecl e) with
+			| None -> ()
+			| Some e -> op ctx (OSetField (r,index "__meta__",eval_to ctx e HDyn)));
 
 
-				let ret = alloc_tmp ctx HType in
-				op ctx (OType (ret, et));
-				hold ctx ret;
-				let rt = alloc_tmp ctx HType in
-				op ctx (OType (rt, t));
-				let r = alloc_tmp ctx (class_type ctx ctx.base_enum [] false) in
-				let etr = alloc_tmp ctx et in
-				op ctx (OCall2 (r, alloc_fun_path ctx ([],"Type") "initEnum", ret, rt));
-				free ctx ret;
-				op ctx (OSafeCast (etr, r));
+
+		| TAbstractDecl { a_path = [], name; a_pos = pos } ->
+			(match name with
+			| "Int" | "Float" | "Dynamic" | "Bool" ->
+				let is_bool = name = "Bool" in
+				let t = class_type ctx (if is_bool then ctx.core_enum else ctx.core_type) [] false in
 
 
 				let index name =
 				let index name =
-					match et with
+					match t with
 					| HObj o ->
 					| HObj o ->
 						fst (try get_index name o with Not_found -> die "" __LOC__)
 						fst (try get_index name o with Not_found -> die "" __LOC__)
 					| _ ->
 					| _ ->
 						die "" __LOC__
 						die "" __LOC__
 				in
 				in
 
 
-				let avalues = alloc_tmp ctx (HArray t) in
-				op ctx (OField (avalues, r, index "__evalues__"));
+				let g = alloc_global ctx ("$" ^ name) t in
+				let r = alloc_tmp ctx t in
+				let rt = alloc_tmp ctx HType in
+				op ctx (ONew r);
+				op ctx (OType (rt,(match name with "Int" -> HI32 | "Float" -> HF64 | "Dynamic" -> HDyn | "Bool" -> HBool | _ -> die "" __LOC__)));
+				op ctx (OSetField (r,index "__type__",rt));
+				op ctx (OSetField (r,index (if is_bool then "__ename__" else "__name__"),make_string ctx name pos));
+				op ctx (OSetGlobal (g,r));
 
 
-				List.iter (fun n ->
-					let f = PMap.find n e.e_constrs in
-					match follow f.ef_type with
-					| TFun _ -> ()
-					| _ ->
-						let g = alloc_global ctx (efield_name e f) t in
-						let r = alloc_tmp ctx t in
-						let rd = alloc_tmp ctx HDyn in
-						op ctx (OGetArray (rd,avalues, reg_int ctx f.ef_index));
-						op ctx (OSafeCast (r, rd));
-						op ctx (OSetGlobal (g,r));
-						op ctx (OSetField (etr, index f.ef_name ,r));
-				) e.e_names;
-
-				(match Texpr.build_metadata ctx.com.basic (TEnumDecl e) with
-				| None -> ()
-				| Some e -> op ctx (OSetField (r,index "__meta__",eval_to ctx e HDyn)));
-
-
-			| TAbstractDecl { a_path = [], name; a_pos = pos } ->
-				(match name with
-				| "Int" | "Float" | "Dynamic" | "Bool" ->
-					let is_bool = name = "Bool" in
-					let t = class_type ctx (if is_bool then ctx.core_enum else ctx.core_type) [] false in
-
-					let index name =
-						match t with
-						| HObj o ->
-							fst (try get_index name o with Not_found -> die "" __LOC__)
-						| _ ->
-							die "" __LOC__
-					in
+				let bytes = alloc_tmp ctx HBytes in
+				op ctx (OString (bytes, alloc_string ctx name));
+				op ctx (OCall2 (alloc_tmp ctx HVoid, alloc_fun_path ctx ([],"Type") "register",bytes,r));
+			| _ ->
+				())
+		| _ ->
+			()
 
 
-					let g = alloc_global ctx ("$" ^ name) t in
-					let r = alloc_tmp ctx t in
-					let rt = alloc_tmp ctx HType in
-					op ctx (ONew r);
-					op ctx (OType (rt,(match name with "Int" -> HI32 | "Float" -> HF64 | "Dynamic" -> HDyn | "Bool" -> HBool | _ -> die "" __LOC__)));
-					op ctx (OSetField (r,index "__type__",rt));
-					op ctx (OSetField (r,index (if is_bool then "__ename__" else "__name__"),make_string ctx name pos));
-					op ctx (OSetGlobal (g,r));
+	) types;
 
 
-					let bytes = alloc_tmp ctx HBytes in
-					op ctx (OString (bytes, alloc_string ctx name));
-					op ctx (OCall2 (alloc_tmp ctx HVoid, alloc_fun_path ctx ([],"Type") "register",bytes,r));
-				| _ ->
-					())
-			| _ ->
-				()
+	let j = jump ctx (fun d -> OJTrue (is_init,d)) in
+	op ctx (ORet (alloc_tmp ctx HVoid));
+	j();
+	free ctx is_init;
+	ignore(eval_expr ctx f.tf_expr);
+	op ctx (ORet (alloc_tmp ctx HVoid))
 
 
-		) types;
+let generate_static_init ctx types main =
+	let exprs = ref [] in
+	let t_void = ctx.com.basic.tvoid in
 
 
-		let j = jump ctx (fun d -> OJTrue (is_init,d)) in
-		op ctx (ORet (alloc_tmp ctx HVoid));
-		j();
-		free ctx is_init;
-	in
 	(* init class statics *)
 	(* init class statics *)
 	let init_exprs = ref [] in
 	let init_exprs = ref [] in
 	List.iter (fun t ->
 	List.iter (fun t ->
-		(match t with TClassDecl { cl_init = Some {cf_expr = Some e} } -> init_exprs := e :: !init_exprs | _ -> ());
+		(match t with TClassDecl ({ cl_init = Some {cf_expr = Some e} } as c) when not (is_excluded c) -> init_exprs := e :: !init_exprs | _ -> ());
 		match t with
 		match t with
-		| TClassDecl c when not (has_class_flag c CExtern) ->
+		| TClassDecl c when not (has_class_flag c CExtern) && not (is_excluded c) ->
 			List.iter (fun f ->
 			List.iter (fun f ->
 				match f.cf_kind, f.cf_expr with
 				match f.cf_kind, f.cf_expr with
 				| Var _, Some e ->
 				| Var _, Some e ->
@@ -3836,7 +3844,9 @@ let generate_static_init ctx types main =
 	let fid = lookup_alloc ctx.cfids () in
 	let fid = lookup_alloc ctx.cfids () in
 	let exprs = List.rev !init_exprs @ List.rev !exprs in
 	let exprs = List.rev !init_exprs @ List.rev !exprs in
 	let initpos = fake_pos "fun$init" in
 	let initpos = fake_pos "fun$init" in
-	ignore(make_fun ~gen_content ctx ("","") fid { tf_expr = mk (TBlock exprs) t_void initpos; tf_args = []; tf_type = t_void } None None);
+	let f = { tf_expr = mk (TBlock exprs) t_void initpos; tf_args = []; tf_type = t_void } in
+	let gen_content() = generate_static_content ctx types f in
+	ignore(make_fun ~gen_content ctx ("","") fid f None None);
 	fid
 	fid
 
 
 (* --------------------------------------------------------------------------------------------------------------------- *)
 (* --------------------------------------------------------------------------------------------------------------------- *)

+ 4 - 2
std/hl/Api.hx

@@ -59,7 +59,9 @@ extern class Api {
 	}
 	}
 	#end
 	#end
 	#if (hl_ver >= version("1.16.0"))
 	#if (hl_ver >= version("1.16.0"))
-	@:hlNative('std', 'sys_timestamp_ms')
-	static function timestampMs():haxe.Int64;
+	@:hlNative("?std", "sys_timestamp_ms") static function timestampMs():haxe.Int64;
+	@:hlNative("?std", "sys_resolve_type") static function resolveTypeDyn( t : hl.Type, gt : hl.Type ) : Dynamic;
+	@:hlNative("?std", "sys_load_plugin") private static function _loadPlugin( file : hl.Bytes ) : Bool;
+	static inline function loadPlugin( file : String ) : Bool { return _loadPlugin(@:privateAccess file.bytes); }
 	#end
 	#end
 }
 }

+ 18 - 1
std/hl/_std/Type.hx

@@ -45,7 +45,7 @@ class Type {
 		return true;
 		return true;
 	}
 	}
 
 
-	@:keep static function initClass(ct:hl.Type, t:hl.Type, name:hl.Bytes):hl.BaseType.Class@:privateAccess {
+	@:keep static function initClass(ct:hl.Type, t:hl.Type, name:hl.Bytes):hl.BaseType.Class @:privateAccess {
 		var c:hl.BaseType.Class = cast t.getGlobal();
 		var c:hl.BaseType.Class = cast t.getGlobal();
 		if( c != null )
 		if( c != null )
 			return c;
 			return c;
@@ -57,6 +57,23 @@ class Type {
 		return c;
 		return c;
 	}
 	}
 
 
+	@:keep static function loadClass(ct:hl.Type, t:hl.Type, name:hl.Bytes):hl.BaseType.Class @:privateAccess {
+		#if (hl_ver < version("1.16.0"))
+		throw "Resolving classes dynamicaly requires -D hl-ver=1.16.0";
+		#else
+		var c:hl.BaseType.Class = cast t.getGlobal();
+		if( c != null )
+			return c;
+		c = hl.Api.resolveTypeDyn(t,ct);
+		if( c == null )
+			throw "Imported type '"+name+"' could not be resolved";
+		t.setGlobal(c);
+		register(name, c);
+		return c;
+		#end
+	}
+
+
 	@:keep static function initEnum(et:hl.Type, t:hl.Type):hl.BaseType.Enum@:privateAccess {
 	@:keep static function initEnum(et:hl.Type, t:hl.Type):hl.BaseType.Enum@:privateAccess {
 		var e:hl.BaseType.Enum = cast t.getGlobal();
 		var e:hl.BaseType.Enum = cast t.getGlobal();
 		if( e != null )
 		if( e != null )