mirror of
https://github.com/Ed94/Odin.git
synced 2026-07-20 16:36:46 +00:00
Add basic package support (no IR support yet)
This commit is contained in:
+112
-3
@@ -1,3 +1,38 @@
|
||||
enum TargetOsKind {
|
||||
TargetOs_Invalid,
|
||||
|
||||
TargetOs_windows,
|
||||
TargetOs_osx,
|
||||
TargetOs_linux,
|
||||
TargetOs_essence,
|
||||
|
||||
TargetOs_COUNT,
|
||||
};
|
||||
|
||||
enum TargetArchKind {
|
||||
TargetArch_Invalid,
|
||||
|
||||
TargetArch_amd64,
|
||||
TargetArch_x64,
|
||||
|
||||
TargetArch_COUNT,
|
||||
};
|
||||
|
||||
String target_os_names[TargetOs_COUNT] = {
|
||||
str_lit(""),
|
||||
str_lit("windows"),
|
||||
str_lit("osx"),
|
||||
str_lit("linux"),
|
||||
str_lit("essence"),
|
||||
};
|
||||
|
||||
String target_arch_names[TargetArch_COUNT] = {
|
||||
str_lit(""),
|
||||
str_lit("amd64"),
|
||||
str_lit("x86"),
|
||||
};
|
||||
|
||||
|
||||
// This stores the information for the specify architecture of this build
|
||||
struct BuildContext {
|
||||
// Constants
|
||||
@@ -15,6 +50,9 @@ struct BuildContext {
|
||||
|
||||
String command;
|
||||
|
||||
TargetOsKind target_os;
|
||||
TargetArchKind target_arch;
|
||||
|
||||
String out_filepath;
|
||||
String resource_filepath;
|
||||
bool has_resource;
|
||||
@@ -37,6 +75,72 @@ struct BuildContext {
|
||||
gb_global BuildContext build_context = {0};
|
||||
|
||||
|
||||
TargetOsKind get_target_os_from_string(String str) {
|
||||
for (isize i = 0; i < TargetOs_COUNT; i++) {
|
||||
if (target_os_names[i] == str) {
|
||||
return cast(TargetOsKind)i;
|
||||
}
|
||||
}
|
||||
return TargetOs_Invalid;
|
||||
}
|
||||
|
||||
TargetArchKind get_target_arch_from_string(String str) {
|
||||
for (isize i = 0; i < TargetArch_COUNT; i++) {
|
||||
if (target_os_names[i] == str) {
|
||||
return cast(TargetArchKind)i;
|
||||
}
|
||||
}
|
||||
return TargetArch_Invalid;
|
||||
}
|
||||
|
||||
bool is_excluded_target_filename(String name) {
|
||||
String const ext = str_lit(".odin");
|
||||
GB_ASSERT(string_ends_with(name, ext));
|
||||
name = substring(name, 0, name.len-ext.len);
|
||||
|
||||
String str1 = {};
|
||||
String str2 = {};
|
||||
isize n = 0;
|
||||
|
||||
str1 = name;
|
||||
n = str1.len;
|
||||
for (isize i = str1.len-1; i >= 0 && str1[i] != '_'; i--) {
|
||||
n -= 1;
|
||||
}
|
||||
str1 = substring(str1, n, str1.len);
|
||||
|
||||
str2 = str1;
|
||||
n = str2.len;
|
||||
for (isize i = str2.len-1; i >= 0 && str2[i] != '_'; i--) {
|
||||
n -= 1;
|
||||
}
|
||||
str2 = substring(str2, n, str2.len);
|
||||
|
||||
if (str1 == name) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
TargetOsKind os1 = get_target_os_from_string(str1);
|
||||
TargetArchKind arch1 = get_target_arch_from_string(str1);
|
||||
TargetOsKind os2 = get_target_os_from_string(str2);
|
||||
TargetArchKind arch2 = get_target_arch_from_string(str2);
|
||||
|
||||
if (arch1 != TargetArch_Invalid && os2 != TargetOs_Invalid) {
|
||||
return arch1 != build_context.target_arch || os2 != build_context.target_os;
|
||||
} else if (arch1 != TargetArch_Invalid && os1 != TargetOs_Invalid) {
|
||||
return arch2 != build_context.target_arch || os1 != build_context.target_os;
|
||||
} else if (os1 != TargetOs_Invalid) {
|
||||
return os1 != build_context.target_os;
|
||||
} else if (arch1 != TargetArch_Invalid) {
|
||||
return arch1 != build_context.target_arch;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
struct LibraryCollections {
|
||||
String name;
|
||||
String path;
|
||||
@@ -327,11 +431,14 @@ void init_build_context(void) {
|
||||
bc->ODIN_ROOT = odin_root_dir();
|
||||
|
||||
#if defined(GB_SYSTEM_WINDOWS)
|
||||
bc->ODIN_OS = str_lit("windows");
|
||||
bc->ODIN_OS = str_lit("windows");
|
||||
bc->target_os = TargetOs_windows;
|
||||
#elif defined(GB_SYSTEM_OSX)
|
||||
bc->ODIN_OS = str_lit("osx");
|
||||
bc->ODIN_OS = str_lit("osx");
|
||||
bc->target_os = TargetOs_osx;
|
||||
#else
|
||||
bc->ODIN_OS = str_lit("linux");
|
||||
bc->ODIN_OS = str_lit("linux");
|
||||
bc->target_os = TargetOs_linux;
|
||||
#endif
|
||||
|
||||
if (cross_compile_target.len) {
|
||||
@@ -340,8 +447,10 @@ void init_build_context(void) {
|
||||
|
||||
#if defined(GB_ARCH_64_BIT)
|
||||
bc->ODIN_ARCH = str_lit("amd64");
|
||||
bc->target_arch = TargetArch_amd64;
|
||||
#else
|
||||
bc->ODIN_ARCH = str_lit("x86");
|
||||
bc->target_arch = TargetArch_x86;
|
||||
#endif
|
||||
|
||||
{
|
||||
|
||||
+2
-2
@@ -535,7 +535,7 @@ void check_proc_decl(Checker *c, Entity *e, DeclInfo *d) {
|
||||
e->deprecated_message = ac.deprecated_message;
|
||||
ac.link_name = handle_link_name(c, e->token, ac.link_name, ac.link_prefix);
|
||||
|
||||
if (d->scope->file != nullptr && e->token.string == "main") {
|
||||
if (d->scope->package != nullptr && e->token.string == "main") {
|
||||
if (pt->param_count != 0 ||
|
||||
pt->result_count != 0) {
|
||||
gbString str = type_to_string(proc_type);
|
||||
@@ -583,7 +583,7 @@ void check_proc_decl(Checker *c, Entity *e, DeclInfo *d) {
|
||||
|
||||
GB_ASSERT(pl->body->kind == AstNode_BlockStmt);
|
||||
if (!pt->is_polymorphic) {
|
||||
check_procedure_later(c, c->curr_ast_file, e->token, d, proc_type, pl->body, pl->tags);
|
||||
check_procedure_later(c, c->curr_ast_package, e->token, d, proc_type, pl->body, pl->tags);
|
||||
}
|
||||
} else if (!is_foreign) {
|
||||
if (e->Procedure.is_export) {
|
||||
|
||||
+7
-6
@@ -109,7 +109,7 @@ void error_operand_no_value(Operand *o) {
|
||||
|
||||
void check_scope_decls(Checker *c, Array<AstNode *> nodes, isize reserve_size) {
|
||||
Scope *s = c->context.scope;
|
||||
GB_ASSERT(s->file == nullptr);
|
||||
GB_ASSERT(s->package == nullptr);
|
||||
|
||||
check_collect_entities(c, nodes);
|
||||
|
||||
@@ -342,17 +342,18 @@ bool find_or_generate_polymorphic_procedure(Checker *c, Entity *base_entity, Typ
|
||||
// NOTE(bill): Set the scope afterwards as this is not real overloading
|
||||
entity->scope = scope->parent;
|
||||
|
||||
AstFile *file = nullptr;
|
||||
AstPackage *package = nullptr;
|
||||
{
|
||||
Scope *s = entity->scope;
|
||||
while (s != nullptr && s->file == nullptr) {
|
||||
file = s->file;
|
||||
while (s != nullptr && s->package == nullptr) {
|
||||
package = s->package;
|
||||
s = s->parent;
|
||||
}
|
||||
}
|
||||
|
||||
ProcedureInfo proc_info = {};
|
||||
proc_info.file = file;
|
||||
// proc_info.file = file;
|
||||
proc_info.package = package;
|
||||
proc_info.token = token;
|
||||
proc_info.decl = d;
|
||||
proc_info.type = final_proc_type;
|
||||
@@ -5362,7 +5363,7 @@ ExprKind check_expr_base_internal(Checker *c, Operand *o, AstNode *node, Type *t
|
||||
return kind;
|
||||
}
|
||||
|
||||
check_procedure_later(c, c->curr_ast_file, empty_token, decl, type, pl->body, pl->tags);
|
||||
check_procedure_later(c, c->curr_ast_package, empty_token, decl, type, pl->body, pl->tags);
|
||||
}
|
||||
check_close_scope(c);
|
||||
|
||||
|
||||
+4
-1
@@ -627,7 +627,10 @@ void check_switch_stmt(Checker *c, AstNode *node, u32 mod_flags) {
|
||||
Token token = {};
|
||||
token.pos = ast_node_token(ss->body).pos;
|
||||
token.string = str_lit("true");
|
||||
x.expr = ast_ident(c->curr_ast_file, token);
|
||||
|
||||
x.expr = gb_alloc_item(c->allocator, AstNode);
|
||||
x.expr->kind = AstNode_Ident;
|
||||
x.expr->Ident.token = token;
|
||||
}
|
||||
|
||||
// NOTE(bill): Check for multiple defaults
|
||||
|
||||
+241
-506
File diff suppressed because it is too large
Load Diff
+14
-14
@@ -194,7 +194,8 @@ struct DeclInfo {
|
||||
|
||||
// ProcedureInfo stores the information needed for checking a procedure
|
||||
struct ProcedureInfo {
|
||||
AstFile * file;
|
||||
// AstFile * file;
|
||||
AstPackage * package;
|
||||
Token token;
|
||||
DeclInfo * decl;
|
||||
Type * type; // Type_Procedure
|
||||
@@ -204,6 +205,7 @@ struct ProcedureInfo {
|
||||
};
|
||||
|
||||
|
||||
|
||||
struct Scope {
|
||||
AstNode * node;
|
||||
Scope * parent;
|
||||
@@ -214,17 +216,18 @@ struct Scope {
|
||||
PtrSet<Entity *> implicit;
|
||||
|
||||
Array<Scope *> shared;
|
||||
Array<AstNode *> delayed_file_decls;
|
||||
Array<AstNode *> delayed_asserts;
|
||||
Array<AstNode *> delayed_imports;
|
||||
PtrSet<Scope *> imported;
|
||||
PtrSet<Scope *> exported; // NOTE(bhall): Contains 'using import' too
|
||||
bool is_proc;
|
||||
bool is_global;
|
||||
bool is_file;
|
||||
bool is_package;
|
||||
bool is_init;
|
||||
bool is_struct;
|
||||
bool has_been_imported; // This is only applicable to file scopes
|
||||
AstFile * file;
|
||||
|
||||
AstPackage * package;
|
||||
};
|
||||
|
||||
|
||||
@@ -250,7 +253,7 @@ typedef PtrSet<ImportGraphNode *> ImportGraphNodeSet;
|
||||
struct ImportGraphNode {
|
||||
Scope * scope;
|
||||
String path;
|
||||
isize file_id;
|
||||
isize package_id;
|
||||
ImportGraphNodeSet pred;
|
||||
ImportGraphNodeSet succ;
|
||||
isize index; // Index in array/queue
|
||||
@@ -268,7 +271,7 @@ struct ForeignContext {
|
||||
typedef Array<Entity *> CheckerTypePath;
|
||||
|
||||
struct CheckerContext {
|
||||
Scope * file_scope;
|
||||
Scope * package_scope;
|
||||
Scope * scope;
|
||||
DeclInfo * decl;
|
||||
u32 stmt_state_flags;
|
||||
@@ -282,7 +285,6 @@ struct CheckerContext {
|
||||
CheckerTypePath *type_path;
|
||||
isize type_level; // TODO(bill): Actually handle correctly
|
||||
|
||||
bool collect_delayed_decls;
|
||||
bool allow_polymorphic_types;
|
||||
bool no_polymorphic_errors;
|
||||
bool in_polymorphic_specialization;
|
||||
@@ -295,6 +297,7 @@ struct CheckerInfo {
|
||||
Map<TypeAndValue> types; // Key: AstNode * | Expression -> Type (and value)
|
||||
Map<ExprInfo> untyped; // Key: AstNode * | Expression -> ExprInfo
|
||||
Map<AstFile *> files; // Key: String (full path)
|
||||
Map<AstPackage *> packages; // Key: String (full path)
|
||||
Map<Entity *> foreigns; // Key: String
|
||||
Array<Entity *> definitions;
|
||||
Array<Entity *> entities;
|
||||
@@ -318,12 +321,12 @@ struct Checker {
|
||||
CheckerInfo info;
|
||||
gbMutex mutex;
|
||||
|
||||
AstFile * curr_ast_file;
|
||||
AstPackage * curr_ast_package;
|
||||
Scope * global_scope;
|
||||
// NOTE(bill): Procedures to check
|
||||
Array<ProcedureInfo> procs;
|
||||
Map<Scope *> file_scopes; // Key: String (fullpath)
|
||||
Array<ImportGraphNode *> file_order;
|
||||
Map<Scope *> package_scopes; // Key: String (fullpath)
|
||||
Array<ImportGraphNode *> package_order;
|
||||
|
||||
gbAllocator allocator;
|
||||
gbArena arena;
|
||||
@@ -334,9 +337,6 @@ struct Checker {
|
||||
|
||||
Array<Type *> proc_stack;
|
||||
bool done_preload;
|
||||
|
||||
PtrSet<AstFile *> checked_files;
|
||||
|
||||
};
|
||||
|
||||
|
||||
@@ -382,7 +382,7 @@ void add_entity_and_decl_info(Checker *c, AstNode *identifier, Entity *e, D
|
||||
void add_type_info_type (Checker *c, Type *t);
|
||||
|
||||
void check_add_import_decl(Checker *c, AstNodeImportDecl *id);
|
||||
void check_add_export_decl(Checker *c, AstNodeExportDecl *ed);
|
||||
// void check_add_export_decl(Checker *c, AstNodeExportDecl *ed);
|
||||
void check_add_foreign_import_decl(Checker *c, AstNode *decl);
|
||||
|
||||
|
||||
|
||||
+19
-1
@@ -748,6 +748,8 @@ enum ReadDirectoryError {
|
||||
ReadDirectory_None,
|
||||
|
||||
ReadDirectory_InvalidPath,
|
||||
ReadDirectory_NotExists,
|
||||
ReadDirectory_Permission,
|
||||
ReadDirectory_NotDir,
|
||||
ReadDirectory_EOF,
|
||||
ReadDirectory_Unknown,
|
||||
@@ -760,6 +762,8 @@ enum ReadDirectoryError {
|
||||
ReadDirectoryError read_directory(String path, Array<FileInfo> *fi) {
|
||||
GB_ASSERT(fi != nullptr);
|
||||
|
||||
gbAllocator a = heap_allocator();
|
||||
|
||||
while (path.len > 0) {
|
||||
Rune end = path[path.len-1];
|
||||
if (end == '/') {
|
||||
@@ -774,11 +778,25 @@ ReadDirectoryError read_directory(String path, Array<FileInfo> *fi) {
|
||||
if (path.len == 0) {
|
||||
return ReadDirectory_InvalidPath;
|
||||
}
|
||||
{
|
||||
char *c_str = alloc_cstring(a, path);
|
||||
defer (gb_free(a, c_str));
|
||||
|
||||
gbFile f = {};
|
||||
gbFileError file_err = gb_file_open(&f, c_str);
|
||||
defer (gb_file_close(&f));
|
||||
|
||||
switch (file_err) {
|
||||
case gbFileError_Invalid: return ReadDirectory_InvalidPath;
|
||||
case gbFileError_NotExists: return ReadDirectory_NotExists;
|
||||
// case gbFileError_Permission: return ReadDirectory_Permission;
|
||||
}
|
||||
}
|
||||
|
||||
if (!path_is_directory(path)) {
|
||||
return ReadDirectory_NotDir;
|
||||
}
|
||||
|
||||
gbAllocator a = heap_allocator();
|
||||
|
||||
char *new_path = gb_alloc_array(a, char, path.len+3);
|
||||
defer (gb_free(a, new_path));
|
||||
|
||||
@@ -6,6 +6,7 @@ struct DeclInfo;
|
||||
|
||||
#define ENTITY_KINDS \
|
||||
ENTITY_KIND(Invalid) \
|
||||
ENTITY_KIND(Package) \
|
||||
ENTITY_KIND(Constant) \
|
||||
ENTITY_KIND(Variable) \
|
||||
ENTITY_KIND(TypeName) \
|
||||
@@ -85,6 +86,12 @@ struct Entity {
|
||||
String deprecated_message;
|
||||
|
||||
union {
|
||||
struct {
|
||||
String fullpath;
|
||||
String name;
|
||||
Scope *scope;
|
||||
// Array<Entity *> imports; // Entity_Package
|
||||
} Package;
|
||||
struct {
|
||||
ExactValue value;
|
||||
} Constant;
|
||||
@@ -189,6 +196,15 @@ Entity *alloc_entity(EntityKind kind, Scope *scope, Token token, Type *type) {
|
||||
return entity;
|
||||
}
|
||||
|
||||
Entity *alloc_entity_package(Scope *scope, Type *type, String fullpath, String name) {
|
||||
Token token = empty_token;
|
||||
token.string = name;
|
||||
Entity *entity = alloc_entity(Entity_Package, scope, token, type);
|
||||
entity->Package.fullpath = fullpath;
|
||||
entity->Package.name = name;
|
||||
return entity;
|
||||
}
|
||||
|
||||
Entity *alloc_entity_variable(Scope *scope, Token token, Type *type, bool is_immutable, EntityState state = EntityState_Unresolved) {
|
||||
Entity *entity = alloc_entity(Entity_Variable, scope, token, type);
|
||||
entity->Variable.is_immutable = is_immutable;
|
||||
|
||||
+17
-12
@@ -12,9 +12,9 @@
|
||||
#include "checker.hpp"
|
||||
|
||||
#include "parser.cpp"
|
||||
#if 0
|
||||
#include "docs.cpp"
|
||||
#include "checker.cpp"
|
||||
#if 0
|
||||
#include "ir.cpp"
|
||||
#include "ir_opt.cpp"
|
||||
#include "ir_print.cpp"
|
||||
@@ -574,16 +574,22 @@ bool parse_build_flags(Array<String> args) {
|
||||
}
|
||||
|
||||
void show_timings(Checker *c, Timings *t) {
|
||||
Parser *p = c->parser;
|
||||
isize lines = p->total_line_count;
|
||||
isize tokens = p->total_token_count;
|
||||
isize files = p->files.count;
|
||||
Parser *p = c->parser;
|
||||
isize lines = p->total_line_count;
|
||||
isize tokens = p->total_token_count;
|
||||
isize files = 0;
|
||||
isize packages = p->packages.count;
|
||||
for_array(i, p->packages) {
|
||||
files += p->packages[i]->files.entries.count;
|
||||
}
|
||||
|
||||
{
|
||||
timings_print_all(t);
|
||||
gb_printf("\n");
|
||||
gb_printf("Total Lines - %td\n", lines);
|
||||
gb_printf("Total Tokens - %td\n", tokens);
|
||||
gb_printf("Total Files - %td\n", files);
|
||||
gb_printf("Total Lines - %td\n", lines);
|
||||
gb_printf("Total Tokens - %td\n", tokens);
|
||||
gb_printf("Total Files - %td\n", files);
|
||||
gb_printf("Total Packages - %td\n", packages);
|
||||
gb_printf("\n");
|
||||
}
|
||||
{
|
||||
@@ -774,9 +780,8 @@ int main(int arg_count, char **arg_ptr) {
|
||||
print_usage_line(0, "%s 32-bit is not yet supported", args[0]);
|
||||
return 1;
|
||||
}
|
||||
#if 0
|
||||
|
||||
init_universal_scope();
|
||||
#endif
|
||||
// TODO(bill): prevent compiling without a linker
|
||||
|
||||
timings_start_section(&timings, str_lit("parse files"));
|
||||
@@ -791,9 +796,8 @@ int main(int arg_count, char **arg_ptr) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
#if 0
|
||||
if (build_context.generate_docs) {
|
||||
generate_documentation(&parser);
|
||||
// generate_documentation(&parser);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -807,6 +811,7 @@ int main(int arg_count, char **arg_ptr) {
|
||||
|
||||
check_parsed_files(&checker);
|
||||
|
||||
#if 0
|
||||
if (build_context.no_output_files) {
|
||||
if (build_context.show_timings) {
|
||||
show_timings(&checker, &timings);
|
||||
|
||||
+97
-106
@@ -61,7 +61,7 @@ Token ast_node_token(AstNode *node) {
|
||||
|
||||
case AstNode_ValueDecl: return ast_node_token(node->ValueDecl.names[0]);
|
||||
case AstNode_ImportDecl: return node->ImportDecl.token;
|
||||
case AstNode_ExportDecl: return node->ExportDecl.token;
|
||||
// case AstNode_ExportDecl: return node->ExportDecl.token;
|
||||
case AstNode_ForeignImportDecl: return node->ForeignImportDecl.token;
|
||||
|
||||
case AstNode_ForeignBlockDecl: return node->ForeignBlockDecl.token;
|
||||
@@ -1002,15 +1002,15 @@ AstNode *ast_import_decl(AstFile *f, Token token, bool is_using, Token relpath,
|
||||
return result;
|
||||
}
|
||||
|
||||
AstNode *ast_export_decl(AstFile *f, Token token, Token relpath,
|
||||
CommentGroup docs, CommentGroup comment) {
|
||||
AstNode *result = make_ast_node(f, AstNode_ExportDecl);
|
||||
result->ExportDecl.token = token;
|
||||
result->ExportDecl.relpath = relpath;
|
||||
result->ExportDecl.docs = docs;
|
||||
result->ExportDecl.comment = comment;
|
||||
return result;
|
||||
}
|
||||
// AstNode *ast_export_decl(AstFile *f, Token token, Token relpath,
|
||||
// CommentGroup docs, CommentGroup comment) {
|
||||
// AstNode *result = make_ast_node(f, AstNode_ExportDecl);
|
||||
// result->ExportDecl.token = token;
|
||||
// result->ExportDecl.relpath = relpath;
|
||||
// result->ExportDecl.docs = docs;
|
||||
// result->ExportDecl.comment = comment;
|
||||
// return result;
|
||||
// }
|
||||
|
||||
AstNode *ast_foreign_import_decl(AstFile *f, Token token, Token filepath, Token library_name,
|
||||
CommentGroup docs, CommentGroup comment) {
|
||||
@@ -1309,7 +1309,7 @@ bool is_semicolon_optional_for_node(AstFile *f, AstNode *s) {
|
||||
return s->ProcLit.body != nullptr;
|
||||
|
||||
case AstNode_ImportDecl:
|
||||
case AstNode_ExportDecl:
|
||||
// case AstNode_ExportDecl:
|
||||
case AstNode_ForeignImportDecl:
|
||||
return true;
|
||||
|
||||
@@ -3477,21 +3477,21 @@ AstNode *parse_import_decl(AstFile *f, ImportDeclKind kind) {
|
||||
return s;
|
||||
}
|
||||
|
||||
AstNode *parse_export_decl(AstFile *f) {
|
||||
CommentGroup docs = f->lead_comment;
|
||||
Token token = expect_token(f, Token_export);
|
||||
Token file_path = expect_token_after(f, Token_String, "export");
|
||||
AstNode *s = nullptr;
|
||||
if (f->curr_proc != nullptr) {
|
||||
syntax_error(token, "You cannot use 'export' within a procedure. This must be done at the file scope");
|
||||
s = ast_bad_decl(f, token, file_path);
|
||||
} else {
|
||||
s = ast_export_decl(f, token, file_path, docs, f->line_comment);
|
||||
array_add(&f->imports_and_exports, s);
|
||||
}
|
||||
expect_semicolon(f, s);
|
||||
return s;
|
||||
}
|
||||
// AstNode *parse_export_decl(AstFile *f) {
|
||||
// CommentGroup docs = f->lead_comment;
|
||||
// Token token = expect_token(f, Token_export);
|
||||
// Token file_path = expect_token_after(f, Token_String, "export");
|
||||
// AstNode *s = nullptr;
|
||||
// if (f->curr_proc != nullptr) {
|
||||
// syntax_error(token, "You cannot use 'export' within a procedure. This must be done at the file scope");
|
||||
// s = ast_bad_decl(f, token, file_path);
|
||||
// } else {
|
||||
// s = ast_export_decl(f, token, file_path, docs, f->line_comment);
|
||||
// array_add(&f->imports_and_exports, s);
|
||||
// }
|
||||
// expect_semicolon(f, s);
|
||||
// return s;
|
||||
// }
|
||||
|
||||
AstNode *parse_foreign_decl(AstFile *f) {
|
||||
CommentGroup docs = f->lead_comment;
|
||||
@@ -3584,8 +3584,8 @@ AstNode *parse_stmt(AstFile *f) {
|
||||
case Token_import:
|
||||
return parse_import_decl(f, ImportDecl_Standard);
|
||||
|
||||
case Token_export:
|
||||
return parse_export_decl(f);
|
||||
// case Token_export:
|
||||
// return parse_export_decl(f);
|
||||
|
||||
|
||||
case Token_if: return parse_if_stmt(f);
|
||||
@@ -3632,13 +3632,13 @@ AstNode *parse_stmt(AstFile *f) {
|
||||
import_decl->ImportDecl.using_in_list = list;
|
||||
}
|
||||
return import_decl;
|
||||
} else if (f->curr_token.kind == Token_export) {
|
||||
} /* else if (f->curr_token.kind == Token_export) {
|
||||
AstNode *export_decl = parse_export_decl(f);
|
||||
if (export_decl->kind == AstNode_ExportDecl) {
|
||||
export_decl->ExportDecl.using_in_list = list;
|
||||
}
|
||||
return export_decl;
|
||||
}
|
||||
} */
|
||||
|
||||
AstNode *expr = parse_expr(f, true);
|
||||
expect_semicolon(f, expr);
|
||||
@@ -3883,9 +3883,9 @@ void destroy_ast_file(AstFile *f) {
|
||||
|
||||
bool init_parser(Parser *p) {
|
||||
GB_ASSERT(p != nullptr);
|
||||
map_init(&p->packages, heap_allocator());
|
||||
map_init(&p->imported_files, heap_allocator());
|
||||
array_init(&p->packages, heap_allocator());
|
||||
array_init(&p->imports, heap_allocator());
|
||||
array_init(&p->files, heap_allocator());
|
||||
gb_mutex_init(&p->file_add_mutex);
|
||||
gb_mutex_init(&p->file_decl_mutex);
|
||||
return true;
|
||||
@@ -3894,22 +3894,27 @@ bool init_parser(Parser *p) {
|
||||
void destroy_parser(Parser *p) {
|
||||
GB_ASSERT(p != nullptr);
|
||||
// TODO(bill): Fix memory leak
|
||||
for_array(i, p->files) {
|
||||
destroy_ast_file(p->files[i]);
|
||||
for_array(i, p->packages) {
|
||||
AstPackage *package = p->packages[i];
|
||||
for_array(j, package->files.entries) {
|
||||
destroy_ast_file(package->files.entries[j].value);
|
||||
}
|
||||
map_destroy(&package->files);
|
||||
}
|
||||
#if 0
|
||||
for_array(i, p->imports) {
|
||||
// gb_free(heap_allocator(), p->imports[i].text);
|
||||
}
|
||||
#endif
|
||||
array_free(&p->files);
|
||||
array_free(&p->packages);
|
||||
array_free(&p->imports);
|
||||
map_destroy(&p->imported_files);
|
||||
gb_mutex_destroy(&p->file_add_mutex);
|
||||
gb_mutex_destroy(&p->file_decl_mutex);
|
||||
}
|
||||
|
||||
// NOTE(bill): Returns true if it's added
|
||||
bool try_add_import_path(Parser *p, String path, String rel_path, TokenPos pos) {
|
||||
bool try_add_import_path(Parser *p, String path, String rel_path, TokenPos pos, ImportedPackageKind kind = ImportedPackage_Normal) {
|
||||
if (build_context.generate_docs) {
|
||||
return false;
|
||||
}
|
||||
@@ -3917,22 +3922,20 @@ bool try_add_import_path(Parser *p, String path, String rel_path, TokenPos pos)
|
||||
path = string_trim_whitespace(path);
|
||||
rel_path = string_trim_whitespace(rel_path);
|
||||
|
||||
for_array(i, p->imports) {
|
||||
String import = p->imports[i].path;
|
||||
if (import == path) {
|
||||
return false;
|
||||
}
|
||||
HashKey key = hash_string(path);
|
||||
if (map_get(&p->imported_files, key) != nullptr) {
|
||||
return false;
|
||||
}
|
||||
map_set(&p->imported_files, key, true);
|
||||
|
||||
ImportedPackage item = {};
|
||||
item.kind = ImportedPackage_Normal;
|
||||
item.kind = kind;
|
||||
item.path = path;
|
||||
item.rel_path = rel_path;
|
||||
item.pos = pos;
|
||||
item.index = p->imports.count;
|
||||
array_add(&p->imports, item);
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -4054,34 +4057,12 @@ bool determine_path_from_string(Parser *p, AstNode *node, String base_dir, Strin
|
||||
}
|
||||
|
||||
|
||||
void parse_setup_file_decls(Parser *p, AstFile *f, String base_dir, Array<AstNode *> decls);
|
||||
|
||||
void parse_setup_file_when_stmt(Parser *p, AstFile *f, String base_dir, AstNodeWhenStmt *ws) {
|
||||
if (ws->body != nullptr) {
|
||||
auto stmts = ws->body->BlockStmt.stmts;
|
||||
parse_setup_file_decls(p, f, base_dir, stmts);
|
||||
}
|
||||
|
||||
if (ws->else_stmt != nullptr) {
|
||||
switch (ws->else_stmt->kind) {
|
||||
case AstNode_BlockStmt: {
|
||||
auto stmts = ws->else_stmt->BlockStmt.stmts;
|
||||
parse_setup_file_decls(p, f, base_dir, stmts);
|
||||
} break;
|
||||
case AstNode_WhenStmt:
|
||||
parse_setup_file_when_stmt(p, f, base_dir, &ws->else_stmt->WhenStmt);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void parse_setup_file_decls(Parser *p, AstFile *f, String base_dir, Array<AstNode *> decls) {
|
||||
for_array(i, decls) {
|
||||
AstNode *node = decls[i];
|
||||
if (!is_ast_node_decl(node) &&
|
||||
node->kind != AstNode_BadStmt &&
|
||||
node->kind != AstNode_EmptyStmt &&
|
||||
node->kind != AstNode_WhenStmt) {
|
||||
node->kind != AstNode_EmptyStmt) {
|
||||
// NOTE(bill): Sanity check
|
||||
|
||||
if (node->kind == AstNode_ExprStmt) {
|
||||
@@ -4108,7 +4089,7 @@ void parse_setup_file_decls(Parser *p, AstFile *f, String base_dir, Array<AstNod
|
||||
|
||||
id->fullpath = import_path;
|
||||
try_add_import_path(p, import_path, original_string, ast_node_token(node).pos);
|
||||
} else if (node->kind == AstNode_ExportDecl) {
|
||||
} /* else if (node->kind == AstNode_ExportDecl) {
|
||||
ast_node(ed, ExportDecl, node);
|
||||
|
||||
String original_string = ed->relpath.string;
|
||||
@@ -4123,7 +4104,7 @@ void parse_setup_file_decls(Parser *p, AstFile *f, String base_dir, Array<AstNod
|
||||
|
||||
ed->fullpath = export_path;
|
||||
try_add_import_path(p, export_path, original_string, ast_node_token(node).pos);
|
||||
} else if (node->kind == AstNode_ForeignImportDecl) {
|
||||
} */else if (node->kind == AstNode_ForeignImportDecl) {
|
||||
ast_node(fl, ForeignImportDecl, node);
|
||||
|
||||
String file_str = fl->filepath.string;
|
||||
@@ -4140,9 +4121,6 @@ void parse_setup_file_decls(Parser *p, AstFile *f, String base_dir, Array<AstNod
|
||||
fl->fullpath = foreign_path;
|
||||
}
|
||||
|
||||
} else if (node->kind == AstNode_WhenStmt) {
|
||||
ast_node(ws, WhenStmt, node);
|
||||
parse_setup_file_when_stmt(p, f, base_dir, ws);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -4241,7 +4219,6 @@ skip:
|
||||
// file->id = imported_package.index;
|
||||
HashKey key = hash_string(fi->fullpath);
|
||||
map_set(&package->files, key, file);
|
||||
array_add(&p->files, file);
|
||||
|
||||
if (package->name.len == 0) {
|
||||
package->name = file->package_name;
|
||||
@@ -4262,41 +4239,47 @@ ParseFileError parse_import(Parser *p, ImportedPackage imported_package) {
|
||||
String import_rel_path = imported_package.rel_path;
|
||||
TokenPos pos = imported_package.pos;
|
||||
|
||||
HashKey path_key = hash_string(import_path);
|
||||
if (map_get(&p->packages, path_key) != nullptr) {
|
||||
return ParseFile_None;
|
||||
}
|
||||
|
||||
|
||||
Array<FileInfo> list = {};
|
||||
ReadDirectoryError rd_err = read_directory(import_path, &list);
|
||||
defer (array_free(&list));
|
||||
|
||||
if (rd_err != ReadDirectory_EOF && rd_err != ReadDirectory_None && pos.line != 0) {
|
||||
gb_printf_err("%.*s(%td:%td) ", LIT(pos.file), pos.line, pos.column);
|
||||
if (list.count == 1) {
|
||||
GB_ASSERT(import_path != list[0].fullpath);
|
||||
}
|
||||
|
||||
switch (rd_err) {
|
||||
case ReadDirectory_InvalidPath:
|
||||
gb_printf_err("Invalid path: %.*s\n", LIT(import_rel_path));
|
||||
if (rd_err != ReadDirectory_EOF && rd_err != ReadDirectory_None) {
|
||||
if (pos.line != 0) {
|
||||
gb_printf_err("%.*s(%td:%td) ", LIT(pos.file), pos.line, pos.column);
|
||||
}
|
||||
gb_mutex_lock(&global_error_collector.mutex);
|
||||
defer (gb_mutex_unlock(&global_error_collector.mutex));
|
||||
global_error_collector.count++;
|
||||
gb_mutex_unlock(&global_error_collector.mutex);
|
||||
return ParseFile_InvalidFile;
|
||||
case ReadDirectory_NotDir:
|
||||
gb_printf_err("Expected a directory for a package, got a file: %.*s\n", LIT(import_rel_path));
|
||||
gb_mutex_lock(&global_error_collector.mutex);
|
||||
global_error_collector.count++;
|
||||
gb_mutex_unlock(&global_error_collector.mutex);
|
||||
return ParseFile_InvalidFile;
|
||||
case ReadDirectory_Unknown:
|
||||
gb_printf_err("Unknown error whilst reading directory");
|
||||
gb_mutex_lock(&global_error_collector.mutex);
|
||||
global_error_collector.count++;
|
||||
gb_mutex_unlock(&global_error_collector.mutex);
|
||||
return ParseFile_InvalidFile;
|
||||
case ReadDirectory_EOF:
|
||||
break;
|
||||
|
||||
|
||||
switch (rd_err) {
|
||||
case ReadDirectory_InvalidPath:
|
||||
gb_printf_err("Invalid path: %.*s\n", LIT(import_rel_path));
|
||||
return ParseFile_InvalidFile;
|
||||
|
||||
case ReadDirectory_NotExists:
|
||||
gb_printf_err("Path does not exist: %.*s\n", LIT(import_rel_path));
|
||||
return ParseFile_NotFound;
|
||||
|
||||
case ReadDirectory_NotDir:
|
||||
gb_printf_err("Expected a directory for a package, got a file: %.*s\n", LIT(import_rel_path));
|
||||
return ParseFile_InvalidFile;
|
||||
|
||||
case ReadDirectory_Unknown:
|
||||
gb_printf_err("Unknown error whilst reading path %.*s\n", LIT(import_rel_path));
|
||||
return ParseFile_InvalidFile;
|
||||
case ReadDirectory_Permission:
|
||||
gb_printf_err("Unknown error whilst reading path %.*s\n", LIT(import_rel_path));
|
||||
return ParseFile_InvalidFile;
|
||||
|
||||
case ReadDirectory_EOF:
|
||||
gb_printf_err("Unknown error whilst reading path %.*s\n", LIT(import_rel_path));
|
||||
return ParseFile_InvalidFile;
|
||||
}
|
||||
}
|
||||
|
||||
AstPackage *package = gb_alloc_item(heap_allocator(), AstPackage);
|
||||
@@ -4307,7 +4290,12 @@ ParseFileError parse_import(Parser *p, ImportedPackage imported_package) {
|
||||
// TODO(bill): Fix concurrency
|
||||
for_array(i, list) {
|
||||
FileInfo *fi = &list[i];
|
||||
if (string_ends_with(fi->name, str_lit(".odin"))) {
|
||||
String name = fi->name;
|
||||
String const ext = str_lit(".odin");
|
||||
if (string_ends_with(name, ext)) {
|
||||
if (is_excluded_target_filename(name)) {
|
||||
continue;
|
||||
}
|
||||
ParseFileError err = parse_imported_file(p, package, fi, pos);
|
||||
if (err != ParseFile_None) {
|
||||
return err;
|
||||
@@ -4315,6 +4303,10 @@ ParseFileError parse_import(Parser *p, ImportedPackage imported_package) {
|
||||
}
|
||||
}
|
||||
|
||||
package->id = p->packages.count+1;
|
||||
array_add(&p->packages, package);
|
||||
|
||||
|
||||
return ParseFile_None;
|
||||
}
|
||||
|
||||
@@ -4342,25 +4334,24 @@ ParseFileError parse_packages(Parser *p, String init_filename) {
|
||||
TokenPos init_pos = {};
|
||||
ImportedPackage init_imported_package = {ImportedPackage_Init, init_fullpath, init_fullpath, init_pos};
|
||||
|
||||
isize shared_file_count = 0;
|
||||
isize shared_package_count = 0;
|
||||
if (!build_context.generate_docs) {
|
||||
String s = get_fullpath_core(heap_allocator(), str_lit("runtime"));
|
||||
ImportedPackage runtime_package = {ImportedPackage_Runtime, s, s, init_pos};
|
||||
array_add(&p->imports, runtime_package);
|
||||
shared_file_count++;
|
||||
try_add_import_path(p, s, s, init_pos, ImportedPackage_Runtime);
|
||||
shared_package_count++;
|
||||
}
|
||||
|
||||
array_add(&p->imports, init_imported_package);
|
||||
p->init_fullpath = init_fullpath;
|
||||
|
||||
// IMPORTANT TODO(bill): Figure out why this doesn't work on *nix sometimes
|
||||
#if defined(GB_SYSTEM_WINDOWS)
|
||||
#if 0 && defined(GB_SYSTEM_WINDOWS)
|
||||
isize thread_count = gb_max(build_context.thread_count, 1);
|
||||
if (thread_count > 1) {
|
||||
isize volatile curr_import_index = 0;
|
||||
|
||||
// NOTE(bill): Make sure that these are in parsed in this order
|
||||
for (isize i = 0; i < shared_file_count; i++) {
|
||||
for (isize i = 0; i < shared_package_count; i++) {
|
||||
ParseFileError err = parse_import(p, p->imports[i]);
|
||||
if (err != ParseFile_None) {
|
||||
return err;
|
||||
|
||||
+11
-7
@@ -67,8 +67,8 @@ struct AstFile {
|
||||
|
||||
AstNode * curr_proc;
|
||||
isize scope_level;
|
||||
Scope * scope; // NOTE(bill): Created in checker
|
||||
DeclInfo * decl_info; // NOTE(bill): Created in checker
|
||||
// Scope * scope; // NOTE(bill): Created in checker
|
||||
// DeclInfo * decl_info; // NOTE(bill): Created in checker
|
||||
|
||||
|
||||
CommentGroup lead_comment; // Comment (block) before the decl
|
||||
@@ -84,17 +84,21 @@ struct AstFile {
|
||||
|
||||
|
||||
struct AstPackage {
|
||||
isize id;
|
||||
ImportedPackageKind kind;
|
||||
String name;
|
||||
String fullpath;
|
||||
Map<AstFile *> files; // Key: String (names)
|
||||
|
||||
Scope * scope; // NOTE(bill): Created in checker
|
||||
DeclInfo *decl_info; // NOTE(bill): Created in checker
|
||||
};
|
||||
|
||||
|
||||
struct Parser {
|
||||
String init_fullpath;
|
||||
Map<AstPackage *> packages; // Key: String (fullpath)
|
||||
Array<AstFile *> files;
|
||||
Map<bool> imported_files; // Key: String (fullpath)
|
||||
Array<AstPackage *> packages;
|
||||
Array<ImportedPackage> imports;
|
||||
isize total_token_count;
|
||||
isize total_line_count;
|
||||
@@ -351,7 +355,7 @@ AST_NODE_KIND(_DeclBegin, "", struct {}) \
|
||||
bool been_handled; \
|
||||
}) \
|
||||
AST_NODE_KIND(ImportDecl, "import declaration", struct { \
|
||||
AstFile *file; \
|
||||
AstPackage *package; \
|
||||
Token token; \
|
||||
Token relpath; \
|
||||
String fullpath; \
|
||||
@@ -362,7 +366,7 @@ AST_NODE_KIND(_DeclBegin, "", struct {}) \
|
||||
bool is_using; \
|
||||
bool been_handled; \
|
||||
}) \
|
||||
AST_NODE_KIND(ExportDecl, "export declaration", struct { \
|
||||
/* AST_NODE_KIND(ExportDecl, "export declaration", struct { \
|
||||
AstFile *file; \
|
||||
Token token; \
|
||||
Token relpath; \
|
||||
@@ -371,7 +375,7 @@ AST_NODE_KIND(_DeclBegin, "", struct {}) \
|
||||
CommentGroup docs; \
|
||||
CommentGroup comment; \
|
||||
bool been_handled; \
|
||||
}) \
|
||||
}) */ \
|
||||
AST_NODE_KIND(ForeignImportDecl, "foreign import declaration", struct { \
|
||||
Token token; \
|
||||
Token filepath; \
|
||||
|
||||
@@ -94,6 +94,13 @@ String substring(String const &s, isize lo, isize hi) {
|
||||
}
|
||||
|
||||
|
||||
char *alloc_cstring(gbAllocator a, String s) {
|
||||
char *c_str = gb_alloc_array(a, char, s.len+1);
|
||||
gb_memcopy(c_str, s.text, s.len);
|
||||
c_str[s.len] = '\0';
|
||||
return c_str;
|
||||
}
|
||||
|
||||
|
||||
|
||||
gb_inline bool str_eq_ignore_case(String const &a, String const &b) {
|
||||
|
||||
+1
-4
@@ -448,12 +448,9 @@ void advance_to_next_rune(Tokenizer *t) {
|
||||
TokenizerInitError init_tokenizer(Tokenizer *t, String fullpath) {
|
||||
TokenizerInitError err = TokenizerInit_None;
|
||||
|
||||
char *c_str = gb_alloc_array(heap_allocator(), char, fullpath.len+1);
|
||||
char *c_str = alloc_cstring(heap_allocator(), fullpath);
|
||||
defer (gb_free(heap_allocator(), c_str));
|
||||
|
||||
gb_memcopy(c_str, fullpath.text, fullpath.len);
|
||||
c_str[fullpath.len] = '\0';
|
||||
|
||||
// TODO(bill): Memory map rather than copy contents
|
||||
gbFileContents fc = gb_file_read_contents(heap_allocator(), true, c_str);
|
||||
gb_zero_item(t);
|
||||
|
||||
Reference in New Issue
Block a user