size_t max_param_count;
} parser_t;
-static const ast_expression *intrinsic_debug_typestring = (ast_expression*)0x10;
+static ast_expression * const intrinsic_debug_typestring = (ast_expression*)0x1;
static void parser_enterblock(parser_t *parser);
static bool parser_leaveblock(parser_t *parser);
static ast_expression* parse_expression(parser_t *parser, bool stopatcomma, bool with_labels);
static ast_value* parser_create_array_setter_proto(parser_t *parser, ast_value *array, const char *funcname);
static ast_value* parser_create_array_getter_proto(parser_t *parser, ast_value *array, const ast_expression *elemtype, const char *funcname);
+static ast_value *parse_typename(parser_t *parser, ast_value **storebase, ast_value *cached_typedef);
static void parseerror(parser_t *parser, const char *fmt, ...)
{
if (ast_istype(fun, ast_value)) {
funval = (ast_value*)fun;
if ((fun->expression.flags & AST_FLAG_VARIADIC) &&
- !(funval->cvq == CV_CONST && funval->hasvalue && funval->constval.vfunc->builtin))
+ !(/*funval->cvq == CV_CONST && */ funval->hasvalue && funval->constval.vfunc->builtin))
{
size_t va_count;
if (paramcount < vec_size(fun->expression.params))
}
}
+static ast_expression* parse_vararg_do(parser_t *parser)
+{
+ ast_expression *idx, *out;
+ ast_value *typevar;
+ ast_value *funtype = parser->function->vtype;
+
+ lex_ctx ctx = parser_ctx(parser);
+
+ if (!parser_next(parser) || parser->tok != '(') {
+ parseerror(parser, "expected parameter index and type in parenthesis");
+ return NULL;
+ }
+ if (!parser_next(parser)) {
+ parseerror(parser, "error parsing parameter index");
+ return NULL;
+ }
+
+ idx = parse_expression_leave(parser, true, false, false);
+ if (!idx)
+ return NULL;
+
+ if (parser->tok != ',') {
+ ast_unref(idx);
+ parseerror(parser, "expected comma after parameter index");
+ return NULL;
+ }
+
+ if (!parser_next(parser) || (parser->tok != TOKEN_IDENT && parser->tok != TOKEN_TYPENAME)) {
+ ast_unref(idx);
+ parseerror(parser, "expected typename for vararg");
+ return NULL;
+ }
+
+ typevar = parse_typename(parser, NULL, NULL);
+ if (!typevar) {
+ ast_unref(idx);
+ return NULL;
+ }
+
+ if (parser->tok != ')') {
+ ast_unref(idx);
+ ast_delete(typevar);
+ parseerror(parser, "expected closing paren");
+ return NULL;
+ }
+
+#if 0
+ if (!parser_next(parser)) {
+ ast_unref(idx);
+ ast_delete(typevar);
+ parseerror(parser, "parse error after vararg");
+ return NULL;
+ }
+#endif
+
+ if (!parser->function->varargs) {
+ ast_unref(idx);
+ ast_delete(typevar);
+ parseerror(parser, "function has no variable argument list");
+ return NULL;
+ }
+
+ if (funtype->expression.varparam &&
+ !ast_compare_type((ast_expression*)typevar, (ast_expression*)funtype->expression.varparam))
+ {
+ char ty1[1024];
+ char ty2[1024];
+ ast_type_to_string((ast_expression*)typevar, ty1, sizeof(ty1));
+ ast_type_to_string((ast_expression*)funtype->expression.varparam, ty2, sizeof(ty2));
+ compile_error(ast_ctx(typevar),
+ "function was declared to take varargs of type `%s`, requested type is: %s",
+ ty2, ty1);
+ }
+
+ out = (ast_expression*)ast_array_index_new(ctx, (ast_expression*)(parser->function->varargs), idx);
+ ast_type_adopt(out, typevar);
+ ast_delete(typevar);
+ return out;
+}
+
+static ast_expression* parse_vararg(parser_t *parser)
+{
+ bool old_noops = parser->lex->flags.noops;
+ enum parser_pot *old_pot = parser->pot;
+
+ ast_expression *out;
+
+ parser->pot = NULL;
+ parser->lex->flags.noops = true;
+ out = parse_vararg_do(parser);
+
+ parser->pot = old_pot;
+ parser->lex->flags.noops = old_noops;
+ return out;
+}
+
static ast_expression* parse_expression_leave(parser_t *parser, bool stopatcomma, bool truthvalue, bool with_labels)
{
ast_expression *expr = NULL;
goto onerr;
}
}
+ else if (parser->tok == TOKEN_DOTS)
+ {
+ ast_expression *va;
+ if (!OPTS_FLAG(VARIADIC_ARGS)) {
+ parseerror(parser, "cannot access varargs (try -fvariadic-args)");
+ goto onerr;
+ }
+ if (wantop) {
+ parseerror(parser, "expected operator or end of statement");
+ goto onerr;
+ }
+ wantop = true;
+ va = parse_vararg(parser);
+ if (!va)
+ goto onerr;
+ vec_push(sy.out, syexp(parser_ctx(parser), va));
+ DEBUGSHUNTDO(con_out("push `...`\n"));
+ }
else if (parser->tok == TOKEN_IDENT)
{
const char *ctoken = parser_tokval(parser);
return false;
}
- if (var->expression.flags & AST_FLAG_VARIADIC) {
+ if (!OPTS_FLAG(VARIADIC_ARGS) && var->expression.flags & AST_FLAG_VARIADIC) {
if (parsewarning(parser, WARN_VARIADIC_FUNCTION,
"variadic function with implementation will not be able to access additional parameters"))
{
}
vec_push(parser->functions, func);
- if (var->expression.flags & AST_FLAG_VARIADIC) {
+ if (var->argcounter) {
+ ast_value *argc = ast_value_new(ast_ctx(var), var->argcounter, TYPE_FLOAT);
+ parser_addlocal(parser, argc->name, (ast_expression*)argc);
+ func->argc = argc;
+ }
+
+ if (OPTS_FLAG(VARIADIC_ARGS) && var->expression.flags & AST_FLAG_VARIADIC) {
char name[1024];
ast_value *varargs = ast_value_new(ast_ctx(var), "reserved:va_args", TYPE_ARRAY);
varargs->expression.flags |= AST_FLAG_IS_VARARG;
if (!subscript)
return NULL;
+ subscript->expression.next = ast_type_copy(ast_ctx(subscript), (ast_expression*)subscript);
+ subscript->expression.vtype = TYPE_FIELD;
+
entfield = ast_entfield_new_force(ctx,
(ast_expression*)entity,
(ast_expression*)subscript,
goto cleanup;
*/
}
- if (opts.standard == COMPILER_QCC &&
+ if ((opts.standard == COMPILER_QCC || opts.standard == COMPILER_FTEQCC) &&
(old = parser_find_global(parser, var->name)))
{
parseerror(parser, "cannot declare a field and a global of the same name with -std=qcc");