static void ast_expression_init(ast_expression *self,
ast_expression_codegen *codegen)
{
- self->expression.codegen = codegen;
- self->expression.vtype = TYPE_VOID;
- self->expression.next = NULL;
- self->expression.outl = NULL;
- self->expression.outr = NULL;
+ self->expression.codegen = codegen;
+ self->expression.vtype = TYPE_VOID;
+ self->expression.next = NULL;
+ self->expression.outl = NULL;
+ self->expression.outr = NULL;
+ self->expression.variadic = false;
MEM_VECTOR_INIT(&self->expression, params);
}
}
fromex = &self->expression;
selfex = &cp->expression;
+ selfex->variadic = fromex->variadic;
for (i = 0; i < fromex->params_count; ++i) {
ast_value *v = ast_value_copy(fromex->params[i]);
if (!v || !ast_expression_common_params_add(selfex, v)) {
}
fromex = &other->expression;
selfex = &self->expression;
+ selfex->variadic = fromex->variadic;
for (i = 0; i < fromex->params_count; ++i) {
ast_value *v = ast_value_copy(fromex->params[i]);
if (!v || !ast_expression_common_params_add(selfex, v))
else
selfex->next = NULL;
+ selfex->variadic = fromex->variadic;
for (i = 0; i < fromex->params_count; ++i) {
ast_value *v = ast_value_copy(fromex->params[i]);
if (!v || !ast_expression_common_params_add(selfex, v)) {
return false;
if (a->expression.params_count != b->expression.params_count)
return false;
+ if (a->expression.variadic != b->expression.variadic)
+ return false;
if (a->expression.params_count) {
size_t i;
for (i = 0; i < a->expression.params_count; ++i) {
/* this is the WIP test for the parser...
* constantly adding stuff here to see if things break
*/
-void(string) print = #1;
+void(string,...) print = #1;
void(string,string) print2 = #1;
void(string,string,string) print3 = #1;
string(float) ftos = #2;
$modelname foobar
$modelname foobar3
+void(string a, ...) hasvaria = {
+};
+
void() main = {
entity pawn;
vector vec;
pawn = spawn();
pawn.mema = 3;
pawn.memb = 5;
- print2(ftos(pawn.mema), "\n");
- print2(ftos(pawn.memb), "\n");
+ print(ftos(pawn.mema), "\n");
+ print(ftos(pawn.memb), "\n");
print("SECOND TEST\n");
for (a = 0; a < 3; a = a + 1) {
int vtype = basetype;
int temptype;
size_t i;
+ bool variadic = false;
MEM_VECTOR_INIT(¶ms, p);
}
}
+ if (parser->tok == TOKEN_DOTS) {
+ /* variadic args */
+ variadic = true;
+ if (!parser_next(parser))
+ goto on_error;
+ if (parser->tok != ')') {
+ parseerror(parser, "`...` must be the last parameter of a variadic function declaration");
+ goto on_error;
+ }
+ break;
+ }
+
temptype = parser_token(parser)->constval.t;
if (!parser_next(parser))
goto on_error;
}
fval->expression.next = (ast_expression*)param;
MEM_VECTOR_MOVE(¶m->expression, params, &fval->expression, params);
+ fval->expression.variadic = param->expression.variadic;
param = fval;
}
var = ast_value_new(ctx, "<unnamed>", vtype);
if (!var)
goto on_error;
+ var->expression.variadic = variadic;
MEM_VECTOR_MOVE(¶ms, p, &var->expression, params);
return var;
on_error:
parseerror(parser, "could not determine function return type");
return false;
} else {
- if (fun->expression.params_count != paramcount) {
+ if (fun->expression.params_count != paramcount &&
+ !(fun->expression.variadic &&
+ fun->expression.params_count < paramcount))
+ {
ast_value *fval;
+ const char *fewmany = (fun->expression.params_count > paramcount) ? "few" : "many";
+
fval = (ast_istype(fun, ast_value) ? ((ast_value*)fun) : NULL);
if (opts_standard == COMPILER_GMQCC)
{
if (fval)
- parseerror(parser, "too few parameters for call to %s: expected %i, got %i",
+ parseerror(parser, "too %s parameters for call to %s: expected %i, got %i", fewmany,
fval->name, (int)fun->expression.params_count, paramcount);
else
- parseerror(parser, "too few parameters for function call: expected %i, got %i",
+ parseerror(parser, "too %s parameters for function call: expected %i, got %i", fewmany,
(int)fun->expression.params_count, paramcount);
return false;
}
{
if (fval)
return !parsewarning(parser, WARN_TOO_FEW_PARAMETERS,
- "too few parameters for call to %s: expected %i, got %i",
+ "too %s parameters for call to %s: expected %i, got %i", fewmany,
fval->name, (int)fun->expression.params_count, paramcount);
else
return !parsewarning(parser, WARN_TOO_FEW_PARAMETERS,
- "too few parameters for function call: expected %i, got %i",
+ "too %s parameters for function call: expected %i, got %i", fewmany,
(int)fun->expression.params_count, paramcount);
}
}
fval->expression.next = (ast_expression*)var;
MEM_VECTOR_MOVE(&var->expression, params, &fval->expression, params);
+ fval->expression.variadic = var->expression.variadic;
/* we compare the type late here, but it's easier than
* messing with the parameter-vector etc. earlier
has_frame_think = false;
old = parser->function;
+ if (var->expression.variadic) {
+ if (parsewarning(parser, WARN_VARIADIC_FUNCTION,
+ "variadic function with implementation will not be able to access additional parameters"))
+ {
+ ast_value_delete(typevar);
+ return false;
+ }
+ }
+
if (localblock) {
parseerror(parser, "cannot declare functions within functions");
ast_value_delete(typevar);
}
fval->expression.next = (ast_expression*)var;
MEM_VECTOR_MOVE(&var->expression, params, &fval->expression, params);
+ fval->expression.variadic = var->expression.variadic;
var = fval;
}