From 65fb4b34b5f5432ff55fa39aa0c891904a167145 Mon Sep 17 00:00:00 2001 From: "Wolfgang (Blub) Bumiller" Date: Tue, 14 Aug 2012 14:14:56 +0200 Subject: [PATCH] type comparison, function prototypes --- ast.c | 21 +++++++++++++++ ast.h | 2 ++ parser.c | 81 +++++++++++++++++++++++++++++++++++++++++++------------- 3 files changed, 86 insertions(+), 18 deletions(-) diff --git a/ast.c b/ast.c index cbeb274..c99a051 100644 --- a/ast.c +++ b/ast.c @@ -156,6 +156,27 @@ static ast_expression* ast_type_copy(lex_ctx ctx, const ast_expression *ex) } } +bool ast_compare_type(ast_expression *a, ast_expression *b) +{ + if (a->expression.vtype != b->expression.vtype) + return false; + if (!a->expression.next != !b->expression.next) + return false; + if (a->expression.params_count != b->expression.params_count) + return false; + if (a->expression.params_count) { + size_t i; + for (i = 0; i < a->expression.params_count; ++i) { + if (!ast_compare_type((ast_expression*)a->expression.params[i], + (ast_expression*)b->expression.params[i])) + return false; + } + } + if (a->expression.next) + return ast_compare_type(a->expression.next, b->expression.next); + return true; +} + ast_value* ast_value_new(lex_ctx ctx, const char *name, int t) { ast_instantiate(ast_value, ctx, ast_value_delete); diff --git a/ast.h b/ast.h index 42a4b9a..0059e82 100644 --- a/ast.h +++ b/ast.h @@ -160,6 +160,8 @@ 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); + /* Binary * * A value-returning binary expression. diff --git a/parser.c b/parser.c index 6327d58..05c4313 100644 --- a/parser.c +++ b/parser.c @@ -1398,8 +1398,9 @@ static bool parser_variable(parser_t *parser, ast_block *localblock) return false; } - isfunc = false; - func = NULL; + olddecl = NULL; + isfunc = false; + func = NULL; ctx = parser_ctx(parser); var = parser_parse_type(parser, basetype, &isfunc); @@ -1411,18 +1412,20 @@ static bool parser_variable(parser_t *parser, ast_block *localblock) return false; } - if (!localblock && (olddecl = parser_find_global(parser, parser_tokval(parser)))) { - ast_value_delete(var); - parseerror(parser, "global %s already declared here: %s:%i\n", - parser_tokval(parser), ast_ctx(olddecl).file, (int)ast_ctx(olddecl).line); - return false; - } + if (!isfunc) { + if (!localblock && (olddecl = parser_find_global(parser, parser_tokval(parser)))) { + ast_value_delete(var); + parseerror(parser, "global %s already declared here: %s:%i\n", + parser_tokval(parser), ast_ctx(olddecl).file, (int)ast_ctx(olddecl).line); + return false; + } - if (localblock && parser_find_local(parser, parser_tokval(parser), parser->blocklocal)) { - ast_value_delete(var); - parseerror(parser, "local %s already declared here: %s:%i\n", - parser_tokval(parser), ast_ctx(olddecl).file, (int)ast_ctx(olddecl).line); - return false; + if (localblock && parser_find_local(parser, parser_tokval(parser), parser->blocklocal)) { + ast_value_delete(var); + parseerror(parser, "local %s already declared here: %s:%i\n", + parser_tokval(parser), ast_ctx(olddecl).file, (int)ast_ctx(olddecl).line); + return false; + } } if (!ast_value_set_name(var, parser_tokval(parser))) { @@ -1434,6 +1437,30 @@ static bool parser_variable(parser_t *parser, ast_block *localblock) if (isfunc) { /* a function was defined */ ast_value *fval; + ast_value *proto = NULL; + + if (!localblock) + olddecl = parser_find_global(parser, parser_tokval(parser)); + else + olddecl = parser_find_local(parser, parser_tokval(parser), parser->blocklocal); + + if (olddecl) { + /* we had a prototype */ + if (!ast_istype(olddecl, ast_value)) { + /* theoretically not possible you think? + * well: + * vector v; + * void() v_x = {} + * got it? + */ + parseerror(parser, "cannot declare a function with the same name as a vector's member: %s", + parser_tokval(parser)); + ast_value_delete(var); + return false; + } + + proto = (ast_value*)olddecl; + } /* turn var into a value of TYPE_FUNCTION, with the old var * as return type @@ -1450,11 +1477,29 @@ static bool parser_variable(parser_t *parser, ast_block *localblock) fval->expression.next = (ast_expression*)var; MEM_VECTOR_MOVE(&var->expression, params, &fval->expression, params); - if (!parser_t_functions_add(parser, func)) { - ast_value_delete(var); - if (fval) ast_value_delete(fval); - if (func) ast_function_delete(func); - return false; + /* we compare the type late here, but it's easier than + * messing with the parameter-vector etc. earlier + */ + if (proto) { + if (!ast_compare_type((ast_expression*)proto, (ast_expression*)fval)) { + parseerror(parser, "prototype declared at %s:%i had a different type", + ast_ctx(fval).file, ast_ctx(fval).line); + ast_function_delete(func); + ast_value_delete(fval); + return false; + } + ast_function_delete(func); + ast_value_delete(fval); + var = proto; + func = var->constval.vfunc; + } + else + { + if (!parser_t_functions_add(parser, func)) { + ast_function_delete(func); + ast_value_delete(fval); + return false; + } } var = fval; -- 2.39.2