Browse Source

reverse index features while typing, check during DCE

Simon Krajewski 12 years ago
parent
commit
71f2acd4ff
4 changed files with 33 additions and 18 deletions
  1. 3 1
      common.ml
  2. 18 16
      dce.ml
  3. 1 1
      std/js/Boot.hx
  4. 11 0
      typeload.ml

+ 3 - 1
common.ml

@@ -127,6 +127,7 @@ type context = {
 	mutable file : string;
 	mutable file : string;
 	mutable flash_version : float;
 	mutable flash_version : float;
 	mutable features : (string,bool) Hashtbl.t;
 	mutable features : (string,bool) Hashtbl.t;
+	mutable reverse_features : (string,(tclass * tclass_field * bool) list) Hashtbl.t;
 	mutable modules : Type.module_def list;
 	mutable modules : Type.module_def list;
 	mutable main : Type.texpr option;
 	mutable main : Type.texpr option;
 	mutable types : Type.module_type list;
 	mutable types : Type.module_type list;
@@ -609,6 +610,7 @@ let create v args =
 		verbose = false;
 		verbose = false;
 		foptimize = true;
 		foptimize = true;
 		features = Hashtbl.create 0;
 		features = Hashtbl.create 0;
+		reverse_features = Hashtbl.create 0;
 		platform = Cross;
 		platform = Cross;
 		config = default_config;
 		config = default_config;
 		print = (fun s -> print_string s; flush stdout);
 		print = (fun s -> print_string s; flush stdout);
@@ -653,7 +655,7 @@ let log com str =
 
 
 let clone com =
 let clone com =
 	let t = com.basic in
 	let t = com.basic in
-	{ com with basic = { t with tvoid = t.tvoid }; main_class = None; features = Hashtbl.create 0; }
+	{ com with basic = { t with tvoid = t.tvoid }; main_class = None; features = Hashtbl.create 0; reverse_features = Hashtbl.create 0; }
 
 
 let file_time file =
 let file_time file =
 	try (Unix.stat file).Unix.st_mtime with _ -> 0.
 	try (Unix.stat file).Unix.st_mtime with _ -> 0.

+ 18 - 16
dce.ml

@@ -35,6 +35,7 @@ type dce = {
 	mutable marked_maybe_fields : tclass_field list;
 	mutable marked_maybe_fields : tclass_field list;
 	mutable t_stack : t list;
 	mutable t_stack : t list;
 	mutable ts_stack : t list;
 	mutable ts_stack : t list;
+	mutable checked_features : (string,bool) Hashtbl.t;
 }
 }
 
 
 (* checking *)
 (* checking *)
@@ -61,28 +62,28 @@ let keep_whole_class dce c =
 		| { cl_path = [],"Array" } -> not (dce.com.platform = Js)
 		| { cl_path = [],"Array" } -> not (dce.com.platform = Js)
 		| _ -> false)
 		| _ -> false)
 
 
-(* check if a metadata contains @:ifFeature with a used feature argument *)
-let has_used_feature com meta =
-	try
-		let _,el,_ = Meta.get Meta.IfFeature meta in
-		List.exists (fun e -> match fst e with
-			| EConst(String s) when Common.has_feature com s -> true
-			| _ -> false
-		) el
-	with Not_found ->
-		false
-
 (* check if a field is kept *)
 (* check if a field is kept *)
 let keep_field dce cf =
 let keep_field dce cf =
 	Meta.has Meta.Keep cf.cf_meta
 	Meta.has Meta.Keep cf.cf_meta
 	|| Meta.has Meta.Used cf.cf_meta
 	|| Meta.has Meta.Used cf.cf_meta
 	|| cf.cf_name = "__init__"
 	|| cf.cf_name = "__init__"
-	|| has_used_feature dce.com cf.cf_meta
 
 
 (* marking *)
 (* marking *)
 
 
+let rec check_feature dce s =
+	if not (Hashtbl.mem dce.checked_features s) then begin
+		add_feature dce.com s;
+		Hashtbl.add dce.checked_features s true;
+		try
+			List.iter (fun (c,cf,stat) ->
+				mark_field dce c cf stat
+			) (Hashtbl.find dce.com.reverse_features s)
+		with Not_found ->
+			()
+	end
+
 (* mark a field as kept *)
 (* mark a field as kept *)
-let rec mark_field dce c cf stat =
+and mark_field dce c cf stat =
 	let add cf =
 	let add cf =
 		if not (Meta.has Meta.Used cf.cf_meta) then begin
 		if not (Meta.has Meta.Used cf.cf_meta) then begin
 			cf.cf_meta <- (Meta.Used,[],cf.cf_pos) :: cf.cf_meta;
 			cf.cf_meta <- (Meta.Used,[],cf.cf_pos) :: cf.cf_meta;
@@ -298,7 +299,7 @@ and expr dce e =
 			mark_t dce v.v_type;
 			mark_t dce v.v_type;
 		) vl;
 		) vl;
 	| TCast(e, Some mt) ->
 	| TCast(e, Some mt) ->
-		add_feature dce.com "typed_cast";
+		check_feature dce "typed_cast";
 		mark_mt dce mt;
 		mark_mt dce mt;
 		expr dce e;
 		expr dce e;
 	| TTypeExpr mt ->
 	| TTypeExpr mt ->
@@ -306,12 +307,12 @@ and expr dce e =
 	| TTry(e, vl) ->
 	| TTry(e, vl) ->
 		expr dce e;
 		expr dce e;
 		List.iter (fun (v,e) ->
 		List.iter (fun (v,e) ->
-			if v.v_type != t_dynamic then add_feature dce.com "typed_catch";
+			if v.v_type != t_dynamic then check_feature dce "typed_catch";
 			expr dce e;
 			expr dce e;
 			mark_t dce v.v_type;
 			mark_t dce v.v_type;
 		) vl;
 		) vl;
 	| TCall ({eexpr = TLocal ({v_name = "__define_feature__"})},[{eexpr = TConst (TString ft)};e]) ->
 	| TCall ({eexpr = TLocal ({v_name = "__define_feature__"})},[{eexpr = TConst (TString ft)};e]) ->
-		Common.add_feature dce.com ft;
+		check_feature dce ft;
 		expr dce e
 		expr dce e
 	(* keep toString method when the class is argument to Std.string or haxe.Log.trace *)
 	(* keep toString method when the class is argument to Std.string or haxe.Log.trace *)
 	| TCall ({eexpr = TField({eexpr = TTypeExpr (TClassDecl ({cl_path = (["haxe"],"Log")} as c))},FStatic (_,{cf_name="trace"}))} as ef, ([e2;_] as args))
 	| TCall ({eexpr = TField({eexpr = TTypeExpr (TClassDecl ({cl_path = (["haxe"],"Log")} as c))},FStatic (_,{cf_name="trace"}))} as ef, ([e2;_] as args))
@@ -365,6 +366,7 @@ let run com main full =
 		marked_maybe_fields = [];
 		marked_maybe_fields = [];
 		t_stack = [];
 		t_stack = [];
 		ts_stack = [];
 		ts_stack = [];
+		checked_features = Hashtbl.create 0;
 	} in
 	} in
 	begin match main with
 	begin match main with
 		| Some {eexpr = TCall({eexpr = TField(e,(FStatic(c,cf)))},_)} ->
 		| Some {eexpr = TCall({eexpr = TField(e,(FStatic(c,cf)))},_)} ->

+ 1 - 1
std/js/Boot.hx

@@ -159,7 +159,7 @@ class Boot {
 		return __interfLoop(cc.__super__,cl);
 		return __interfLoop(cc.__super__,cl);
 	}
 	}
 
 
-	@:ifFeature("typed_catch", "typed_cast") private static function __instanceof(o : Dynamic,cl : Dynamic) {
+	@:ifFeature("typed_catch") private static function __instanceof(o : Dynamic,cl : Dynamic) {
 		if( cl == null )
 		if( cl == null )
 			return false;
 			return false;
 		switch( cl ) {
 		switch( cl ) {

+ 11 - 0
typeload.ml

@@ -1880,6 +1880,17 @@ let init_class ctx c p context_init herits fields =
 			let fd , constr, f = 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 || 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;
+			begin try
+				let _,args,_ = Meta.get Meta.IfFeature f.cf_meta in
+				List.iter (fun e -> match fst e with
+					| EConst(String s) ->
+						let fl,v = ctx.com.reverse_features,(c,f,is_static) in
+						if Hashtbl.mem fl s then Hashtbl.replace fl s (v :: Hashtbl.find fl s)
+						else Hashtbl.add fl s [v]
+					| _ ->
+						error "String expected" (pos e)
+				) args
+			with Not_found -> () end;
 			let req = check_require fd.cff_meta in
 			let req = check_require fd.cff_meta in
 			let req = (match req with None -> if is_static || constr then cl_req else None | _ -> req) in
 			let req = (match req with None -> if is_static || constr then cl_req else None | _ -> req) in
 			(match req with
 			(match req with