Browse Source

properly store abstract resolve methods on the abstract

Simon Krajewski 10 years ago
parent
commit
a59ed34c54
6 changed files with 19 additions and 6 deletions
  1. 2 1
      interp.ml
  2. 6 0
      std/haxe/macro/Type.hx
  3. 1 1
      tests/unit/src/unit/issues/Issue3753.hx
  4. 2 0
      type.ml
  5. 4 1
      typeload.ml
  6. 4 3
      typer.ml

+ 2 - 1
interp.ml

@@ -276,7 +276,7 @@ let constants =
 	"$";"add";"remove";"has";"__t";"module";"isPrivate";"isPublic";"isExtern";"isInterface";"exclude";
 	"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";
+	"binops";"unops";"from";"to";"array";"op";"isPostfix";"impl";"resolve";
 	"id";"capture";"extra";"v";"ids";"vars";"en";"overrides";"status"];
 	h
 
@@ -4371,6 +4371,7 @@ and encode_tabstract a =
 		"from", enc_array ((List.map (fun t -> enc_obj [ "t",encode_type t; "field",VNull]) a.a_from) @ (List.map (fun (t,cf) -> enc_obj [ "t",encode_type t; "field",encode_cfield cf]) a.a_from_field));
 		"to", enc_array ((List.map (fun t -> enc_obj [ "t",encode_type t; "field",VNull]) a.a_to) @ (List.map (fun (t,cf) -> enc_obj [ "t",encode_type t; "field",encode_cfield cf]) a.a_to_field));
 		"array", enc_array (List.map encode_cfield a.a_array);
+		"resolve", (match a.a_resolve with None -> VNull | Some cf -> encode_cfref cf)
 	]
 
 and encode_efield f =

+ 6 - 0
std/haxe/macro/Type.hx

@@ -505,6 +505,12 @@ typedef AbstractType = {>BaseType,
 		The defined array-access fields of the abstract.
 	**/
 	var array : Array<ClassField>;
+
+	/**
+		The method used for resolving unknown field access, if available.
+	**/
+	@:require(haxe_ver >= 3.3)
+	var resolve : Null<ClassField>;
 }
 
 /**

+ 1 - 1
tests/unit/src/unit/issues/Issue3753.hx

@@ -9,7 +9,7 @@ private abstract A(Map<String, String>) from Map<String, String> {
 
 private abstract B(Map<String, String>) from Map<String, String> {
 	@:resolve
-	static function resolve(lhs:B, name:String) {
+	static function resolve2(lhs:B, name:String) {
 		return lhs.get()[name];
 	}
 

+ 2 - 0
type.ml

@@ -263,6 +263,7 @@ and tabstract = {
 	mutable a_to : t list;
 	mutable a_to_field : (t * tclass_field) list;
 	mutable a_array : tclass_field list;
+	mutable a_resolve : tclass_field option;
 }
 
 and module_type =
@@ -439,6 +440,7 @@ let null_abstract = {
 	a_to = [];
 	a_to_field = [];
 	a_array = [];
+	a_resolve = None;
 }
 
 let add_dependency m mdep =

+ 4 - 1
typeload.ml

@@ -131,6 +131,7 @@ let make_module ctx mpath file tdecls loadp =
 				a_impl = None;
 				a_array = [];
 				a_this = mk_mono();
+				a_resolve = None;
 			} in
 			decls := (TAbstractDecl a, decl) :: !decls;
 			match d.d_data with
@@ -2375,6 +2376,7 @@ let init_class ctx c p context_init herits fields =
 							end;
 							loop ml
 						| (Meta.Resolve,_,_) :: _ ->
+							if a.a_resolve <> None then error "Multiple resolve methods are not supported" cf.cf_pos;
 							let targ = if Meta.has Meta.Impl f.cff_meta then tthis else ta in
 							begin match follow t with
 								| TFun([(_,_,t1);(_,_,t2)],_) ->
@@ -2384,7 +2386,8 @@ let init_class ctx c p context_init herits fields =
 									end
 								| _ ->
 									error ("Field type of resolve must be " ^ (s_type (print_context()) targ) ^ " -> String -> T") f.cff_pos
-							end
+							end;
+							a.a_resolve <- Some cf;
 						| _ :: ml ->
 							loop ml
 						| [] ->

+ 4 - 3
typer.ml

@@ -1630,9 +1630,10 @@ and type_field ?(resume=false) ctx e i p mode =
 			| FunMemberAbstract, TConst (TThis) -> type_field ctx {e with etype = apply_params a.a_params pl a.a_this} i p mode;
 			| _ -> raise Not_found)
 		with Not_found -> try
-			let c = (match a.a_impl with None -> raise Not_found | Some c -> c) in
-			let cf = PMap.find "resolve" c.cl_statics in
-			if not (Meta.has Meta.Resolve cf.cf_meta) then raise Not_found;
+			let c,cf = match a.a_impl,a.a_resolve with
+				| Some c,Some cf -> c,cf
+				| _ -> raise Not_found
+			in
 			let et = type_module_type ctx (TClassDecl c) None p in
 			let t = apply_params a.a_params pl (field_type ctx c [] cf p) in
 			let ef = mk (TField (et,FStatic (c,cf))) t p in