Automatic prototyping of frame-functions

This commit is contained in:
Wolfgang (Blub) Bumiller 2012-08-19 19:24:43 +02:00
parent 9aa86bee16
commit bd64d7d7b4
4 changed files with 56 additions and 10 deletions

6
ast.c
View file

@ -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;

3
ast.h
View file

@ -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
*

View file

@ -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;

View file

@ -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) {