ast_value *imm_float_one;
ast_value *imm_vector_zero;
ast_value *nil;
+ ast_value *reserved_version;
size_t crc_globals;
size_t crc_fields;
/* pragma flags */
bool noref;
+
+ /* collected information */
+ size_t max_param_count;
} parser_t;
static const ast_expression *intrinsic_debug_typestring = (ast_expression*)0x10;
params->exprs = NULL;
ast_delete(params);
}
+ if (parser->max_param_count < paramcount)
+ parser->max_param_count = paramcount;
(void)!ast_call_check_types(call);
} else {
parseerror(parser, "invalid function call");
else if (!strcmp(parser_tokval(parser), "deprecated") && !(flags & AST_FLAG_DEPRECATED)) {
flags |= AST_FLAG_DEPRECATED;
*message = NULL;
-
+
if (!parser_next(parser)) {
parseerror(parser, "parse error in attribute");
goto argerr;
}
}
}
- else if (!strcmp(parser_tokval(parser), "static"))
+ else if (with_local && !strcmp(parser_tokval(parser), "static"))
had_static = true;
else if (!strcmp(parser_tokval(parser), "const"))
had_const = true;
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;
parser->const_vec[0] = ast_value_new(empty_ctx, "<vector.x>", TYPE_NOEXPR);
parser->const_vec[1] = ast_value_new(empty_ctx, "<vector.y>", TYPE_NOEXPR);
parser->const_vec[2] = ast_value_new(empty_ctx, "<vector.z>", TYPE_NOEXPR);
+
+ if (opts.add_info) {
+ parser->reserved_version = ast_value_new(empty_ctx, "reserved:version", TYPE_STRING);
+ parser->reserved_version->cvq = CV_CONST;
+ parser->reserved_version->hasvalue = true;
+ parser->reserved_version->expression.flags |= AST_FLAG_INCLUDE_DEF;
+ parser->reserved_version->constval.vstring = util_strdup(GMQCC_FULL_VERSION_STRING);
+ } else {
+ parser->reserved_version = NULL;
+ }
return true;
}
return false;
}
}
+ if (parser->reserved_version &&
+ !ast_global_codegen(parser->reserved_version, ir, false))
+ {
+ con_out("failed to generate reserved::version");
+ ir_builder_delete(ir);
+ return false;
+ }
for (i = 0; i < vec_size(parser->imm_float); ++i) {
if (!ast_global_codegen(parser->imm_float[i], ir, false)) {
con_out("failed to generate global %s\n", parser->imm_float[i]->name);