Forráskód Böngészése

[python] add reverse mapping to access native fields of kwArgs, fix #4011

frabbit 10 éve
szülő
commit
95795a09b8
4 módosított fájl, 59 hozzáadás és 13 törlés
  1. 22 13
      genpy.ml
  2. 6 0
      std/python/KwArgs.hx
  3. 16 0
      std/python/internal/HxOverrides.hx
  4. 15 0
      tests/unit/src/unit/TestPython.hx

+ 22 - 13
genpy.ml

@@ -1587,8 +1587,6 @@ module Printer = struct
 
 	and print_call pctx e1 el call_expr =
 		let get_native_fields t = match follow t with
-		| TAbstract(abst, [tx]) ->
-			(match follow tx with
 			| TAnon(a) ->
 				let fold f cf acc =
 					if Meta.has Meta.Native cf.cf_meta then begin
@@ -1600,9 +1598,14 @@ module Printer = struct
 				in
 				let mapping = PMap.foldi fold a.a_fields PMap.empty in
 				mapping
-			| _ -> PMap.empty)
-		| _ ->
-			assert false
+			| _ -> PMap.empty
+		in
+		let native_fields_str native_fields =
+			let fold_dict k v acc =
+				let prefix = if acc = "" then "" else "," in
+				Printf.sprintf "%s%s\"%s\":\"%s\"" acc prefix (handle_keywords k) v
+			in
+			PMap.foldi fold_dict native_fields ""
 		in
 		match e1.eexpr, el with
 			| TLocal { v_name = "`trace" }, [e;infos] ->
@@ -1616,17 +1619,23 @@ module Printer = struct
 			| TField(e1,((FAnon {cf_name = (("iterator" | "toUpperCase" | "toLowerCase" | "pop" | "shift") as s)}) | FDynamic (("iterator" | "toUpperCase" | "toLowerCase" | "pop" | "shift") as s))), [] ->
 				Printf.sprintf "HxOverrides.%s(%s)" s (print_expr pctx e1)
 			| TField(_, (FStatic({cl_path = ["python"; "_KwArgs"], "KwArgs_Impl_"},{ cf_name="fromT" }))), [e2]  ->
-				let native_fields = get_native_fields call_expr.etype in
+				let t = match follow call_expr.etype with
+				| TAbstract(_, [t]) -> t
+				| _ -> assert false
+				in
+				let native_fields = get_native_fields t in
 				if PMap.is_empty native_fields then
 					print_call2 pctx e1 el
 				else
-					let fold_dict k v acc =
-						let prefix = if acc = "" then "" else "," in
-						Printf.sprintf "%s%s\"%s\":\"%s\"" acc prefix (handle_keywords k) v
-					in
-					let native_map = PMap.foldi fold_dict native_fields ""
-					in
-					Printf.sprintf "python__KwArgs_KwArgs_Impl_.fromT(HxOverrides.mapKwArgs(%s, {%s}))" (print_expr pctx e2) native_map
+					let s1 = native_fields_str native_fields in
+					Printf.sprintf "python__KwArgs_KwArgs_Impl_.fromT(HxOverrides.mapKwArgs(%s, {%s}))" (print_expr pctx e2) s1
+			| TField(_, (FStatic({cl_path = ["python"; "_KwArgs"], "KwArgs_Impl_"},{ cf_name="toDictHelper" }))), [e2; et]  ->
+				let native_fields = get_native_fields et.etype in
+				if PMap.is_empty native_fields then
+					print_call2 pctx e1 el
+				else
+					let s1 = native_fields_str native_fields in
+					Printf.sprintf "python__KwArgs_KwArgs_Impl_.toDictHelper(HxOverrides.reverseMapKwArgs(%s, {%s}), None)" (print_expr pctx e2) s1
 			| _,_ ->
 				print_call2 pctx e1 el
 

+ 6 - 0
std/python/KwArgs.hx

@@ -38,6 +38,12 @@ abstract KwArgs<T:{}>(Dict<String,Dynamic>) {
 	}
 
 	@:to public inline function toDict():Dict<String,Dynamic> {
+		// pass null, it's just to have the type information available in genpy
+		return toDictHelper(null);
+	}
+	// this is a helper method (hack) which is matched in genpy to extract the type information for reverse mapping
+	// of keyword fields.
+	function toDictHelper(x:T):Dict<String,Dynamic> {
 		return this;
 	}
 

+ 16 - 0
std/python/internal/HxOverrides.hx

@@ -161,4 +161,20 @@ class HxOverrides {
 		return a;
 	}
 
+	@:ifFeature("python._KwArgs.KwArgs_Impl_.toDictHelper")
+	static public function reverseMapKwArgs(a:Dict<String,Dynamic>, v:Dict<String,String>)
+	{
+		var a = a.copy();
+		for (k in v.keys()) {
+
+			var val = v.get(k);
+			if (a.hasKey(val)) {
+				var x = a.get(val, null);
+				a.set(k, x);
+				a.remove(val);
+			}
+		}
+		return a;
+	}
+
 }

+ 15 - 0
tests/unit/src/unit/TestPython.hx

@@ -228,6 +228,21 @@ class TestPython extends Test {
 		test(x,a);
 	}
 
+	function testSoftKeywords () {
+		function test (len:String, bytes:String) {
+			eq(len.length,bytes.length);
+		}
+		test("x", "x");
+	}
+
+	function testKwArgsNativeNames () {
+		function test (?kw:KwArgs<{ @:native("default") var def:Int; }>) {
+			eq(1, kw.typed().def);
+		}
+
+		test({ def : 1});
+	}
+
 	function testOptionalVarArgs () {
 		function test (?va:VarArgs<Dynamic>, ?kw:KwArgs<Dynamic>) {
 			var a = va.toArray();