New concept of AST_MODULE, Ast_File and Ast_Module are now both scopes.
Concept of loading and importing.
This commit is contained in:
35
ast.cpp
35
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<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;
|
||||
}
|
||||
|
||||
73
ccodegen.cpp
73
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);
|
||||
}
|
||||
|
||||
17
compiler.h
17
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<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;
|
||||
|
||||
@@ -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
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
15
main.cpp
15
main.cpp
@@ -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();
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
order2 :: #load "order2.kl"
|
||||
|
||||
recursive_lambda :: (thing: S64)
|
||||
in_val := recursive_lambda
|
||||
some_value := thing + const_in_lambda
|
||||
|
||||
31
parsing.cpp
31
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);
|
||||
|
||||
@@ -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();
|
||||
|
||||
Reference in New Issue
Block a user