mirror of
https://github.com/odin-lang/Odin.git
synced 2026-02-14 23:33:15 +00:00
Basic module system (only file namespacing)
This commit is contained in:
@@ -1,13 +1,10 @@
|
||||
// #load "basic.odin"
|
||||
#import "runtime.odin"
|
||||
#import "print.odin"
|
||||
|
||||
test_proc :: proc() {
|
||||
println("Hello?")
|
||||
}
|
||||
|
||||
|
||||
main :: proc() {
|
||||
println("% % % %", "Hellope", true, 6.28, {4}int{1, 2, 3, 4})
|
||||
x: struct #ordered {
|
||||
x, y: int
|
||||
z: f32
|
||||
}
|
||||
println("%", x)
|
||||
}
|
||||
|
||||
@@ -1,6 +1,12 @@
|
||||
#foreign_system_library "user32"
|
||||
#foreign_system_library "gdi32"
|
||||
|
||||
|
||||
test_proc :: proc() {
|
||||
x := "Goodbye?"
|
||||
}
|
||||
|
||||
|
||||
HANDLE :: type rawptr
|
||||
HWND :: type HANDLE
|
||||
HDC :: type HANDLE
|
||||
@@ -398,3 +404,4 @@ Key_Code :: enum i32 {
|
||||
PA1 = 0xFD,
|
||||
OEM_CLEAR = 0xFE,
|
||||
}
|
||||
|
||||
|
||||
@@ -117,6 +117,7 @@ struct Scope {
|
||||
b32 is_proc;
|
||||
b32 is_global;
|
||||
b32 is_file;
|
||||
b32 is_init;
|
||||
};
|
||||
|
||||
enum ExprKind {
|
||||
@@ -819,6 +820,10 @@ void check_parsed_files(Checker *c) {
|
||||
scope = make_scope(c->global_scope, c->allocator);
|
||||
scope->is_global = f->is_global_scope;
|
||||
scope->is_file = true;
|
||||
if (i == 0) {
|
||||
// NOTE(bill): First file is always the initial file
|
||||
scope->is_init = true;
|
||||
}
|
||||
|
||||
if (scope->is_global) {
|
||||
gb_array_append(c->global_scope->shared, scope);
|
||||
@@ -844,9 +849,6 @@ void check_parsed_files(Checker *c) {
|
||||
switch (decl->kind) {
|
||||
case_ast_node(bd, BadDecl, decl);
|
||||
case_end;
|
||||
case_ast_node(ld, LoadDecl, decl);
|
||||
// NOTE(bill): ignore
|
||||
case_end;
|
||||
case_ast_node(id, ImportDecl, decl);
|
||||
// NOTE(bill): Handle later
|
||||
case_end;
|
||||
@@ -947,37 +949,34 @@ void check_parsed_files(Checker *c) {
|
||||
|
||||
gb_for_array(decl_index, f->decls) {
|
||||
AstNode *decl = f->decls[decl_index];
|
||||
if (decl->kind != AstNode_ImportDecl) {
|
||||
continue;
|
||||
}
|
||||
#if 1
|
||||
ast_node(id, ImportDecl, decl);
|
||||
|
||||
HashKey key = hash_string(id->fullpath);
|
||||
auto found = map_get(&file_scopes, key);
|
||||
GB_ASSERT_MSG(found != NULL, "Unable to find scope for file: %.*s", LIT(id->fullpath));
|
||||
Scope *scope = *found;
|
||||
b32 previously_added = false;
|
||||
gb_for_array(import_index, file_scope->imported) {
|
||||
Scope *prev = file_scope->imported[import_index];
|
||||
if (prev == scope) {
|
||||
previously_added = true;
|
||||
break;
|
||||
switch (decl->kind) {
|
||||
case_ast_node(id, ImportDecl, decl);
|
||||
HashKey key = hash_string(id->fullpath);
|
||||
auto found = map_get(&file_scopes, key);
|
||||
GB_ASSERT_MSG(found != NULL, "Unable to find scope for file: %.*s", LIT(id->fullpath));
|
||||
Scope *scope = *found;
|
||||
b32 previously_added = false;
|
||||
gb_for_array(import_index, file_scope->imported) {
|
||||
Scope *prev = file_scope->imported[import_index];
|
||||
if (prev == scope) {
|
||||
previously_added = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!previously_added) {
|
||||
gb_array_append(file_scope->imported, scope);
|
||||
}
|
||||
|
||||
// NOTE(bill): Add imported entities to this file's scope
|
||||
gb_for_array(elem_index, scope->elements.entries) {
|
||||
Entity *e = scope->elements.entries[elem_index].value;
|
||||
// NOTE(bill): Do not add other imported entities
|
||||
if (e->scope == scope) {
|
||||
add_entity(c, file_scope, NULL, e);
|
||||
if (!previously_added) {
|
||||
gb_array_append(file_scope->imported, scope);
|
||||
}
|
||||
|
||||
// NOTE(bill): Add imported entities to this file's scope
|
||||
gb_for_array(elem_index, scope->elements.entries) {
|
||||
Entity *e = scope->elements.entries[elem_index].value;
|
||||
// NOTE(bill): Do not add other imported entities
|
||||
if (e->scope == scope) {
|
||||
add_entity(c, file_scope, NULL, e);
|
||||
}
|
||||
}
|
||||
case_end;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -66,12 +66,45 @@ void ssa_gen_tree(ssaGen *s) {
|
||||
gb_for_array(i, info->entities.entries) {
|
||||
auto *entry = &info->entities.entries[i];
|
||||
Entity *e = cast(Entity *)cast(uintptr)entry->key.key;
|
||||
DeclInfo *decl = entry->value;
|
||||
|
||||
String name = e->token.string;
|
||||
|
||||
DeclInfo *decl = entry->value;
|
||||
Scope *scope = e->scope;
|
||||
if (scope->is_global ||
|
||||
scope->is_init) {
|
||||
|
||||
} else {
|
||||
// NOTE(bill): prefix names not in the init scope
|
||||
// TODO(bill): make robust and not just rely on the file's name
|
||||
String path = e->token.pos.file;
|
||||
char *str = gb_alloc_array(a, char, path.len+1);
|
||||
gb_memcopy(str, path.text, path.len);
|
||||
str[path.len] = 0;
|
||||
for (isize i = 0; i < path.len; i++) {
|
||||
if (str[i] == '\\') {
|
||||
str[i] = '/';
|
||||
}
|
||||
}
|
||||
char const *base = gb_path_base_name(str);
|
||||
char const *ext = gb_path_extension(base);
|
||||
isize base_len = ext-1-base;
|
||||
|
||||
isize new_len = base_len + 1 + name.len;
|
||||
u8 *new_name = gb_alloc_array(a, u8, new_len);
|
||||
gb_memcopy(new_name, base, base_len);
|
||||
new_name[base_len] = '.';
|
||||
gb_memcopy(new_name+base_len+1, name.text, name.len);
|
||||
|
||||
name = make_string(new_name, new_len);
|
||||
// gb_printf("%.*s\n", new_len, new_name);
|
||||
}
|
||||
|
||||
|
||||
switch (e->kind) {
|
||||
case Entity_TypeName:
|
||||
GB_ASSERT(e->type->kind == Type_Named);
|
||||
// HACK(bill): Rename type's name for ssa gen
|
||||
e->type->Named.name = name;
|
||||
ssa_gen_global_type_name(m, e, name);
|
||||
break;
|
||||
|
||||
@@ -107,9 +140,11 @@ void ssa_gen_tree(ssaGen *s) {
|
||||
|
||||
case Entity_Procedure: {
|
||||
auto *pd = &decl->proc_decl->ProcDecl;
|
||||
String original_name = e->token.string;
|
||||
String name = original_name;
|
||||
String original_name = name;
|
||||
AstNode *body = pd->body;
|
||||
if (pd->tags & ProcTag_foreign) {
|
||||
name = pd->name->Ident.string;
|
||||
}
|
||||
if (pd->foreign_name.len > 0) {
|
||||
name = pd->foreign_name;
|
||||
}
|
||||
|
||||
@@ -103,7 +103,7 @@ int main(int argc, char **argv) {
|
||||
|
||||
PRINT_TIMER("Semantic Checker");
|
||||
#endif
|
||||
#if 0
|
||||
#if 1
|
||||
ssaGen ssa = {};
|
||||
if (!ssa_gen_init(&ssa, &checker))
|
||||
return 1;
|
||||
|
||||
@@ -230,7 +230,6 @@ AST_NODE_KIND(_DeclBegin, "", struct{}) \
|
||||
String foreign_name; \
|
||||
}) \
|
||||
AST_NODE_KIND(TypeDecl, "type declaration", struct { Token token; AstNode *name, *type; }) \
|
||||
AST_NODE_KIND(LoadDecl, "load declaration", struct { Token token, filepath; }) \
|
||||
AST_NODE_KIND(ImportDecl, "import declaration", struct { \
|
||||
Token token, relpath; \
|
||||
String fullpath; \
|
||||
@@ -410,8 +409,6 @@ Token ast_node_token(AstNode *node) {
|
||||
return node->ProcDecl.name->Ident;
|
||||
case AstNode_TypeDecl:
|
||||
return node->TypeDecl.token;
|
||||
case AstNode_LoadDecl:
|
||||
return node->LoadDecl.token;
|
||||
case AstNode_ImportDecl:
|
||||
return node->ImportDecl.token;
|
||||
case AstNode_ForeignSystemLibrary:
|
||||
@@ -886,14 +883,6 @@ gb_inline AstNode *make_type_decl(AstFile *f, Token token, AstNode *name, AstNod
|
||||
return result;
|
||||
}
|
||||
|
||||
gb_inline AstNode *make_load_decl(AstFile *f, Token token, Token filepath) {
|
||||
AstNode *result = make_node(f, AstNode_LoadDecl);
|
||||
result->LoadDecl.token = token;
|
||||
result->LoadDecl.filepath = filepath;
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
gb_inline AstNode *make_import_decl(AstFile *f, Token token, Token relpath) {
|
||||
AstNode *result = make_node(f, AstNode_ImportDecl);
|
||||
result->ImportDecl.token = token;
|
||||
@@ -2551,13 +2540,6 @@ AstNode *parse_stmt(AstFile *f) {
|
||||
}
|
||||
ast_file_err(f, token, "You cannot use #global_scope within a procedure. This must be done at the file scope.");
|
||||
return make_bad_decl(f, token, f->cursor[0]);
|
||||
} else if (are_strings_equal(tag, make_string("load"))) {
|
||||
Token file_path = expect_token(f, Token_String);
|
||||
if (f->curr_proc == NULL) {
|
||||
return make_load_decl(f, s->TagStmt.token, file_path);
|
||||
}
|
||||
ast_file_err(f, token, "You cannot use #load within a procedure. This must be done at the file scope.");
|
||||
return make_bad_decl(f, token, file_path);
|
||||
} else if (are_strings_equal(tag, make_string("import"))) {
|
||||
Token file_path = expect_token(f, Token_String);
|
||||
if (f->curr_proc == NULL) {
|
||||
@@ -2796,29 +2778,7 @@ void parse_file(Parser *p, AstFile *f) {
|
||||
// NOTE(bill): Sanity check
|
||||
ast_file_err(f, ast_node_token(node), "Only declarations are allowed at file scope");
|
||||
} else {
|
||||
if (node->kind == AstNode_LoadDecl) {
|
||||
auto *id = &node->LoadDecl;
|
||||
String file_str = id->filepath.string;
|
||||
|
||||
if (!is_import_path_valid(file_str)) {
|
||||
ast_file_err(f, ast_node_token(node), "Invalid `load` path");
|
||||
continue;
|
||||
}
|
||||
|
||||
isize str_len = base_dir.len+file_str.len;
|
||||
u8 *str = gb_alloc_array(gb_heap_allocator(), u8, str_len+1);
|
||||
defer (gb_free(gb_heap_allocator(), str));
|
||||
|
||||
gb_memcopy(str, base_dir.text, base_dir.len);
|
||||
gb_memcopy(str+base_dir.len, file_str.text, file_str.len);
|
||||
str[str_len] = '\0';
|
||||
char *path_str = gb_path_get_full_name(gb_heap_allocator(), cast(char *)str);
|
||||
String import_file = make_string(path_str);
|
||||
|
||||
if (!try_add_import_path(p, import_file, node)) {
|
||||
gb_free(gb_heap_allocator(), import_file.text);
|
||||
}
|
||||
} else if (node->kind == AstNode_ImportDecl) {
|
||||
if (node->kind == AstNode_ImportDecl) {
|
||||
auto *id = &node->ImportDecl;
|
||||
String file_str = id->relpath.string;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user