From de48503aef098d855754ab6f85558402130188d7 Mon Sep 17 00:00:00 2001 From: dec05eba Date: Sun, 25 Aug 2019 11:38:32 +0200 Subject: Find tokenizer by code reference instead of using scope parser --- include/ast.h | 2 - include/compiler.h | 1 + src/ast.c | 143 +++++++++++++---------------------------------------- src/parser.c | 1 - 4 files changed, 36 insertions(+), 111 deletions(-) diff --git a/include/ast.h b/include/ast.h index bdab6c3..edf225b 100644 --- a/include/ast.h +++ b/include/ast.h @@ -130,8 +130,6 @@ struct Scope { Buffer/**/ ast_objects; HashMapType(BufferView, Ast*) named_objects; /* Value is always an Ast* with type LhsExpr */ Scope *parent; - /* Is null unless the scope is a file scope, in which case this is the parser that owns the scope */ - Parser *parser; FunctionSignature *function_signature; /* Borrowed from FunctionDecl. Only used if the scope belongs to FunctionDecl */ }; diff --git a/include/compiler.h b/include/compiler.h index 3e3cc92..1ed98f3 100644 --- a/include/compiler.h +++ b/include/compiler.h @@ -70,6 +70,7 @@ CHECK_RESULT int amal_compiler_internal_load_file(amal_compiler *self, const cha /* Returns a reference to the parsers tokenizer that contains the code reference, or NULL. Note: The lifetime of the tokenizer returned is the same as the lifetime of the parser that owns it. + Should only be called once code has been parsed (in AST stage or later), in which case it's thread-safe. */ Tokenizer* amal_compiler_find_tokenizer_by_code_reference(amal_compiler *self, const char *code_ref); diff --git a/src/ast.c b/src/ast.c index cb4d875..76cbf9c 100644 --- a/src/ast.c +++ b/src/ast.c @@ -17,7 +17,6 @@ static void variable_type_resolve(VariableType *self, AstCompilerContext *context, AstResolvedType *resolved_type); static void ast_resolve(Ast *self, AstCompilerContext *context); -static BufferView variable_type_get_name(VariableType *self); static void scope_named_object_init(ScopeNamedObject *self) { self->type = NAMED_OBJECT_NONE; @@ -56,7 +55,7 @@ static BufferView ast_resolved_type_get_name(AstResolvedType *self) { result = create_buffer_view("", 0); break; case RESOLVED_TYPE_LHS_EXPR: - result = variable_type_get_name(&self->value.lhs_expr->type); + result = self->value.lhs_expr->var_name; break; case RESOLVED_TYPE_FUNC_SIG: { if(!self->value.func_sig->func_decl || !self->value.func_sig->func_decl->lhs_expr) { @@ -381,7 +380,6 @@ int scope_init(Scope *self, Scope *parent, ArenaAllocator *allocator) { return_if_error(buffer_init(&self->ast_objects, allocator)); return_if_error(hash_map_init(&self->named_objects, allocator, sizeof(Ast*), hash_map_compare_string, amal_hash_string)); self->parent = parent; - self->parser = NULL; self->function_signature = NULL; return 0; } @@ -432,27 +430,18 @@ void scope_resolve(Scope *self, AstCompilerContext *context) { context->scope = prev_scope; } -static Parser* scope_get_parser(Scope *scope) { - while(scope) { - if(scope->parser) - return scope->parser; - scope = scope->parent; +static void compiler_print_error(amal_compiler *compiler, const char *ref, const char *fmt, ...) { + Tokenizer *tokenizer = amal_compiler_find_tokenizer_by_code_reference(compiler, ref); + if(!tokenizer) { + amal_log_error("Failed to find tokenizer for code reference %p. Is it an invalid reference?", ref ? ref : "(null)"); + return; } - return NULL; -} -static void parser_print_error(Parser *parser, const char *ref, const char *fmt, ...) { va_list args; va_start(args, fmt); - if(parser) { - tokenizer_print_error_args(&parser->tokenizer, - tokenizer_get_code_reference_index(&parser->tokenizer, ref), - fmt, args); - } else { - /* TODO: Redirect error to compiler error callback if set */ - amal_log_error("TODO: Fix this:"); - amal_log_error(fmt, args); - } + tokenizer_print_error_args(tokenizer, + tokenizer_get_code_reference_index(tokenizer, ref), + fmt, args); va_end(args); } @@ -485,12 +474,8 @@ static void __scope_get_resolved_variable(Scope *self, Scope *start, AstCompiler return; } - { - Parser *parser; - parser = scope_get_parser(start); - parser_print_error(parser, name.data, "Undefined reference to variable \"%.*s\"", name.size, name.data); - throw(AST_ERR); - } + compiler_print_error(context->compiler, name.data, "Undefined reference to variable \"%.*s\"", name.size, name.data); + throw(AST_ERR); } /* @@ -563,25 +548,6 @@ void variable_type_resolve(VariableType *self, AstCompilerContext *context, AstR } } -BufferView variable_type_get_name(VariableType *self) { - BufferView result; - switch(self->type) { - case VARIABLE_TYPE_NONE: - result.data = NULL; - result.size = 0; - break; - case VARIABLE_TYPE_VARIABLE: - result = self->value.variable->name; - break; - case VARIABLE_TYPE_SIGNATURE: - /* TODO: Save reference to signature in code in the FunctionSignature type */ - result.data = "fn()"; - result.size = 4; - break; - } - return result; -} - static void lhsexpr_resolve_rhs(LhsExpr *self, AstCompilerContext *context, AstResolvedType *result) { ast_resolve(self->rhs_expr, context); if(ast_is_decl(self->rhs_expr)) { @@ -629,14 +595,11 @@ static void lhsexpr_resolve(Ast *ast, AstCompilerContext *context) { /* TODO: Add casting */ if(ast->resolve_data.type.type == RESOLVED_TYPE_LHS_EXPR && !ast_resolved_type_equals(&ast->resolve_data.type, &rhs_resolve_type)) { - Parser *parser; - parser = scope_get_parser(context->scope); /* - TODO: Instead of using self->var_name, using type name. This cant be done right now because + TODO: Instead of using self->var_name, use type name. This cant be done right now because type can be function signature. */ - parser_print_error(parser, self->var_name.data, - "Variable type and variable assignment type (right-hand side) do not match"); + compiler_print_error(context->compiler, self->var_name.data, "Variable type and variable assignment type (right-hand side) do not match"); throw(AST_ERR); } ast->resolve_data.type = rhs_resolve_type; @@ -683,26 +646,19 @@ static void assignmentexpr_resolve(Ast *ast, AstCompilerContext *context) { /* This also covers extern variables, since extern variables are always const */ /* TODO: var.field type expressions should also be checked */ if(is_lhs_const) { - Parser *parser; - parser = scope_get_parser(context->scope); - parser_print_error(parser, ast_get_code_reference(self->lhs_expr).data, "Can't assign to a const value"); + compiler_print_error(context->compiler, ast_get_code_reference(self->lhs_expr).data, "Can't assign to a const value"); throw(AST_ERR); } /* TODO: Add casting */ if(!ast_resolved_type_equals(&self->lhs_expr->resolve_data.type, &self->rhs_expr->resolve_data.type)) { - Parser *parser; - BufferView rhs_type_name; - BufferView lhs_type_name; - - parser = scope_get_parser(context->scope); - rhs_type_name = ast_resolved_type_get_name(&self->rhs_expr->resolve_data.type); - lhs_type_name = ast_resolved_type_get_name(&self->lhs_expr->resolve_data.type); + BufferView rhs_type_name = ast_resolved_type_get_name(&self->rhs_expr->resolve_data.type); + BufferView lhs_type_name = ast_resolved_type_get_name(&self->lhs_expr->resolve_data.type); /* - TODO: Instead of using self->var_name, using type name. This cant be done right now because + TODO: Instead of using self->var_name, use type name. This cant be done right now because type can be function signature. */ - parser_print_error(parser, ast_get_code_reference(self->lhs_expr).data, + compiler_print_error(context->compiler, ast_get_code_reference(self->lhs_expr).data, "Can't cast data of type %.*s to type %.*s", rhs_type_name.size, rhs_type_name.data, lhs_type_name.size, lhs_type_name.data); throw(AST_ERR); } @@ -750,12 +706,6 @@ static Scope* ast_resolved_type_get_scope(AstResolvedType *self) { return NULL; } -/* @self has to have a resolved type before calling this */ -static Parser* get_resolved_type_parser(Ast *self) { - assert(self->resolve_data.type.type == RESOLVED_TYPE_LHS_EXPR && "Expected get_resolved_type_parser to only be called for non-extern function declaration, struct declaration and import"); - return scope_get_parser(lhsexpr_get_scope(self->resolve_data.type.value.lhs_expr)); -} - static void funcdecl_resolve(Ast *self, AstCompilerContext *context) { FunctionDecl *func_decl; func_decl = self->value.func_decl; @@ -787,19 +737,12 @@ static void funccall_resolve(Ast *self, AstCompilerContext *context) { variable_resolve(&func_call->func, context, &self->resolve_data.type); /* Attemping to use call syntax (variable_name ( ) ) with a variable that is not a function */ if(self->resolve_data.type.type != RESOLVED_TYPE_FUNC_SIG) { - 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 = ast_resolved_type_get_name(&self->resolve_data.type); - - parser_print_error(caller_parser, func_call->func.name.data, + BufferView callee_code_ref = ast_resolved_type_get_name(&self->resolve_data.type); + compiler_print_error(context->compiler, 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 */ - parser_print_error(callee_parser, callee_code_ref.data, "Type was declared here"); + compiler_print_error(context->compiler, callee_code_ref.data, "Type was declared here"); throw(AST_ERR); } @@ -835,21 +778,16 @@ static bool is_struct_decl(Ast *self) { 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; ScopeNamedObject rhs_resolved_var; 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); - parser_print_error(caller_parser, code_ref.data, "Accessing fields is only applicable for variables"); + compiler_print_error(context->compiler, ast_get_code_reference(self->lhs).data, "Accessing fields is only applicable for variables"); throw(AST_ERR); } @@ -857,23 +795,22 @@ static void binop_resolve_dot_access(Ast *ast, AstCompilerContext *context) { scope_get_resolved_variable(lhs_scope, context, self->rhs->value.variable->name, &rhs_resolved_var); self->rhs->resolve_data.type = scope_named_object_get_resolved_type(&rhs_resolved_var, context); - callee_parser = get_resolved_type_parser(self->rhs); caller_code_ref = ast_get_code_reference(self->rhs); callee_code_ref = ast_resolved_type_get_name(&self->rhs->resolve_data.type); if(!is_struct_decl(self->lhs)) { - parser_print_error(caller_parser, caller_code_ref.data, "Can only access field of structs"); + compiler_print_error(context->compiler, caller_code_ref.data, "Can only access field of structs"); /* TODO: use tokenizer_print_note, once it has been added */ /* TODO: Print type */ - parser_print_error(callee_parser, callee_code_ref.data, "Type was declared here"); + compiler_print_error(context->compiler, callee_code_ref.data, "Type was declared here"); throw(AST_ERR); } if(self->rhs->resolve_data.type.type != RESOLVED_TYPE_LHS_EXPR || !LHS_EXPR_IS_PUB(self->rhs->resolve_data.type.value.lhs_expr)) { - parser_print_error(caller_parser, caller_code_ref.data, "Can't access non-public field \"%.*s\"", caller_code_ref.size, caller_code_ref.data); + compiler_print_error(context->compiler, 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 */ - parser_print_error(callee_parser, callee_code_ref.data, "Type was declared non-public here"); + compiler_print_error(context->compiler, callee_code_ref.data, "Type was declared non-public here"); throw(AST_ERR); } } @@ -906,32 +843,24 @@ static void binop_resolve(Ast *ast, AstCompilerContext *context) { TODO: Use note for the additional information instead of error. */ - BufferView lhs_type_name, rhs_type_name; - Parser *parser; - - lhs_type_name = ast_resolved_type_get_name(&self->lhs->resolve_data.type); - rhs_type_name = ast_resolved_type_get_name(&self->rhs->resolve_data.type); - parser = scope_get_parser(context->scope); - parser_print_error(parser, ast_get_code_reference(self->rhs).data, - "Can't cast type \"%.*s\" to type \"%.*s\"", + BufferView lhs_type_name = ast_resolved_type_get_name(&self->lhs->resolve_data.type); + BufferView rhs_type_name = ast_resolved_type_get_name(&self->rhs->resolve_data.type); + compiler_print_error(context->compiler, ast_get_code_reference(self->rhs).data, + "Can't cast type %.*s to type %.*s", rhs_type_name.size, rhs_type_name.data, lhs_type_name.size, lhs_type_name.data); - parser_print_error(parser, ast_get_code_reference(self->lhs).data, + compiler_print_error(context->compiler, ast_get_code_reference(self->lhs).data, "Left-hand side is of type %.*s", lhs_type_name.size, lhs_type_name.data); - parser_print_error(parser, ast_get_code_reference(self->rhs).data, + compiler_print_error(context->compiler, ast_get_code_reference(self->rhs).data, "Right-hand side is of type %.*s", rhs_type_name.size, rhs_type_name.data); throw(AST_ERR); /* TODO: Optimize this? store arithmetic type in the LhsExpr itself? */ } else if(self->lhs->resolve_data.type.type != RESOLVED_TYPE_LHS_EXPR || !is_arithmetic_type(self->lhs->resolve_data.type.value.lhs_expr, context->compiler)) { /* TODO: Point the error at the binop instead of LHS */ - BufferView lhs_type_name; - Parser *parser; - - lhs_type_name = ast_resolved_type_get_name(&self->lhs->resolve_data.type); - parser = scope_get_parser(context->scope); - parser_print_error(parser, ast_get_code_reference(self->lhs).data, + BufferView lhs_type_name = ast_resolved_type_get_name(&self->lhs->resolve_data.type); + compiler_print_error(context->compiler, ast_get_code_reference(self->lhs).data, "Arithmetic operation can only be performed with the types i8, u8, i16, u16, i32, u32, i64, u64, isize and usize", lhs_type_name.size, lhs_type_name.data); throw(AST_ERR); @@ -992,9 +921,7 @@ void ast_resolve(Ast *self, AstCompilerContext *context) { before another file has done it, and it can be different everytime the files are compiled. */ } else if(self->resolve_data.status == AST_RESOLVING && self->parser == context->parser) { - Parser *parser; - parser = scope_get_parser(context->scope); - parser_print_error(parser, ast_get_code_reference(self).data, "Found recursive dependency"); + compiler_print_error(context->compiler, ast_get_code_reference(self).data, "Found recursive dependency"); throw(AST_ERR); } diff --git a/src/parser.c b/src/parser.c index a6b4ecf..df326f0 100644 --- a/src/parser.c +++ b/src/parser.c @@ -39,7 +39,6 @@ int parser_init(Parser *self, amal_compiler *compiler, ArenaAllocator *allocator self->error.str = NULL; self->error_context = ERROR_CONTEXT_NONE; return_if_error(structdecl_init(&self->struct_decl, &compiler->root_scope, allocator)); - self->struct_decl.body.parser = self; lhsexpr_init(&self->file_decl, DECL_FLAG_EXTERN | DECL_FLAG_PUB | DECL_FLAG_CONST, create_buffer_view_null()); return_if_error(ast_create(self->allocator, &self->struct_decl, AST_STRUCT_DECL, &self->file_decl.rhs_expr)); self->current_scope = &self->struct_decl.body; -- cgit v1.2.3