From 77dd89282880373645769101c6f795a9a5ce6ff3 Mon Sep 17 00:00:00 2001 From: lemon Date: Mon, 10 Oct 2022 16:18:02 +0200 Subject: varargs --- pez.c | 61 +++++++++++++++++++++++++++++++++++++++++++++++++------------ test.pez | 9 +++++++++ 2 files changed, 58 insertions(+), 12 deletions(-) diff --git a/pez.c b/pez.c index 19d53ce..622ebc6 100644 --- a/pez.c +++ b/pez.c @@ -1021,6 +1021,8 @@ fixtrunc(fixnum f) { return f & ~(uint32_t)0xFFF; } _(upval, 1) \ _(setupv,-1) \ _(close, 0) \ + _(argc, 1) \ + _(vararg, 0) \ _(global, 0) \ _(setglo,-2) \ _(putglo,-2) \ @@ -1619,6 +1621,19 @@ exefn(PezContext *cx, Fn *fn, uint nargs) uint8_t idx = code[ip++]; closeups(cx, &locals[idx]); } + CASE(Oargc) { + TRY(push(cx, box_num(inttofix(nargs - pr->nparams)))); + } + CASE(Ovararg) { + Val a = pop(cx); + fixnum num = unbox_num(a); + int idx = fixtoint(num) + pr->nparams; + if (!isnum(a) || num < 0 || fixtrunc(num) != num) { + runerr(cx, fn, ip, "SEL expected positive integer index"); + return 0; + } + TRY(push(cx, idx >= nargs ? VOID : args[idx])); + } CASE(Oglobal) { Val k = pop(cx), *v; if ((v = getglobal(cx, k))) { @@ -2487,6 +2502,15 @@ compclosure(Comp *cm, Proto *pr) return 1; } +static bool +reserved(const char *s) +{ + return !strcmp(s, "FOR") + || !strcmp(s, "RET") + || !strcmp(s, "SEL") + || !strcmp(s, "SEL$"); +} + static bool lambdaexpr(Comp *cm, const char *name) { @@ -2510,13 +2534,23 @@ lambdaexpr(Comp *cm, const char *name) char name[NAMEMAX]; int c; eatspaces(cm); - if ((c = peekchr(cm)) != '_' && !aisalpha(c)) { - comperr(cm, c, "expected identifier"); - return 0; + if ((c = peekchr(cm)) == '_' || aisalpha(c)) { + ETRY(readident(cm, name, sizeof name)); + if (reserved(name)) { + comperr(cm, *name, "'%s' is a reserved keyword", name); + goto Err; + } + ETRY(addparam(cm, name)); + } else if (c == '*') { + nextchr(cm); + proto->variadic = 1; + matchspchr(cm, ','); + ETRY(expectspchr(cm, ']')); + break; + } else { + comperr(cm, c, "expected param name"); + goto Err; } - ETRY(readident(cm, name, sizeof name)); - - ETRY(addparam(cm, name)); if (!matchspchr(cm, ',')) { ETRY(expectspchr(cm, ']')); @@ -2554,12 +2588,6 @@ flushconst(Comp *cm) return 1; } -static bool -reserved(const char *s) -{ - return !strcmp(s, "FOR") || !strcmp(s, "RET"); -} - static bool primaryexpr(Comp *cm) { @@ -2615,6 +2643,15 @@ primaryexpr(Comp *cm) // identifier *buf = c; TRY(readident(cm, buf + 1, sizeof buf - 1)); + if (!strcmp(buf, "SEL$")) { + return compop(cm, Oargc); + } else if (!strcmp(buf, "SEL")) { + TRY(expectspchr(cm, '[')); + TRY(expr(cm)); + TRY(expectspchr(cm, ']')); + TRY(compop(cm, Ovararg)); + return 1; + } if (reserved(buf)) { comperr(cm, *buf, "'%s' is a reserved keyword", buf); return 0; diff --git a/test.pez b/test.pez index eb98d75..b6dcd8c 100644 --- a/test.pez +++ b/test.pez @@ -26,3 +26,12 @@ FOR [@x: 0][< 10][+ 1] m[x, y] = x ^ y printf["%a == %a\n", m[3,7], 3^7] + +@add: {[*] + @acc = 0 + FOR [@i: 0][< SEL$][+ 1] + acc += SEL[i] + acc +} + +printf["4+1+3: %a\n", add[4,1,3]] -- cgit v1.2.3