浏览代码

added -D key=value and #if (key >= value) operations (fixed issue #1241)

Nicolas Cannasse 13 年之前
父节点
当前提交
a79ea4a968
共有 7 个文件被更改,包括 80 次插入19 次删除
  1. 11 7
      common.ml
  2. 1 0
      doc/CHANGES.txt
  3. 5 0
      interp.ml
  4. 50 6
      parser.ml
  5. 7 0
      std/haxe/macro/Context.hx
  6. 2 2
      typeload.ml
  7. 4 4
      typer.ml

+ 11 - 7
common.ml

@@ -101,7 +101,7 @@ type context = {
 	mutable std_path : string list;
 	mutable std_path : string list;
 	mutable class_path : string list;
 	mutable class_path : string list;
 	mutable main_class : Type.path option;
 	mutable main_class : Type.path option;
-	mutable defines : (string,unit) PMap.t;
+	mutable defines : (string,string) PMap.t;
 	mutable package_rules : (string,package_rule) PMap.t;
 	mutable package_rules : (string,package_rule) PMap.t;
 	mutable error : string -> pos -> unit;
 	mutable error : string -> pos -> unit;
 	mutable warning : string -> pos -> unit;
 	mutable warning : string -> pos -> unit;
@@ -388,7 +388,7 @@ let create v args =
 		std_path = [];
 		std_path = [];
 		class_path = [];
 		class_path = [];
 		main_class = None;
 		main_class = None;
-		defines = PMap.add "true" () (if !display_default then PMap.add "display" () PMap.empty else PMap.empty);
+		defines = PMap.add "true" "1" (if !display_default then PMap.add "display" "1" PMap.empty else PMap.empty);
 		package_rules = PMap.empty;
 		package_rules = PMap.empty;
 		file = "";
 		file = "";
 		types = [];
 		types = [];
@@ -434,11 +434,11 @@ let get_signature com =
 	match com.defines_signature with
 	match com.defines_signature with
 	| Some s -> s
 	| Some s -> s
 	| None ->
 	| None ->
-		let str = String.concat "@" (PMap.foldi (fun k _ acc ->
+		let str = String.concat "@" (PMap.foldi (fun k v acc ->
 			(* don't make much difference between these special compilation flags *)
 			(* don't make much difference between these special compilation flags *)
 			match k with
 			match k with
 			| "display" | "use_rtti_doc" | "macrotimes" -> acc
 			| "display" | "use_rtti_doc" | "macrotimes" -> acc
-			| _ -> k :: acc
+			| _ -> k :: v :: acc
 		) com.defines []) in
 		) com.defines []) in
 		let s = Digest.string str in
 		let s = Digest.string str in
 		com.defines_signature <- Some s;
 		com.defines_signature <- Some s;
@@ -483,10 +483,14 @@ let raw_defined ctx v =
 let defined ctx v =
 let defined ctx v =
 	raw_defined ctx (fst (Define.infos v))
 	raw_defined ctx (fst (Define.infos v))
 
 
+let defined_value ctx k =
+	PMap.find k ctx.defines
+
 let raw_define ctx v =
 let raw_define ctx v =
-	ctx.defines <- PMap.add v () ctx.defines;
-	let v = String.concat "_" (ExtString.String.nsplit v "-") in
-	ctx.defines <- PMap.add v () ctx.defines;
+	let k,v = try ExtString.String.split v "=" with _ -> v,"1" in
+	ctx.defines <- PMap.add k v ctx.defines;
+	let k = String.concat "_" (ExtString.String.nsplit k "-") in
+	ctx.defines <- PMap.add k v ctx.defines;
 	ctx.defines_signature <- None
 	ctx.defines_signature <- None
 
 
 let define ctx v =
 let define ctx v =

+ 1 - 0
doc/CHANGES.txt

@@ -20,6 +20,7 @@
 	all : DCE always run on standard library files
 	all : DCE always run on standard library files
 	all : Haxe3 packages changes (see http://haxe.org/manual/haxe3)
 	all : Haxe3 packages changes (see http://haxe.org/manual/haxe3)
 	all : Removed haxe.Int32, haxe.Firebug, haxe.TimerQueue
 	all : Removed haxe.Int32, haxe.Firebug, haxe.TimerQueue
+	all : added -D key=value and #if (key >= value) operations
 	
 	
 2012-07-16: 2.10
 2012-07-16: 2.10
 	java/cs : added two new targets (beta)
 	java/cs : added two new targets (beta)

+ 5 - 0
interp.ml

@@ -2056,6 +2056,11 @@ let macro_lib =
 			| VString s -> VBool (Common.raw_defined (ccom()) s)
 			| VString s -> VBool (Common.raw_defined (ccom()) s)
 			| _ -> error();
 			| _ -> error();
 		);
 		);
+		"defined_value", Fun1 (fun s ->
+			match s with
+			| VString s -> (try VString (Common.defined_value (ccom()) s) with Not_found -> VNull)
+			| _ -> error();
+		);
 		"get_type", Fun1 (fun s ->
 		"get_type", Fun1 (fun s ->
 			match s with
 			match s with
 			| VString s ->
 			| VString s ->

+ 50 - 6
parser.ml

@@ -878,6 +878,12 @@ and parse_macro_cond allow_op s =
 	match s with parser
 	match s with parser
 	| [< '(Const (Ident t),p) >] ->
 	| [< '(Const (Ident t),p) >] ->
 		parse_macro_ident allow_op t p s
 		parse_macro_ident allow_op t p s
+	| [< '(Const (String s),p) >] ->
+		None, (EConst (String s),p)
+	| [< '(Const (Int i),p) >] ->
+		None, (EConst (Int i),p)
+	| [< '(Const (Float f),p) >] ->
+		None, (EConst (Float f),p)
 	| [< '(Kwd k,p) >] ->
 	| [< '(Kwd k,p) >] ->
 		parse_macro_ident allow_op (s_keyword k) p s
 		parse_macro_ident allow_op (s_keyword k) p s
 	| [< '(POpen, p1); _,e = parse_macro_cond true; '(PClose, p2) >] ->
 	| [< '(POpen, p1); _,e = parse_macro_cond true; '(PClose, p2) >] ->
@@ -913,6 +919,12 @@ and secure_expr s =
 	| [< e = expr >] -> e
 	| [< e = expr >] -> e
 	| [< >] -> serror()
 	| [< >] -> serror()
 
 
+type small_type =
+	| TNull
+	| TBool of bool
+	| TFloat of float
+	| TString of string
+	
 let parse ctx code =
 let parse ctx code =
 	let old = Lexer.save() in
 	let old = Lexer.save() in
 	let old_cache = !cache in
 	let old_cache = !cache in
@@ -963,18 +975,50 @@ let parse ctx code =
 			tk
 			tk
 
 
 	and enter_macro p =
 	and enter_macro p =
+		let is_true = function
+			| TBool false | TNull | TFloat 0. | TString "" -> false
+			| _ -> true
+		in
+		let cmp v1 v2 =
+			match v1, v2 with
+			| TNull, TNull -> 0
+			| TFloat a, TFloat b -> compare a b
+			| TString a, TString b -> compare a b
+			| TBool a, TBool b -> compare a b
+			| TString a, TFloat b -> compare (float_of_string a) b
+			| TFloat a, TString b -> compare a (float_of_string b)
+			| _ -> raise Exit (* always false *)
+		in
 		let rec loop (e,p) =
 		let rec loop (e,p) =
 			match e with
 			match e with
-			| EConst (Ident i) -> Common.raw_defined ctx i
-			| EBinop (OpBoolAnd, e1, e2) -> loop e1 && loop e2
-			| EBinop (OpBoolOr, e1, e2) -> loop e1 || loop e2
-			| EUnop (Not, _, e) -> not (loop e)
+			| EConst (Ident i) -> (try TString (Common.defined_value ctx i) with Not_found -> TNull)
+			| EConst (String s) -> TString s
+			| EConst (Int i) -> TFloat (float_of_string i)
+			| EConst (Float f) -> TFloat (float_of_string f)
+			| EBinop (OpBoolAnd, e1, e2) -> TBool (is_true (loop e1) && is_true (loop e2))
+			| EBinop (OpBoolOr, e1, e2) -> TBool (is_true (loop e1) || is_true(loop e2))
+			| EUnop (Not, _, e) -> TBool (not (is_true (loop e)))
 			| EParenthesis e -> loop e
 			| EParenthesis e -> loop e
-			| _ -> error Unclosed_macro p
+			| EBinop (op, e1, e2) ->
+				let v1 = loop e1 in
+				let v2 = loop e2 in
+				let compare op =
+					TBool (try op (cmp v1 v2) 0 with _ -> false)
+				in
+				(match op with
+				| OpEq -> compare (=)
+				| OpNotEq -> compare (<>)
+				| OpGt -> compare (>)
+				| OpGte -> compare (>=)
+				| OpLt -> compare (<)
+				| OpLte -> compare (<=)
+				| _ -> error (Custom "Insupported operation") p)
+			| _ ->
+				error Unclosed_macro p
 		in
 		in
 		let tk, e = parse_macro_cond false sraw in
 		let tk, e = parse_macro_cond false sraw in
 		let tk = (match tk with None -> Lexer.token code | Some tk -> tk) in
 		let tk = (match tk with None -> Lexer.token code | Some tk -> tk) in
-		if loop e then begin
+		if is_true (loop e) then begin
 			mstack := p :: !mstack;
 			mstack := p :: !mstack;
 			tk
 			tk
 		end else
 		end else

+ 7 - 0
std/haxe/macro/Context.hx

@@ -121,6 +121,13 @@ class Context {
 	public static function defined( s : String ) : Bool {
 	public static function defined( s : String ) : Bool {
 		return load("defined", 1)(untyped s.__s);
 		return load("defined", 1)(untyped s.__s);
 	}
 	}
+	
+	/**
+		Returns the value defined through -D key=value
+	**/
+	public static function definedValue( key : String ) : String {
+		return load("defined_value", 1)(untyped key.__s);
+	}	
 
 
 	/**
 	/**
 		Resolve a type from its name.
 		Resolve a type from its name.

+ 2 - 2
typeload.ml

@@ -298,7 +298,7 @@ let rec load_instance ctx t p allow_no_params =
 				| TInst (c,[]) ->
 				| TInst (c,[]) ->
 					(* mark a generic class as recursively used if it is used with an "unresolved" non-generic type parameter *)
 					(* mark a generic class as recursively used if it is used with an "unresolved" non-generic type parameter *)
 					(match get_generic_parameter_kind ctx c,cg with
 					(match get_generic_parameter_kind ctx c,cg with
-					| (GPField _ | GPNone), Some c -> 
+					| (GPField _ | GPNone), Some c ->
 						if not (has_meta ":?genericRec" c.cl_meta) then c.cl_meta <- (":?genericRec",[],p) :: c.cl_meta
 						if not (has_meta ":?genericRec" c.cl_meta) then c.cl_meta <- (":?genericRec",[],p) :: c.cl_meta
 					| _ ->
 					| _ ->
 						());
 						());
@@ -1365,7 +1365,7 @@ let init_class ctx c p context_init herits fields =
 					if not (Common.raw_defined ctx.com i) then
 					if not (Common.raw_defined ctx.com i) then
 						Some (i,(match List.rev l with (EConst (String msg),_) :: _ -> Some msg | _ -> None))
 						Some (i,(match List.rev l with (EConst (String msg),_) :: _ -> Some msg | _ -> None))
 					else
 					else
-						loop l				
+						loop l
 				| _ -> error "Invalid require identifier" p
 				| _ -> error "Invalid require identifier" p
 			in
 			in
 			loop conds
 			loop conds

+ 4 - 4
typer.ml

@@ -162,7 +162,7 @@ let rec can_access ctx c cf stat =
 	in
 	in
 	let has m c f path =
 	let has m c f path =
 		let rec loop = function
 		let rec loop = function
-			| (m2,[e],_) :: l when m = m2 -> 
+			| (m2,[e],_) :: l when m = m2 ->
 				let p = expr_path [] e in
 				let p = expr_path [] e in
 				(p <> [] && chk_path p path) || loop l
 				(p <> [] && chk_path p path) || loop l
 			| _ :: l -> loop l
 			| _ :: l -> loop l
@@ -1420,7 +1420,7 @@ and type_switch ctx e cases def need_val with_type p =
 				| EConst (Ident "_") -> None
 				| EConst (Ident "_") -> None
 				| EConst (Ident i) -> Some i
 				| EConst (Ident i) -> Some i
 				| _ -> raise Exit
 				| _ -> raise Exit
-			) pl in			
+			) pl in
 			(match e.eexpr with
 			(match e.eexpr with
 			| TEnumField (en,s) | TClosure ({ eexpr = TTypeExpr (TEnumDecl en) },s) -> type_match e en s pl
 			| TEnumField (en,s) | TClosure ({ eexpr = TTypeExpr (TEnumDecl en) },s) -> type_match e en s pl
 			| _ -> if pl = [] then case_expr e else raise Exit)
 			| _ -> if pl = [] then case_expr e else raise Exit)
@@ -2297,7 +2297,7 @@ and type_expr ctx ?(need_val=true) (e,p) =
 			| TAnon a ->
 			| TAnon a ->
 				(match !(a.a_status) with
 				(match !(a.a_status) with
 				| Statics c ->
 				| Statics c ->
-					PMap.fold (fun f acc -> if can_access ctx c f true then PMap.add f.cf_name { f with cf_public = true; cf_type = opt_type f.cf_type } acc else acc) a.a_fields PMap.empty 
+					PMap.fold (fun f acc -> if can_access ctx c f true then PMap.add f.cf_name { f with cf_public = true; cf_type = opt_type f.cf_type } acc else acc) a.a_fields PMap.empty
 				| _ ->
 				| _ ->
 					a.a_fields)
 					a.a_fields)
 			| _ ->
 			| _ ->
@@ -2995,7 +2995,7 @@ let get_macro_context ctx p =
 		com2.class_path <- List.map (fun p -> p ^ "neko" ^ "/_std/") com2.std_path @ com2.class_path;
 		com2.class_path <- List.map (fun p -> p ^ "neko" ^ "/_std/") com2.std_path @ com2.class_path;
 		let to_remove = List.map (fun d -> fst (Define.infos d)) [Define.NoTraces] in
 		let to_remove = List.map (fun d -> fst (Define.infos d)) [Define.NoTraces] in
 		let to_remove = to_remove @ List.map (fun (_,d) -> "flash" ^ d) Common.flash_versions in
 		let to_remove = to_remove @ List.map (fun (_,d) -> "flash" ^ d) Common.flash_versions in
-		com2.defines <- PMap.foldi (fun k _ acc -> if List.mem k to_remove then acc else PMap.add k () acc) com2.defines PMap.empty;
+		com2.defines <- PMap.foldi (fun k v acc -> if List.mem k to_remove then acc else PMap.add k v acc) com2.defines PMap.empty;
 		Common.define com2 Define.Macro;
 		Common.define com2 Define.Macro;
 		Common.init_platform com2 Neko;
 		Common.init_platform com2 Neko;
 		let ctx2 = ctx.g.do_create com2 in
 		let ctx2 = ctx.g.do_create com2 in