From e2d07923c8cd75180fdaaa8046b74b3dfcce3391 Mon Sep 17 00:00:00 2001 From: Krzosa Karol Date: Fri, 10 Jun 2022 16:12:47 +0200 Subject: [PATCH] Add parent_scope on all nodes --- ast.cpp | 57 ++++++++++++++++++++++++++++++------------------ ccodegen.cpp | 41 +++++++++++++++++++++++++++++----- compiler.h | 1 + lambdas.kl | 5 ++++- parsing.cpp | 34 ++++++++++++++++------------- typechecking.cpp | 57 ++++++++++++------------------------------------ 6 files changed, 109 insertions(+), 86 deletions(-) diff --git a/ast.cpp b/ast.cpp index 053d231..873eda9 100644 --- a/ast.cpp +++ b/ast.cpp @@ -55,6 +55,7 @@ struct Ast{ Ast_Kind kind; Ast *parent; + Ast_Scope *parent_scope; Ast_Flag flags; }; @@ -226,6 +227,7 @@ struct Ast_Package : Ast_Scope{ Ast_##T *result = exp_alloc_type(pctx->perm, Ast_##T, AF_ZeroMemory);\ result->flags = iflags; \ result->kind = AST_##ikind; \ + result->parent_scope = pctx->currently_parsed_scope; \ result->pos = ipos; \ result->id = ++pctx->unique_ids @@ -417,38 +419,52 @@ ast_array(Token *pos, Ast_Expr *expr){ } function Ast_Scope * -ast_decl_scope(Token *pos, Array decls){ +begin_decl_scope(Allocator *scratch, Token *pos){ AST_NEW(Scope, SCOPE, pos, AST_DECL); - result->decls = decls.tight_copy(pctx->perm); - For(result->decls){ - it->parent = result; - } + result->decls = {scratch}; + pctx->currently_parsed_scope = result; return result; } +function void +finalize_decl_scope(Ast_Scope *scope){ + scope->decls = scope->decls.tight_copy(pctx->perm); + pctx->currently_parsed_scope = scope->parent_scope; + For(scope->decls){ + it->parent = scope; + } +} + function Ast_Scope * -ast_stmt_scope(Token *pos, Array stmts){ +begin_stmt_scope(Allocator *scratch, Token *pos){ AST_NEW(Scope, SCOPE, pos, AST_STMT); - result->stmts = stmts.tight_copy(pctx->perm); + result->stmts = {scratch}; result->decls = {pctx->heap}; - For(result->stmts){ - it->parent = result; - } + pctx->currently_parsed_scope = result; return result; } +function void +finalize_stmt_scope(Ast_Scope *scope){ + scope->stmts = scope->stmts.tight_copy(pctx->perm); + pctx->currently_parsed_scope = scope->parent_scope; + For(scope->stmts){ + it->parent = scope; + } +} + function Ast_Decl * -ast_struct(Token *pos, Array decls){ +ast_struct(Token *pos, Ast_Scope *scope){ AST_NEW(Decl, STRUCT, pos, AST_DECL | AST_AGGREGATE); - result->scope = ast_decl_scope(pos, decls); + result->scope = scope; result->scope->parent = result; return result; } function Ast_Decl * -ast_enum(Token *pos, Ast_Expr *typespec, Array decls){ +ast_enum(Token *pos, Ast_Expr *typespec, Ast_Scope *scope){ AST_NEW(Decl, ENUM, pos, AST_DECL | AST_AGGREGATE); - result->scope = ast_decl_scope(pos, decls); + result->scope = scope; result->typespec = typespec; result->scope->parent = result; if(result->typespec) result->typespec->parent = result; @@ -492,13 +508,12 @@ ast_type(Token *pos, Intern_String name, Ast_Resolved_Type *type){ return result; } -function Ast_Package -ast_package(Allocator *allocator, Intern_String name, Array decls){ - Ast_Package result = {}; - result.kind = AST_PACKAGE; - result.decls = decls.copy(allocator); - result.name = name; - For(result.decls) it->parent = &result; +function Ast_Package * +ast_package(Token *pos, Allocator *allocator, Intern_String name){ + AST_NEW(Package, PACKAGE, pos, 0); + result->kind = AST_PACKAGE; + result->decls = {allocator}; + result->name = name; return result; } diff --git a/ccodegen.cpp b/ccodegen.cpp index 80e6af4..47df6db 100644 --- a/ccodegen.cpp +++ b/ccodegen.cpp @@ -536,24 +536,53 @@ compile_files(Array filename){ parse_init(&ctx, scratch, &heap); F64 parse_begin = os_time(); - Array packages = {&heap}; + Array packages = {&heap}; For(files){ - parse_file(&it); + Scratch file_scratch; + lex_restream(pctx, it.filecontent, it.filename); + + // Figure out package name + // by default it's name of the file + // but if you add [package name] then it's overwritten + Token *token = token_get(); + it.name = token->file; + + if(token_is(SAME_SCOPE) && token_is_keyword(keyword_package, 1)){ + token_next(); token_next(); + Token *package_token = token_expect(TK_Identifier); + it.name = package_token->intern_val; + } Ast_Package *package = find_package(it.name, &packages); if(package){ package->decls.add(it.decls); } else { - Ast_Package p = ast_package(&heap, it.name, it.decls); - insert_builtin_types_into_package(&p); - packages.add(p); + package = ast_package(token, &heap, it.name); + insert_builtin_types_into_package(package); + packages.add(package); + } + pctx->currently_parsed_scope = package; + while(token_expect(SAME_SCOPE)){ + Ast_Decl *decl = parse_decl(true); + if(!decl) break; + + if(decl->kind == AST_STRUCT){ + decl->type = type_type; + decl->type_val = type_incomplete(decl); + decl->state = DECL_RESOLVED; + } + + package->decls.add(decl); + } + pctx->currently_parsed_scope = 0; + } F64 parse_end = os_time(); For(packages){ - resolve_package(&it); + resolve_package(it); } For(pctx->ordered_decls){ diff --git a/compiler.h b/compiler.h index c79e656..73b9412 100644 --- a/compiler.h +++ b/compiler.h @@ -176,6 +176,7 @@ struct Parse_Ctx:Lexer{ U64 unique_ids; Map type_map; + Ast_Scope *currently_parsed_scope; Array scopes; Ast_Package *resolving_package; Array ordered_decls; diff --git a/lambdas.kl b/lambdas.kl index 6b8b14a..a6884f3 100644 --- a/lambdas.kl +++ b/lambdas.kl @@ -17,7 +17,10 @@ if_stmt :: (cond: S64): type for_stmt :: () for i := 0, i < 10, i+=1 - pass + out_of_order_resolving() + +out_of_order_resolving :: () + i = 10 add_10 :: (size: S64): S64 add_20 :: (new_size: S64): S64 diff --git a/parsing.cpp b/parsing.cpp index 1e3669d..19c1c56 100644 --- a/parsing.cpp +++ b/parsing.cpp @@ -185,23 +185,23 @@ parse_optional_type(){ function Ast_Scope * parse_stmt_scope(){ - Ast_Scope *block = 0; + Ast_Scope *scope = 0; if(token_expect(OPEN_SCOPE)){ // @todo: Fix error message here, it doesn't show proper token context Token *token_block = token_get(); Scratch scratch; - Array stmts = {scratch}; + scope = begin_stmt_scope(scratch, token_block); do{ Token *token = token_get(); if(token_match_keyword(keyword_return)){ Ast_Expr *expr = 0; if(!token_is_scope()) expr = parse_expr(); - stmts.add(ast_return(token, expr)); + scope->stmts.add(ast_return(token, expr)); } else if(token_match_keyword(keyword_pass)){ - stmts.add(ast_pass(token)); + scope->stmts.add(ast_pass(token)); } else if(token_match_keyword(keyword_for)){ @@ -226,7 +226,7 @@ parse_stmt_scope(){ } Ast_Scope *for_block = parse_stmt_scope(); - stmts.add(ast_for(token, init, cond, iter, for_block)); + scope->stmts.add(ast_for(token, init, cond, iter, for_block)); } else if(token_match_keyword(keyword_if)){ @@ -260,7 +260,7 @@ parse_stmt_scope(){ } } Ast_If *result_if = ast_if(token, if_nodes); - stmts.add(result_if); + scope->stmts.add(result_if); } else{ @@ -272,7 +272,7 @@ parse_stmt_scope(){ if(result) { result->flags = set_flag(result->flags, AST_STMT); - stmts.add(result); + scope->stmts.add(result); } else { compiler_error(token, "Unexpected token [%s] while parsing statement", name(token->kind)); @@ -281,9 +281,10 @@ parse_stmt_scope(){ } } while(token_match(SAME_SCOPE)); token_expect(CLOSE_SCOPE); - block = ast_stmt_scope(token_block, stmts); + + finalize_stmt_scope(scope); } - return block; + return scope; } function Ast_Lambda * @@ -507,9 +508,10 @@ parse_assign_expr(){ function Ast_Decl * parse_struct(Token *pos){ Scratch scratch; - Array members = {scratch}; + token_match(OPEN_SCOPE); + Ast_Scope *scope = begin_decl_scope(scratch, token_get()); do{ Token *token = token_get(); @@ -517,32 +519,34 @@ parse_struct(Token *pos){ if(!decl) compiler_error(token, "Failed to parse struct member"); decl->flags = set_flag(decl->flags, AST_AGGREGATE_CHILD); - members.add(decl); + scope->decls.add(decl); }while(token_match(SAME_SCOPE)); token_expect(CLOSE_SCOPE); - Ast_Decl *result = ast_struct(pos, members); + finalize_decl_scope(scope); + Ast_Decl *result = ast_struct(pos, scope); return result; } function Ast_Decl * parse_enum(Token *pos){ Scratch scratch; - Array members = {scratch}; Ast_Expr *typespec = parse_optional_type(); token_match(OPEN_SCOPE); + Ast_Scope *scope = begin_decl_scope(scratch, token_get()); do{ Token *name = token_expect(TK_Identifier); Ast_Expr *value = parse_assign_expr(); Ast_Decl *member = ast_const(name, name->intern_val, value); member->flags = set_flag(member->flags, AST_AGGREGATE_CHILD); - members.add(member); + scope->decls.add(member); }while(token_match(SAME_SCOPE)); + finalize_decl_scope(scope); token_expect(CLOSE_SCOPE); - Ast_Decl *result = ast_enum(pos, typespec, members); + Ast_Decl *result = ast_enum(pos, typespec, scope); return result; } diff --git a/typechecking.cpp b/typechecking.cpp index df68a05..d772402 100644 --- a/typechecking.cpp +++ b/typechecking.cpp @@ -550,6 +550,11 @@ search_for_decl_in_current_context(Intern_String name){ function void insert_into_scope(Ast_Scope *scope, Ast_Decl *decl){ + Ast_Decl *find = search_for_decl(scope, decl->name); + if(find){ + compiler_error(decl->pos, "[%s] is already defined in this scope", decl->name.str); + } + scope->decls.add(decl); } @@ -562,6 +567,7 @@ function void insert_type_into_package(Ast_Package *p, String name, Ast_Resolved_Type *type){ Intern_String string = pctx->intern(name); Ast_Decl *decl = ast_type(&null_token, string, type); + decl->parent_scope = p; decl->state = DECL_RESOLVED; insert_into_scope(p, decl); } @@ -634,6 +640,8 @@ require_const_int(Ast_Expr *expr, B32 flags){ function void resolve_stmt(Ast *ast, Ast_Resolved_Type *ret){ if(!ast) return; + assert(ast->parent_scope->kind == AST_SCOPE || ast->parent_scope->kind == AST_PACKAGE); + switch(ast->kind){ CASE(RETURN, Return){ // @todo: need to check if all paths return a value @@ -749,7 +757,7 @@ function Operand resolve_expr(Ast_Expr *ast, B32 flags){ if(!ast && is_flag_set(flags, AST_CAN_BE_NULL)) return {}; assert(is_flag_set(ast->flags, AST_EXPR)); - + assert(ast->parent_scope->kind == AST_SCOPE || ast->parent_scope->kind == AST_PACKAGE); switch(ast->kind){ @@ -1009,13 +1017,14 @@ resolve_decl(Ast_Decl *ast, B32 flags){ if(!op.is_const){ compiler_error(node->pos, "Assigning a value that is not constant to a constant declaration"); } - + node->value = op.value; if(op.value.type == type_type){ node->kind = AST_TYPE; } BREAK(); } + CASE(VAR, Decl){ Ast_Resolved_Type *type = resolve_typespec(node->typespec, AST_CAN_BE_NULL | RESOLVE_TYPESPEC_COMPLETE); Operand op = resolve_expr(node->expr, AST_CAN_BE_NULL); @@ -1075,44 +1084,6 @@ resolve_package(Ast_Package *package){ } } -function void -parse_file(Ast_File *file){ - lex_restream(pctx, file->filecontent, file->filename); - - Scratch scratch; - // - // @note: pop the first token with token_next() / token_expect() - // which always should be an indentation token, - // it updates the indent info on the parser, - // making sure that indentation on - // the first line is properly updated - // - Token *token = token_get(); - file->name = token->file; - file->decls = {scratch}; - - if(token_is(SAME_SCOPE) && token_is_keyword(keyword_package, 1)){ - token_next(); token_next(); - Token *package = token_expect(TK_Identifier); - file->name = package->intern_val; - } - - while(token_expect(SAME_SCOPE)){ - Ast_Decl *decl = parse_decl(true); - if(!decl) break; - - if(decl->kind == AST_STRUCT){ - decl->type = type_type; - decl->type_val = type_incomplete(decl); - decl->state = DECL_RESOLVED; - } - - file->decls.add(decl); - } - - file->decls = file->decls.tight_copy(pctx->perm); -} - function Ast_File ast_file(String filename, String filecontent){ Ast_File result = {}; @@ -1122,10 +1093,10 @@ ast_file(String filename, String filecontent){ } function Ast_Package * -find_package(Intern_String name, Array *packages){ +find_package(Intern_String name, Array *packages){ For(*packages){ - if(it.name == name){ - return ⁢ + if(it->name == name){ + return it; } } return 0;