diff options
author | dec05eba <dec05eba@protonmail.com> | 2019-03-23 16:16:59 +0100 |
---|---|---|
committer | dec05eba <dec05eba@protonmail.com> | 2020-07-25 14:36:46 +0200 |
commit | dc90305a767feaacc3430aaee0928b745a8e5b0f (patch) | |
tree | 6d85df4245a84820dfdf6425f0aa095a563cabbe /src | |
parent | 4f308829ad0e81a59971e172284c018cf2bdca3d (diff) |
Use ast pointers to fix resolving, remove try/throwing macros
Diffstat (limited to 'src')
-rw-r--r-- | src/ast.c | 229 | ||||
-rw-r--r-- | src/compiler.c | 12 | ||||
-rw-r--r-- | src/parser.c | 312 | ||||
-rw-r--r-- | src/ssa/ssa.c | 40 |
4 files changed, 321 insertions, 272 deletions
@@ -4,37 +4,38 @@ #include "../include/std/hash.h" #include <assert.h> -#define throw(result) do { longjmp(context->env, (result)); } while(0) +#define throw(result) do { throw_debug_msg; longjmp(context->env, (result)); } while(0) #define throw_if_error(result) \ -do { \ - int return_if_result; \ - return_if_result = (result); \ - if((return_if_result) != 0) \ - throw(return_if_result); \ -} while(0) + do { \ + int return_if_result; \ + return_if_result = (result); \ + if((return_if_result) != 0) \ + throw(return_if_result); \ + } while(0) static void ast_resolve(Ast *self, AstCompilerContext *context); -Ast ast_none() { - Ast ast; - ast.value.func_decl = NULL; - ast.type = AST_NONE; - ast.resolve_status = AST_NOT_RESOLVED; - ast.resolved_type = NULL; - return ast; +static void resolve_data_init(AstResolveData *self) { + self->status = AST_NOT_RESOLVED; + self->type = NULL; } -void ast_init(Ast *self, void *value, AstType type) { - self->value.data = value; - self->type = type; - self->resolve_status = AST_NOT_RESOLVED; - self->resolved_type = NULL; +int ast_create(ScopedAllocator *allocator, void *value, AstType type, Ast **result) { + return_if_error(scoped_allocator_alloc(allocator, sizeof(Ast), (void**)result)); + (*result)->value.data = value; + (*result)->type = type; + resolve_data_init(&(*result)->resolve_data); + return 0; +} + +static bool ast_is_decl(Ast *self) { + /* TODO: Add more types as they are introduced */ + return self->type == AST_FUNCTION_DECL || self->type == AST_STRUCT_DECL; } BufferView ast_get_name(Ast *self) { BufferView name; switch(self->type) { - case AST_NONE: case AST_FUNCTION_DECL: case AST_STRUCT_DECL: case AST_IMPORT: @@ -87,7 +88,7 @@ int lhsexpr_init(LhsExpr *self, bool is_pub, bool is_const, BufferView var_name, self->is_const = is_const; variable_init(&self->type, create_buffer_view_null()); self->var_name = var_name; - self->rhs_expr = ast_none(); + self->rhs_expr = NULL; if(is_pub && allocator) return_if_error(scoped_allocator_create_mutex(allocator, &self->mutex)); else @@ -116,15 +117,15 @@ void variable_init(Variable *self, BufferView name) { } void binop_init(Binop *self) { - self->lhs = ast_none(); - self->rhs = ast_none(); + self->lhs = NULL; + self->rhs = NULL; self->type = BINOP_ADD; self->grouped = bool_false; } 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)); + return_if_error(hash_map_init(&self->named_objects, allocator, sizeof(Ast*), hash_compare_string, amal_hash_string)); self->parent = parent; return 0; } @@ -143,7 +144,7 @@ int file_scope_reference_init(FileScopeReference *self, BufferView canonical_pat } int scope_add_child(Scope *self, Ast *child) { - Ast existing_child; + Ast *existing_child; bool child_already_exists; /* TODO: Implement for parameter */ @@ -154,9 +155,9 @@ int scope_add_child(Scope *self, Ast *child) { if(child_already_exists) return AST_ERR_DEF_DUP; - cleanup_if_error(hash_map_insert(&self->named_objects, var_name, child)); + cleanup_if_error(hash_map_insert(&self->named_objects, var_name, &child)); } - cleanup_if_error(buffer_append(&self->ast_objects, child, sizeof(Ast))); + cleanup_if_error(buffer_append(&self->ast_objects, &child, sizeof(Ast*))); return 0; cleanup: @@ -164,20 +165,20 @@ int scope_add_child(Scope *self, Ast *child) { } void scope_resolve(Scope *self, AstCompilerContext *context) { - Ast *ast; - Ast *ast_end; + Ast **ast; + Ast **ast_end; ast = buffer_start(&self->ast_objects); ast_end = buffer_end(&self->ast_objects); context->scope = self; for(; ast != ast_end; ++ast) { - ast_resolve(ast, context); + ast_resolve(*ast, context); } context->scope = self->parent; } static LhsExpr* scope_get_resolved_variable(Scope *self, AstCompilerContext *context, BufferView name) { - Ast result; + Ast *result; bool exists; Scope *prev_scope; @@ -200,54 +201,82 @@ static LhsExpr* scope_get_resolved_variable(Scope *self, AstCompilerContext *con */ prev_scope = context->scope; context->scope = self; - ast_resolve(&result, context); + ast_resolve(result, context); context->scope = prev_scope; - assert(result.type == AST_LHS); - return result.value.lhs_expr; + assert(result->type == AST_LHS); + return result->value.lhs_expr; } -/* @resolved_type is the same field as the ast resolved_type for the variable @self */ -static void variable_resolve(Variable *self, AstCompilerContext *context, LhsExpr **resolved_type) { - /* TODO: Verify this is correct in all cases */ - *resolved_type = scope_get_resolved_variable(context->scope, context, self->name); +static void variable_resolve(Variable *self, AstCompilerContext *context, AstResolveData *resolve_data) { + if(!resolve_data->type) + resolve_data->type = scope_get_resolved_variable(context->scope, context, self->name); } -static void lhsexpr_resolve(Ast *self, AstCompilerContext *context) { - LhsExpr *lhs_expr; - lhs_expr = self->value.lhs_expr; +static LhsExpr* lhsexpr_resolve_rhs(Ast *ast, AstCompilerContext *context, LhsExpr *lhs_expr) { + LhsExpr *rhs_resolved_type; + ast_resolve(ast, context); + if(ast_is_decl(ast)) + rhs_resolved_type = lhs_expr; + else + rhs_resolved_type = ast->resolve_data.type; + return rhs_resolved_type; +} - if(lhs_expr->type.name.data) - variable_resolve(&lhs_expr->type, context, &self->resolved_type); - self->resolve_status = AST_RESOLVED; - ast_resolve(&lhs_expr->rhs_expr, context); +static void lhsexpr_resolve(Ast *ast, AstCompilerContext *context) { + LhsExpr *self; + LhsExpr *rhs_resolve_type; - if(self->resolved_type && - lhs_expr->rhs_expr.type != AST_NONE && - self->resolved_type != lhs_expr->rhs_expr.resolved_type) { - tokenizer_print_error(&context->parser->tokenizer, - tokenizer_get_code_reference_index(&context->parser->tokenizer, ast_get_code_reference(self).data), - "Variable type and variable assignment type (right-hand side) do not match"); - throw(AST_ERR); + assert(ast->type == AST_LHS); + self = ast->value.lhs_expr; + rhs_resolve_type = NULL; + + if(self->type.name.data) + variable_resolve(&self->type, context, &ast->resolve_data); + + /* + TODO: When parameters and return types are implemented, AST_RESOLVE_END should be set after + the parameters and return types have been resolved as recursive function calls should + be allowed but recursive function calls still require parameters and return types to be known. + */ + if(self->rhs_expr) { + 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); + + /* 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), + "Variable type and variable assignment type (right-hand side) do not match"); + throw(AST_ERR); + } } - self->resolved_type = lhs_expr->rhs_expr.resolved_type; + + if(rhs_resolve_type) + ast->resolve_data.type = rhs_resolve_type; } /* LhsExpr has to be resolved before this is called */ +#if 0 static Scope* lhsexpr_get_scope(LhsExpr *self) { - switch(self->rhs_expr.type) { + switch(self->rhs_expr->type) { case AST_FUNCTION_DECL: - return &self->rhs_expr.value.func_decl->body; + return &self->rhs_expr->value.func_decl->body; case AST_STRUCT_DECL: - return &self->rhs_expr.value.struct_decl->body; + return &self->rhs_expr->value.struct_decl->body; case AST_IMPORT: - return self->rhs_expr.value.import->file_scope->scope; + return self->rhs_expr->value.import->file_scope->scope; default: break; } assert(bool_false && "Expected lhsexpr_get_scope to only be called for function decl and struct decl"); return NULL; } +#endif static void import_resolve(Ast *self, AstCompilerContext *context) { Import *import; @@ -258,32 +287,27 @@ static void import_resolve(Ast *self, AstCompilerContext *context) { /* TODO: Convert all scopes to structs and set import->resolved_type to import->file_scope->scope; */ } -static void funcdecl_resolve(Ast *self, AstCompilerContext *context) { - /* TODO: Implement */ - FunctionDecl *func_decl; - assert(self->type == AST_FUNCTION_DECL); - func_decl = self->value.func_decl; - self->resolve_status = AST_RESOLVED; - scope_resolve(&func_decl->body, context); +static void funcdecl_resolve(FunctionDecl *self, AstCompilerContext *context) { + /* TODO: Implement parameters and return types */ + scope_resolve(&self->body, context); } static void funccall_resolve(Ast *self, AstCompilerContext *context) { FunctionCall *func_call; - Ast *ast; - Ast *ast_end; + Ast **ast; + Ast **ast_end; func_call = self->value.func_call; - variable_resolve(&func_call->func, context, &self->resolved_type); + variable_resolve(&func_call->func, context, &self->resolve_data); ast = buffer_start(&func_call->args); ast_end = buffer_end(&func_call->args); for(; ast != ast_end; ++ast) { - ast_resolve(ast, context); + ast_resolve(*ast, context); } } static void structdecl_resolve(Ast *self, AstCompilerContext *context) { - /* TODO: What to do with resolved_type? */ StructDecl *struct_decl; struct_decl = self->value.struct_decl; scope_resolve(&struct_decl->body, context); @@ -293,26 +317,52 @@ static void structfield_resolve(Ast *self, AstCompilerContext *context) { /* TODO: Implement */ StructField *struct_field; struct_field = self->value.struct_field; - variable_resolve(&struct_field->type, context, &self->resolved_type); + variable_resolve(&struct_field->type, context, &self->resolve_data); } -static void binop_resolve(Binop *self, AstCompilerContext *context) { - /* TODO: Implement */ - ast_resolve(&self->lhs, context); - if(self->rhs.type == AST_VARIABLE) { - Scope *prev_scope; - assert(self->lhs.resolved_type); - prev_scope = context->scope; - context->scope = lhsexpr_get_scope(self->lhs.resolved_type); - assert(context->scope); - ast_resolve(&self->rhs, context); - context->scope = prev_scope; +static void binop_resolve(Ast *ast, AstCompilerContext *context) { + Binop *self; + assert(ast->type == AST_BINOP); + self = ast->value.binop; + ast_resolve(self->lhs, context); + #if 0 /* TODO: Readd this once mutex has been added for types */ + if(self->type == BINOP_DOT && self->rhs->type == AST_VARIABLE) { + Scope *lhs_scope; + 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); + self->rhs->resolve_data.status = AST_RESOLVED; + ast->resolve_data.type = self->rhs->resolve_data.type; } else { - ast_resolve(&self->rhs, context); + ast_resolve(self->rhs, context); + /* TODO: Convert types that can be safely converted */ + if(self->lhs->resolve_data.type != self->rhs->resolve_data.type) { + /* + 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->lhs).data), + "Right-hand side and left-hand side are different types"); + tokenizer_print_error(&context->parser->tokenizer, + tokenizer_get_code_reference_index(&context->parser->tokenizer, ast_get_code_reference(self->lhs).data), + "Left-hand side is of type %.*s", + self->rhs->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), + "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); + } } + #else + ast_resolve(self->rhs, context); + #endif } void ast_resolve(Ast *self, AstCompilerContext *context) { + assert(self); /* TODO: Move these to the types that need checks for recursive dependency (function declaration, struct declaration) For function declaration, it should be marked as resolved when the signature has been resolved @@ -320,23 +370,22 @@ void ast_resolve(Ast *self, AstCompilerContext *context) { because the body can have function call that calls functions that are resolving or even recursive function call, which should be allowed. */ - if(self->resolve_status == AST_RESOLVED) { + if(self->resolve_data.status == AST_RESOLVED) { return; - } else if(self->resolve_status == AST_RESOLVING) { + } 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), "Found recursive dependency"); throw(AST_ERR); } - self->resolve_status = AST_RESOLVING; + self->resolve_data.status = AST_RESOLVING; switch(self->type) { - case AST_NONE: case AST_NUMBER: /* Nothing to resolve for numbers */ break; case AST_FUNCTION_DECL: - funcdecl_resolve(self, context); + funcdecl_resolve(self->value.func_decl, context); break; case AST_FUNCTION_CALL: funccall_resolve(self, context); @@ -358,12 +407,12 @@ void ast_resolve(Ast *self, AstCompilerContext *context) { /* TODO: Convert special combinations. For example \n to newline */ break; case AST_VARIABLE: - variable_resolve(self->value.variable, context, &self->resolved_type); + variable_resolve(self->value.variable, context, &self->resolve_data); break; case AST_BINOP: - binop_resolve(self->value.binop, context); + binop_resolve(self, context); break; } /* TODO: See comment at the top of this function */ - self->resolve_status = AST_RESOLVED; + self->resolve_data.status = AST_RESOLVED; } diff --git a/src/compiler.c b/src/compiler.c index 50678d8..cc35d1e 100644 --- a/src/compiler.c +++ b/src/compiler.c @@ -41,7 +41,7 @@ static usize strnlen(const char *str, usize max_length) { static CHECK_RESULT int create_default_type(amal_compiler *compiler, const char *name) { StructDecl *struct_decl; LhsExpr *lhs_expr; - Ast expr; + Ast *expr; return_if_error(scoped_allocator_alloc(&compiler->allocator, sizeof(StructDecl), (void**)&struct_decl)); return_if_error(structdecl_init(struct_decl, &compiler->root_scope, &compiler->allocator)); @@ -50,11 +50,11 @@ static CHECK_RESULT int create_default_type(amal_compiler *compiler, const char return_if_error(lhsexpr_init(lhs_expr, bool_true, bool_true, create_buffer_view(name, strnlen(name, PATH_MAX)), NULL)); - ast_init(&lhs_expr->rhs_expr, struct_decl, AST_STRUCT_DECL); - ast_init(&expr, lhs_expr, AST_LHS); - expr.resolved_type = lhs_expr; - expr.resolve_status = AST_RESOLVED; - return scope_add_child(&compiler->root_scope, &expr); + return_if_error(ast_create(&compiler->allocator, struct_decl, AST_STRUCT_DECL, &lhs_expr->rhs_expr)); + return_if_error(ast_create(&compiler->allocator, lhs_expr, AST_LHS, &expr)); + expr->resolve_data.type = lhs_expr; + expr->resolve_data.status = AST_RESOLVED; + return scope_add_child(&compiler->root_scope, expr); } static CHECK_RESULT int init_default_types(amal_compiler *compiler) { diff --git a/src/parser.c b/src/parser.c index b1764a1..9e92ddd 100644 --- a/src/parser.c +++ b/src/parser.c @@ -11,19 +11,6 @@ #include <stdlib.h> #include <assert.h> -#ifdef AMAL_PEDANTIC - #define throw_debug_msg do {} while(0) -#else - #define throw_debug_msg do { amal_log_info("Throwing from %s:%d", __FUNCTION__, __LINE__); } while(0) -#endif - -#define THROWABLE CHECK_RESULT int -#define try(result) \ -do { \ - int return_if_result; \ - return_if_result = (result); \ - (void)return_if_result; \ -} while(0) #define throw(result) do { throw_debug_msg; longjmp(self->parse_env, (result)); } while(0) #define throw_if_error(result) \ do { \ @@ -33,10 +20,10 @@ do { \ throw(return_if_result); \ } while(0) -static THROWABLE parser_parse_rhs_start(Parser *self, Ast *rhs_expr, bool is_standalone); -static THROWABLE parser_parse_body(Parser *self, Ast *ast); -static THROWABLE parser_parse_struct_body(Parser *self, Ast *ast); -static THROWABLE parser_queue_file(Parser *self, BufferView path, FileScopeReference **file_scope); +static CHECK_RESULT Ast* parser_parse_rhs_start(Parser *self, bool is_standalone); +static CHECK_RESULT Ast* parser_parse_body(Parser *self); +static CHECK_RESULT Ast* parser_parse_struct_body(Parser *self); +static void parser_queue_file(Parser *self, BufferView path, FileScopeReference **file_scope); int parser_thread_data_init(ParserThreadData *self) { am_memset(&self->allocator, 0, sizeof(self->allocator)); @@ -82,23 +69,23 @@ static bool parser_is_global_scope(Parser *self) { /* BODY_LOOP = BODY* @end_token */ -static THROWABLE parser_parse_body_loop(Parser *self, Scope *scope, Token end_token) { +static void parser_parse_body_loop(Parser *self, Scope *scope, Token end_token) { int result; for(;;) { - Ast body_obj; + Ast *body_obj; bool is_end_token; throw_if_error(tokenizer_consume_if(&self->tokenizer, end_token, &is_end_token)); if(is_end_token) break; - try(parser_parse_body(self, &body_obj)); - result = scope_add_child(scope, &body_obj); + body_obj = parser_parse_body(self); + result = scope_add_child(scope, body_obj); if(result == 0) { continue; } else if(result == AST_ERR_DEF_DUP) { /* TODO: Convert ast type to string for error message */ BufferView obj_name; - obj_name = ast_get_name(&body_obj); + obj_name = ast_get_name(body_obj); self->error = tokenizer_create_error(&self->tokenizer, tokenizer_get_code_reference_index(&self->tokenizer, obj_name.data), "Variable with the name %.*s was declared twice in the same scope", obj_name.size, obj_name.data); @@ -108,30 +95,29 @@ static THROWABLE parser_parse_body_loop(Parser *self, Scope *scope, Token end_to throw(result); } } - return PARSER_OK; } /* STRUCT_BODY_LOOP = '{' STRUCT_BODY* '}' */ -static THROWABLE parser_parse_struct_body_loop(Parser *self, Scope *scope) { +static void parser_parse_struct_body_loop(Parser *self, Scope *scope) { int result; throw_if_error(tokenizer_accept(&self->tokenizer, TOK_OPEN_BRACE)); for(;;) { - Ast body_obj; + Ast *body_obj; bool is_end_token; throw_if_error(tokenizer_consume_if(&self->tokenizer, TOK_CLOSING_BRACE, &is_end_token)); if(is_end_token) break; - try(parser_parse_struct_body(self, &body_obj)); - result = scope_add_child(scope, &body_obj); + body_obj = parser_parse_struct_body(self); + result = scope_add_child(scope, body_obj); if(result == 0) { continue; } else if(result == AST_ERR_DEF_DUP) { /* TODO: Convert ast type to string for error message */ BufferView obj_name; - obj_name = ast_get_name(&body_obj); + obj_name = ast_get_name(body_obj); self->error = tokenizer_create_error(&self->tokenizer, tokenizer_get_code_reference_index(&self->tokenizer, obj_name.data), "Variable with the name %.*s was declared twice in the struct", obj_name.size, obj_name.data); @@ -141,32 +127,32 @@ static THROWABLE parser_parse_struct_body_loop(Parser *self, Scope *scope) { throw(result); } } - return PARSER_OK; } /* VAR_TYPE_DEF = ':' TOK_IDENTIFIER */ -static THROWABLE parser_parse_var_type_def(Parser *self, BufferView *type_name) { +static void parser_parse_var_type_def(Parser *self, BufferView *type_name) { bool match; throw_if_error(tokenizer_consume_if(&self->tokenizer, TOK_COLON, &match)); if(match) { throw_if_error(tokenizer_accept(&self->tokenizer, TOK_IDENTIFIER)); *type_name = self->tokenizer.value.identifier; } - return PARSER_OK; } /* -LHS = ('const' TOK_IDENTIFIER VAR_TYPE_DEF? '=') | - ('var' TOK_IDENTIFIER VAR_TYPE_DEF? '='|';') +LHS = ('pub'? 'const' TOK_IDENTIFIER VAR_TYPE_DEF? '=') | + ('pub'? 'var' TOK_IDENTIFIER VAR_TYPE_DEF? '='|';') */ -static THROWABLE parser_parse_lhs(Parser *self, LhsExpr **result, bool *assignment_or_rhs) { +static CHECK_RESULT LhsExpr* parser_parse_lhs(Parser *self, bool *assignment_or_rhs) { + LhsExpr *result; bool is_pub; bool is_const; bool match; BufferView var_name; - *result = NULL; + + result = NULL; *assignment_or_rhs = bool_true; throw_if_error(tokenizer_consume_if(&self->tokenizer, TOK_PUB, &is_pub)); @@ -182,23 +168,23 @@ static THROWABLE parser_parse_lhs(Parser *self, LhsExpr **result, bool *assignme bool isVar; throw_if_error(tokenizer_consume_if(&self->tokenizer, TOK_VAR, &isVar)); if(!isVar) - return PARSER_OK; + return result; } throw_if_error(tokenizer_accept(&self->tokenizer, TOK_IDENTIFIER)); var_name = self->tokenizer.value.identifier; - throw_if_error(scoped_allocator_alloc(self->allocator, sizeof(LhsExpr), (void**)result)); - throw_if_error(lhsexpr_init(*result, is_pub, is_const, var_name, self->allocator)); + throw_if_error(scoped_allocator_alloc(self->allocator, sizeof(LhsExpr), (void**)&result)); + throw_if_error(lhsexpr_init(result, is_pub, is_const, var_name, self->allocator)); - try(parser_parse_var_type_def(self, &(*result)->type.name)); + parser_parse_var_type_def(self, &result->type.name); throw_if_error(tokenizer_consume_if(&self->tokenizer, TOK_EQUALS, &match)); if(match) { *assignment_or_rhs = bool_true; - return PARSER_OK; + return result; } - if(!(*result)->type.name.data) { + if(!result->type.name.data) { self->error = tokenizer_create_error(&self->tokenizer, tokenizer_get_error_index(&self->tokenizer), "Variable declaration requires type or right-hand side expression (Expected ':' or '=')"); @@ -219,20 +205,21 @@ static THROWABLE parser_parse_lhs(Parser *self, LhsExpr **result, bool *assignme "Expected ';'"); throw(PARSER_UNEXPECTED_TOKEN); } - return PARSER_OK; + return result; } /* -TODO: Implement params +TODO: Implement params and return types CLOSURE = 'fn' ('(' PARAM* ')')? '{' BODY_LOOP '}' */ -static THROWABLE parser_parse_function_decl(Parser *self, FunctionDecl **func_decl) { +static CHECK_RESULT FunctionDecl* parser_parse_closure(Parser *self) { + FunctionDecl *result; bool match; - *func_decl = NULL; + result = NULL; throw_if_error(tokenizer_consume_if(&self->tokenizer, TOK_FN, &match)); if(!match) - return PARSER_OK; + return result; throw_if_error(tokenizer_consume_if(&self->tokenizer, TOK_OPEN_BRACE, &match)); if(!match) { @@ -243,46 +230,47 @@ static THROWABLE parser_parse_function_decl(Parser *self, FunctionDecl **func_de throw_if_error(tokenizer_accept(&self->tokenizer, TOK_OPEN_BRACE)); } - throw_if_error(scoped_allocator_alloc(self->allocator, sizeof(FunctionDecl), (void**)func_decl)); - throw_if_error(funcdecl_init(*func_decl, self->current_scope, self->allocator)); + throw_if_error(scoped_allocator_alloc(self->allocator, sizeof(FunctionDecl), (void**)&result)); + throw_if_error(funcdecl_init(result, self->current_scope, self->allocator)); - self->current_scope = &(*func_decl)->body; - try(parser_parse_body_loop(self, self->current_scope, TOK_CLOSING_BRACE)); - self->current_scope = (*func_decl)->body.parent; - return PARSER_OK; + self->current_scope = &result->body; + parser_parse_body_loop(self, self->current_scope, TOK_CLOSING_BRACE); + self->current_scope = result->body.parent; + return result; } /* STRUCT = 'struct' '{' STRUCT_BODY_LOOP '}' */ -static THROWABLE parser_parse_struct_decl(Parser *self, StructDecl **struct_decl) { +static CHECK_RESULT StructDecl* parser_parse_struct_decl(Parser *self) { + StructDecl *result; bool match; - *struct_decl = NULL; + result = NULL; throw_if_error(tokenizer_consume_if(&self->tokenizer, TOK_STRUCT, &match)); if(!match) - return PARSER_OK; + return result; - throw_if_error(scoped_allocator_alloc(self->allocator, sizeof(StructDecl), (void**)struct_decl)); - throw_if_error(structdecl_init(*struct_decl, self->current_scope, self->allocator)); + throw_if_error(scoped_allocator_alloc(self->allocator, sizeof(StructDecl), (void**)&result)); + throw_if_error(structdecl_init(result, self->current_scope, self->allocator)); - self->current_scope = &(*struct_decl)->body; - try(parser_parse_struct_body_loop(self, self->current_scope)); - self->current_scope = (*struct_decl)->body.parent; - return PARSER_OK; + self->current_scope = &result->body; + parser_parse_struct_body_loop(self, self->current_scope); + self->current_scope = result->body.parent; + return result; } /* FUNC_ARGS = (RHS_START)? (',' RHS_START)* ')' */ -static THROWABLE parser_parse_function_args(Parser *self, FunctionCall *func_call) { +static void parser_parse_function_args(Parser *self, FunctionCall *func_call) { bool first_arg; first_arg = bool_true; for(;;) { - Ast arg_expr; + Ast *arg_expr; bool is_end_token; - arg_expr = ast_none(); + arg_expr = NULL; throw_if_error(tokenizer_consume_if(&self->tokenizer, TOK_CLOSING_PAREN, &is_end_token)); if(is_end_token) @@ -292,25 +280,25 @@ static THROWABLE parser_parse_function_args(Parser *self, FunctionCall *func_cal throw_if_error(tokenizer_accept(&self->tokenizer, TOK_COMMA)); first_arg = bool_false; - try(parser_parse_rhs_start(self, &arg_expr, bool_false)); + arg_expr = parser_parse_rhs_start(self, bool_false); throw_if_error(buffer_append(&func_call->args, &arg_expr, sizeof(arg_expr))); } - - return PARSER_OK; } /* VARIABLE = TOK_IDENTIFIER FUNC_CALL_OR_VARIABLE = VARIABLE '(' FUNC_ARGS ')' */ -static THROWABLE parser_parse_function_call_or_variable(Parser *self, Ast *expr) { +static CHECK_RESULT Ast* parser_parse_function_call_or_variable(Parser *self) { + Ast *result; bool match; BufferView identifier; FunctionCall *func_call; + result = NULL; throw_if_error(tokenizer_consume_if(&self->tokenizer, TOK_IDENTIFIER, &match)); if(!match) - return PARSER_OK; + return result; identifier = self->tokenizer.value.identifier; throw_if_error(tokenizer_consume_if(&self->tokenizer, TOK_OPEN_PAREN, &match)); @@ -318,70 +306,74 @@ static THROWABLE parser_parse_function_call_or_variable(Parser *self, Ast *expr) Variable *variable; throw_if_error(scoped_allocator_alloc(self->allocator, sizeof(Variable), (void**)&variable)); variable_init(variable, identifier); - ast_init(expr, variable, AST_VARIABLE); - return PARSER_OK; + throw_if_error(ast_create(self->allocator, variable, AST_VARIABLE, &result)); + return result; } throw_if_error(scoped_allocator_alloc(self->allocator, sizeof(FunctionCall), (void**)&func_call)); throw_if_error(funccall_init(func_call, self->tokenizer.value.identifier, self->allocator)); - ast_init(expr, func_call, AST_FUNCTION_CALL); - try(parser_parse_function_args(self, func_call)); - return PARSER_OK; + throw_if_error(ast_create(self->allocator, func_call, AST_FUNCTION_CALL, &result)); + parser_parse_function_args(self, func_call); + return result; } /* IMPORT = IMPORT_SYMBOL */ -static THROWABLE parser_parse_import(Parser *self, Import **import) { +static CHECK_RESULT Import* parser_parse_import(Parser *self) { + Import *result; bool match; - *import = NULL; + result = NULL; throw_if_error(tokenizer_consume_if(&self->tokenizer, TOK_IMPORT, &match)); if(!match) - return PARSER_OK; + return result; - throw_if_error(scoped_allocator_alloc(self->allocator, sizeof(Import), (void**)import)); - import_init(*import, self->tokenizer.value.string); - return PARSER_OK; + throw_if_error(scoped_allocator_alloc(self->allocator, sizeof(Import), (void**)&result)); + import_init(result, self->tokenizer.value.string); + return result; } -static THROWABLE parser_parse_number(Parser *self, Ast *rhs_expr) { +static CHECK_RESULT Ast* parser_parse_number(Parser *self) { + Ast *result; bool match; Number *number; + result = NULL; throw_if_error(tokenizer_consume_if(&self->tokenizer, TOK_NUMBER, &match)); if(!match) - return PARSER_OK; + return result; throw_if_error(scoped_allocator_alloc(self->allocator, sizeof(Number), (void**)&number)); number_init(number, self->tokenizer.value.integer, self->tokenizer.number_is_integer); - ast_init(rhs_expr, number, AST_NUMBER); - return PARSER_OK; + throw_if_error(ast_create(self->allocator, number, AST_NUMBER, &result)); + return result; } /* RHS_S = STRING | NUMBER | FUNC_CALL_OR_VARIABLE */ -static THROWABLE parser_parse_rhs_single_expr(Parser *self, Ast *rhs_expr) { +static Ast* parser_parse_rhs_single_expr(Parser *self) { + Ast *result; bool match; - *rhs_expr = ast_none(); + result = NULL; throw_if_error(tokenizer_consume_if(&self->tokenizer, TOK_STRING, &match)); if(match) { String *string; throw_if_error(scoped_allocator_alloc(self->allocator, sizeof(String), (void**)&string)); throw_if_error(string_init(string, self->tokenizer.value.string)); - ast_init(rhs_expr, string, AST_STRING); - return PARSER_OK; + throw_if_error(ast_create(self->allocator, string, AST_STRING, &result)); + return result; } - try(parser_parse_number(self, rhs_expr)); - if(rhs_expr->type != AST_NONE) - return PARSER_OK; + result = parser_parse_number(self); + if(result) + return result; - try(parser_parse_function_call_or_variable(self, rhs_expr)); - if(rhs_expr->type != AST_NONE) - return PARSER_OK; + result = parser_parse_function_call_or_variable(self); + if(result) + return result; self->error = tokenizer_create_error(&self->tokenizer, tokenizer_get_error_index(&self->tokenizer), @@ -389,25 +381,24 @@ static THROWABLE parser_parse_rhs_single_expr(Parser *self, Ast *rhs_expr) { throw(PARSER_UNEXPECTED_TOKEN); } -static THROWABLE parser_parse_rhs_binop(Parser *self, Ast *expr); +static CHECK_RESULT Ast* parser_parse_rhs_binop(Parser *self); /* RHS_BINOP_OPT_PAREN = RHS_S | '(' RHS_BINOP ')' */ -static THROWABLE parser_parse_rhs_binop_opt_paren(Parser *self, Ast *expr) { +static CHECK_RESULT Ast* parser_parse_rhs_binop_opt_paren(Parser *self) { + Ast *result; bool match; + throw_if_error(tokenizer_consume_if(&self->tokenizer, TOK_OPEN_PAREN, &match)); - if(!match) { - try(parser_parse_rhs_single_expr(self, expr)); - return PARSER_OK; - } + if(!match) + return parser_parse_rhs_single_expr(self); - try(parser_parse_rhs_binop(self, expr)); + result = parser_parse_rhs_binop(self); throw_if_error(tokenizer_accept(&self->tokenizer, TOK_CLOSING_PAREN)); - if(expr->type == AST_BINOP) - expr->value.binop->grouped = bool_true; - - return PARSER_OK; + if(result->type == AST_BINOP) + result->value.binop->grouped = bool_true; + return result; } /* @@ -415,29 +406,28 @@ RHS_BINOP = RHS_BINOP_OPT_PAREN (TOK_BINOP RHS_BINOP_OPT_PAREN)? Note: Parantheses count has to match for the beginning paranthesis and the ending parenthesis. */ -int parser_parse_rhs_binop(Parser *self, Ast *expr) { +Ast* parser_parse_rhs_binop(Parser *self) { bool match; - Ast lhs; - Ast rhs; + Ast *result; + Ast *lhs; + Ast *rhs; BinopType binop_type; Binop *binop; - try(parser_parse_rhs_binop_opt_paren(self, &lhs)); + lhs = parser_parse_rhs_binop_opt_paren(self); throw_if_error(tokenizer_consume_if(&self->tokenizer, TOK_BINOP, &match)); - if(!match) { - *expr = lhs; - return PARSER_OK; - } + if(!match) + return lhs; binop_type = self->tokenizer.value.binop_type; - try(parser_parse_rhs_binop(self, &rhs)); + rhs = parser_parse_rhs_binop(self); throw_if_error(scoped_allocator_alloc(self->allocator, sizeof(Binop), (void**)&binop)); binop_init(binop); binop->type = binop_type; binop->lhs = lhs; binop->rhs = rhs; - ast_init(expr, binop, AST_BINOP); - return PARSER_OK; + throw_if_error(ast_create(self->allocator, binop, AST_BINOP, &result)); + return result; } /* @@ -445,48 +435,51 @@ RHS = RHS_BINOP ';' Note: Parantheses count has to match for the beginning paranthesis and the ending parenthesis. */ -static THROWABLE parser_parse_rhs(Parser *self, Ast *rhs_expr) { +static CHECK_RESULT Ast* parser_parse_rhs(Parser *self) { /* TODO: If binop only contains one expression, then use that directly for @rhs_expr */ - try(parser_parse_rhs_binop(self, rhs_expr)); + Ast *result; + result = parser_parse_rhs_binop(self); /* TODO: Implement this */ /*binop_reorder_by_precedence(binop);*/ - return PARSER_OK; + return result; } /* RHS_START = CLOSURE | IMPORT | RHS */ -int parser_parse_rhs_start(Parser *self, Ast *rhs_expr, bool is_standalone) { - FunctionDecl *func_decl; - StructDecl *struct_decl; - Import *import; +Ast* parser_parse_rhs_start(Parser *self, bool is_standalone) { + Ast *result; if(!is_standalone) { - try(parser_parse_function_decl(self, &func_decl)); + FunctionDecl *func_decl; + StructDecl *struct_decl; + Import *import; + + func_decl = parser_parse_closure(self); if(func_decl) { - ast_init(rhs_expr, func_decl, AST_FUNCTION_DECL); - return PARSER_OK; + throw_if_error(ast_create(self->allocator, func_decl, AST_FUNCTION_DECL, &result)); + return result; } - try(parser_parse_struct_decl(self, &struct_decl)); + struct_decl = parser_parse_struct_decl(self); if(struct_decl) { - ast_init(rhs_expr, struct_decl, AST_STRUCT_DECL); - return PARSER_OK; + throw_if_error(ast_create(self->allocator, struct_decl, AST_STRUCT_DECL, &result)); + return result; } - try(parser_parse_import(self, &import)); + import = parser_parse_import(self); if(import) { - try(parser_queue_file(self, import->path, &import->file_scope)); - ast_init(rhs_expr, import, AST_IMPORT); - return PARSER_OK; + parser_queue_file(self, import->path, &import->file_scope); + throw_if_error(ast_create(self->allocator, import, AST_IMPORT, &result)); + return result; } self->error_context = ERROR_CONTEXT_RHS_STANDALONE; } - try(parser_parse_rhs(self, rhs_expr)); + result = parser_parse_rhs(self); self->error_context = ERROR_CONTEXT_NONE; - return PARSER_OK; + return result; } /* @@ -494,7 +487,7 @@ BODY_SEMICOLON = ';' Note: Semicolon is not required for closures, structs and tables */ -static THROWABLE parser_parse_body_semicolon(Parser *self, Ast *expr) { +static void parser_parse_body_semicolon(Parser *self, Ast *expr) { if(expr->type == AST_BINOP) { bool match; throw_if_error(tokenizer_consume_if(&self->tokenizer, TOK_SEMICOLON, &match)); @@ -505,14 +498,12 @@ static THROWABLE parser_parse_body_semicolon(Parser *self, Ast *expr) { "Expected ';' or binop"); throw(PARSER_UNEXPECTED_TOKEN); } - return PARSER_OK; + return; } /* TODO: Check for tables */ if(expr->type != AST_FUNCTION_DECL && expr->type != AST_STRUCT_DECL) throw_if_error(tokenizer_accept(&self->tokenizer, TOK_SEMICOLON)); - - return PARSER_OK; } /* @@ -520,37 +511,38 @@ BODY = LHS ';' | (LHS '=' RHS_START BODY_SEMICOLON) | (RHS_START BODY_SEMICOLON) */ -int parser_parse_body(Parser *self, Ast *ast) { +Ast* parser_parse_body(Parser *self) { bool assignment_or_rhs; + Ast *result; LhsExpr *lhs_expr; - Ast rhs_expr; - rhs_expr = ast_none(); + Ast *rhs_expr; - try(parser_parse_lhs(self, &lhs_expr, &assignment_or_rhs)); + lhs_expr = parser_parse_lhs(self, &assignment_or_rhs); if(!assignment_or_rhs) { - ast_init(ast, lhs_expr, AST_LHS); - return PARSER_OK; + throw_if_error(ast_create(self->allocator, lhs_expr, AST_LHS, &result)); + return result; } if(!lhs_expr) self->error_context = ERROR_CONTEXT_NO_LHS; - try(parser_parse_rhs_start(self, &rhs_expr, lhs_expr == NULL)); + rhs_expr = parser_parse_rhs_start(self, !lhs_expr); if(lhs_expr) { lhs_expr->rhs_expr = rhs_expr; - ast_init(ast, lhs_expr, AST_LHS); + throw_if_error(ast_create(self->allocator, lhs_expr, AST_LHS, &result)); } else { - *ast = rhs_expr; + result = rhs_expr; } - try(parser_parse_body_semicolon(self, &rhs_expr)); - return PARSER_OK; + parser_parse_body_semicolon(self, rhs_expr); + return result; } /* -STRUCT_BODY = LHS ';' +STRUCT_BODY = TOK_IDENTIFIER ':' TOK_IDENTIFIER ';' */ -int parser_parse_struct_body(Parser *self, Ast *ast) { +Ast* parser_parse_struct_body(Parser *self) { + Ast *result; BufferView var_name; BufferView type_name; StructField *struct_field; @@ -563,8 +555,8 @@ int parser_parse_struct_body(Parser *self, Ast *ast) { throw_if_error(tokenizer_accept(&self->tokenizer, TOK_SEMICOLON)); throw_if_error(scoped_allocator_alloc(self->allocator, sizeof(LhsExpr), (void**)&struct_field)); structfield_init(struct_field, var_name, type_name); - ast_init(ast, struct_field, AST_STRUCT_FIELD); - return PARSER_OK; + throw_if_error(ast_create(self->allocator, struct_field, AST_STRUCT_FIELD, &result)); + return result; } /* @@ -575,7 +567,7 @@ int parser_parse_buffer(Parser *self, BufferView code_buffer, BufferView buffer_ throw_if_error(tokenizer_init(&self->tokenizer, self->allocator, code_buffer, buffer_name)); result = setjmp(self->parse_env); if(result == 0) - try(parser_parse_body_loop(self, &self->scope, TOK_END_OF_FILE)); + parser_parse_body_loop(self, &self->scope, TOK_END_OF_FILE); else if(self->error.str != NULL) { switch(self->error_context) { case ERROR_CONTEXT_NONE: @@ -592,9 +584,8 @@ int parser_parse_buffer(Parser *self, BufferView code_buffer, BufferView buffer_ break; } } - if(result != 0) { - amal_log_info("Failed, reason: %d", result); - } + if(result != 0) + amal_log_error("Failed, reason: %d", result); return result; } @@ -626,14 +617,14 @@ static CHECK_RESULT int file_path_join(BufferView directory, BufferView file, ch Path can be path to included library path (or system library path) in which case the path separator is a dot, otherwise the path separator is forward slash '/' */ -int parser_queue_file(Parser *self, BufferView path, FileScopeReference **file_scope) { +void parser_queue_file(Parser *self, BufferView path, FileScopeReference **file_scope) { /* TODO: Parse special path (to include library path with dots) */ BufferView file_directory; char *path_relative; int result; file_directory = file_get_parent_directory(self->tokenizer.code_name); - return_if_error(file_path_join(file_directory, path, &path_relative)); + throw_if_error(file_path_join(file_directory, path, &path_relative)); /* We want buffer to be null-terminated but null character should not be included for the size */ result = amal_compiler_load_file(self->compiler, path_relative, file_scope); if(result != 0) { @@ -644,5 +635,4 @@ int parser_queue_file(Parser *self, BufferView path, FileScopeReference **file_s throw(result); } am_free(path_relative); - return PARSER_OK; } diff --git a/src/ssa/ssa.c b/src/ssa/ssa.c index b04e469..e55f687 100644 --- a/src/ssa/ssa.c +++ b/src/ssa/ssa.c @@ -256,15 +256,15 @@ static CHECK_RESULT SsaRegister funcdecl_generate_ssa(FunctionDecl *self, SsaCom static CHECK_RESULT SsaRegister funccall_generate_ssa(FunctionCall *self, SsaCompilerContext *context) { /* TODO: Implement */ - Ast *ast; - Ast *ast_end; + Ast **ast; + Ast **ast_end; SsaRegister reg; ast = buffer_start(&self->args); ast_end = buffer_end(&self->args); for(; ast != ast_end; ++ast) { SsaRegister arg_reg; - arg_reg = ast_generate_ssa(ast, context); + arg_reg = ast_generate_ssa(*ast, context); throw_if_error(ssa_ins_push(&context->ssa, arg_reg)); } /* TODO: Use real func index */ @@ -287,10 +287,16 @@ static CHECK_RESULT SsaRegister structfield_generate_ssa(StructField *self, SsaC static CHECK_RESULT SsaRegister lhs_generate_ssa(LhsExpr *self, SsaCompilerContext *context) { /* TODO: Implement */ - SsaRegister rhs_reg; - rhs_reg = ast_generate_ssa(&self->rhs_expr, context); - /* TODO: Is this correct? */ - return rhs_reg; + 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) { @@ -328,17 +334,21 @@ 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); + 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; } CHECK_RESULT SsaRegister ast_generate_ssa(Ast *self, SsaCompilerContext *context) { - assert(self->resolve_status == AST_RESOLVED); + assert(self); + #ifdef DEBUG + if(self->resolve_data.status != AST_RESOLVED) { + amal_log_error("Ast type not resolved: %d", self->type); + assert(bool_false); + } + #endif switch(self->type) { - case AST_NONE: - return 0; case AST_NUMBER: return number_generate_ssa(self->value.number, context); case AST_FUNCTION_DECL: @@ -365,11 +375,11 @@ CHECK_RESULT SsaRegister ast_generate_ssa(Ast *self, SsaCompilerContext *context } void scope_generate_ssa(Scope *self, SsaCompilerContext *context) { - Ast *ast; - Ast *ast_end; + Ast **ast; + Ast **ast_end; ast = buffer_start(&self->ast_objects); ast_end = buffer_end(&self->ast_objects); for(; ast != ast_end; ++ast) { - ignore_result_int(ast_generate_ssa(ast, context)); + ignore_result_int(ast_generate_ssa(*ast, context)); } } |