commit 0e62706aed4499a4b0bc7b0f349b851d9d9eb104 from: Omar Polo date: Wed Aug 04 22:01:03 2021 UTC add OP_REST for rest arguments commit - 5de2d36f1a5eb853fde34fb18b57bca902f17362 commit + 0e62706aed4499a4b0bc7b0f349b851d9d9eb104 blob - 8735f24bd0c12b7159d6687776b08f688c2197e7 blob + 3207aba3d37bbaa7e4064702c8554c2e3bf328c2 --- np.y +++ np.y @@ -206,10 +206,14 @@ funcall : procname { ; 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 @@ -278,6 +278,12 @@ free_op(struct op *op) { /* TODO: probably more... */ free(op); +} + +struct op * +op_rest(void) +{ + return newop(OP_REST); } struct op * @@ -505,6 +511,9 @@ pp_op(struct op *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); @@ -723,10 +732,10 @@ proc_setup_body(void) 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; @@ -752,13 +761,19 @@ proc_done(char *name) 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 @@ -51,6 +51,7 @@ struct value { }; enum { + OP_REST, OP_ASSIGN, OP_ASSERT, OP_FUNCALL, @@ -139,6 +140,7 @@ int global_set(char *, struct op *); 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 *);