Add basic package support (no IR support yet)

This commit is contained in:
gingerBill
2018-05-26 23:12:55 +01:00
parent 5b6770f3d2
commit c067b90403
20 changed files with 698 additions and 818 deletions
@@ -3,10 +3,7 @@ package atomics
// TODO(bill): Use assembly instead here to implement atomics // TODO(bill): Use assembly instead here to implement atomics
// Inline vs external file? // Inline vs external file?
when ODIN_OS == "windows" { import "core:sys/win32"
import win32 "core:sys/windows.odin"
}
#assert(ODIN_ARCH == "amd64"); // TODO(bill): x86 version
yield_thread :: proc() { win32.mm_pause(); } yield_thread :: proc() { win32.mm_pause(); }
+142 -142
View File
@@ -1,174 +1,174 @@
package os package os
foreign import api "system:api" // foreign import api "system:api"
Handle :: distinct int; // Handle :: distinct int;
Errno :: distinct int; // Errno :: distinct int;
O_RDONLY :: 0x00001; // O_RDONLY :: 0x00001;
O_WRONLY :: 0x00002; // O_WRONLY :: 0x00002;
O_RDWR :: 0x00003; // O_RDWR :: 0x00003;
O_CREATE :: 0x00040; // O_CREATE :: 0x00040;
O_EXCL :: 0x00080; // O_EXCL :: 0x00080;
O_TRUNC :: 0x00200; // O_TRUNC :: 0x00200;
O_APPEND :: 0x00400; // O_APPEND :: 0x00400;
ERROR_NONE : Errno : -1 ; // ERROR_NONE : Errno : -1 ;
ERROR_UNKNOWN_OPERATION_FAILURE : Errno : -7 ; // ERROR_UNKNOWN_OPERATION_FAILURE : Errno : -7 ;
ERROR_PATH_NOT_WITHIN_MOUNTED_VOLUME : Errno : -14; // ERROR_PATH_NOT_WITHIN_MOUNTED_VOLUME : Errno : -14;
ERROR_PATH_NOT_FOUND : Errno : -15; // ERROR_PATH_NOT_FOUND : Errno : -15;
ERROR_FILE_EXISTS : Errno : -19; // ERROR_FILE_EXISTS : Errno : -19;
ERROR_FILE_NOT_FOUND : Errno : -20; // ERROR_FILE_NOT_FOUND : Errno : -20;
ERROR_DRIVE_ERROR_FILE_DAMAGED : Errno : -21; // ERROR_DRIVE_ERROR_FILE_DAMAGED : Errno : -21;
ERROR_ACCESS_NOT_WITHIN_FILE_BOUNDS : Errno : -22; // ERROR_ACCESS_NOT_WITHIN_FILE_BOUNDS : Errno : -22;
ERROR_ACCESS_DENIED : Errno : -23; // ERROR_ACCESS_DENIED : Errno : -23;
ERROR_FILE_IN_EXCLUSIVE_USE : Errno : -24; // ERROR_FILE_IN_EXCLUSIVE_USE : Errno : -24;
ERROR_FILE_CANNOT_GET_EXCLUSIVE_USE : Errno : -25; // ERROR_FILE_CANNOT_GET_EXCLUSIVE_USE : Errno : -25;
ERROR_INCORRECT_NODE_TYPE : Errno : -26; // ERROR_INCORRECT_NODE_TYPE : Errno : -26;
ERROR_EVENT_NOT_SET : Errno : -27; // ERROR_EVENT_NOT_SET : Errno : -27;
ERROR_TIMEOUT_REACHED : Errno : -29; // ERROR_TIMEOUT_REACHED : Errno : -29;
ERROR_REQUEST_CLOSED_BEFORE_COMPLETE : Errno : -30; // ERROR_REQUEST_CLOSED_BEFORE_COMPLETE : Errno : -30;
ERROR_NO_CHARACTER_AT_COORDINATE : Errno : -31; // ERROR_NO_CHARACTER_AT_COORDINATE : Errno : -31;
ERROR_FILE_ON_READ_ONLY_VOLUME : Errno : -32; // ERROR_FILE_ON_READ_ONLY_VOLUME : Errno : -32;
ERROR_USER_CANCELED_IO : Errno : -33; // ERROR_USER_CANCELED_IO : Errno : -33;
ERROR_DRIVE_CONTROLLER_REPORTED : Errno : -35; // ERROR_DRIVE_CONTROLLER_REPORTED : Errno : -35;
ERROR_COULD_NOT_ISSUE_PACKET : Errno : -36; // ERROR_COULD_NOT_ISSUE_PACKET : Errno : -36;
ERROR_NOT_IMPLEMENTED : Errno : 1; // ERROR_NOT_IMPLEMENTED : Errno : 1;
OS_Node_Type :: enum i32 { // OS_Node_Type :: enum i32 {
File = 0, // File = 0,
Directory = 1, // Directory = 1,
} // }
OS_Node_Information :: struct { // OS_Node_Information :: struct {
handle: Handle, // handle: Handle,
id: [16]byte, // id: [16]byte,
ntype: OS_Node_Type, // ntype: OS_Node_Type,
size: i64, // size: i64,
// Our additions... // // Our additions...
position: i64, // position: i64,
} // }
foreign api { // foreign api {
@(link_name="OSPrintDirect") OSPrintDirect :: proc(str: ^u8, length: int) ---; // @(link_name="OSPrintDirect") OSPrintDirect :: proc(str: ^u8, length: int) ---;
@(link_name="malloc") OSMalloc :: proc(bytes: int) -> rawptr ---; // @(link_name="malloc") OSMalloc :: proc(bytes: int) -> rawptr ---;
@(link_name="free") OSFree :: proc(address: rawptr) ---; // @(link_name="free") OSFree :: proc(address: rawptr) ---;
@(link_name="OSOpenNode") OSOpenNode :: proc(path: ^u8, path_length: int, flags: u64, information: ^OS_Node_Information) -> Errno ---; // @(link_name="OSOpenNode") OSOpenNode :: proc(path: ^u8, path_length: int, flags: u64, information: ^OS_Node_Information) -> Errno ---;
@(link_name="OSResizeFile") OSResizeFile :: proc(handle: Handle, new_size: u64) -> Errno ---; // @(link_name="OSResizeFile") OSResizeFile :: proc(handle: Handle, new_size: u64) -> Errno ---;
@(link_name="OSCloseHandle") OSCloseHandle :: proc(handle: Handle) ---; // @(link_name="OSCloseHandle") OSCloseHandle :: proc(handle: Handle) ---;
@(link_name="OSWriteFileSync") OSWriteFileSync :: proc(handle: Handle, offset: i64, size: i64, buffer: rawptr) -> i64 ---; // @(link_name="OSWriteFileSync") OSWriteFileSync :: proc(handle: Handle, offset: i64, size: i64, buffer: rawptr) -> i64 ---;
@(link_name="OSReadFileSync") OSReadFileSync :: proc(handle: Handle, offset: i64, size: i64, buffer: rawptr) -> i64 ---; // @(link_name="OSReadFileSync") OSReadFileSync :: proc(handle: Handle, offset: i64, size: i64, buffer: rawptr) -> i64 ---;
@(link_name="realloc") OSRealloc :: proc(address: rawptr, size: int) -> rawptr ---; // @(link_name="realloc") OSRealloc :: proc(address: rawptr, size: int) -> rawptr ---;
@(link_name="OSGetThreadID") OSGetThreadID :: proc(handle: Handle) -> int ---; // @(link_name="OSGetThreadID") OSGetThreadID :: proc(handle: Handle) -> int ---;
@(link_name="OSRefreshNodeInformation") OSRefreshNodeInformation :: proc(information: ^OS_Node_Information) ---; // @(link_name="OSRefreshNodeInformation") OSRefreshNodeInformation :: proc(information: ^OS_Node_Information) ---;
} // }
stdin := Handle(-1); // Not implemented // stdin := Handle(-1); // Not implemented
stdout := Handle(0); // stdout := Handle(0);
stderr := Handle(0); // stderr := Handle(0);
current_thread_id :: proc() -> int { // current_thread_id :: proc() -> int {
return OSGetThreadID(Handle(0x1000)); // return OSGetThreadID(Handle(0x1000));
} // }
heap_alloc :: proc(size: int) -> rawptr { // heap_alloc :: proc(size: int) -> rawptr {
return OSMalloc(size); // return OSMalloc(size);
} // }
heap_free :: proc(address: rawptr) { // heap_free :: proc(address: rawptr) {
OSFree(address); // OSFree(address);
} // }
heap_resize :: proc(address: rawptr, new_size: int) -> rawptr { // heap_resize :: proc(address: rawptr, new_size: int) -> rawptr {
return OSRealloc(address, new_size); // return OSRealloc(address, new_size);
} // }
open :: proc(path: string, mode: int = O_RDONLY, perm: u32 = 0) -> (Handle, Errno) { // open :: proc(path: string, mode: int = O_RDONLY, perm: u32 = 0) -> (Handle, Errno) {
flags : u64 = 0; // flags : u64 = 0;
if mode & O_CREATE == O_CREATE { // if mode & O_CREATE == O_CREATE {
flags = flags | 0x9000; // Fail if found and create directories leading to the file if they don't exist // flags = flags | 0x9000; // Fail if found and create directories leading to the file if they don't exist
} else { // } else {
flags = flags | 0x2000; // Fail if not found // flags = flags | 0x2000; // Fail if not found
} // }
if mode & O_EXCL == O_EXCL { // if mode & O_EXCL == O_EXCL {
flags = flags | 0x111; // Block opening the node for any reason // flags = flags | 0x111; // Block opening the node for any reason
} // }
if mode & O_RDONLY == O_RDONLY { // if mode & O_RDONLY == O_RDONLY {
flags = flags | 0x2; // Read access // flags = flags | 0x2; // Read access
} // }
if mode & O_WRONLY == O_WRONLY { // if mode & O_WRONLY == O_WRONLY {
flags = flags | 0x220; // Write and resize access // flags = flags | 0x220; // Write and resize access
} // }
if mode & O_TRUNC == O_TRUNC { // if mode & O_TRUNC == O_TRUNC {
flags = flags | 0x200; // Resize access // flags = flags | 0x200; // Resize access
} // }
information := new(OS_Node_Information); // information := new(OS_Node_Information);
error := OSOpenNode(&path[0], len(path), flags, information); // error := OSOpenNode(&path[0], len(path), flags, information);
if error < ERROR_NONE { // if error < ERROR_NONE {
free(information); // free(information);
return 0, error; // return 0, error;
} // }
if mode & O_TRUNC == O_TRUNC { // if mode & O_TRUNC == O_TRUNC {
error := OSResizeFile(information.handle, 0); // error := OSResizeFile(information.handle, 0);
if error < ERROR_NONE do return 0, ERROR_UNKNOWN_OPERATION_FAILURE; // if error < ERROR_NONE do return 0, ERROR_UNKNOWN_OPERATION_FAILURE;
} // }
if mode & O_APPEND == O_APPEND { // if mode & O_APPEND == O_APPEND {
information.position = information.size; // information.position = information.size;
} else { // } else {
information.position = 0; // information.position = 0;
} // }
return Handle(uintptr(information)), ERROR_NONE; // return Handle(uintptr(information)), ERROR_NONE;
} // }
close :: proc(fd: Handle) { // close :: proc(fd: Handle) {
information := (^OS_Node_Information)(uintptr(fd)); // information := (^OS_Node_Information)(uintptr(fd));
OSCloseHandle(information.handle); // OSCloseHandle(information.handle);
free(information); // free(information);
} // }
file_size :: proc(fd: Handle) -> (i64, Errno) { // file_size :: proc(fd: Handle) -> (i64, Errno) {
x : OS_Node_Information; // x : OS_Node_Information;
OSRefreshNodeInformation(&x); // OSRefreshNodeInformation(&x);
return x.size, ERROR_NONE; // return x.size, ERROR_NONE;
} // }
write :: proc(fd: Handle, data: []byte) -> (int, Errno) { // write :: proc(fd: Handle, data: []byte) -> (int, Errno) {
if fd == 0 { // if fd == 0 {
OSPrintDirect(&data[0], len(data)); // OSPrintDirect(&data[0], len(data));
return len(data), ERROR_NONE; // return len(data), ERROR_NONE;
} else if fd == 1 { // } else if fd == 1 {
assert(false); // assert(false);
return 0, ERROR_NOT_IMPLEMENTED; // return 0, ERROR_NOT_IMPLEMENTED;
} // }
information := (^OS_Node_Information)(uintptr(fd)); // information := (^OS_Node_Information)(uintptr(fd));
count := OSWriteFileSync(information.handle, information.position, i64(len(data)), &data[0]); // count := OSWriteFileSync(information.handle, information.position, i64(len(data)), &data[0]);
if count < 0 do return 0, 1; // if count < 0 do return 0, 1;
information.position += count; // information.position += count;
return int(count), 0; // return int(count), 0;
} // }
read :: proc(fd: Handle, data: []byte) -> (int, Errno) { // read :: proc(fd: Handle, data: []byte) -> (int, Errno) {
if (fd == 0 || fd == 1) { // if (fd == 0 || fd == 1) {
assert(false); // assert(false);
return 0, ERROR_NOT_IMPLEMENTED; // return 0, ERROR_NOT_IMPLEMENTED;
} // }
information := (^OS_Node_Information)(uintptr(fd)); // information := (^OS_Node_Information)(uintptr(fd));
count := OSReadFileSync(information.handle, information.position, i64(len(data)), &data[0]); // count := OSReadFileSync(information.handle, information.position, i64(len(data)), &data[0]);
if count < 0 do return 0, ERROR_UNKNOWN_OPERATION_FAILURE; // if count < 0 do return 0, ERROR_UNKNOWN_OPERATION_FAILURE;
information.position += count; // information.position += count;
return int(count), ERROR_NONE; // return int(count), ERROR_NONE;
} // }
+1 -1
View File
@@ -1,7 +1,7 @@
package os package os
import "core:sys/win32" import "core:sys/win32"
import "core:mem" // import "core:mem"
Handle :: distinct uintptr; Handle :: distinct uintptr;
File_Time :: distinct u64; File_Time :: distinct u64;
+2 -2
View File
@@ -1,8 +1,8 @@
package win32 package win32
when ODIN_OS == "windows" { // when ODIN_OS == "windows" {
foreign import "system:opengl32.lib" foreign import "system:opengl32.lib"
} // }
CONTEXT_MAJOR_VERSION_ARB :: 0x2091; CONTEXT_MAJOR_VERSION_ARB :: 0x2091;
+2 -2
View File
@@ -1,12 +1,12 @@
package win32 package win32
when ODIN_OS == "windows" { // when ODIN_OS == "windows" {
foreign import "system:kernel32.lib" foreign import "system:kernel32.lib"
foreign import "system:user32.lib" foreign import "system:user32.lib"
foreign import "system:gdi32.lib" foreign import "system:gdi32.lib"
foreign import "system:winmm.lib" foreign import "system:winmm.lib"
foreign import "system:shell32.lib" foreign import "system:shell32.lib"
} // }
Handle :: distinct rawptr; Handle :: distinct rawptr;
Hwnd :: distinct Handle; Hwnd :: distinct Handle;
+1 -4
View File
@@ -1,10 +1,7 @@
package thread package thread
#assert(ODIN_OS == "windows"); #assert(ODIN_OS == "windows");
import "core:sys/win32"
when ODIN_OS == "windows" {
import win32 "core:sys/windows.odin"
}
Thread_Proc :: #type proc(^Thread) -> int; Thread_Proc :: #type proc(^Thread) -> int;
+1 -1
View File
@@ -1,4 +1,4 @@
package utf8 package utf16
import "core:unicode/utf8" import "core:unicode/utf8"
+112 -3
View File
@@ -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 // This stores the information for the specify architecture of this build
struct BuildContext { struct BuildContext {
// Constants // Constants
@@ -15,6 +50,9 @@ struct BuildContext {
String command; String command;
TargetOsKind target_os;
TargetArchKind target_arch;
String out_filepath; String out_filepath;
String resource_filepath; String resource_filepath;
bool has_resource; bool has_resource;
@@ -37,6 +75,72 @@ struct BuildContext {
gb_global BuildContext build_context = {0}; 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 { struct LibraryCollections {
String name; String name;
String path; String path;
@@ -327,11 +431,14 @@ void init_build_context(void) {
bc->ODIN_ROOT = odin_root_dir(); bc->ODIN_ROOT = odin_root_dir();
#if defined(GB_SYSTEM_WINDOWS) #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) #elif defined(GB_SYSTEM_OSX)
bc->ODIN_OS = str_lit("osx"); bc->ODIN_OS = str_lit("osx");
bc->target_os = TargetOs_osx;
#else #else
bc->ODIN_OS = str_lit("linux"); bc->ODIN_OS = str_lit("linux");
bc->target_os = TargetOs_linux;
#endif #endif
if (cross_compile_target.len) { if (cross_compile_target.len) {
@@ -340,8 +447,10 @@ void init_build_context(void) {
#if defined(GB_ARCH_64_BIT) #if defined(GB_ARCH_64_BIT)
bc->ODIN_ARCH = str_lit("amd64"); bc->ODIN_ARCH = str_lit("amd64");
bc->target_arch = TargetArch_amd64;
#else #else
bc->ODIN_ARCH = str_lit("x86"); bc->ODIN_ARCH = str_lit("x86");
bc->target_arch = TargetArch_x86;
#endif #endif
{ {
+2 -2
View File
@@ -535,7 +535,7 @@ void check_proc_decl(Checker *c, Entity *e, DeclInfo *d) {
e->deprecated_message = ac.deprecated_message; e->deprecated_message = ac.deprecated_message;
ac.link_name = handle_link_name(c, e->token, ac.link_name, ac.link_prefix); 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 || if (pt->param_count != 0 ||
pt->result_count != 0) { pt->result_count != 0) {
gbString str = type_to_string(proc_type); 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); GB_ASSERT(pl->body->kind == AstNode_BlockStmt);
if (!pt->is_polymorphic) { 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) { } else if (!is_foreign) {
if (e->Procedure.is_export) { if (e->Procedure.is_export) {
+7 -6
View File
@@ -109,7 +109,7 @@ void error_operand_no_value(Operand *o) {
void check_scope_decls(Checker *c, Array<AstNode *> nodes, isize reserve_size) { void check_scope_decls(Checker *c, Array<AstNode *> nodes, isize reserve_size) {
Scope *s = c->context.scope; Scope *s = c->context.scope;
GB_ASSERT(s->file == nullptr); GB_ASSERT(s->package == nullptr);
check_collect_entities(c, nodes); 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 // NOTE(bill): Set the scope afterwards as this is not real overloading
entity->scope = scope->parent; entity->scope = scope->parent;
AstFile *file = nullptr; AstPackage *package = nullptr;
{ {
Scope *s = entity->scope; Scope *s = entity->scope;
while (s != nullptr && s->file == nullptr) { while (s != nullptr && s->package == nullptr) {
file = s->file; package = s->package;
s = s->parent; s = s->parent;
} }
} }
ProcedureInfo proc_info = {}; ProcedureInfo proc_info = {};
proc_info.file = file; // proc_info.file = file;
proc_info.package = package;
proc_info.token = token; proc_info.token = token;
proc_info.decl = d; proc_info.decl = d;
proc_info.type = final_proc_type; 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; 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); check_close_scope(c);
+4 -1
View File
@@ -627,7 +627,10 @@ void check_switch_stmt(Checker *c, AstNode *node, u32 mod_flags) {
Token token = {}; Token token = {};
token.pos = ast_node_token(ss->body).pos; token.pos = ast_node_token(ss->body).pos;
token.string = str_lit("true"); 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 // NOTE(bill): Check for multiple defaults
+241 -506
View File
File diff suppressed because it is too large Load Diff
+14 -14
View File
@@ -194,7 +194,8 @@ struct DeclInfo {
// ProcedureInfo stores the information needed for checking a procedure // ProcedureInfo stores the information needed for checking a procedure
struct ProcedureInfo { struct ProcedureInfo {
AstFile * file; // AstFile * file;
AstPackage * package;
Token token; Token token;
DeclInfo * decl; DeclInfo * decl;
Type * type; // Type_Procedure Type * type; // Type_Procedure
@@ -204,6 +205,7 @@ struct ProcedureInfo {
}; };
struct Scope { struct Scope {
AstNode * node; AstNode * node;
Scope * parent; Scope * parent;
@@ -214,17 +216,18 @@ struct Scope {
PtrSet<Entity *> implicit; PtrSet<Entity *> implicit;
Array<Scope *> shared; Array<Scope *> shared;
Array<AstNode *> delayed_file_decls;
Array<AstNode *> delayed_asserts; Array<AstNode *> delayed_asserts;
Array<AstNode *> delayed_imports;
PtrSet<Scope *> imported; PtrSet<Scope *> imported;
PtrSet<Scope *> exported; // NOTE(bhall): Contains 'using import' too PtrSet<Scope *> exported; // NOTE(bhall): Contains 'using import' too
bool is_proc; bool is_proc;
bool is_global; bool is_global;
bool is_file; bool is_package;
bool is_init; bool is_init;
bool is_struct; bool is_struct;
bool has_been_imported; // This is only applicable to file scopes 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 { struct ImportGraphNode {
Scope * scope; Scope * scope;
String path; String path;
isize file_id; isize package_id;
ImportGraphNodeSet pred; ImportGraphNodeSet pred;
ImportGraphNodeSet succ; ImportGraphNodeSet succ;
isize index; // Index in array/queue isize index; // Index in array/queue
@@ -268,7 +271,7 @@ struct ForeignContext {
typedef Array<Entity *> CheckerTypePath; typedef Array<Entity *> CheckerTypePath;
struct CheckerContext { struct CheckerContext {
Scope * file_scope; Scope * package_scope;
Scope * scope; Scope * scope;
DeclInfo * decl; DeclInfo * decl;
u32 stmt_state_flags; u32 stmt_state_flags;
@@ -282,7 +285,6 @@ struct CheckerContext {
CheckerTypePath *type_path; CheckerTypePath *type_path;
isize type_level; // TODO(bill): Actually handle correctly isize type_level; // TODO(bill): Actually handle correctly
bool collect_delayed_decls;
bool allow_polymorphic_types; bool allow_polymorphic_types;
bool no_polymorphic_errors; bool no_polymorphic_errors;
bool in_polymorphic_specialization; bool in_polymorphic_specialization;
@@ -295,6 +297,7 @@ struct CheckerInfo {
Map<TypeAndValue> types; // Key: AstNode * | Expression -> Type (and value) Map<TypeAndValue> types; // Key: AstNode * | Expression -> Type (and value)
Map<ExprInfo> untyped; // Key: AstNode * | Expression -> ExprInfo Map<ExprInfo> untyped; // Key: AstNode * | Expression -> ExprInfo
Map<AstFile *> files; // Key: String (full path) Map<AstFile *> files; // Key: String (full path)
Map<AstPackage *> packages; // Key: String (full path)
Map<Entity *> foreigns; // Key: String Map<Entity *> foreigns; // Key: String
Array<Entity *> definitions; Array<Entity *> definitions;
Array<Entity *> entities; Array<Entity *> entities;
@@ -318,12 +321,12 @@ struct Checker {
CheckerInfo info; CheckerInfo info;
gbMutex mutex; gbMutex mutex;
AstFile * curr_ast_file; AstPackage * curr_ast_package;
Scope * global_scope; Scope * global_scope;
// NOTE(bill): Procedures to check // NOTE(bill): Procedures to check
Array<ProcedureInfo> procs; Array<ProcedureInfo> procs;
Map<Scope *> file_scopes; // Key: String (fullpath) Map<Scope *> package_scopes; // Key: String (fullpath)
Array<ImportGraphNode *> file_order; Array<ImportGraphNode *> package_order;
gbAllocator allocator; gbAllocator allocator;
gbArena arena; gbArena arena;
@@ -334,9 +337,6 @@ struct Checker {
Array<Type *> proc_stack; Array<Type *> proc_stack;
bool done_preload; 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 add_type_info_type (Checker *c, Type *t);
void check_add_import_decl(Checker *c, AstNodeImportDecl *id); 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); void check_add_foreign_import_decl(Checker *c, AstNode *decl);
+19 -1
View File
@@ -748,6 +748,8 @@ enum ReadDirectoryError {
ReadDirectory_None, ReadDirectory_None,
ReadDirectory_InvalidPath, ReadDirectory_InvalidPath,
ReadDirectory_NotExists,
ReadDirectory_Permission,
ReadDirectory_NotDir, ReadDirectory_NotDir,
ReadDirectory_EOF, ReadDirectory_EOF,
ReadDirectory_Unknown, ReadDirectory_Unknown,
@@ -760,6 +762,8 @@ enum ReadDirectoryError {
ReadDirectoryError read_directory(String path, Array<FileInfo> *fi) { ReadDirectoryError read_directory(String path, Array<FileInfo> *fi) {
GB_ASSERT(fi != nullptr); GB_ASSERT(fi != nullptr);
gbAllocator a = heap_allocator();
while (path.len > 0) { while (path.len > 0) {
Rune end = path[path.len-1]; Rune end = path[path.len-1];
if (end == '/') { if (end == '/') {
@@ -774,11 +778,25 @@ ReadDirectoryError read_directory(String path, Array<FileInfo> *fi) {
if (path.len == 0) { if (path.len == 0) {
return ReadDirectory_InvalidPath; 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)) { if (!path_is_directory(path)) {
return ReadDirectory_NotDir; return ReadDirectory_NotDir;
} }
gbAllocator a = heap_allocator();
char *new_path = gb_alloc_array(a, char, path.len+3); char *new_path = gb_alloc_array(a, char, path.len+3);
defer (gb_free(a, new_path)); defer (gb_free(a, new_path));
+16
View File
@@ -6,6 +6,7 @@ struct DeclInfo;
#define ENTITY_KINDS \ #define ENTITY_KINDS \
ENTITY_KIND(Invalid) \ ENTITY_KIND(Invalid) \
ENTITY_KIND(Package) \
ENTITY_KIND(Constant) \ ENTITY_KIND(Constant) \
ENTITY_KIND(Variable) \ ENTITY_KIND(Variable) \
ENTITY_KIND(TypeName) \ ENTITY_KIND(TypeName) \
@@ -85,6 +86,12 @@ struct Entity {
String deprecated_message; String deprecated_message;
union { union {
struct {
String fullpath;
String name;
Scope *scope;
// Array<Entity *> imports; // Entity_Package
} Package;
struct { struct {
ExactValue value; ExactValue value;
} Constant; } Constant;
@@ -189,6 +196,15 @@ Entity *alloc_entity(EntityKind kind, Scope *scope, Token token, Type *type) {
return entity; 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 *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 *entity = alloc_entity(Entity_Variable, scope, token, type);
entity->Variable.is_immutable = is_immutable; entity->Variable.is_immutable = is_immutable;
+17 -12
View File
@@ -12,9 +12,9 @@
#include "checker.hpp" #include "checker.hpp"
#include "parser.cpp" #include "parser.cpp"
#if 0
#include "docs.cpp" #include "docs.cpp"
#include "checker.cpp" #include "checker.cpp"
#if 0
#include "ir.cpp" #include "ir.cpp"
#include "ir_opt.cpp" #include "ir_opt.cpp"
#include "ir_print.cpp" #include "ir_print.cpp"
@@ -574,16 +574,22 @@ bool parse_build_flags(Array<String> args) {
} }
void show_timings(Checker *c, Timings *t) { void show_timings(Checker *c, Timings *t) {
Parser *p = c->parser; Parser *p = c->parser;
isize lines = p->total_line_count; isize lines = p->total_line_count;
isize tokens = p->total_token_count; isize tokens = p->total_token_count;
isize files = p->files.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); timings_print_all(t);
gb_printf("\n"); gb_printf("\n");
gb_printf("Total Lines - %td\n", lines); gb_printf("Total Lines - %td\n", lines);
gb_printf("Total Tokens - %td\n", tokens); gb_printf("Total Tokens - %td\n", tokens);
gb_printf("Total Files - %td\n", files); gb_printf("Total Files - %td\n", files);
gb_printf("Total Packages - %td\n", packages);
gb_printf("\n"); 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]); print_usage_line(0, "%s 32-bit is not yet supported", args[0]);
return 1; return 1;
} }
#if 0
init_universal_scope(); init_universal_scope();
#endif
// TODO(bill): prevent compiling without a linker // TODO(bill): prevent compiling without a linker
timings_start_section(&timings, str_lit("parse files")); timings_start_section(&timings, str_lit("parse files"));
@@ -791,9 +796,8 @@ int main(int arg_count, char **arg_ptr) {
return 1; return 1;
} }
#if 0
if (build_context.generate_docs) { if (build_context.generate_docs) {
generate_documentation(&parser); // generate_documentation(&parser);
return 0; return 0;
} }
@@ -807,6 +811,7 @@ int main(int arg_count, char **arg_ptr) {
check_parsed_files(&checker); check_parsed_files(&checker);
#if 0
if (build_context.no_output_files) { if (build_context.no_output_files) {
if (build_context.show_timings) { if (build_context.show_timings) {
show_timings(&checker, &timings); show_timings(&checker, &timings);
+97 -106
View File
@@ -61,7 +61,7 @@ Token ast_node_token(AstNode *node) {
case AstNode_ValueDecl: return ast_node_token(node->ValueDecl.names[0]); case AstNode_ValueDecl: return ast_node_token(node->ValueDecl.names[0]);
case AstNode_ImportDecl: return node->ImportDecl.token; 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_ForeignImportDecl: return node->ForeignImportDecl.token;
case AstNode_ForeignBlockDecl: return node->ForeignBlockDecl.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; return result;
} }
AstNode *ast_export_decl(AstFile *f, Token token, Token relpath, // AstNode *ast_export_decl(AstFile *f, Token token, Token relpath,
CommentGroup docs, CommentGroup comment) { // CommentGroup docs, CommentGroup comment) {
AstNode *result = make_ast_node(f, AstNode_ExportDecl); // AstNode *result = make_ast_node(f, AstNode_ExportDecl);
result->ExportDecl.token = token; // result->ExportDecl.token = token;
result->ExportDecl.relpath = relpath; // result->ExportDecl.relpath = relpath;
result->ExportDecl.docs = docs; // result->ExportDecl.docs = docs;
result->ExportDecl.comment = comment; // result->ExportDecl.comment = comment;
return result; // return result;
} // }
AstNode *ast_foreign_import_decl(AstFile *f, Token token, Token filepath, Token library_name, AstNode *ast_foreign_import_decl(AstFile *f, Token token, Token filepath, Token library_name,
CommentGroup docs, CommentGroup comment) { CommentGroup docs, CommentGroup comment) {
@@ -1309,7 +1309,7 @@ bool is_semicolon_optional_for_node(AstFile *f, AstNode *s) {
return s->ProcLit.body != nullptr; return s->ProcLit.body != nullptr;
case AstNode_ImportDecl: case AstNode_ImportDecl:
case AstNode_ExportDecl: // case AstNode_ExportDecl:
case AstNode_ForeignImportDecl: case AstNode_ForeignImportDecl:
return true; return true;
@@ -3477,21 +3477,21 @@ AstNode *parse_import_decl(AstFile *f, ImportDeclKind kind) {
return s; return s;
} }
AstNode *parse_export_decl(AstFile *f) { // AstNode *parse_export_decl(AstFile *f) {
CommentGroup docs = f->lead_comment; // CommentGroup docs = f->lead_comment;
Token token = expect_token(f, Token_export); // Token token = expect_token(f, Token_export);
Token file_path = expect_token_after(f, Token_String, "export"); // Token file_path = expect_token_after(f, Token_String, "export");
AstNode *s = nullptr; // AstNode *s = nullptr;
if (f->curr_proc != nullptr) { // if (f->curr_proc != nullptr) {
syntax_error(token, "You cannot use 'export' within a procedure. This must be done at the file scope"); // 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); // s = ast_bad_decl(f, token, file_path);
} else { // } else {
s = ast_export_decl(f, token, file_path, docs, f->line_comment); // s = ast_export_decl(f, token, file_path, docs, f->line_comment);
array_add(&f->imports_and_exports, s); // array_add(&f->imports_and_exports, s);
} // }
expect_semicolon(f, s); // expect_semicolon(f, s);
return s; // return s;
} // }
AstNode *parse_foreign_decl(AstFile *f) { AstNode *parse_foreign_decl(AstFile *f) {
CommentGroup docs = f->lead_comment; CommentGroup docs = f->lead_comment;
@@ -3584,8 +3584,8 @@ AstNode *parse_stmt(AstFile *f) {
case Token_import: case Token_import:
return parse_import_decl(f, ImportDecl_Standard); return parse_import_decl(f, ImportDecl_Standard);
case Token_export: // case Token_export:
return parse_export_decl(f); // return parse_export_decl(f);
case Token_if: return parse_if_stmt(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; import_decl->ImportDecl.using_in_list = list;
} }
return import_decl; 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); AstNode *export_decl = parse_export_decl(f);
if (export_decl->kind == AstNode_ExportDecl) { if (export_decl->kind == AstNode_ExportDecl) {
export_decl->ExportDecl.using_in_list = list; export_decl->ExportDecl.using_in_list = list;
} }
return export_decl; return export_decl;
} } */
AstNode *expr = parse_expr(f, true); AstNode *expr = parse_expr(f, true);
expect_semicolon(f, expr); expect_semicolon(f, expr);
@@ -3883,9 +3883,9 @@ void destroy_ast_file(AstFile *f) {
bool init_parser(Parser *p) { bool init_parser(Parser *p) {
GB_ASSERT(p != nullptr); 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->imports, heap_allocator());
array_init(&p->files, heap_allocator());
gb_mutex_init(&p->file_add_mutex); gb_mutex_init(&p->file_add_mutex);
gb_mutex_init(&p->file_decl_mutex); gb_mutex_init(&p->file_decl_mutex);
return true; return true;
@@ -3894,22 +3894,27 @@ bool init_parser(Parser *p) {
void destroy_parser(Parser *p) { void destroy_parser(Parser *p) {
GB_ASSERT(p != nullptr); GB_ASSERT(p != nullptr);
// TODO(bill): Fix memory leak // TODO(bill): Fix memory leak
for_array(i, p->files) { for_array(i, p->packages) {
destroy_ast_file(p->files[i]); 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 #if 0
for_array(i, p->imports) { for_array(i, p->imports) {
// gb_free(heap_allocator(), p->imports[i].text); // gb_free(heap_allocator(), p->imports[i].text);
} }
#endif #endif
array_free(&p->files); array_free(&p->packages);
array_free(&p->imports); array_free(&p->imports);
map_destroy(&p->imported_files);
gb_mutex_destroy(&p->file_add_mutex); gb_mutex_destroy(&p->file_add_mutex);
gb_mutex_destroy(&p->file_decl_mutex); gb_mutex_destroy(&p->file_decl_mutex);
} }
// NOTE(bill): Returns true if it's added // 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) { if (build_context.generate_docs) {
return false; 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); path = string_trim_whitespace(path);
rel_path = string_trim_whitespace(rel_path); rel_path = string_trim_whitespace(rel_path);
for_array(i, p->imports) { HashKey key = hash_string(path);
String import = p->imports[i].path; if (map_get(&p->imported_files, key) != nullptr) {
if (import == path) { return false;
return false;
}
} }
map_set(&p->imported_files, key, true);
ImportedPackage item = {}; ImportedPackage item = {};
item.kind = ImportedPackage_Normal; item.kind = kind;
item.path = path; item.path = path;
item.rel_path = rel_path; item.rel_path = rel_path;
item.pos = pos; item.pos = pos;
item.index = p->imports.count; item.index = p->imports.count;
array_add(&p->imports, item); array_add(&p->imports, item);
return true; 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) { void parse_setup_file_decls(Parser *p, AstFile *f, String base_dir, Array<AstNode *> decls) {
for_array(i, decls) { for_array(i, decls) {
AstNode *node = decls[i]; AstNode *node = decls[i];
if (!is_ast_node_decl(node) && if (!is_ast_node_decl(node) &&
node->kind != AstNode_BadStmt && node->kind != AstNode_BadStmt &&
node->kind != AstNode_EmptyStmt && node->kind != AstNode_EmptyStmt) {
node->kind != AstNode_WhenStmt) {
// NOTE(bill): Sanity check // NOTE(bill): Sanity check
if (node->kind == AstNode_ExprStmt) { 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; id->fullpath = import_path;
try_add_import_path(p, import_path, original_string, ast_node_token(node).pos); 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); ast_node(ed, ExportDecl, node);
String original_string = ed->relpath.string; 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; ed->fullpath = export_path;
try_add_import_path(p, export_path, original_string, ast_node_token(node).pos); 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); ast_node(fl, ForeignImportDecl, node);
String file_str = fl->filepath.string; 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; 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; // file->id = imported_package.index;
HashKey key = hash_string(fi->fullpath); HashKey key = hash_string(fi->fullpath);
map_set(&package->files, key, file); map_set(&package->files, key, file);
array_add(&p->files, file);
if (package->name.len == 0) { if (package->name.len == 0) {
package->name = file->package_name; 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; String import_rel_path = imported_package.rel_path;
TokenPos pos = imported_package.pos; 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 = {}; Array<FileInfo> list = {};
ReadDirectoryError rd_err = read_directory(import_path, &list); ReadDirectoryError rd_err = read_directory(import_path, &list);
defer (array_free(&list)); defer (array_free(&list));
if (rd_err != ReadDirectory_EOF && rd_err != ReadDirectory_None && pos.line != 0) { if (list.count == 1) {
gb_printf_err("%.*s(%td:%td) ", LIT(pos.file), pos.line, pos.column); GB_ASSERT(import_path != list[0].fullpath);
} }
switch (rd_err) { if (rd_err != ReadDirectory_EOF && rd_err != ReadDirectory_None) {
case ReadDirectory_InvalidPath: if (pos.line != 0) {
gb_printf_err("Invalid path: %.*s\n", LIT(import_rel_path)); gb_printf_err("%.*s(%td:%td) ", LIT(pos.file), pos.line, pos.column);
}
gb_mutex_lock(&global_error_collector.mutex); gb_mutex_lock(&global_error_collector.mutex);
defer (gb_mutex_unlock(&global_error_collector.mutex));
global_error_collector.count++; global_error_collector.count++;
gb_mutex_unlock(&global_error_collector.mutex);
return ParseFile_InvalidFile;
case ReadDirectory_NotDir: switch (rd_err) {
gb_printf_err("Expected a directory for a package, got a file: %.*s\n", LIT(import_rel_path)); case ReadDirectory_InvalidPath:
gb_mutex_lock(&global_error_collector.mutex); gb_printf_err("Invalid path: %.*s\n", LIT(import_rel_path));
global_error_collector.count++; return ParseFile_InvalidFile;
gb_mutex_unlock(&global_error_collector.mutex);
return ParseFile_InvalidFile; case ReadDirectory_NotExists:
case ReadDirectory_Unknown: gb_printf_err("Path does not exist: %.*s\n", LIT(import_rel_path));
gb_printf_err("Unknown error whilst reading directory"); return ParseFile_NotFound;
gb_mutex_lock(&global_error_collector.mutex);
global_error_collector.count++; case ReadDirectory_NotDir:
gb_mutex_unlock(&global_error_collector.mutex); gb_printf_err("Expected a directory for a package, got a file: %.*s\n", LIT(import_rel_path));
return ParseFile_InvalidFile; return ParseFile_InvalidFile;
case ReadDirectory_EOF:
break; 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); AstPackage *package = gb_alloc_item(heap_allocator(), AstPackage);
@@ -4307,7 +4290,12 @@ ParseFileError parse_import(Parser *p, ImportedPackage imported_package) {
// TODO(bill): Fix concurrency // TODO(bill): Fix concurrency
for_array(i, list) { for_array(i, list) {
FileInfo *fi = &list[i]; 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); ParseFileError err = parse_imported_file(p, package, fi, pos);
if (err != ParseFile_None) { if (err != ParseFile_None) {
return err; 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; return ParseFile_None;
} }
@@ -4342,25 +4334,24 @@ ParseFileError parse_packages(Parser *p, String init_filename) {
TokenPos init_pos = {}; TokenPos init_pos = {};
ImportedPackage init_imported_package = {ImportedPackage_Init, init_fullpath, init_fullpath, 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) { if (!build_context.generate_docs) {
String s = get_fullpath_core(heap_allocator(), str_lit("runtime")); String s = get_fullpath_core(heap_allocator(), str_lit("runtime"));
ImportedPackage runtime_package = {ImportedPackage_Runtime, s, s, init_pos}; try_add_import_path(p, s, s, init_pos, ImportedPackage_Runtime);
array_add(&p->imports, runtime_package); shared_package_count++;
shared_file_count++;
} }
array_add(&p->imports, init_imported_package); array_add(&p->imports, init_imported_package);
p->init_fullpath = init_fullpath; p->init_fullpath = init_fullpath;
// IMPORTANT TODO(bill): Figure out why this doesn't work on *nix sometimes // 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); isize thread_count = gb_max(build_context.thread_count, 1);
if (thread_count > 1) { if (thread_count > 1) {
isize volatile curr_import_index = 0; isize volatile curr_import_index = 0;
// NOTE(bill): Make sure that these are in parsed in this order // 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]); ParseFileError err = parse_import(p, p->imports[i]);
if (err != ParseFile_None) { if (err != ParseFile_None) {
return err; return err;
+11 -7
View File
@@ -67,8 +67,8 @@ struct AstFile {
AstNode * curr_proc; AstNode * curr_proc;
isize scope_level; isize scope_level;
Scope * scope; // NOTE(bill): Created in checker // Scope * scope; // NOTE(bill): Created in checker
DeclInfo * decl_info; // NOTE(bill): Created in checker // DeclInfo * decl_info; // NOTE(bill): Created in checker
CommentGroup lead_comment; // Comment (block) before the decl CommentGroup lead_comment; // Comment (block) before the decl
@@ -84,17 +84,21 @@ struct AstFile {
struct AstPackage { struct AstPackage {
isize id;
ImportedPackageKind kind; ImportedPackageKind kind;
String name; String name;
String fullpath; String fullpath;
Map<AstFile *> files; // Key: String (names) Map<AstFile *> files; // Key: String (names)
Scope * scope; // NOTE(bill): Created in checker
DeclInfo *decl_info; // NOTE(bill): Created in checker
}; };
struct Parser { struct Parser {
String init_fullpath; String init_fullpath;
Map<AstPackage *> packages; // Key: String (fullpath) Map<bool> imported_files; // Key: String (fullpath)
Array<AstFile *> files; Array<AstPackage *> packages;
Array<ImportedPackage> imports; Array<ImportedPackage> imports;
isize total_token_count; isize total_token_count;
isize total_line_count; isize total_line_count;
@@ -351,7 +355,7 @@ AST_NODE_KIND(_DeclBegin, "", struct {}) \
bool been_handled; \ bool been_handled; \
}) \ }) \
AST_NODE_KIND(ImportDecl, "import declaration", struct { \ AST_NODE_KIND(ImportDecl, "import declaration", struct { \
AstFile *file; \ AstPackage *package; \
Token token; \ Token token; \
Token relpath; \ Token relpath; \
String fullpath; \ String fullpath; \
@@ -362,7 +366,7 @@ AST_NODE_KIND(_DeclBegin, "", struct {}) \
bool is_using; \ bool is_using; \
bool been_handled; \ bool been_handled; \
}) \ }) \
AST_NODE_KIND(ExportDecl, "export declaration", struct { \ /* AST_NODE_KIND(ExportDecl, "export declaration", struct { \
AstFile *file; \ AstFile *file; \
Token token; \ Token token; \
Token relpath; \ Token relpath; \
@@ -371,7 +375,7 @@ AST_NODE_KIND(_DeclBegin, "", struct {}) \
CommentGroup docs; \ CommentGroup docs; \
CommentGroup comment; \ CommentGroup comment; \
bool been_handled; \ bool been_handled; \
}) \ }) */ \
AST_NODE_KIND(ForeignImportDecl, "foreign import declaration", struct { \ AST_NODE_KIND(ForeignImportDecl, "foreign import declaration", struct { \
Token token; \ Token token; \
Token filepath; \ Token filepath; \
+7
View File
@@ -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) { gb_inline bool str_eq_ignore_case(String const &a, String const &b) {
+1 -4
View File
@@ -448,12 +448,9 @@ void advance_to_next_rune(Tokenizer *t) {
TokenizerInitError init_tokenizer(Tokenizer *t, String fullpath) { TokenizerInitError init_tokenizer(Tokenizer *t, String fullpath) {
TokenizerInitError err = TokenizerInit_None; 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)); 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 // TODO(bill): Memory map rather than copy contents
gbFileContents fc = gb_file_read_contents(heap_allocator(), true, c_str); gbFileContents fc = gb_file_read_contents(heap_allocator(), true, c_str);
gb_zero_item(t); gb_zero_item(t);