2
0
Эх сурвалжийг харах

add `@:forwardStatics` (closes #3254)

No more excuses Caue!
Simon Krajewski 11 жил өмнө
parent
commit
98407abfd3
4 өөрчлөгдсөн 59 нэмэгдсэн , 26 устгасан
  1. 1 0
      ast.ml
  2. 1 0
      common.ml
  3. 14 0
      tests/unit/issues/Issue3254.hx
  4. 43 26
      typer.ml

+ 1 - 0
ast.ml

@@ -75,6 +75,7 @@ module Meta = struct
 		| FlatEnum
 		| Font
 		| Forward
+		| ForwardStatics
 		| From
 		| FunctionCode
 		| FunctionTailCode

+ 1 - 0
common.ml

@@ -407,6 +407,7 @@ module MetaInfo = struct
 		| FlatEnum -> ":flatEnum",("Internally used to mark an enum as being flat, i.e. having no function constructors",[UsedOn TEnum; Internal])
 		| Font -> ":font",("Embeds the given TrueType font into the class (must extend flash.text.Font)",[HasParam "TTF path";HasParam "Range String";UsedOn TClass])
 		| Forward -> ":forward",("Forwards field access to underlying type",[HasParam "List of field names";UsedOn TAbstract])
+		| ForwardStatics -> ":forwardStatics",("Forwards static field access to underlying type",[HasParam "List of field names";UsedOn TAbstract])
 		| From -> ":from",("Specifies that the field of the abstract is a cast operation from the type identified in the function",[UsedOn TAbstractField])
 		| FunctionCode -> ":functionCode",("Used to inject platform-native code into a function",[Platforms [Cpp;Java;Cs]])
 		| FunctionTailCode -> ":functionTailCode",("",[Platform Cpp])

+ 14 - 0
tests/unit/issues/Issue3254.hx

@@ -0,0 +1,14 @@
+package unit.issues;
+
+private class Data {
+	static public function test() { return 12; }
+}
+
+@:forward
+private abstract AData(Data) { }
+
+class Issue3254 extends Test {
+	function test() {
+		eq(12, AData.test());
+	}
+}

+ 43 - 26
typer.ml

@@ -1438,6 +1438,20 @@ and type_field ?(resume=false) ctx e i p mode =
 		end;
 		AKExpr (mk (TField (e,FDynamic i)) (mk_mono()) p)
 	in
+	let does_forward a stat =
+		try
+			let _,el,_ = Meta.get (if stat then Meta.ForwardStatics else Meta.Forward) a.a_meta in
+			match el with
+				| [] ->
+					true
+				| _ ->
+					List.exists (fun e -> match fst e with
+						| EConst(Ident s | String s) -> s = i
+						| _ -> error "Identifier or string expected as argument to @:forward" (pos e)
+					) el
+		with Not_found ->
+			false
+	in
 	match follow e.etype with
 	| TInst (c,params) ->
 		let rec loop_dyn c params =
@@ -1540,26 +1554,34 @@ and type_field ?(resume=false) ctx e i p mode =
 						FAnon f, t
 			) in
 			field_access ctx mode f fmode ft e p
-		with Not_found ->
-			if is_closed a then try
-				using_field ctx mode e i p
+		with Not_found -> try
+				match !(a.a_status) with
+				| Statics {cl_kind = KAbstractImpl a} when does_forward a true ->
+					let mt = try module_type_of_type a.a_this with Exit -> raise Not_found in
+					let et = type_module_type ctx mt None p in
+					type_field ctx et i p mode;
+				| _ ->
+					raise Not_found
 			with Not_found ->
-				no_field()
-			else
-			let f = {
-				cf_name = i;
-				cf_type = mk_mono();
-				cf_doc = None;
-				cf_meta = no_meta;
-				cf_public = true;
-				cf_pos = p;
-				cf_kind = Var { v_read = AccNormal; v_write = (match mode with MSet -> AccNormal | MGet | MCall -> AccNo) };
-				cf_expr = None;
-				cf_params = [];
-				cf_overloads = [];
-			} in
-			a.a_fields <- PMap.add i f a.a_fields;
-			field_access ctx mode f (FAnon f) (Type.field_type f) e p
+				if is_closed a then try
+					using_field ctx mode e i p
+				with Not_found ->
+					no_field()
+				else
+				let f = {
+					cf_name = i;
+					cf_type = mk_mono();
+					cf_doc = None;
+					cf_meta = no_meta;
+					cf_public = true;
+					cf_pos = p;
+					cf_kind = Var { v_read = AccNormal; v_write = (match mode with MSet -> AccNormal | MGet | MCall -> AccNo) };
+					cf_expr = None;
+					cf_params = [];
+					cf_overloads = [];
+				} in
+				a.a_fields <- PMap.add i f a.a_fields;
+				field_access ctx mode f (FAnon f) (Type.field_type f) e p
 		)
 	| TMono r ->
 		let f = {
@@ -1633,14 +1655,9 @@ and type_field ?(resume=false) ctx e i p mode =
 				AKUsing (ef,c,f,e)
 			| MSet, _ ->
 				error "This operation is unsupported" p)
-		with Not_found -> try
-			let _,el,_ = Meta.get Meta.Forward a.a_meta in
-			if not (List.exists (fun e -> match fst e with
-				| EConst(Ident s | String s) -> s = i
-				| _ -> error "Identifier or string expected as argument to @:forward" (pos e)
-			) el) && el <> [] then raise Not_found;
+		with Not_found when does_forward a false ->
 			type_field ctx {e with etype = apply_params a.a_params pl a.a_this} i p mode;
-		with Not_found -> try
+		| Not_found -> try
 			using_field ctx mode e i p
 		with Not_found -> try
 			(match ctx.curfun, e.eexpr with