commit - 5de2d36f1a5eb853fde34fb18b57bca902f17362
commit + 0e62706aed4499a4b0bc7b0f349b851d9d9eb104
blob - 8735f24bd0c12b7159d6687776b08f688c2197e7
blob + 3207aba3d37bbaa7e4064702c8554c2e3bf328c2
--- np.y
+++ np.y
;
optcomma: /* empty */ | ',' ;
+
+dots : '.' '.' '.' ;
args : /* empty */
| args ',' expr { push_arg($3); }
+ | args ',' dots { push_arg(op_rest()); }
| expr { push_arg($1); }
+ | dots { push_arg(op_rest()); }
;
proc : PROC SYMBOL {
blob - 5bb65d30e98066b8b74e712420d77168aaa25689
blob + 69dbdc54ccd1194af8b5463ab94cc061aef8a661
--- script.c
+++ script.c
{
/* TODO: probably more... */
free(op);
+}
+
+struct op *
+op_rest(void)
+{
+ return newop(OP_REST);
}
struct op *
struct op *aux;
switch (op->type) {
+ case OP_REST:
+ printf("...");
+ break;
case OP_ASSIGN:
printf("%s = ", op->v.assign.name);
pp_op(op->v.assign.expr);
argv = peek(&args);
for (i = 0, op = argv->base.next; op != NULL; i++) {
/*
- * TODO: should free the whole list but.., we're gonna
- * exit real soon(tm)!
+ * TODO: should free the whole list on error but..,
+ * we're gonna exit real soon(tm)!
*/
- if (op->type != OP_VAR)
+ if (op->type != OP_VAR && op->type != OP_REST)
return 0;
op = op->next;
proc->minargs = argc;
for (i = 0, op = argv; op != NULL; ++i) {
+ if (op->type == OP_REST) {
+ proc->vararg = 1;
+ proc->minargs = i;
+ break;
+ }
+
proc->args[i] = xstrdup(op->v.var);
next = op->next;
free_op(op);
op = next;
}
- assert(i == argc);
+ assert(i == argc || (proc->vararg && i == proc->minargs));
proc->body = body;
blob - 28896865a4f7b7adaaf21480fa6c533b78787ea4
blob + 8d50f348364bead955dc6c4a819478aa79cd1da3
--- script.h
+++ script.h
};
enum {
+ OP_REST,
OP_ASSIGN,
OP_ASSERT,
OP_FUNCALL,
struct op *newop(int);
void free_op(struct op *);
+struct op *op_rest(void);
struct op *op_assign(char *, struct op *);
struct op *op_assert(struct op *);
struct op *op_var(char *);