New concept of AST_MODULE, Ast_File and Ast_Module are now both scopes.

Concept of loading and importing.
This commit is contained in:
Krzosa Karol
2022-06-13 13:39:31 +02:00
parent 8bd5e9638f
commit bcd825c154
8 changed files with 132 additions and 75 deletions

35
ast.cpp
View File

@@ -6,7 +6,10 @@ enum Ast_Kind: U32{
AST_NONE,
AST_FILE_NAMESPACE,
AST_MODULE_NAMESPACE,
AST_MODULE,
AST_FILE,
AST_SCOPE,
AST_VALUE,
AST_CAST,
@@ -196,11 +199,28 @@ enum Ast_Decl_State{
DECL_RESOLVING,
};
struct Ast_Decl;
struct Ast_Scope: Ast{
Array<Ast_Module *> implicit_imports;
Array<Ast_File *> implicit_loads;
Array<Ast_Decl *> decls;
Array<Ast *> stmts;
Ast_File *file;
Ast_File *file; // Null for module scope, file scope
};
struct Ast_Module: Ast_Scope{
Intern_String name;
Array<Ast_File *> all_loaded_files;
};
struct Ast_File: Ast_Scope{
Intern_String filename;
Ast_Module *module;
B32 global_implicit_load;
String filecontent;
Intern_String name;
};
struct Ast_Decl: Ast{
@@ -483,8 +503,15 @@ ast_decl_scope(Token *pos, Allocator *allocator, Ast_File *file){
function Ast_Decl *
ast_file_namespace(Token *pos, Ast_File *file, Intern_String name){
AST_NEW(Decl, FILE_NAMESPACE, pos, AST_DECL);
result->kind = AST_FILE_NAMESPACE;
result->scope = file->scope;
result->scope = file;
result->name = name;
return result;
}
function Ast_Decl *
ast_module_namespace(Token *pos, Ast_Module *module, Intern_String name){
AST_NEW(Decl, MODULE_NAMESPACE, pos, AST_DECL);
result->scope = module;
result->name = name;
return result;
}

View File

@@ -400,6 +400,7 @@ gen_ast(Ast *ast){
BREAK();
}
case AST_MODULE_NAMESPACE:
CASE(FILE_NAMESPACE, File_Namespace){unused(node); BREAK();}
default: {
@@ -423,12 +424,15 @@ parse_file(Ast_File *file){
String name = string_chop_last_period(file->filename.s);
file->name = pctx->intern(name);
pctx->currently_parsed_scope = file->scope;
pctx->currently_parsed_scope = file;
lex_restream(pctx, file->filecontent, file->filename.s);
while(token_expect(SAME_SCOPE)){
if(token_match_pound(pctx->intern("load"_s))){
parse_load(true);
continue;
} else if(token_match_pound(pctx->intern("import"_s))){
parse_import(true);
continue;
}
Ast_Decl *decl = parse_decl(true);
@@ -441,31 +445,19 @@ parse_file(Ast_File *file){
decl->state = DECL_RESOLVED;
}
insert_into_scope(file->scope, decl);
insert_into_scope(file, decl);
}
pctx->currently_parsed_scope = 0;
pctx->currently_parsed_file = 0;
}
global F64 parsing_time_begin;
global F64 parsing_time_end;
function void
parse_files(Ast_Module *module){
parsing_time_begin = os_time();
for(S64 i = 0; i < module->files.len; i++){
auto it = module->files.data[i];
parse_file(it);
}
parsing_time_end = os_time();
}
function void
insert_type_into_file(Ast_File *p, String name, Ast_Type *type){
Intern_String string = pctx->intern(name);
Ast_Decl *decl = ast_type(&null_token, string, type);
decl->parent_scope = p->scope;
decl->parent_scope = p;
decl->state = DECL_RESOLVED;
insert_into_scope(p->scope, decl);
insert_into_scope(p, decl);
}
function void
@@ -487,14 +479,43 @@ insert_builtin_types_into_file(Ast_File *p){
insert_type_into_file(p, "F64"_s, type_f64);
}
global F64 parsing_time_begin;
global F64 parsing_time_end;
function void
parse_files(Ast_Module *module){
for(S64 i = 0; i < module->all_loaded_files.len; i++){
auto it = module->all_loaded_files.data[i];
parse_file(it);
}
}
function void
parse_all_modules(){
parsing_time_begin = os_time();
For(pctx->modules){
parse_files(it);
// @todo maybe add module?
insert_builtin_types_into_file(it->all_loaded_files[0]);
}
parsing_time_end = os_time();
}
function Ast_Module *
parse_module(String filename){
add_module(Intern_String filename){
For(pctx->modules){
if(it->name == filename)
return it;
}
Ast_Module *result = exp_alloc_type(pctx->perm, Ast_Module);
result->name = pctx->intern(filename);
result->files = {pctx->heap};
Ast_File *file = register_ast_file(result->name, result, true);
parse_files(result);
insert_builtin_types_into_file(file);
result->kind = AST_MODULE;
result->name = filename;
result->all_loaded_files = {pctx->heap};
result->implicit_loads = {pctx->heap};
result->implicit_imports = {pctx->heap};
register_ast_file(result->name, result, true);
pctx->modules.add(result);
return result;
}
@@ -504,10 +525,10 @@ global F64 resolving_time_end;
function void
resolve_everything_in_module(Ast_Module *module){
resolving_time_begin = os_time();
for(S64 i = 0; i < module->files.len; i++){
Ast_File *it = module->files[i];
For_Named(it->scope->decls, jt){
resolve_name(it->scope, jt->pos, jt->name);
for(S64 i = 0; i < module->all_loaded_files.len; i++){
Ast_File *it = module->all_loaded_files[i];
For_Named(it->decls, jt){
resolve_name(it, jt->pos, jt->name);
if(jt->kind == AST_STRUCT){
type_complete(jt->type);
}

View File

@@ -167,21 +167,7 @@ struct Ast_Scope;
struct Ast_Decl;
struct Ast_File_Namespace;
struct Ast_File;
struct Ast_Module{
Intern_String name;
Array<Ast_File *> files;
};
struct Ast_File{
Intern_String filename;
Ast_Module *module;
B32 global_implicit_load;
String filecontent;
Intern_String name;
Ast_Scope *scope;
};
struct Ast_Module;
struct Parse_Ctx:Lexer{
Allocator *perm; // Stores: AST, tokens, interns
Allocator *heap;
@@ -190,7 +176,6 @@ struct Parse_Ctx:Lexer{
Map type_map;
Array<Ast_Module *> modules;
Array<Ast_File_Namespace *> packages;
Ast_Scope *currently_parsed_scope;
Ast_File *currently_parsed_file;
Array<Ast_Decl *> ordered_decls;

View File

@@ -1,9 +1,13 @@
lambdas :: #load "lambdas.kl"
Memory :: #load "enums.kl"
order :: #import "order1.kl"
test_load :: ()
new_types :: #load "new_types.kl"
new_types.basic_type_assignment()
arena: order.order2.Arena
//-----------------------------------------------------------------------------
// Function types
//-----------------------------------------------------------------------------

View File

@@ -172,20 +172,11 @@ int main(int argument_count, char **arguments){
system((const char *)run_program.str);
}
#else
// Scratch scratch;
// Array<String> files = {scratch};
// files.add("lambdas.kl"_s);
// files.add("order1.kl"_s);
// files.add("order2.kl"_s);
// files.add("new_types.kl"_s);
// files.add("enums.kl"_s);
// files.add("Windows.kl"_s);
// files.add("euler.kl"_s);
// String result = compile_files(files);
F64 total_time = os_time();
begin_compilation();
Ast_Module *module = parse_module("Windows.kl"_s);
add_module(pctx->intern("order1.kl"_s));
Ast_Module *module = add_module(pctx->intern("Windows.kl"_s));
parse_all_modules();
assert(module);
resolve_everything_in_module(module);
String result = end_compilation();

View File

@@ -1,3 +1,5 @@
order2 :: #load "order2.kl"
recursive_lambda :: (thing: S64)
in_val := recursive_lambda
some_value := thing + const_in_lambda

View File

@@ -585,7 +585,7 @@ parse_enum(Token *pos){
function Ast_File *
register_ast_file(Intern_String filename, Ast_Module *module, B32 global_implicit_load){
Ast_File *file = 0;
For(module->files){
For(module->all_loaded_files){
if(it->filename == filename){
file = it;
break;
@@ -593,13 +593,20 @@ register_ast_file(Intern_String filename, Ast_Module *module, B32 global_implici
}
if(!file){
file = exp_alloc_type(pctx->perm, Ast_File, AF_ZeroMemory);
file->kind = AST_FILE;
file->filename = filename;
file->module = module;
file->scope = ast_decl_scope(0, pctx->heap, file);
file->module->files.add(file);
file->file = file; // @warning: self referential!
file->decls = {pctx->heap};
file->implicit_loads = {pctx->heap};
file->implicit_imports = {pctx->heap};
file->module->all_loaded_files.add(file);
}
if(global_implicit_load) file->global_implicit_load = true;
if(global_implicit_load) {
file->global_implicit_load = true;
module->implicit_loads.add(file);
}
return file;
}
@@ -611,6 +618,17 @@ parse_load(B32 global_implicit_load){
return result;
}
function Ast_Module *add_module(Intern_String filename);
function Ast_Module *
parse_import(B32 global_implicit_import){
Token *file = token_expect(TK_StringLit);
Ast_Module *result = add_module(file->intern_val);
if(global_implicit_import){
pctx->currently_parsed_file->module->implicit_imports.add(result);
}
return result;
}
/*
Needs peeking only because I didn't want to duplicate code
for parsing statements and it makes code nicer.
@@ -648,6 +666,11 @@ parse_decl(B32 is_global){
result = ast_file_namespace(tname, file, tname->intern_val);
}
else if(token_match_pound(pctx->intern("import"_s))){
Ast_Module *module = parse_import(false);
result = ast_module_namespace(tname, module, tname->intern_val);
}
else{
Ast_Expr *expr = parse_expr();
result = ast_const(tname, tname->intern_val, expr);

View File

@@ -319,6 +319,17 @@ _search_for_decl(Ast_Scope *scope, Intern_String name){
return it;
}
}
For(scope->implicit_loads){
Ast_Decl *result = _search_for_decl(it, name);
if(result) return result;
}
For(scope->implicit_imports){
Ast_Decl *result = _search_for_decl(it, name);
if(result) return result;
}
return 0;
}
@@ -332,15 +343,7 @@ search_for_decl(Ast_Scope *scope, Intern_String name, Search_Flag flags = 0){
}
if(!result && !is_flag_set(flags, SEARCH_ONLY_CURRENT_SCOPE)){
For(scope->file->module->files){
if(scope->file != it){
// If parsing the scope can be invalid
if(it->scope == 0 && pctx->currently_parsed_file != 0) continue;
if(it->global_implicit_load == false) continue;
result = _search_for_decl(it->scope, name);
if(result) break;
}
}
result = _search_for_decl(scope->file->module, name);
}
return result;
}
@@ -647,7 +650,7 @@ resolve_field_access(Ast_Expr *node, Ast_Scope *context){
Ast_Scope *scope = context ? context : node->parent_scope;
Search_Flag flag = context ? SEARCH_ONLY_CURRENT_SCOPE : 0;
Ast_Decl *decl = resolve_name(scope, node->pos, ident->intern_val, flag);
if(decl->kind == AST_FILE_NAMESPACE){
if(decl->kind == AST_FILE_NAMESPACE || decl->kind == AST_MODULE_NAMESPACE){
assert(next);
return resolve_field_access(next, decl->scope);
}
@@ -675,7 +678,7 @@ function Operand
resolve_expr(Ast_Expr *ast, Resolve_Flag flags, Ast_Type *compound_context){
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_FILE_NAMESPACE);
assert(ast->parent_scope->kind == AST_SCOPE || ast->parent_scope->kind == AST_FILE);
switch(ast->kind){
@@ -962,6 +965,7 @@ resolve_decl(Ast_Decl *ast){
BREAK();
}
case AST_MODULE_NAMESPACE:
CASE(FILE_NAMESPACE, File_Namespace){
unused(node);
BREAK();