瀏覽代碼

[macro] add Context.getLocalImports (closes #3560)

Simon Krajewski 10 年之前
父節點
當前提交
be3c6298bf
共有 9 個文件被更改,包括 72 次插入4 次删除
  1. 3 1
      ast.ml
  2. 1 0
      extra/CHANGES.txt
  3. 24 3
      interp.ml
  4. 9 0
      std/haxe/macro/Context.hx
  5. 15 0
      tests/unit/src/unit/issues/Issue3560.hx
  6. 11 0
      tests/unit/src/unit/issues/misc/Issue3560Macro.hx
  7. 1 0
      typecore.ml
  8. 3 0
      typeload.ml
  9. 5 0
      typer.ml

+ 3 - 1
ast.ml

@@ -439,12 +439,14 @@ type import_mode =
 	| IAsName of string
 	| IAll
 
+type import = (string * pos) list * import_mode
+
 type type_def =
 	| EClass of (class_flag, class_field list) definition
 	| EEnum of (enum_flag, enum_constructor list) definition
 	| ETypedef of (enum_flag, complex_type) definition
 	| EAbstract of (abstract_flag, class_field list) definition
-	| EImport of (string * pos) list * import_mode
+	| EImport of import
 	| EUsing of type_path
 
 type type_decl = type_def * pos

+ 1 - 0
extra/CHANGES.txt

@@ -33,6 +33,7 @@
 	Macro features and changes:
 
 	macro : added overloads field to ClassField (#3460)
+	macro : added Context.getLocalImports (#3560)
 
 2015-05-12: 3.2.0
 

+ 24 - 3
interp.ml

@@ -116,6 +116,7 @@ type extern_api = {
 	get_expected_type : unit -> t option;
 	get_call_arguments : unit -> Ast.expr list option;
 	get_local_method : unit -> string;
+	get_local_imports : unit -> Ast.import list;
 	get_local_using : unit -> tclass list;
 	get_local_vars : unit -> (string, Type.tvar) PMap.t;
 	get_build_fields : unit -> value;
@@ -212,6 +213,7 @@ let make_complex_type_ref = ref (fun _ -> assert false)
 let encode_tvar_ref = ref (fun _ -> assert false)
 let decode_path_ref = ref (fun _ -> assert false)
 let decode_import_ref = ref (fun _ -> assert false)
+let encode_import_ref = ref (fun _ -> assert false)
 let get_ctx() = (!get_ctx_ref)()
 let enc_array (l:value list) : value = (!enc_array_ref) l
 let dec_array (l:value) : value list = (!dec_array_ref) l
@@ -229,7 +231,8 @@ let enc_string (s:string) : value = (!enc_string_ref) s
 let make_complex_type (t:Type.t) : Ast.complex_type = (!make_complex_type_ref) t
 let encode_tvar (v:tvar) : value = (!encode_tvar_ref) v
 let decode_path (v:value) : Ast.type_path = (!decode_path_ref) v
-let decode_import (v:value) : ((string * Ast.pos) list * Ast.import_mode) = (!decode_import_ref) v
+let encode_import (i:Ast.import) : value = (!encode_import_ref) i
+let decode_import (v:value) : Ast.import = (!decode_import_ref) v
 
 let to_int f = Int32.of_float (mod_float f 2147483648.0)
 let need_32_bits i = Int32.compare (Int32.logand (Int32.add i 0x40000000l) 0x80000000l) Int32.zero <> 0
@@ -277,7 +280,7 @@ let constants =
 	"constructs";"names";"superClass";"interfaces";"fields";"statics";"constructor";"init";"t";
 	"gid";"uid";"atime";"mtime";"ctime";"dev";"ino";"nlink";"rdev";"size";"mode";"pos";"len";
 	"binops";"unops";"from";"to";"array";"op";"isPostfix";"impl";"resolve";
-	"id";"capture";"extra";"v";"ids";"vars";"en";"overrides";"status";"overloads"];
+	"id";"capture";"extra";"v";"ids";"vars";"en";"overrides";"status";"overloads";"path"];
 	h
 
 let h_get = hash "__get" and h_set = hash "__set"
@@ -2521,6 +2524,9 @@ let macro_lib =
 		"local_using", Fun0 (fun() ->
 			enc_array (List.map encode_clref ((get_ctx()).curapi.get_local_using()))
 		);
+		"local_imports", Fun0 (fun() ->
+			enc_array (List.map encode_import ((get_ctx()).curapi.get_local_imports()))
+		);
 		"local_vars", Fun1 (fun as_var ->
 			let as_var = match as_var with
 				| VNull | VBool false -> false
@@ -3663,6 +3669,7 @@ type enum_index =
 	| IModuleType
 	| IFieldAccess
 	| IAnonStatus
+	| IImportMode
 
 let enum_name = function
 	| IExpr -> "ExprDef"
@@ -3683,9 +3690,10 @@ let enum_name = function
 	| IModuleType -> "ModuleType"
 	| IFieldAccess -> "FieldAccess"
 	| IAnonStatus -> "AnonStatus"
+	| IImportMode -> "ImportMode"
 
 let init ctx =
-	let enums = [IExpr;IBinop;IUnop;IConst;ITParam;ICType;IField;IType;IFieldKind;IMethodKind;IVarAccess;IAccess;IClassKind;ITypedExpr;ITConstant;IModuleType;IFieldAccess;IAnonStatus] in
+	let enums = [IExpr;IBinop;IUnop;IConst;ITParam;ICType;IField;IType;IFieldKind;IMethodKind;IVarAccess;IAccess;IClassKind;ITypedExpr;ITConstant;IModuleType;IFieldAccess;IAnonStatus;IImportMode] in
 	let get_enum_proto e =
 		match get_path ctx ["haxe";"macro";enum_name e] null_pos with
 		| VObject e ->
@@ -3810,6 +3818,18 @@ let encode_unop op =
 	in
 	enc_enum IUnop tag []
 
+let encode_import (path,mode) =
+	let tag,pl = match mode with
+		| INormal -> 0, []
+		| IAsName s -> 1, [enc_string s]
+		| IAll -> 2,[]
+	in
+	let mode = enc_enum IImportMode tag pl in
+	enc_obj [
+		"path", enc_array (List.map (fun (name,p) -> enc_obj [ "pos", encode_pos p; "name", enc_string name]) path);
+		"mode", mode
+	]
+
 let rec encode_path t =
 	let fields = [
 		"pack", enc_array (List.map enc_string t.tpackage);
@@ -5097,3 +5117,4 @@ decode_texpr_ref := decode_texpr;
 encode_tvar_ref := encode_tvar;
 decode_path_ref := decode_path;
 decode_import_ref := decode_import;
+encode_import_ref := encode_import;

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

@@ -177,6 +177,15 @@ class Context {
 		return load("local_using", 0)();
 	}
 
+	/**
+		Returns an `Array` of all imports in the context the macro was called.
+
+		Modifying the returned array has no effect on the compiler.
+	**/
+	public static function getLocalImports() :  Array<ImportExpr> {
+		return load("local_imports", 0)();
+	}
+
 	/**
 		Returns a map of local variables accessible in the context the macro was
 		called.

+ 15 - 0
tests/unit/src/unit/issues/Issue3560.hx

@@ -0,0 +1,15 @@
+package unit.issues;
+
+import String;
+import haxe.Template as T;
+import haxe.macro.*;
+
+class Issue3560 extends Test {
+	function test() {
+		var s = unit.issues.misc.Issue3560Macro.getImportString();
+		// the order isn't really defined, but whatever
+		eq("IAll:haxe.macro", s[0]);
+		eq("IAsName(T):haxe.Template", s[1]);
+		eq("INormal:String", s[2]);
+	}
+}

+ 11 - 0
tests/unit/src/unit/issues/misc/Issue3560Macro.hx

@@ -0,0 +1,11 @@
+package unit.issues.misc;
+
+class Issue3560Macro {
+	macro static public function getImportString() {
+		var imports = haxe.macro.Context.getLocalImports();
+		var s = imports.map(function (i) {
+			return Std.string(i.mode) + ":" + i.path.map(function(p) return p.name).join(".");
+		});
+		return macro $v{s};
+	}
+}

+ 1 - 0
typecore.ml

@@ -87,6 +87,7 @@ and typer_module = {
 	mutable module_using : tclass list;
 	mutable module_globals : (string, (module_type * string)) PMap.t;
 	mutable wildcard_packages : string list list;
+	mutable module_imports : Ast.import list;
 }
 
 and typer = {

+ 3 - 0
typeload.ml

@@ -665,6 +665,7 @@ let hide_params ctx =
 		module_using = [];
 		module_globals = PMap.empty;
 		wildcard_packages = [];
+		module_imports = [];
 	};
 	ctx.type_params <- [];
 	(fun() ->
@@ -2714,6 +2715,7 @@ let rec init_module_type ctx context_init do_init (decl,p) =
 	in
 	match decl with
 	| EImport (path,mode) ->
+		ctx.m.module_imports <- (path,mode) :: ctx.m.module_imports;
 		let rec loop acc = function
 			| x :: l when is_lower_ident (fst x) -> loop (x::acc) l
 			| rest -> List.rev acc, rest
@@ -3114,6 +3116,7 @@ let type_module ctx m file ?(is_extern=false) tdecls p =
 			module_using = [];
 			module_globals = PMap.empty;
 			wildcard_packages = [];
+			module_imports = [];
 		};
 		meta = [];
 		this_stack = [];

+ 5 - 0
typer.ml

@@ -4544,6 +4544,9 @@ let make_macro_api ctx p =
 		Interp.get_local_using = (fun() ->
 			ctx.m.module_using;
 		);
+		Interp.get_local_imports = (fun() ->
+			ctx.m.module_imports;
+		);
 		Interp.get_local_vars = (fun () ->
 			ctx.locals;
 		);
@@ -4745,6 +4748,7 @@ let load_macro ctx cpath f p =
 		module_using = [];
 		module_globals = PMap.empty;
 		wildcard_packages = [];
+		module_imports = [];
 	};
 	add_dependency ctx.m.curmod mloaded;
 	let mt = Typeload.load_type_def mctx p { tpackage = fst cpath; tname = snd cpath; tparams = []; tsub = sub } in
@@ -4994,6 +4998,7 @@ let rec create com =
 			module_using = [];
 			module_globals = PMap.empty;
 			wildcard_packages = [];
+			module_imports = [];
 		};
 		meta = [];
 		this_stack = [];