Skip to content

Commit

Permalink
[python] add reverse mapping to access native fields of kwArgs, fix H…
Browse files Browse the repository at this point in the history
  • Loading branch information
frabbit committed Mar 15, 2015
1 parent 8265c7e commit 95795a0
Show file tree
Hide file tree
Showing 4 changed files with 59 additions and 13 deletions.
35 changes: 22 additions & 13 deletions genpy.ml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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] ->
Expand All @@ -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

Expand Down
6 changes: 6 additions & 0 deletions std/python/KwArgs.hx
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}

Expand Down
16 changes: 16 additions & 0 deletions std/python/internal/HxOverrides.hx
Original file line number Diff line number Diff line change
Expand Up @@ -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 changes: 15 additions & 0 deletions tests/unit/src/unit/TestPython.hx
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand Down

0 comments on commit 95795a0

Please sign in to comment.