1
0
mirror of https://github.com/janet-lang/janet synced 2024-06-18 11:19:56 +00:00

Add keyword arguments via &keys.

This makes it easier to document functions that
take keyword arguments and also prevents some allocations
with these functions. Before, this was possible via normal
variadic functions but created an intermediate tuple, and
the generated docstrings did not document the keys.
This commit is contained in:
Calvin Rose 2019-05-24 17:03:22 -04:00
parent ddedae6831
commit 010e2e4652
3 changed files with 46 additions and 6 deletions

View File

@ -127,6 +127,16 @@ void janet_fiber_pushn(JanetFiber *fiber, const Janet *arr, int32_t n) {
fiber->stacktop = newtop;
}
/* Create a struct with n values. If n is odd, the last value is ignored. */
static Janet make_struct_n(const Janet *args, int32_t n) {
int32_t i = 0;
JanetKV *st = janet_struct_begin(n & (~1));
for (; i < n; i += 2) {
janet_struct_put(st, args[i], args[i + 1]);
}
return janet_wrap_struct(janet_struct_end(st));
}
/* Push a stack frame to a fiber */
int janet_fiber_funcframe(JanetFiber *fiber, JanetFunction *func) {
JanetStackFrame *newframe;
@ -164,12 +174,19 @@ int janet_fiber_funcframe(JanetFiber *fiber, JanetFunction *func) {
/* Check varargs */
if (func->def->flags & JANET_FUNCDEF_FLAG_VARARG) {
int32_t tuplehead = fiber->frame + func->def->arity;
int st = func->def->flags & JANET_FUNCDEF_FLAG_STRUCTARG;
if (tuplehead >= oldtop) {
fiber->data[tuplehead] = janet_wrap_tuple(janet_tuple_n(NULL, 0));
fiber->data[tuplehead] = st
? make_struct_n(NULL, 0)
: janet_wrap_tuple(janet_tuple_n(NULL, 0));
} else {
fiber->data[tuplehead] = janet_wrap_tuple(janet_tuple_n(
fiber->data[tuplehead] = st
? make_struct_n(
fiber->data + tuplehead,
oldtop - tuplehead));
oldtop - tuplehead)
: janet_wrap_tuple(janet_tuple_n(
fiber->data + tuplehead,
oldtop - tuplehead));
}
}
@ -220,14 +237,21 @@ int janet_fiber_funcframe_tail(JanetFiber *fiber, JanetFunction *func) {
/* Check varargs */
if (func->def->flags & JANET_FUNCDEF_FLAG_VARARG) {
int32_t tuplehead = fiber->stackstart + func->def->arity;
int st = func->def->flags & JANET_FUNCDEF_FLAG_STRUCTARG;
if (tuplehead >= fiber->stacktop) {
if (tuplehead >= fiber->capacity) janet_fiber_setcapacity(fiber, 2 * (tuplehead + 1));
for (i = fiber->stacktop; i < tuplehead; ++i) fiber->data[i] = janet_wrap_nil();
fiber->data[tuplehead] = janet_wrap_tuple(janet_tuple_n(NULL, 0));
fiber->data[tuplehead] = st
? make_struct_n(NULL, 0)
: janet_wrap_tuple(janet_tuple_n(NULL, 0));
} else {
fiber->data[tuplehead] = janet_wrap_tuple(janet_tuple_n(
fiber->data[tuplehead] = st
? make_struct_n(
fiber->data + tuplehead,
fiber->stacktop - tuplehead));
fiber->stacktop - tuplehead)
: janet_wrap_tuple(janet_tuple_n(
fiber->data + tuplehead,
fiber->stacktop - tuplehead));
}
stacksize = tuplehead - fiber->stackstart + 1;
} else {

View File

@ -652,6 +652,7 @@ static JanetSlot janetc_fn(JanetFopts opts, int32_t argn, const Janet *argv) {
/* Function flags */
int vararg = 0;
int structarg = 0;
int allow_extra = 0;
int selfref = 0;
int seenamp = 0;
@ -712,6 +713,19 @@ static JanetSlot janetc_fn(JanetFopts opts, int32_t argn, const Janet *argv) {
min_arity = i;
arity--;
seenopt = 1;
} else if (!janet_cstrcmp(janet_unwrap_symbol(param), "&keys")) {
if (seenamp) {
errmsg = "&keys in unexpected location";
goto error;
} else if (i == paramcount - 2) {
vararg = 1;
structarg = 1;
arity -= 2;
} else {
errmsg = "&keys in unexpected location";
goto error;
}
seenamp = 1;
} else {
janetc_nameslot(c, janet_unwrap_symbol(param), janetc_farslot(c));
}
@ -749,6 +763,7 @@ static JanetSlot janetc_fn(JanetFopts opts, int32_t argn, const Janet *argv) {
def->min_arity = min_arity;
def->max_arity = max_arity;
if (vararg) def->flags |= JANET_FUNCDEF_FLAG_VARARG;
if (structarg) def->flags |= JANET_FUNCDEF_FLAG_STRUCTARG;
if (selfref) def->name = janet_unwrap_symbol(head);
defindex = janetc_addfuncdef(c, def);

View File

@ -753,6 +753,7 @@ struct JanetAbstractHead {
#define JANET_FUNCDEF_FLAG_HASDEFS 0x200000
#define JANET_FUNCDEF_FLAG_HASENVS 0x400000
#define JANET_FUNCDEF_FLAG_HASSOURCEMAP 0x800000
#define JANET_FUNCDEF_FLAG_STRUCTARG 0x1000000
#define JANET_FUNCDEF_FLAG_TAG 0xFFFF
/* Source mapping structure for a bytecode instruction */