diff options
Diffstat (limited to 'src/ast.c')
-rw-r--r-- | src/ast.c | 61 |
1 files changed, 45 insertions, 16 deletions
@@ -128,6 +128,7 @@ int scope_init(Scope *self, Scope *parent, ScopedAllocator *allocator) { return_if_error(buffer_init(&self->ast_objects, allocator)); return_if_error(hash_map_init(&self->named_objects, allocator, sizeof(Ast*), hash_compare_string, amal_hash_string)); self->parent = parent; + self->parser = NULL; return 0; } @@ -271,7 +272,6 @@ static void import_resolve(Ast *ast, AstCompilerContext *context) { assert(ast->resolve_data.type); } -/* LhsExpr has to be resolved before this is called */ static Scope* lhsexpr_get_scope(LhsExpr *self) { AstValue value; value = self->rhs_expr->value; @@ -289,6 +289,19 @@ static Scope* lhsexpr_get_scope(LhsExpr *self) { return NULL; } +/* @self has to be resolved 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; +} + static void funcdecl_resolve(FunctionDecl *self, AstCompilerContext *context) { /* TODO: Implement parameters and return types */ scope_resolve(&self->body, context); @@ -301,6 +314,22 @@ 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 *callee_parser; + BufferView callee_code_ref; + 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), + "\"%.*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_get_code_reference_index(&callee_parser->tokenizer, callee_code_ref.data), + "Type was declared here"); + throw(AST_ERR); + } ast = buffer_start(&func_call->args); ast_end = buffer_end(&func_call->args); @@ -327,6 +356,7 @@ static void binop_resolve_dot_access(Ast *ast, AstCompilerContext *context) { Scope *lhs_scope; Parser *callee_parser; BufferView caller_code_ref; + BufferView callee_code_ref; assert(ast->type == AST_BINOP); self = ast->value.binop; @@ -343,24 +373,20 @@ static void binop_resolve_dot_access(Ast *ast, AstCompilerContext *context) { lhs_scope = lhsexpr_get_scope(self->lhs->resolve_data.type); self->rhs->resolve_data.type = scope_get_resolved_variable(lhs_scope, context, self->rhs->value.variable->name)->resolve_data.type; - self->rhs->resolve_data.status = AST_RESOLVED; - /* - const io = @import("std.io"); - io.write ^ - ^-from this, to-' - */ - if(self->lhs->resolve_data.type->rhs_expr->type == AST_IMPORT) - callee_parser = self->lhs->resolve_data.type->rhs_expr->value.import->file_scope->parser; - + callee_parser = get_resolved_type_parser(self->rhs); caller_code_ref = ast_get_code_reference(self->rhs); - callee_parser = context->parser; + callee_code_ref = self->rhs->resolve_data.type->var_name; - if(self->rhs->resolve_data.type->rhs_expr->type != AST_STRUCT_DECL) { - /* TODO: Add note where the referenced data was declared */ + 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), - "Can only access field of struct's"); + "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_get_code_reference_index(&callee_parser->tokenizer, callee_code_ref.data), + "Type was declared here"); throw(AST_ERR); } @@ -371,7 +397,7 @@ static void binop_resolve_dot_access(Ast *ast, AstCompilerContext *context) { /* TODO: use tokenizer_print_note, once it has been added */ /* TODO: Print type */ tokenizer_print_error(&context->parser->tokenizer, - tokenizer_get_code_reference_index(&callee_parser->tokenizer, caller_code_ref.data), + tokenizer_get_code_reference_index(&callee_parser->tokenizer, callee_code_ref.data), "Type was declared non-public here"); throw(AST_ERR); } @@ -382,8 +408,11 @@ static void binop_resolve(Ast *ast, AstCompilerContext *context) { assert(ast->type == AST_BINOP); self = ast->value.binop; ast_resolve(self->lhs, context); - if(self->type == BINOP_DOT && self->rhs->type == AST_VARIABLE) { + if(self->type == BINOP_DOT && (self->rhs->type == AST_VARIABLE || self->rhs->type == AST_FUNCTION_CALL)) { binop_resolve_dot_access(ast, context); + /* Only function call has extra data that needs to be resolved (args) */ + if(self->rhs->type == AST_FUNCTION_CALL) + ast_resolve(self->rhs, context); self->rhs->resolve_data.status = AST_RESOLVED; ast->resolve_data.type = self->rhs->resolve_data.type; } else { |