diff --git a/ast.cpp b/ast.cpp index b43b7d0..62e2b60 100644 --- a/ast.cpp +++ b/ast.cpp @@ -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 decls; - Array stmts; - Ast_File *file; + Array implicit_imports; + Array implicit_loads; + Array decls; + Array stmts; + + Ast_File *file; // Null for module scope, file scope +}; + + +struct Ast_Module: Ast_Scope{ + Intern_String name; + Array 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; } diff --git a/ccodegen.cpp b/ccodegen.cpp index b036be6..49e8d2f 100644 --- a/ccodegen.cpp +++ b/ccodegen.cpp @@ -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); } diff --git a/compiler.h b/compiler.h index a56a2e9..d213513 100644 --- a/compiler.h +++ b/compiler.h @@ -167,21 +167,7 @@ struct Ast_Scope; struct Ast_Decl; struct Ast_File_Namespace; struct Ast_File; -struct Ast_Module{ - Intern_String name; - Array 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 modules; - Array packages; Ast_Scope *currently_parsed_scope; Ast_File *currently_parsed_file; Array ordered_decls; diff --git a/globals.kl b/globals.kl index febe128..2dd393f 100644 --- a/globals.kl +++ b/globals.kl @@ -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 //----------------------------------------------------------------------------- diff --git a/main.cpp b/main.cpp index 6c902be..0c1df63 100644 --- a/main.cpp +++ b/main.cpp @@ -172,20 +172,11 @@ int main(int argument_count, char **arguments){ system((const char *)run_program.str); } #else - // Scratch scratch; - // Array 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(); diff --git a/order1.kl b/order1.kl index e70a4d5..33cdc9f 100644 --- a/order1.kl +++ b/order1.kl @@ -1,3 +1,5 @@ +order2 :: #load "order2.kl" + recursive_lambda :: (thing: S64) in_val := recursive_lambda some_value := thing + const_in_lambda diff --git a/parsing.cpp b/parsing.cpp index 296aae6..ee10e9e 100644 --- a/parsing.cpp +++ b/parsing.cpp @@ -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); diff --git a/typechecking.cpp b/typechecking.cpp index 73df763..2b832a2 100644 --- a/typechecking.cpp +++ b/typechecking.cpp @@ -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();