self->expression.params = NULL;
self->expression.count = 0;
self->expression.flags = 0;
+ self->expression.varparam = NULL;
}
static void ast_expression_delete(ast_expression *self)
size_t count;
ast_value* *params;
uint32_t flags;
+ /* void foo(string...) gets varparam set as a restriction
+ * for variadic parameters
+ */
+ ast_expression *varparam;
/* The codegen functions should store their output values
* so we can call it multiple times without re-evaluating.
* Store lvalue and rvalue seperately though. So that
#define AST_FLAG_INITIALIZED (1<<3)
#define AST_FLAG_DEPRECATED (1<<4)
#define AST_FLAG_INCLUDE_DEF (1<<5)
+#define AST_FLAG_VARARG_COUNT (1<<6)
#define AST_FLAG_TYPE_MASK (AST_FLAG_VARIADIC | AST_FLAG_NORETURN)
/* Value
ast_value *fval;
bool first = true;
bool variadic = false;
+ ast_value *varparam = NULL;
ctx = parser_ctx(parser);
if (parser->tok == TOKEN_DOTS) {
/* '...' indicates a varargs function */
variadic = true;
- if (!parser_next(parser)) {
- parseerror(parser, "expected parameter");
- return NULL;
- }
- if (parser->tok != ')') {
+ if (!parser_next(parser) || parser->tok != ')') {
parseerror(parser, "`...` must be the last parameter of a variadic function declaration");
goto on_error;
}
parseerror(parser, "type not supported as part of a parameter list: %s", tname);
goto on_error;
}
+ /* type-restricted varargs */
+ if (parser->tok == TOKEN_DOTS) {
+ variadic = true;
+ varparam = vec_last(params);
+ vec_pop(params);
+ if (!parser_next(parser) || parser->tok != ')') {
+ parseerror(parser, "`...` must be the last parameter of a variadic function declaration");
+ goto on_error;
+ }
+ }
}
}
fval->expression.flags |= AST_FLAG_VARIADIC;
var = fval;
- var->expression.params = params;
+ var->expression.params = params;
+ var->expression.varparam = (ast_expression*)varparam;
params = NULL;
return var;