From fe9971d379766a4f7d4576495caff9ffaa80cfef Mon Sep 17 00:00:00 2001 From: dec05eba Date: Tue, 26 Mar 2019 20:54:54 +0100 Subject: Synchronize funccall generate. Uses correct func index now --- include/ast.h | 2 ++ include/parser.h | 1 + src/ast.c | 61 +++++++++++++++++++++++++++++++++++++-------------- src/parser.c | 16 ++++++++------ src/ssa/ssa.c | 67 ++++++++++++++++++++++++++++++++++++-------------------- src/std/log.c | 2 +- tests/main.amal | 3 ++- 7 files changed, 103 insertions(+), 49 deletions(-) diff --git a/include/ast.h b/include/ast.h index eaf2352..580ca24 100644 --- a/include/ast.h +++ b/include/ast.h @@ -76,6 +76,8 @@ struct Scope { Buffer/**/ ast_objects; HashMap/*(key=BufferView, value=Ast*)*/ named_objects; Scope *parent; + /* Is null unless the scope is a file scope, in which case this is the parser that owns the scope */ + Parser *parser; }; struct FileScopeReference { diff --git a/include/parser.h b/include/parser.h index a203b7d..0261800 100644 --- a/include/parser.h +++ b/include/parser.h @@ -38,6 +38,7 @@ struct Parser { StructDecl struct_decl; LhsExpr file_decl; Scope *current_scope; + bool has_func_parent; ScopedAllocator *allocator; /* borrowed. Copied from @compiler for faster access to allocator */ amal_compiler *compiler; bool started; diff --git a/src/ast.c b/src/ast.c index 4ee0934..a2a927c 100644 --- a/src/ast.c +++ b/src/ast.c @@ -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 { diff --git a/src/parser.c b/src/parser.c index 7b69ee7..bac7b3a 100644 --- a/src/parser.c +++ b/src/parser.c @@ -59,16 +59,14 @@ int parser_init(Parser *self, amal_compiler *compiler, ScopedAllocator *allocato 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; return_if_error(lhsexpr_init(&self->file_decl, bool_true, bool_true, create_buffer_view_null(), self->allocator)); 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; + self->has_func_parent = bool_false; return PARSER_OK; } -static bool parser_is_global_scope(Parser *self) { - return self->current_scope == &self->struct_decl.body; -} - /* BODY_LOOP = BODY* @end_token */ @@ -159,10 +157,10 @@ static CHECK_RESULT LhsExpr* parser_parse_lhs(Parser *self, bool *assignment_or_ *assignment_or_rhs = bool_true; throw_if_error(tokenizer_consume_if(&self->tokenizer, TOK_PUB, &is_pub)); - if(is_pub && !parser_is_global_scope(self)) { + if(is_pub && self->has_func_parent) { self->error = tokenizer_create_error(&self->tokenizer, tokenizer_get_code_reference_index(&self->tokenizer, self->tokenizer.value.identifier.data), - "Only declarations in global scope can be public"); + "Only declarations in structs can be public"); throw(PARSER_UNEXPECTED_TOKEN); } @@ -213,11 +211,12 @@ static CHECK_RESULT LhsExpr* parser_parse_lhs(Parser *self, bool *assignment_or_ /* TODO: Implement params and return types -CLOSURE = 'fn' ('(' PARAM* ')')? '{' BODY_LOOP '}' +CLOSURE = 'fn' ('(' PARAM? (',' PARAM)* ')')? '{' BODY_LOOP '}' */ static CHECK_RESULT FunctionDecl* parser_parse_closure(Parser *self) { FunctionDecl *result; bool match; + bool prev_has_func_parent; result = NULL; throw_if_error(tokenizer_consume_if(&self->tokenizer, TOK_FN, &match)); @@ -237,8 +236,11 @@ static CHECK_RESULT FunctionDecl* parser_parse_closure(Parser *self) { throw_if_error(funcdecl_init(result, self->current_scope, self->allocator)); self->current_scope = &result->body; + prev_has_func_parent = self->has_func_parent; + self->has_func_parent = bool_true; parser_parse_body_loop(self, self->current_scope, TOK_CLOSING_BRACE); self->current_scope = result->body.parent; + self->has_func_parent = prev_has_func_parent; return result; } diff --git a/src/ssa/ssa.c b/src/ssa/ssa.c index e55f687..3fffb63 100644 --- a/src/ssa/ssa.c +++ b/src/ssa/ssa.c @@ -2,6 +2,7 @@ #include "../../include/std/mem.h" #include "../../include/std/log.h" #include "../../include/std/hash.h" +#include "../../include/std/thread.h" #include "../../include/ast.h" #include @@ -246,6 +247,27 @@ static CHECK_RESULT SsaRegister number_generate_ssa(Number *self, SsaCompilerCon return reg; } + +static CHECK_RESULT SsaRegister lhs_generate_ssa(LhsExpr *self, SsaCompilerContext *context) { + /* TODO: Implement */ + SsaRegister reg; + throw_if_error(amal_mutex_lock(self->mutex, "lhs_generate_ssa")); + throw_if_error(ssa_get_unique_reg(&context->ssa, ®)); + if(self->rhs_expr) { + SsaRegister rhs_reg; + rhs_reg = ast_generate_ssa(self->rhs_expr, context); + throw_if_error(ssa_ins_assign_reg(&context->ssa, reg, rhs_reg)); + } else { + /* TODO: assign default value to reg depending on LhsExpr type */ + } + throw_if_error(amal_mutex_unlock(self->mutex)); + return reg; +} + +/* +TODO: Each function declaration should be in separate SSA instances so ast can be converted into ssa +in any order. +*/ static CHECK_RESULT SsaRegister funcdecl_generate_ssa(FunctionDecl *self, SsaCompilerContext *context) { /* TODO: Implement */ throw_if_error(ssa_ins_func_start(&context->ssa, 0, &self->ssa_func_index)); @@ -254,21 +276,27 @@ static CHECK_RESULT SsaRegister funcdecl_generate_ssa(FunctionDecl *self, SsaCom return 0; } -static CHECK_RESULT SsaRegister funccall_generate_ssa(FunctionCall *self, SsaCompilerContext *context) { +static CHECK_RESULT SsaRegister funccall_generate_ssa(Ast *self, SsaCompilerContext *context) { /* TODO: Implement */ + FunctionCall *func_call; Ast **ast; Ast **ast_end; SsaRegister reg; - ast = buffer_start(&self->args); - ast_end = buffer_end(&self->args); + assert(self->type == AST_FUNCTION_CALL); + func_call = self->value.func_call; + ast = buffer_start(&func_call->args); + ast_end = buffer_end(&func_call->args); for(; ast != ast_end; ++ast) { SsaRegister arg_reg; arg_reg = ast_generate_ssa(*ast, context); throw_if_error(ssa_ins_push(&context->ssa, arg_reg)); } - /* TODO: Use real func index */ - throw_if_error(ssa_ins_call(&context->ssa, 0, ®)); + + assert(self->resolve_data.type->rhs_expr->type == AST_FUNCTION_DECL); + ignore_result_int(lhs_generate_ssa(self->resolve_data.type, context)); + amal_log_debug("SSA funccall %.*s, func index: %d", func_call->func.name.size, func_call->func.name.data, self->resolve_data.type->rhs_expr->value.func_decl->ssa_func_index); + throw_if_error(ssa_ins_call(&context->ssa, self->resolve_data.type->rhs_expr->value.func_decl->ssa_func_index, ®)); return reg; } @@ -285,20 +313,6 @@ static CHECK_RESULT SsaRegister structfield_generate_ssa(StructField *self, SsaC return 0; } -static CHECK_RESULT SsaRegister lhs_generate_ssa(LhsExpr *self, SsaCompilerContext *context) { - /* TODO: Implement */ - SsaRegister reg; - throw_if_error(ssa_get_unique_reg(&context->ssa, ®)); - if(self->rhs_expr) { - SsaRegister rhs_reg; - rhs_reg = ast_generate_ssa(self->rhs_expr, context); - throw_if_error(ssa_ins_assign_reg(&context->ssa, reg, rhs_reg)); - } else { - /* TODO: assign default value to reg depending on LhsExpr type */ - } - return reg; -} - static CHECK_RESULT SsaRegister string_generate_ssa(String *self, SsaCompilerContext *context) { SsaRegister reg; throw_if_error(ssa_get_unique_reg(&context->ssa, ®)); @@ -324,7 +338,7 @@ static SsaInstructionType binop_type_to_ssa_type(BinopType binop_type) { case BINOP_DIV: return SSA_DIV; case BINOP_DOT: - assert(bool_false && "TODO: Implement dot access"); + assert(bool_false && "Binop dot not valid for arithmetic operation and requires special functionality"); return 0; } return 0; @@ -334,9 +348,14 @@ static CHECK_RESULT SsaRegister binop_generate_ssa(Binop *self, SsaCompilerConte SsaRegister lhs_reg; SsaRegister rhs_reg; SsaRegister reg; - lhs_reg = ast_generate_ssa(self->lhs, context); - rhs_reg = ast_generate_ssa(self->rhs, context); - throw_if_error(ssa_ins_binop(&context->ssa, binop_type_to_ssa_type(self->type), lhs_reg, rhs_reg, ®)); + + if(self->type == BINOP_DOT && self->rhs->resolve_data.type->rhs_expr->type == AST_FUNCTION_DECL) { + reg = ast_generate_ssa(self->rhs, context); + } else { + lhs_reg = ast_generate_ssa(self->lhs, context); + rhs_reg = ast_generate_ssa(self->rhs, context); + throw_if_error(ssa_ins_binop(&context->ssa, binop_type_to_ssa_type(self->type), lhs_reg, rhs_reg, ®)); + } return reg; } @@ -354,7 +373,7 @@ CHECK_RESULT SsaRegister ast_generate_ssa(Ast *self, SsaCompilerContext *context case AST_FUNCTION_DECL: return funcdecl_generate_ssa(self->value.func_decl, context); case AST_FUNCTION_CALL: - return funccall_generate_ssa(self->value.func_call, context); + return funccall_generate_ssa(self, context); case AST_STRUCT_DECL: return structdecl_generate_ssa(self->value.struct_decl, context); case AST_STRUCT_FIELD: diff --git a/src/std/log.c b/src/std/log.c index 2059445..a03e62f 100644 --- a/src/std/log.c +++ b/src/std/log.c @@ -4,7 +4,7 @@ #include #include -/*#define LOG_DEBUG*/ +#define LOG_DEBUG static amal_mutex mutex; static bool mutex_initialized = bool_false; diff --git a/tests/main.amal b/tests/main.amal index 02a9c0a..f778a14 100644 --- a/tests/main.amal +++ b/tests/main.amal @@ -15,7 +15,8 @@ const main = fn { var num1: i64; const num2 = 23232; const num3 = num1 + num2 * 30; - const num4 = (num1 + num2) * num3 * ((34 + 32) / 234.345); + //const num4 = (num1 + num2) * num3 * ((34 + 32) / 234.345); + const num4 = (num1 + num2) * num3 * ((34 + 32) / 2); // pub cost num34 = 45; // error, only declarations in global scope can be public //const num4 = 23; // error, variable redeclaration /* -- cgit v1.2.3