From 3b3bf7b0b5cbff06ee0c43e44659182ab8e661e7 Mon Sep 17 00:00:00 2001 From: Reini Urban Date: Tue, 18 Jun 2013 17:38:18 -0500 Subject: [PATCH] sigopt: abuse unused vm_proto self arg for numargs --- core/potion.h | 4 +++- core/vm.c | 28 ++++++++++++++++++++++------ test/api/potion-test.c | 23 +++++++++++------------ 3 files changed, 36 insertions(+), 19 deletions(-) diff --git a/core/potion.h b/core/potion.h index 4cb01bee..da89bd70 100644 --- a/core/potion.h +++ b/core/potion.h @@ -179,7 +179,9 @@ struct PNVtable; #define PN_IS_PROTO(v) (PN_TYPE(v) == PN_TPROTO) #define PN_IS_REF(v) (PN_TYPE(v) == PN_TWEAK) #define PN_IS_METACLASS(v) (((struct PNVtable *)v)->meta == PN_NIL) -#define PN_IS_FFIPTR(p) (PN_IS_PTR(p) && !(p >= (_PN)P->mem && p <= (_PN)P->mem->old_hi)) +#define PN_IS_FFIPTR(p) ((PN_IS_PTR(p) && !(p >= (_PN)P->mem && p <= (_PN)P->mem->birth_hi)) \ + || (!PN_IS_PTR(p) && p > (_PN)P->mem->birth_hi)) + ///\class PNNumber /// Either a PN_INT immediate object (no struct) 0x...1 diff --git a/core/vm.c b/core/vm.c index f37e0307..5063b576 100644 --- a/core/vm.c +++ b/core/vm.c @@ -116,15 +116,22 @@ void potion_vm_init(Potion *P) { /** entrypoint for all bytecode methods from the C api. \see potion_test_eval() + \param cl PNClosure to be called + \param self PN - sets self (ignored for most user defined functions). + if self is a int < 10 it defines the number of args provided + \param ... - arguments to the cl +x \verbatim - add = potion_eval(P, potion_str(P, "(x=N,y=N): x + y."), 0); + add = potion_eval(P, potion_str(P, "(x=N|y=N): x + y."), 0); addfn = PN_CLOSURE_F(add); // i.e. potion_vm_proto - num = addfn(P, add, PN_NUM(3), PN_NUM(5)); + num = addfn(P, add, 2, PN_NUM(3), PN_NUM(5)); + num = addfn(P, add, 1, PN_NUM(3)); // 1 arg provided, 2nd arg=0 \endverbatim Note that methods with optional arguments ... are not very safe to call. potion_vm_proto() does not know the number of arguments on the stack. - So it checks for all optional args the matching type. */ + So it checks for all optional args the matching type. + You can help by providing numargs as self argument if numargs < 10. */ PN potion_vm_proto(Potion *P, PN cl, PN self, ...) { PN ary = PN_NIL; vPN(Proto) f = (struct PNProto *)PN_CLOSURE(cl)->data[0]; @@ -132,18 +139,27 @@ PN potion_vm_proto(Potion *P, PN cl, PN self, ...) { PN_SIZE i; int arity = PN_CLOSURE(cl)->arity; int minargs = PN_CLOSURE(cl)->minargs; + int numargs = 0; va_list args; ary = PN_TUP0(); va_start(args, self); - //ary = PN_PUSH(ary, self); + if (self < 10) { + numargs = self; + self = 0; + } for (i=0; i < arity; i++) { PN s = potion_sig_at(P, f->sig, i); if (i < minargs || PN_TUPLE_LEN(s) < 2) { //mandatory or no type ary = PN_PUSH(ary, va_arg(args, PN)); } else { //vararg call heuristic: check type of stack var, replace with default PN arg = va_arg(args, PN); - char type = (char)(PN_TUPLE_LEN(s) > 1 ? PN_INT(PN_TUPLE_AT(s,1)) : 0); - if (PN_IS_FFIPTR(arg) || (type && potion_type_char(PN_TYPE(arg)) != type)) { //replace with default + char type = (char)(PN_TUPLE_LEN(s) > 2 + ? potion_type_char(PN_TYPE(PN_TUPLE_AT(s,2))) + : PN_TUPLE_LEN(s) > 1 + ? PN_INT(PN_TUPLE_AT(s,1)) : 0); + if ((numargs && (i >= numargs)) //numargs provided via self + || PN_IS_FFIPTR(arg) + || (type && (potion_type_char(PN_TYPE(arg)) != type))) { //replace with default // default value or 0 ary = PN_PUSH(ary, PN_TUPLE_LEN(s) == 3 ? PN_TUPLE_AT(s,2) : potion_type_default(type)); } else { diff --git a/test/api/potion-test.c b/test/api/potion-test.c index 1cd8d755..a7d73ea0 100644 --- a/test/api/potion-test.c +++ b/test/api/potion-test.c @@ -163,44 +163,43 @@ void potion_test_eval(CuTest *T) { add = potion_eval(P, potion_str(P, "(x, y): x + y."), 0); addfn = PN_CLOSURE_F(add); // c callback CuAssertPtrNotNull(T, addfn); - num = addfn(P, add, PN_NUM(3), PN_NUM(5)); + num = addfn(P, add, 0, PN_NUM(3), PN_NUM(5)); CuAssertIntEquals(T, "calling closure as c func", 8, PN_INT(num)); add = potion_eval(P, potion_str(P, "(x=N|y=N): x + y."), 0); addfn = PN_CLOSURE_F(add); - num = addfn(P, add, PN_NUM(3), PN_NUM(5)); + num = addfn(P, add, 0, PN_NUM(3), PN_NUM(5)); CuAssertIntEquals(T, "calling closure as c func (opt)", 8, PN_INT(num)); - num = addfn(P, add, PN_NUM(1), PN_NUM(3)); + num = addfn(P, add, 1, PN_NUM(3)); CuAssertIntEquals(T, "optional num = 0", 3, PN_INT(num)); add = potion_eval(P, potion_str(P, "(x=N,y:=1): x + y."), 0); //TODO: x=N|y:=1 addfn = PN_CLOSURE_F(add); - num = addfn(P, add, PN_NUM(3), PN_NUM(5)); - CuAssertIntEquals(T, "calling closure as c func (default)", - PN_INT(num), 8); - num = addfn(P, add, PN_NUM(3)); + num = addfn(P, add, 2, PN_NUM(3), PN_NUM(5)); + CuAssertIntEquals(T, "calling closure as c func (default)", 8, PN_INT(num)); + num = addfn(P, add, 1, PN_NUM(3)); CuAssertIntEquals(T, "default num = 1", 4, PN_INT(num)); #if POTION_JIT add = potion_eval(P, potion_str(P, "(x, y): x + y."), POTION_JIT); addfn = PN_CLOSURE_F(add); // c callback CuAssertPtrNotNull(T, addfn); - num = addfn(P, add, PN_NUM(3), PN_NUM(5)); + num = addfn(P, add, 0, PN_NUM(3), PN_NUM(5)); CuAssertIntEquals(T, "calling closure as c func (jit)", 8, PN_INT(num)); //P->flags += DEBUG_COMPILE; add = potion_eval(P, potion_str(P, "(x=N|y=N): x + y."), POTION_JIT); addfn = PN_CLOSURE_F(add); - num = addfn(P, add, PN_NUM(3), PN_NUM(5)); + num = addfn(P, add, 0, PN_NUM(3), PN_NUM(5)); CuAssertIntEquals(T, "calling closure as c func (jit+opt)", 8, PN_INT(num)); - num = addfn(P, add, PN_NUM(3)); + num = addfn(P, add, 1, PN_NUM(3)); CuAssertIntEquals(T, "optional num = 0 (jit)", 3, PN_INT(num)); add = potion_eval(P, potion_str(P, "(x=N|y:=1): x + y."), POTION_JIT); addfn = PN_CLOSURE_F(add); - num = addfn(P, add, PN_NUM(3), PN_NUM(5)); + num = addfn(P, add, 0, PN_NUM(3), PN_NUM(5)); CuAssertIntEquals(T, "calling closure as c func (jit+default)", 8, PN_INT(num)); - num = addfn(P, add, PN_NUM(3)); + num = addfn(P, add, 1, PN_NUM(3)); CuAssertIntEquals(T, "default num = 1 (jit)", 4, PN_INT(num)); #endif