type comparison, function prototypes

This commit is contained in:
Wolfgang (Blub) Bumiller 2012-08-14 14:14:56 +02:00
parent e35a26a9e1
commit 65fb4b34b5
3 changed files with 86 additions and 18 deletions

21
ast.c
View file

@ -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_value* ast_value_new(lex_ctx ctx, const char *name, int t)
{ {
ast_instantiate(ast_value, ctx, ast_value_delete); ast_instantiate(ast_value, ctx, ast_value_delete);

2
ast.h
View file

@ -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 GMQCC_WARN ast_value_params_add(ast_value*, ast_value*);
bool ast_compare_type(ast_expression *a, ast_expression *b);
/* Binary /* Binary
* *
* A value-returning binary expression. * A value-returning binary expression.

View file

@ -1398,8 +1398,9 @@ static bool parser_variable(parser_t *parser, ast_block *localblock)
return false; return false;
} }
isfunc = false; olddecl = NULL;
func = NULL; isfunc = false;
func = NULL;
ctx = parser_ctx(parser); ctx = parser_ctx(parser);
var = parser_parse_type(parser, basetype, &isfunc); var = parser_parse_type(parser, basetype, &isfunc);
@ -1411,18 +1412,20 @@ static bool parser_variable(parser_t *parser, ast_block *localblock)
return false; return false;
} }
if (!localblock && (olddecl = parser_find_global(parser, parser_tokval(parser)))) { if (!isfunc) {
ast_value_delete(var); if (!localblock && (olddecl = parser_find_global(parser, parser_tokval(parser)))) {
parseerror(parser, "global %s already declared here: %s:%i\n", ast_value_delete(var);
parser_tokval(parser), ast_ctx(olddecl).file, (int)ast_ctx(olddecl).line); parseerror(parser, "global %s already declared here: %s:%i\n",
return false; 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)) { if (localblock && parser_find_local(parser, parser_tokval(parser), parser->blocklocal)) {
ast_value_delete(var); ast_value_delete(var);
parseerror(parser, "local %s already declared here: %s:%i\n", parseerror(parser, "local %s already declared here: %s:%i\n",
parser_tokval(parser), ast_ctx(olddecl).file, (int)ast_ctx(olddecl).line); parser_tokval(parser), ast_ctx(olddecl).file, (int)ast_ctx(olddecl).line);
return false; return false;
}
} }
if (!ast_value_set_name(var, parser_tokval(parser))) { 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) { if (isfunc) {
/* a function was defined */ /* a function was defined */
ast_value *fval; 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 /* turn var into a value of TYPE_FUNCTION, with the old var
* as return type * as return type
@ -1450,11 +1477,29 @@ static bool parser_variable(parser_t *parser, ast_block *localblock)
fval->expression.next = (ast_expression*)var; fval->expression.next = (ast_expression*)var;
MEM_VECTOR_MOVE(&var->expression, params, &fval->expression, params); MEM_VECTOR_MOVE(&var->expression, params, &fval->expression, params);
if (!parser_t_functions_add(parser, func)) { /* we compare the type late here, but it's easier than
ast_value_delete(var); * messing with the parameter-vector etc. earlier
if (fval) ast_value_delete(fval); */
if (func) ast_function_delete(func); if (proto) {
return false; 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; var = fval;