From: Wolfgang (Blub) Bumiller Date: Sun, 19 Aug 2012 17:24:43 +0000 (+0200) Subject: Automatic prototyping of frame-functions X-Git-Tag: 0.1-rc1~156 X-Git-Url: https://git.rm.cloudns.org/?a=commitdiff_plain;h=bd64d7d7b4b5505c26c8494c357a184729172fe8;p=xonotic%2Fgmqcc.git Automatic prototyping of frame-functions --- diff --git a/ast.c b/ast.c index 6598181..8bbce8f 100644 --- a/ast.c +++ b/ast.c @@ -91,7 +91,6 @@ static void ast_expression_delete_full(ast_expression *self) MEM_VEC_FUNCTIONS(ast_expression_common, ast_value*, params) -static ast_expression* ast_type_copy(lex_ctx ctx, const ast_expression *ex); ast_value* ast_value_copy(const ast_value *self) { size_t i; @@ -117,8 +116,7 @@ ast_value* ast_value_copy(const ast_value *self) return cp; } -#define ast_type_adopt(a, b) ast_type_adopt_impl((ast_expression*)(a), (ast_expression*)(b)) -static bool ast_type_adopt_impl(ast_expression *self, const ast_expression *other) +bool ast_type_adopt_impl(ast_expression *self, const ast_expression *other) { size_t i; const ast_expression_common *fromex; @@ -149,7 +147,7 @@ static ast_expression* ast_shallow_type(lex_ctx ctx, int vtype) return self; } -static ast_expression* ast_type_copy(lex_ctx ctx, const ast_expression *ex) +ast_expression* ast_type_copy(lex_ctx ctx, const ast_expression *ex) { size_t i; const ast_expression_common *fromex; diff --git a/ast.h b/ast.h index d118adb..55691eb 100644 --- a/ast.h +++ b/ast.h @@ -162,6 +162,9 @@ bool ast_global_codegen(ast_value *self, ir_builder *ir); bool GMQCC_WARN ast_value_params_add(ast_value*, ast_value*); bool ast_compare_type(ast_expression *a, ast_expression *b); +ast_expression* ast_type_copy(lex_ctx ctx, const ast_expression *ex); +#define ast_type_adopt(a, b) ast_type_adopt_impl((ast_expression*)(a), (ast_expression*)(b)) +bool ast_type_adopt_impl(ast_expression *self, const ast_expression *other); /* Binary * diff --git a/data/frames.qc b/data/frames.qc index e62964c..ab19ad1 100644 --- a/data/frames.qc +++ b/data/frames.qc @@ -16,7 +16,7 @@ $frame stand1 stand2 standX entity self; float time; -void() stand2; +// void() stand2; this is auto-prototyped void() stand1 = [ 0, stand2 ] { // expands to: //self.frame = 0; diff --git a/parser.c b/parser.c index 621f98a..10bcd37 100644 --- a/parser.c +++ b/parser.c @@ -2151,6 +2151,8 @@ nextvar: * self.nextthink = time + 0.1; * self.think = nextthink; */ + nextthink = NULL; + fld_think = parser_find_field(parser, "think"); fld_nextthink = parser_find_field(parser, "nextthink"); fld_frame = parser_find_field(parser, "frame"); @@ -2193,11 +2195,54 @@ nextvar: return false; } - nextthink = parser_expression_leave(parser, true); - if (!nextthink) { - ast_unref(framenum); - parseerror(parser, "expected a think-function in [frame,think] notation"); - return false; + if (parser->tok == TOKEN_IDENT && !parser_find_var(parser, parser_tokval(parser))) + { + /* qc allows the use of not-yet-declared functions here + * - this automatically creates a prototype */ + varentry_t varent; + ast_value *thinkfunc; + ast_expression *functype = fld_think->expression.next; + + thinkfunc = ast_value_new(parser_ctx(parser), parser_tokval(parser), functype->expression.vtype); + if (!thinkfunc || !ast_type_adopt(nextthink, functype)) { + ast_unref(framenum); + parseerror(parser, "failed to create implicit prototype for `%s`", parser_tokval(parser)); + return false; + } + + if (!parser_next(parser)) { + ast_unref(framenum); + return false; + } + + varent.var = (ast_expression*)thinkfunc; + varent.name = util_strdup(thinkfunc->name); + if (nextthink->expression.vtype == TYPE_FUNCTION) + { + ast_function *func; + + func = ast_function_new(parser_ctx(parser), thinkfunc->name, thinkfunc); + if (!func) { + ast_delete(nextthink); + ast_unref(framenum); + parseerror(parser, "failed to create function for implicit prototype for `%s`", + thinkfunc->name); + return false; + } + (void)!parser_t_functions_add(parser, func); + (void)!parser_t_globals_add(parser, varent); + } + else + (void)!parser_t_globals_add(parser, varent); + nextthink = (ast_expression*)thinkfunc; + + } else { + nextthink = parser_expression_leave(parser, true); + if (!nextthink) { + ast_unref(framenum); + parseerror(parser, "expected a think-function in [frame,think] notation"); + return false; + } } if (!ast_istype(nextthink, ast_value) || !( (ast_value*)nextthink )->isconst) {