Add parent_scope on all nodes
This commit is contained in:
57
ast.cpp
57
ast.cpp
@@ -55,6 +55,7 @@ struct Ast{
|
|||||||
|
|
||||||
Ast_Kind kind;
|
Ast_Kind kind;
|
||||||
Ast *parent;
|
Ast *parent;
|
||||||
|
Ast_Scope *parent_scope;
|
||||||
Ast_Flag flags;
|
Ast_Flag flags;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -226,6 +227,7 @@ struct Ast_Package : Ast_Scope{
|
|||||||
Ast_##T *result = exp_alloc_type(pctx->perm, Ast_##T, AF_ZeroMemory);\
|
Ast_##T *result = exp_alloc_type(pctx->perm, Ast_##T, AF_ZeroMemory);\
|
||||||
result->flags = iflags; \
|
result->flags = iflags; \
|
||||||
result->kind = AST_##ikind; \
|
result->kind = AST_##ikind; \
|
||||||
|
result->parent_scope = pctx->currently_parsed_scope; \
|
||||||
result->pos = ipos; \
|
result->pos = ipos; \
|
||||||
result->id = ++pctx->unique_ids
|
result->id = ++pctx->unique_ids
|
||||||
|
|
||||||
@@ -417,38 +419,52 @@ ast_array(Token *pos, Ast_Expr *expr){
|
|||||||
}
|
}
|
||||||
|
|
||||||
function Ast_Scope *
|
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);
|
AST_NEW(Scope, SCOPE, pos, AST_DECL);
|
||||||
result->decls = decls.tight_copy(pctx->perm);
|
result->decls = {scratch};
|
||||||
For(result->decls){
|
pctx->currently_parsed_scope = result;
|
||||||
it->parent = result;
|
|
||||||
}
|
|
||||||
return 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 *
|
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);
|
AST_NEW(Scope, SCOPE, pos, AST_STMT);
|
||||||
result->stmts = stmts.tight_copy(pctx->perm);
|
result->stmts = {scratch};
|
||||||
result->decls = {pctx->heap};
|
result->decls = {pctx->heap};
|
||||||
For(result->stmts){
|
pctx->currently_parsed_scope = result;
|
||||||
it->parent = result;
|
|
||||||
}
|
|
||||||
return 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 *
|
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);
|
AST_NEW(Decl, STRUCT, pos, AST_DECL | AST_AGGREGATE);
|
||||||
result->scope = ast_decl_scope(pos, decls);
|
result->scope = scope;
|
||||||
result->scope->parent = result;
|
result->scope->parent = result;
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
function Ast_Decl *
|
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);
|
AST_NEW(Decl, ENUM, pos, AST_DECL | AST_AGGREGATE);
|
||||||
result->scope = ast_decl_scope(pos, decls);
|
result->scope = scope;
|
||||||
result->typespec = typespec;
|
result->typespec = typespec;
|
||||||
result->scope->parent = result;
|
result->scope->parent = result;
|
||||||
if(result->typespec) result->typespec->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;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
function Ast_Package
|
function Ast_Package *
|
||||||
ast_package(Allocator *allocator, Intern_String name, Array<Ast_Decl *> decls){
|
ast_package(Token *pos, Allocator *allocator, Intern_String name){
|
||||||
Ast_Package result = {};
|
AST_NEW(Package, PACKAGE, pos, 0);
|
||||||
result.kind = AST_PACKAGE;
|
result->kind = AST_PACKAGE;
|
||||||
result.decls = decls.copy(allocator);
|
result->decls = {allocator};
|
||||||
result.name = name;
|
result->name = name;
|
||||||
For(result.decls) it->parent = &result;
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
41
ccodegen.cpp
41
ccodegen.cpp
@@ -536,24 +536,53 @@ compile_files(Array<String> filename){
|
|||||||
parse_init(&ctx, scratch, &heap);
|
parse_init(&ctx, scratch, &heap);
|
||||||
|
|
||||||
F64 parse_begin = os_time();
|
F64 parse_begin = os_time();
|
||||||
Array<Ast_Package> packages = {&heap};
|
Array<Ast_Package *> packages = {&heap};
|
||||||
For(files){
|
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);
|
Ast_Package *package = find_package(it.name, &packages);
|
||||||
if(package){
|
if(package){
|
||||||
package->decls.add(it.decls);
|
package->decls.add(it.decls);
|
||||||
} else {
|
} else {
|
||||||
Ast_Package p = ast_package(&heap, it.name, it.decls);
|
package = ast_package(token, &heap, it.name);
|
||||||
insert_builtin_types_into_package(&p);
|
insert_builtin_types_into_package(package);
|
||||||
packages.add(p);
|
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();
|
F64 parse_end = os_time();
|
||||||
|
|
||||||
For(packages){
|
For(packages){
|
||||||
resolve_package(&it);
|
resolve_package(it);
|
||||||
}
|
}
|
||||||
|
|
||||||
For(pctx->ordered_decls){
|
For(pctx->ordered_decls){
|
||||||
|
|||||||
@@ -176,6 +176,7 @@ struct Parse_Ctx:Lexer{
|
|||||||
U64 unique_ids;
|
U64 unique_ids;
|
||||||
Map type_map;
|
Map type_map;
|
||||||
|
|
||||||
|
Ast_Scope *currently_parsed_scope;
|
||||||
Array<Ast_Scope *> scopes;
|
Array<Ast_Scope *> scopes;
|
||||||
Ast_Package *resolving_package;
|
Ast_Package *resolving_package;
|
||||||
Array<Ast_Decl *> ordered_decls;
|
Array<Ast_Decl *> ordered_decls;
|
||||||
|
|||||||
@@ -17,7 +17,10 @@ if_stmt :: (cond: S64): type
|
|||||||
|
|
||||||
for_stmt :: ()
|
for_stmt :: ()
|
||||||
for i := 0, i < 10, i+=1
|
for i := 0, i < 10, i+=1
|
||||||
pass
|
out_of_order_resolving()
|
||||||
|
|
||||||
|
out_of_order_resolving :: ()
|
||||||
|
i = 10
|
||||||
|
|
||||||
add_10 :: (size: S64): S64
|
add_10 :: (size: S64): S64
|
||||||
add_20 :: (new_size: S64): S64
|
add_20 :: (new_size: S64): S64
|
||||||
|
|||||||
34
parsing.cpp
34
parsing.cpp
@@ -185,23 +185,23 @@ parse_optional_type(){
|
|||||||
|
|
||||||
function Ast_Scope *
|
function Ast_Scope *
|
||||||
parse_stmt_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
|
if(token_expect(OPEN_SCOPE)){ // @todo: Fix error message here, it doesn't show proper token context
|
||||||
Token *token_block = token_get();
|
Token *token_block = token_get();
|
||||||
|
|
||||||
Scratch scratch;
|
Scratch scratch;
|
||||||
Array<Ast *> stmts = {scratch};
|
scope = begin_stmt_scope(scratch, token_block);
|
||||||
do{
|
do{
|
||||||
Token *token = token_get();
|
Token *token = token_get();
|
||||||
if(token_match_keyword(keyword_return)){
|
if(token_match_keyword(keyword_return)){
|
||||||
Ast_Expr *expr = 0;
|
Ast_Expr *expr = 0;
|
||||||
if(!token_is_scope()) expr = parse_expr();
|
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)){
|
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)){
|
else if(token_match_keyword(keyword_for)){
|
||||||
@@ -226,7 +226,7 @@ parse_stmt_scope(){
|
|||||||
}
|
}
|
||||||
|
|
||||||
Ast_Scope *for_block = 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)){
|
else if(token_match_keyword(keyword_if)){
|
||||||
@@ -260,7 +260,7 @@ parse_stmt_scope(){
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
Ast_If *result_if = ast_if(token, if_nodes);
|
Ast_If *result_if = ast_if(token, if_nodes);
|
||||||
stmts.add(result_if);
|
scope->stmts.add(result_if);
|
||||||
|
|
||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
@@ -272,7 +272,7 @@ parse_stmt_scope(){
|
|||||||
|
|
||||||
if(result) {
|
if(result) {
|
||||||
result->flags = set_flag(result->flags, AST_STMT);
|
result->flags = set_flag(result->flags, AST_STMT);
|
||||||
stmts.add(result);
|
scope->stmts.add(result);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
compiler_error(token, "Unexpected token [%s] while parsing statement", name(token->kind));
|
compiler_error(token, "Unexpected token [%s] while parsing statement", name(token->kind));
|
||||||
@@ -281,9 +281,10 @@ parse_stmt_scope(){
|
|||||||
}
|
}
|
||||||
} while(token_match(SAME_SCOPE));
|
} while(token_match(SAME_SCOPE));
|
||||||
token_expect(CLOSE_SCOPE);
|
token_expect(CLOSE_SCOPE);
|
||||||
block = ast_stmt_scope(token_block, stmts);
|
|
||||||
|
finalize_stmt_scope(scope);
|
||||||
}
|
}
|
||||||
return block;
|
return scope;
|
||||||
}
|
}
|
||||||
|
|
||||||
function Ast_Lambda *
|
function Ast_Lambda *
|
||||||
@@ -507,9 +508,10 @@ parse_assign_expr(){
|
|||||||
function Ast_Decl *
|
function Ast_Decl *
|
||||||
parse_struct(Token *pos){
|
parse_struct(Token *pos){
|
||||||
Scratch scratch;
|
Scratch scratch;
|
||||||
Array<Ast_Decl *> members = {scratch};
|
|
||||||
|
|
||||||
token_match(OPEN_SCOPE);
|
token_match(OPEN_SCOPE);
|
||||||
|
Ast_Scope *scope = begin_decl_scope(scratch, token_get());
|
||||||
do{
|
do{
|
||||||
Token *token = token_get();
|
Token *token = token_get();
|
||||||
|
|
||||||
@@ -517,32 +519,34 @@ parse_struct(Token *pos){
|
|||||||
if(!decl) compiler_error(token, "Failed to parse struct member");
|
if(!decl) compiler_error(token, "Failed to parse struct member");
|
||||||
|
|
||||||
decl->flags = set_flag(decl->flags, AST_AGGREGATE_CHILD);
|
decl->flags = set_flag(decl->flags, AST_AGGREGATE_CHILD);
|
||||||
members.add(decl);
|
scope->decls.add(decl);
|
||||||
|
|
||||||
}while(token_match(SAME_SCOPE));
|
}while(token_match(SAME_SCOPE));
|
||||||
token_expect(CLOSE_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;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
function Ast_Decl *
|
function Ast_Decl *
|
||||||
parse_enum(Token *pos){
|
parse_enum(Token *pos){
|
||||||
Scratch scratch;
|
Scratch scratch;
|
||||||
Array<Ast_Decl *> members = {scratch};
|
|
||||||
Ast_Expr *typespec = parse_optional_type();
|
Ast_Expr *typespec = parse_optional_type();
|
||||||
|
|
||||||
token_match(OPEN_SCOPE);
|
token_match(OPEN_SCOPE);
|
||||||
|
Ast_Scope *scope = begin_decl_scope(scratch, token_get());
|
||||||
do{
|
do{
|
||||||
Token *name = token_expect(TK_Identifier);
|
Token *name = token_expect(TK_Identifier);
|
||||||
Ast_Expr *value = parse_assign_expr();
|
Ast_Expr *value = parse_assign_expr();
|
||||||
Ast_Decl *member = ast_const(name, name->intern_val, value);
|
Ast_Decl *member = ast_const(name, name->intern_val, value);
|
||||||
member->flags = set_flag(member->flags, AST_AGGREGATE_CHILD);
|
member->flags = set_flag(member->flags, AST_AGGREGATE_CHILD);
|
||||||
members.add(member);
|
scope->decls.add(member);
|
||||||
}while(token_match(SAME_SCOPE));
|
}while(token_match(SAME_SCOPE));
|
||||||
|
finalize_decl_scope(scope);
|
||||||
token_expect(CLOSE_SCOPE);
|
token_expect(CLOSE_SCOPE);
|
||||||
|
|
||||||
Ast_Decl *result = ast_enum(pos, typespec, members);
|
Ast_Decl *result = ast_enum(pos, typespec, scope);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -550,6 +550,11 @@ search_for_decl_in_current_context(Intern_String name){
|
|||||||
|
|
||||||
function void
|
function void
|
||||||
insert_into_scope(Ast_Scope *scope, Ast_Decl *decl){
|
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);
|
scope->decls.add(decl);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -562,6 +567,7 @@ function void
|
|||||||
insert_type_into_package(Ast_Package *p, String name, Ast_Resolved_Type *type){
|
insert_type_into_package(Ast_Package *p, String name, Ast_Resolved_Type *type){
|
||||||
Intern_String string = pctx->intern(name);
|
Intern_String string = pctx->intern(name);
|
||||||
Ast_Decl *decl = ast_type(&null_token, string, type);
|
Ast_Decl *decl = ast_type(&null_token, string, type);
|
||||||
|
decl->parent_scope = p;
|
||||||
decl->state = DECL_RESOLVED;
|
decl->state = DECL_RESOLVED;
|
||||||
insert_into_scope(p, decl);
|
insert_into_scope(p, decl);
|
||||||
}
|
}
|
||||||
@@ -634,6 +640,8 @@ require_const_int(Ast_Expr *expr, B32 flags){
|
|||||||
function void
|
function void
|
||||||
resolve_stmt(Ast *ast, Ast_Resolved_Type *ret){
|
resolve_stmt(Ast *ast, Ast_Resolved_Type *ret){
|
||||||
if(!ast) return;
|
if(!ast) return;
|
||||||
|
assert(ast->parent_scope->kind == AST_SCOPE || ast->parent_scope->kind == AST_PACKAGE);
|
||||||
|
|
||||||
|
|
||||||
switch(ast->kind){
|
switch(ast->kind){
|
||||||
CASE(RETURN, Return){ // @todo: need to check if all paths return a value
|
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){
|
resolve_expr(Ast_Expr *ast, B32 flags){
|
||||||
if(!ast && is_flag_set(flags, AST_CAN_BE_NULL)) return {};
|
if(!ast && is_flag_set(flags, AST_CAN_BE_NULL)) return {};
|
||||||
assert(is_flag_set(ast->flags, AST_EXPR));
|
assert(is_flag_set(ast->flags, AST_EXPR));
|
||||||
|
assert(ast->parent_scope->kind == AST_SCOPE || ast->parent_scope->kind == AST_PACKAGE);
|
||||||
|
|
||||||
switch(ast->kind){
|
switch(ast->kind){
|
||||||
|
|
||||||
@@ -1016,6 +1024,7 @@ resolve_decl(Ast_Decl *ast, B32 flags){
|
|||||||
}
|
}
|
||||||
BREAK();
|
BREAK();
|
||||||
}
|
}
|
||||||
|
|
||||||
CASE(VAR, Decl){
|
CASE(VAR, Decl){
|
||||||
Ast_Resolved_Type *type = resolve_typespec(node->typespec, AST_CAN_BE_NULL | RESOLVE_TYPESPEC_COMPLETE);
|
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);
|
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
|
function Ast_File
|
||||||
ast_file(String filename, String filecontent){
|
ast_file(String filename, String filecontent){
|
||||||
Ast_File result = {};
|
Ast_File result = {};
|
||||||
@@ -1122,10 +1093,10 @@ ast_file(String filename, String filecontent){
|
|||||||
}
|
}
|
||||||
|
|
||||||
function Ast_Package *
|
function Ast_Package *
|
||||||
find_package(Intern_String name, Array<Ast_Package> *packages){
|
find_package(Intern_String name, Array<Ast_Package *> *packages){
|
||||||
For(*packages){
|
For(*packages){
|
||||||
if(it.name == name){
|
if(it->name == name){
|
||||||
return ⁢
|
return it;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
|
|||||||
Reference in New Issue
Block a user