Add parent_scope on all nodes

This commit is contained in:
Krzosa Karol
2022-06-10 16:12:47 +02:00
parent 3402b4fe4d
commit e2d07923c8
6 changed files with 109 additions and 86 deletions

57
ast.cpp
View File

@@ -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<Ast_Decl *> 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<Ast *> 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<Ast_Decl *> 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<Ast_Decl *> 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<Ast_Decl *> 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;
}

View File

@@ -536,24 +536,53 @@ compile_files(Array<String> filename){
parse_init(&ctx, scratch, &heap);
F64 parse_begin = os_time();
Array<Ast_Package> packages = {&heap};
Array<Ast_Package *> 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){

View File

@@ -176,6 +176,7 @@ struct Parse_Ctx:Lexer{
U64 unique_ids;
Map type_map;
Ast_Scope *currently_parsed_scope;
Array<Ast_Scope *> scopes;
Ast_Package *resolving_package;
Array<Ast_Decl *> ordered_decls;

View File

@@ -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

View File

@@ -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<Ast *> 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<Ast_Decl *> 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<Ast_Decl *> 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;
}

View File

@@ -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){
@@ -1016,6 +1024,7 @@ resolve_decl(Ast_Decl *ast, B32 flags){
}
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<Ast_Package> *packages){
find_package(Intern_String name, Array<Ast_Package *> *packages){
For(*packages){
if(it.name == name){
return &it;
if(it->name == name){
return it;
}
}
return 0;