diff options
Diffstat (limited to 'src/ast.c')
-rw-r--r-- | src/ast.c | 104 |
1 files changed, 60 insertions, 44 deletions
@@ -180,6 +180,16 @@ void scope_resolve(Scope *self, AstCompilerContext *context) { context->scope = self->parent; } +static Parser* scope_get_parser(Scope *scope) { + while(scope) { + if(scope->parser) + return scope->parser; + scope = scope->parent; + } + assert(bool_false && "BUG: At least some scope parent is supposed to have a parser"); + return NULL; +} + static Ast* scope_get_resolved_variable(Scope *self, AstCompilerContext *context, BufferView name) { Ast *result; bool exists; @@ -188,11 +198,13 @@ static Ast* scope_get_resolved_variable(Scope *self, AstCompilerContext *context assert(self); exists = hash_map_get(&self->named_objects, name, &result); if(!exists) { + Parser *parser; if(self->parent) return scope_get_resolved_variable(self->parent, context, name); - tokenizer_print_error(&context->parser->tokenizer, - tokenizer_get_code_reference_index(&context->parser->tokenizer, name.data), + parser = scope_get_parser(self); + tokenizer_print_error(&parser->tokenizer, + tokenizer_get_code_reference_index(&parser->tokenizer, name.data), "Undefined reference to variable \"%.*s\"", name.size, name.data); throw(AST_ERR); } @@ -216,13 +228,13 @@ static void variable_resolve(Variable *self, AstCompilerContext *context, AstRes resolve_data->type = scope_get_resolved_variable(context->scope, context, self->name)->resolve_data.type; } -static LhsExpr* lhsexpr_resolve_rhs(Ast *ast, AstCompilerContext *context, LhsExpr *lhs_expr) { +static LhsExpr* lhsexpr_resolve_rhs(LhsExpr *self, AstCompilerContext *context) { LhsExpr *rhs_resolved_type; - ast_resolve(ast, context); - if(ast_is_decl(ast)) - rhs_resolved_type = lhs_expr; + ast_resolve(self->rhs_expr, context); + if(ast_is_decl(self->rhs_expr)) + rhs_resolved_type = self; else - rhs_resolved_type = ast->resolve_data.type; + rhs_resolved_type = self->rhs_expr->resolve_data.type; return rhs_resolved_type; } @@ -246,14 +258,14 @@ static void lhsexpr_resolve(Ast *ast, AstCompilerContext *context) { if(self->rhs_expr->type == AST_FUNCTION_DECL) ast->resolve_data.status = AST_RESOLVED; - rhs_resolve_type = lhsexpr_resolve_rhs(self->rhs_expr, context, self); + rhs_resolve_type = lhsexpr_resolve_rhs(self, context); /* self->rhs_expr can be null here because this is valid: var num: i32; */ - if(ast->resolve_data.type && - self->rhs_expr && - ast->resolve_data.type != rhs_resolve_type) { - tokenizer_print_error(&context->parser->tokenizer, - tokenizer_get_code_reference_index(&context->parser->tokenizer, self->type.name.data), + if(ast->resolve_data.type && self->rhs_expr && ast->resolve_data.type != rhs_resolve_type) { + Parser *parser; + parser = scope_get_parser(context->scope); + tokenizer_print_error(&parser->tokenizer, + tokenizer_get_code_reference_index(&parser->tokenizer, self->type.name.data), "Variable type and variable assignment type (right-hand side) do not match"); throw(AST_ERR); } @@ -289,17 +301,10 @@ static Scope* lhsexpr_get_scope(LhsExpr *self) { return NULL; } -/* @self has to be resolved before calling this */ +/* @self has to have a resolved type before calling this */ static Parser* get_resolved_type_parser(Ast *self) { - Scope *scope; - scope = lhsexpr_get_scope(self->resolve_data.type); - while(scope) { - if(scope->parser) - return scope->parser; - scope = scope->parent; - } - assert(bool_false && "BUG: At least some parent is supposed to have a parser"); - return NULL; + assert(self->resolve_data.type); + return scope_get_parser(lhsexpr_get_scope(self->resolve_data.type)); } static void funcdecl_resolve(FunctionDecl *self, AstCompilerContext *context) { @@ -315,17 +320,20 @@ static void funccall_resolve(Ast *self, AstCompilerContext *context) { func_call = self->value.func_call; variable_resolve(&func_call->func, context, &self->resolve_data); if(self->resolve_data.type->rhs_expr->type != AST_FUNCTION_DECL) { + Parser *caller_parser; Parser *callee_parser; BufferView callee_code_ref; + + caller_parser = scope_get_parser(context->scope); callee_parser = get_resolved_type_parser(self); callee_code_ref = self->resolve_data.type->var_name; - tokenizer_print_error(&context->parser->tokenizer, - tokenizer_get_code_reference_index(&context->parser->tokenizer, func_call->func.name.data), + tokenizer_print_error(&caller_parser->tokenizer, + tokenizer_get_code_reference_index(&caller_parser->tokenizer, func_call->func.name.data), "\"%.*s\" is not a function. Only functions can be called", func_call->func.name.size, func_call->func.name.data); /* TODO: use tokenizer_print_note, once it has been added */ /* TODO: Print type */ - tokenizer_print_error(&context->parser->tokenizer, + tokenizer_print_error(&callee_parser->tokenizer, tokenizer_get_code_reference_index(&callee_parser->tokenizer, callee_code_ref.data), "Type was declared here"); throw(AST_ERR); @@ -354,19 +362,21 @@ static void structfield_resolve(Ast *self, AstCompilerContext *context) { static void binop_resolve_dot_access(Ast *ast, AstCompilerContext *context) { Binop *self; Scope *lhs_scope; + Parser *caller_parser; Parser *callee_parser; BufferView caller_code_ref; BufferView callee_code_ref; assert(ast->type == AST_BINOP); self = ast->value.binop; + caller_parser = scope_get_parser(context->scope); if(self->lhs->type != AST_VARIABLE) { /* TODO: Allow field access for numbers and string as well */ BufferView code_ref; code_ref = ast_get_code_reference(self->lhs); - tokenizer_print_error(&context->parser->tokenizer, - tokenizer_get_code_reference_index(&context->parser->tokenizer, code_ref.data), + tokenizer_print_error(&caller_parser->tokenizer, + tokenizer_get_code_reference_index(&caller_parser->tokenizer, code_ref.data), "Accessing fields is only applicable for variables"); throw(AST_ERR); } @@ -379,24 +389,24 @@ static void binop_resolve_dot_access(Ast *ast, AstCompilerContext *context) { callee_code_ref = self->rhs->resolve_data.type->var_name; if(self->lhs->resolve_data.type->rhs_expr->type != AST_STRUCT_DECL) { - tokenizer_print_error(&context->parser->tokenizer, - tokenizer_get_code_reference_index(&context->parser->tokenizer, caller_code_ref.data), + tokenizer_print_error(&caller_parser->tokenizer, + tokenizer_get_code_reference_index(&caller_parser->tokenizer, caller_code_ref.data), "Can only access field of structs"); /* TODO: use tokenizer_print_note, once it has been added */ /* TODO: Print type */ - tokenizer_print_error(&context->parser->tokenizer, + tokenizer_print_error(&callee_parser->tokenizer, tokenizer_get_code_reference_index(&callee_parser->tokenizer, callee_code_ref.data), "Type was declared here"); throw(AST_ERR); } if(!self->rhs->resolve_data.type->is_pub) { - tokenizer_print_error(&context->parser->tokenizer, - tokenizer_get_code_reference_index(&context->parser->tokenizer, caller_code_ref.data), + tokenizer_print_error(&caller_parser->tokenizer, + tokenizer_get_code_reference_index(&caller_parser->tokenizer, caller_code_ref.data), "Can't access non-public field \"%.*s\"", caller_code_ref.size, caller_code_ref.data); /* TODO: use tokenizer_print_note, once it has been added */ /* TODO: Print type */ - tokenizer_print_error(&context->parser->tokenizer, + tokenizer_print_error(&callee_parser->tokenizer, tokenizer_get_code_reference_index(&callee_parser->tokenizer, callee_code_ref.data), "Type was declared non-public here"); throw(AST_ERR); @@ -425,17 +435,19 @@ static void binop_resolve(Ast *ast, AstCompilerContext *context) { TODO: For this first error, only print the line without a reference to code. This requires change in tokenizer_print_error to be able to take a line as reference. */ - tokenizer_print_error(&context->parser->tokenizer, - tokenizer_get_code_reference_index(&context->parser->tokenizer, ast_get_code_reference(self->rhs).data), + Parser *parser; + parser = scope_get_parser(context->scope); + tokenizer_print_error(&parser->tokenizer, + tokenizer_get_code_reference_index(&parser->tokenizer, ast_get_code_reference(self->rhs).data), "Can't cast type \"%.*s\" to type \"%.*s\"", self->rhs->resolve_data.type->var_name.size, self->rhs->resolve_data.type->var_name.data, self->lhs->resolve_data.type->var_name.size, self->lhs->resolve_data.type->var_name.data); - tokenizer_print_error(&context->parser->tokenizer, - tokenizer_get_code_reference_index(&context->parser->tokenizer, ast_get_code_reference(self->lhs).data), + tokenizer_print_error(&parser->tokenizer, + tokenizer_get_code_reference_index(&parser->tokenizer, ast_get_code_reference(self->lhs).data), "Left-hand side is of type %.*s", self->lhs->resolve_data.type->var_name.size, self->lhs->resolve_data.type->var_name.data); - tokenizer_print_error(&context->parser->tokenizer, - tokenizer_get_code_reference_index(&context->parser->tokenizer, ast_get_code_reference(self->rhs).data), + tokenizer_print_error(&parser->tokenizer, + tokenizer_get_code_reference_index(&parser->tokenizer, ast_get_code_reference(self->rhs).data), "Right-hand side is of type %.*s", self->rhs->resolve_data.type->var_name.size, self->rhs->resolve_data.type->var_name.data); throw(AST_ERR); @@ -460,8 +472,10 @@ void ast_resolve(Ast *self, AstCompilerContext *context) { if(self->resolve_data.status == AST_RESOLVED) { return; } else if(self->resolve_data.status == AST_RESOLVING) { - tokenizer_print_error(&context->parser->tokenizer, - tokenizer_get_code_reference_index(&context->parser->tokenizer, ast_get_code_reference(self).data), + Parser *parser; + parser = scope_get_parser(context->scope); + tokenizer_print_error(&parser->tokenizer, + tokenizer_get_code_reference_index(&parser->tokenizer, ast_get_code_reference(self).data), "Found recursive dependency"); throw(AST_ERR); } @@ -472,9 +486,11 @@ void ast_resolve(Ast *self, AstCompilerContext *context) { amal_mutex_tryunlock(self->value.lhs_expr->mutex); return; } else if(self->resolve_data.status == AST_RESOLVING) { + Parser *parser; + parser = scope_get_parser(context->scope); amal_mutex_tryunlock(self->value.lhs_expr->mutex); - tokenizer_print_error(&context->parser->tokenizer, - tokenizer_get_code_reference_index(&context->parser->tokenizer, ast_get_code_reference(self).data), + tokenizer_print_error(&parser->tokenizer, + tokenizer_get_code_reference_index(&parser->tokenizer, ast_get_code_reference(self).data), "Found recursive dependency"); throw(AST_ERR); } |