Parse directories to be packages

This commit is contained in:
gingerBill
2018-05-21 20:47:52 +01:00
parent 718b80ba39
commit 5b6770f3d2
39 changed files with 1447 additions and 1209 deletions
+1 -1
View File
@@ -42,7 +42,7 @@ del *.ilk > NUL 2> NUL
cl %compiler_settings% "src\main.cpp" ^ cl %compiler_settings% "src\main.cpp" ^
/link %linker_settings% -OUT:%exe_name% ^ /link %linker_settings% -OUT:%exe_name% ^
&& odin run examples/demo.odin && odin check examples/demo
del *.obj > NUL 2> NUL del *.obj > NUL 2> NUL
@@ -1,3 +1,5 @@
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?
+2
View File
@@ -1,3 +1,5 @@
package bits
U8_MIN :: u8(0); U8_MIN :: u8(0);
U16_MIN :: u16(0); U16_MIN :: u16(0);
U32_MIN :: u32(0); U32_MIN :: u32(0);
+2
View File
@@ -1,3 +1,5 @@
package c
CHAR_BIT :: 8; CHAR_BIT :: 8;
c_bool :: bool; c_bool :: bool;
@@ -1,5 +1,6 @@
// Multiple precision decimal numbers // Multiple precision decimal numbers
// NOTE: This is only for floating point printing and nothing else // NOTE: This is only for floating point printing and nothing else
package decimal
Decimal :: struct { Decimal :: struct {
digits: [384]byte, // big-endian digits digits: [384]byte, // big-endian digits
+8 -6
View File
@@ -1,9 +1,11 @@
import "core:os.odin" package fmt
import "core:mem.odin"
import "core:utf8.odin" import "core:os"
import "core:types.odin" import "core:mem"
import "core:strconv.odin" import "core:unicode/utf8"
import "core:raw.odin" import "core:types"
import "core:strconv"
import "core:raw"
_BUFFER_SIZE :: 1<<12; _BUFFER_SIZE :: 1<<12;
+3 -1
View File
@@ -1,4 +1,6 @@
import "core:mem.odin" package hash
import "core:mem"
adler32 :: proc(data: []byte) -> u32 { adler32 :: proc(data: []byte) -> u32 {
ADLER_CONST :: 65521; ADLER_CONST :: 65521;
+2
View File
@@ -1,3 +1,5 @@
package math
TAU :: 6.28318530717958647692528676655900576; TAU :: 6.28318530717958647692528676655900576;
PI :: 3.14159265358979323846264338327950288; PI :: 3.14159265358979323846264338327950288;
@@ -1,3 +1,5 @@
package rand
Rand :: struct { Rand :: struct {
state: u64, state: u64,
inc: u64, inc: u64,
+6 -5
View File
@@ -1,5 +1,6 @@
import "core:raw.odin" package mem
import "core:mem.odin"
import "core:raw"
foreign __llvm_core { foreign __llvm_core {
@(link_name = "llvm.bswap.i16") swap16 :: proc(b: u16) -> u16 ---; @(link_name = "llvm.bswap.i16") swap16 :: proc(b: u16) -> u16 ---;
@@ -85,11 +86,11 @@ AllocationHeader :: struct {size: int};
allocation_header_fill :: proc(header: ^AllocationHeader, data: rawptr, size: int) { allocation_header_fill :: proc(header: ^AllocationHeader, data: rawptr, size: int) {
header.size = size; header.size = size;
ptr := cast(^uint)(mem.ptr_offset(header, 1)); ptr := cast(^uint)(ptr_offset(header, 1));
n := mem.ptr_sub(cast(^uint)data, ptr); n := ptr_sub(cast(^uint)data, ptr);
for i in 0..n { for i in 0..n {
mem.ptr_offset(ptr, i)^ = ~uint(0); ptr_offset(ptr, i)^ = ~uint(0);
} }
} }
allocation_header :: proc(data: rawptr) -> ^AllocationHeader { allocation_header :: proc(data: rawptr) -> ^AllocationHeader {
+4 -3
View File
@@ -1,7 +1,8 @@
package opengl
when ODIN_OS == "windows" { when ODIN_OS == "windows" {
foreign import lib "system:opengl32.lib" foreign import lib "system:opengl32.lib"
import win32 "core:sys/windows.odin" import win32 "core:sys/win32"
import "core:sys/wgl.odin"
} else when ODIN_OS == "linux" { } else when ODIN_OS == "linux" {
foreign import lib "system:gl" foreign import lib "system:gl"
} }
@@ -48,7 +49,7 @@ get_gl_proc_address :: proc(name: string) -> rawptr {
} }
// NOTE(bill): null terminated // NOTE(bill): null terminated
assert((&name[0] + len(name))^ == 0); assert((&name[0] + len(name))^ == 0);
res := wgl.get_gl_proc_address(cstring(&name[0])); res := win32.get_gl_proc_address(cstring(&name[0]));
if res == nil { if res == nil {
res = win32.get_proc_address(_libgl, cstring(&name[0])); res = win32.get_proc_address(_libgl, cstring(&name[0]));
} }
@@ -1,3 +1,5 @@
package opengl
FALSE :: 0; FALSE :: 0;
TRUE :: 1; TRUE :: 1;
+2 -5
View File
@@ -1,9 +1,6 @@
when ODIN_OS == "windows" do export "core:os/windows.odin"; package os
when ODIN_OS == "osx" do export "core:os/osx.odin";
when ODIN_OS == "linux" do export "core:os/linux.odin";
when ODIN_OS == "essence" do export "core:os/essence.odin";
import "mem.odin"; import "core:mem"
write_string :: proc(fd: Handle, str: string) -> (int, Errno) { write_string :: proc(fd: Handle, str: string) -> (int, Errno) {
return write(fd, cast([]byte)str); return write(fd, cast([]byte)str);
@@ -1,3 +1,5 @@
package os
foreign import api "system:api" foreign import api "system:api"
Handle :: distinct int; Handle :: distinct int;
+4 -2
View File
@@ -1,8 +1,10 @@
package os
foreign import dl "system:dl" foreign import dl "system:dl"
foreign import libc "system:c" foreign import libc "system:c"
import "core:strings.odin" import "core:strings"
import "core:mem.odin" import "core:mem"
Handle :: distinct i32; Handle :: distinct i32;
File_Time :: distinct u64; File_Time :: distinct u64;
+4 -2
View File
@@ -1,8 +1,10 @@
package os
foreign import dl "system:dl" foreign import dl "system:dl"
foreign import libc "system:c" foreign import libc "system:c"
import "core:strings.odin" import "core:strings"
import "core:mem.odin" import "core:mem"
Handle :: distinct i32; Handle :: distinct i32;
File_Time :: distinct u64; File_Time :: distinct u64;
@@ -1,5 +1,7 @@
import win32 "core:sys/windows.odin" package os
import "core:mem.odin"
import "core:sys/win32"
import "core:mem"
Handle :: distinct uintptr; Handle :: distinct uintptr;
File_Time :: distinct u64; File_Time :: distinct u64;
+2
View File
@@ -1,3 +1,5 @@
package raw
Any :: struct { Any :: struct {
data: rawptr, data: rawptr,
typeid: typeid, typeid: typeid,
@@ -1,10 +1,10 @@
#shared_global_scope package runtime
import "core:os.odin" import "core:os"
// import "core:fmt.odin" // TODO(bill): Remove the need for `fmt` here // import "core:fmt" // TODO(bill): Remove the need for `fmt` here
import "core:utf8.odin" import "core:unicode/utf8"
import "core:raw.odin" import "core:raw"
import "core:mem.odin" import "core:mem"
// Naming Conventions: // Naming Conventions:
// In general, Ada_Case for types and snake_case for values // In general, Ada_Case for types and snake_case for values
@@ -1,4 +1,4 @@
#shared_global_scope package runtime
/* /*
@(link_name="__multi3") @(link_name="__multi3")
+2
View File
@@ -1,3 +1,5 @@
package sort
bubble_sort_proc :: proc(array: $A/[]$T, f: proc(T, T) -> int) { bubble_sort_proc :: proc(array: $A/[]$T, f: proc(T, T) -> int) {
assert(f != nil); assert(f != nil);
count := len(array); count := len(array);
@@ -1,4 +1,6 @@
using import "core:decimal.odin" package strconv
using import "core:decimal"
Int_Flag :: enum { Int_Flag :: enum {
Prefix = 1<<0, Prefix = 1<<0,
@@ -1,5 +1,7 @@
import "core:mem.odin" package strings
import "core:raw.odin"
import "core:mem"
import "core:raw"
new_string :: proc(s: string) -> string { new_string :: proc(s: string) -> string {
c := make([]byte, len(s)+1); c := make([]byte, len(s)+1);
@@ -1,6 +1,7 @@
package win32
when ODIN_OS == "windows" { when ODIN_OS == "windows" {
foreign import "system:opengl32.lib" foreign import "system:opengl32.lib"
using import "core:sys/windows.odin"
} }
@@ -1,3 +1,5 @@
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"
@@ -1,3 +1,5 @@
package thread
#assert(ODIN_OS == "windows"); #assert(ODIN_OS == "windows");
when ODIN_OS == "windows" { when ODIN_OS == "windows" {
@@ -1,3 +1,5 @@
package types
are_types_identical :: proc(a, b: ^Type_Info) -> bool { are_types_identical :: proc(a, b: ^Type_Info) -> bool {
if a == b do return true; if a == b do return true;
@@ -1,4 +1,6 @@
import "utf8.odin" package utf8
import "core:unicode/utf8"
REPLACEMENT_CHAR :: '\uFFFD'; REPLACEMENT_CHAR :: '\uFFFD';
MAX_RUNE :: '\U0010FFFF'; MAX_RUNE :: '\U0010FFFF';
@@ -1,3 +1,5 @@
package utf8
RUNE_ERROR :: '\ufffd'; RUNE_ERROR :: '\ufffd';
RUNE_SELF :: 0x80; RUNE_SELF :: 0x80;
RUNE_BOM :: 0xfeff; RUNE_BOM :: 0xfeff;
+100
View File
@@ -734,3 +734,103 @@ String path_to_full_path(gbAllocator a, String path) {
char *fullpath = gb_path_get_full_name(a, path_c); char *fullpath = gb_path_get_full_name(a, path_c);
return make_string_c(fullpath); return make_string_c(fullpath);
} }
struct FileInfo {
String name;
String fullpath;
i64 size;
bool is_dir;
};
enum ReadDirectoryError {
ReadDirectory_None,
ReadDirectory_InvalidPath,
ReadDirectory_NotDir,
ReadDirectory_EOF,
ReadDirectory_Unknown,
ReadDirectory_COUNT,
};
#if defined(GB_SYSTEM_WINDOWS)
ReadDirectoryError read_directory(String path, Array<FileInfo> *fi) {
GB_ASSERT(fi != nullptr);
while (path.len > 0) {
Rune end = path[path.len-1];
if (end == '/') {
path.len -= 1;
} else if (end == '\\') {
path.len -= 1;
} else {
break;
}
}
if (path.len == 0) {
return ReadDirectory_InvalidPath;
}
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));
gb_memmove(new_path, path.text, path.len);
gb_memmove(new_path+path.len, "/*", 2);
new_path[path.len+2] = 0;
String np = make_string(cast(u8 *)new_path, path.len+2);
String16 wstr = string_to_string16(a, np);
defer (gb_free(a, wstr.text));
WIN32_FIND_DATAW file_data = {};
HANDLE find_file = FindFirstFileW(wstr.text, &file_data);
if (find_file == INVALID_HANDLE_VALUE) {
return ReadDirectory_Unknown;
}
defer (FindClose(find_file));
array_init(fi, a, 0, 100);
do {
wchar_t *filename_w = file_data.cFileName;
i64 size = cast(i64)file_data.nFileSizeLow;
size |= (cast(i64)file_data.nFileSizeHigh) << 32;
String name = string16_to_string(a, make_string16_c(filename_w));
if (name == "." || name == "..") {
gb_free(a, name.text);
continue;
}
String filepath = {};
filepath.len = path.len+1+name.len;
filepath.text = gb_alloc_array(a, u8, filepath.len+1);
defer (gb_free(a, filepath.text));
gb_memmove(filepath.text, path.text, path.len);
gb_memmove(filepath.text+path.len, "/", 1);
gb_memmove(filepath.text+path.len+1, name.text, name.len);
FileInfo info = {};
info.name = name;
info.fullpath = path_to_full_path(a, filepath);
info.size = size;
info.is_dir = (file_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0;
array_add(fi, info);
} while (FindNextFileW(find_file, &file_data));
return ReadDirectory_None;
}
#else
#error Implement read_directory
#endif
+10 -10
View File
@@ -93,15 +93,15 @@ void print_declaration(AstNode *decl) {
} }
void generate_documentation(Parser *parser) { void generate_documentation(Parser *parser) {
for_array(file_index, parser->files) { // for_array(file_index, parser->files) {
AstFile *file = parser->files[file_index]; // AstFile *file = parser->files[file_index];
Tokenizer *tokenizer = &file->tokenizer; // Tokenizer *tokenizer = &file->tokenizer;
String fullpath = tokenizer->fullpath; // String fullpath = tokenizer->fullpath;
gb_printf("%.*s\n", LIT(fullpath)); // gb_printf("%.*s\n", LIT(fullpath));
for_array(decl_index, file->decls) { // for_array(decl_index, file->decls) {
AstNode *decl = file->decls[decl_index]; // AstNode *decl = file->decls[decl_index];
print_declaration(decl); // print_declaration(decl);
} // }
} // }
} }
+7 -3
View File
@@ -12,11 +12,13 @@
#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"
#include "ir.cpp" #include "ir.cpp"
#include "ir_opt.cpp" #include "ir_opt.cpp"
#include "ir_print.cpp" #include "ir_print.cpp"
#endif
// NOTE(bill): 'name' is used in debugging and profiling modes // NOTE(bill): 'name' is used in debugging and profiling modes
i32 system_exec_command_line_app(char *name, bool is_silent, char *fmt, ...) { i32 system_exec_command_line_app(char *name, bool is_silent, char *fmt, ...) {
@@ -772,8 +774,9 @@ 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"));
@@ -784,10 +787,11 @@ int main(int arg_count, char **arg_ptr) {
} }
defer (destroy_parser(&parser)); defer (destroy_parser(&parser));
if (parse_files(&parser, init_filename) != ParseFile_None) { if (parse_packages(&parser, init_filename) != ParseFile_None) {
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;
@@ -1054,6 +1058,6 @@ int main(int arg_count, char **arg_ptr) {
system_exec_command_line_app("odin run", false, "%.*s", LIT(output_base)); system_exec_command_line_app("odin run", false, "%.*s", LIT(output_base));
} }
#endif #endif
#endif
return 0; return 0;
} }
+116 -42
View File
@@ -3712,17 +3712,18 @@ AstNode *parse_stmt(AstFile *f) {
Token name = expect_token(f, Token_Ident); Token name = expect_token(f, Token_Ident);
String tag = name.string; String tag = name.string;
if (tag == "shared_global_scope") { // if (tag == "shared_global_scope") {
if (f->curr_proc == nullptr) { // if (f->curr_proc == nullptr) {
f->is_global_scope = true; // f->is_global_scope = true;
s = ast_empty_stmt(f, f->curr_token); // s = ast_empty_stmt(f, f->curr_token);
} else { // } else {
syntax_error(token, "You cannot use #shared_global_scope within a procedure. This must be done at the file scope"); // syntax_error(token, "You cannot use #shared_global_scope within a procedure. This must be done at the file scope");
s = ast_bad_decl(f, token, f->curr_token); // s = ast_bad_decl(f, token, f->curr_token);
} // }
expect_semicolon(f, s); // expect_semicolon(f, s);
return s; // return s;
} else if (tag == "bounds_check") { // } else
if (tag == "bounds_check") {
s = parse_stmt(f); s = parse_stmt(f);
s->stmt_state_flags |= StmtStateFlag_bounds_check; s->stmt_state_flags |= StmtStateFlag_bounds_check;
if ((s->stmt_state_flags & StmtStateFlag_no_bounds_check) != 0) { if ((s->stmt_state_flags & StmtStateFlag_no_bounds_check) != 0) {
@@ -3830,6 +3831,7 @@ ParseFileError init_ast_file(AstFile *f, String fullpath, TokenPos *err_pos) {
isize init_token_cap = cast(isize)gb_max(next_pow2(cast(i64)(file_size/2ll)), 16); isize init_token_cap = cast(isize)gb_max(next_pow2(cast(i64)(file_size/2ll)), 16);
array_init(&f->tokens, heap_allocator(), 0, gb_max(init_token_cap, 16)); array_init(&f->tokens, heap_allocator(), 0, gb_max(init_token_cap, 16));
if (err == TokenizerInit_Empty) { if (err == TokenizerInit_Empty) {
Token token = {Token_EOF}; Token token = {Token_EOF};
token.pos.file = fullpath; token.pos.file = fullpath;
@@ -3881,8 +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);
array_init(&p->files, heap_allocator()); map_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;
@@ -3921,8 +3924,8 @@ bool try_add_import_path(Parser *p, String path, String rel_path, TokenPos pos)
} }
} }
ImportedFile item = {}; ImportedPackage item = {};
item.kind = ImportedFile_Normal; item.kind = ImportedPackage_Normal;
item.path = path; item.path = path;
item.rel_path = rel_path; item.rel_path = rel_path;
item.pos = pos; item.pos = pos;
@@ -4164,28 +4167,33 @@ void parse_file(Parser *p, AstFile *f) {
comsume_comment_groups(f, f->prev_token); comsume_comment_groups(f, f->prev_token);
f->package_token = expect_token(f, Token_package);
Token package_name = expect_token_after(f, Token_Ident, "package");
if (package_name.kind == Token_Ident) {
if (package_name.string == "_") {
error(package_name, "Invalid package name '_'");
} else if (f->package->kind != ImportedPackage_Runtime && package_name.string == "runtime") {
error(package_name, "Use of reserved package name '%.*s'", LIT(package_name.string));
}
}
f->package_name = package_name.string;
f->decls = parse_stmt_list(f); f->decls = parse_stmt_list(f);
parse_setup_file_decls(p, f, base_dir, f->decls); parse_setup_file_decls(p, f, base_dir, f->decls);
} }
ParseFileError parse_imported_file(Parser *p, AstPackage *package, FileInfo *fi, TokenPos pos) {
ParseFileError parse_import(Parser *p, ImportedFile imported_file) {
String import_path = imported_file.path;
String import_rel_path = imported_file.rel_path;
TokenPos pos = imported_file.pos;
AstFile *file = gb_alloc_item(heap_allocator(), AstFile); AstFile *file = gb_alloc_item(heap_allocator(), AstFile);
file->file_kind = imported_file.kind; file->package = package;
if (file->file_kind == ImportedFile_Shared) {
file->is_global_scope = true;
}
TokenPos err_pos = {0}; TokenPos err_pos = {0};
ParseFileError err = init_ast_file(file, import_path, &err_pos); ParseFileError err = init_ast_file(file, fi->fullpath, &err_pos);
if (err != ParseFile_None) { if (err != ParseFile_None) {
if (err == ParseFile_EmptyFile) { if (err == ParseFile_EmptyFile) {
if (import_path == p->init_fullpath) { if (fi->fullpath == p->init_fullpath) {
gb_printf_err("Initial file is empty - %.*s\n", LIT(p->init_fullpath)); gb_printf_err("Initial file is empty - %.*s\n", LIT(p->init_fullpath));
gb_exit(1); gb_exit(1);
} }
@@ -4195,7 +4203,7 @@ ParseFileError parse_import(Parser *p, ImportedFile imported_file) {
if (pos.line != 0) { if (pos.line != 0) {
gb_printf_err("%.*s(%td:%td) ", LIT(pos.file), pos.line, pos.column); gb_printf_err("%.*s(%td:%td) ", LIT(pos.file), pos.line, pos.column);
} }
gb_printf_err("Failed to parse file: %.*s\n\t", LIT(import_rel_path)); gb_printf_err("Failed to parse file: %.*s\n\t", LIT(fi->name));
switch (err) { switch (err) {
case ParseFile_WrongExtension: case ParseFile_WrongExtension:
gb_printf_err("Invalid file extension: File must have the extension '.odin'"); gb_printf_err("Invalid file extension: File must have the extension '.odin'");
@@ -4207,7 +4215,7 @@ ParseFileError parse_import(Parser *p, ImportedFile imported_file) {
gb_printf_err("File permissions problem"); gb_printf_err("File permissions problem");
break; break;
case ParseFile_NotFound: case ParseFile_NotFound:
gb_printf_err("File cannot be found ('%.*s')", LIT(import_path)); gb_printf_err("File cannot be found ('%.*s')", LIT(fi->fullpath));
break; break;
case ParseFile_InvalidToken: case ParseFile_InvalidToken:
gb_printf_err("Invalid token found in file at (%td:%td)", err_pos.line, err_pos.column); gb_printf_err("Invalid token found in file at (%td:%td)", err_pos.line, err_pos.column);
@@ -4230,8 +4238,17 @@ skip:
parse_file(p, file); parse_file(p, file);
gb_mutex_lock(&p->file_add_mutex); gb_mutex_lock(&p->file_add_mutex);
file->id = imported_file.index; // file->id = imported_package.index;
HashKey key = hash_string(fi->fullpath);
map_set(&package->files, key, file);
array_add(&p->files, file); array_add(&p->files, file);
if (package->name.len == 0) {
package->name = file->package_name;
} else if (file->tokens.count > 0 && package->name != file->package_name) {
error(file->package_token, "Different package name, expected '%.*s', got '%.*s'", LIT(package->name), LIT(file->package_name));
}
p->total_line_count += file->tokenizer.line_count; p->total_line_count += file->tokenizer.line_count;
p->total_token_count += file->tokens.count; p->total_token_count += file->tokens.count;
gb_mutex_unlock(&p->file_add_mutex); gb_mutex_unlock(&p->file_add_mutex);
@@ -4239,12 +4256,74 @@ skip:
return ParseFile_None; return ParseFile_None;
} }
ParseFileError parse_import(Parser *p, ImportedPackage imported_package) {
String import_path = imported_package.path;
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);
}
switch (rd_err) {
case ReadDirectory_InvalidPath:
gb_printf_err("Invalid path: %.*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_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;
}
AstPackage *package = gb_alloc_item(heap_allocator(), AstPackage);
package->kind = imported_package.kind;
package->fullpath = import_path;
map_init(&package->files, heap_allocator());
// TODO(bill): Fix concurrency
for_array(i, list) {
FileInfo *fi = &list[i];
if (string_ends_with(fi->name, str_lit(".odin"))) {
ParseFileError err = parse_imported_file(p, package, fi, pos);
if (err != ParseFile_None) {
return err;
}
}
}
return ParseFile_None;
}
GB_THREAD_PROC(parse_worker_file_proc) { GB_THREAD_PROC(parse_worker_file_proc) {
if (thread == nullptr) return 0; if (thread == nullptr) return 0;
auto *p = cast(Parser *)thread->user_data; auto *p = cast(Parser *)thread->user_data;
isize index = thread->user_index; isize index = thread->user_index;
ImportedFile imported_file = p->imports[index]; ImportedPackage imported_package = p->imports[index];
ParseFileError err = parse_import(p, imported_file); ParseFileError err = parse_import(p, imported_package);
return cast(isize)err; return cast(isize)err;
} }
@@ -4254,29 +4333,24 @@ struct ParserThreadWork {
isize import_index; isize import_index;
}; };
ParseFileError parse_files(Parser *p, String init_filename) { ParseFileError parse_packages(Parser *p, String init_filename) {
GB_ASSERT(init_filename.text[init_filename.len] == 0); GB_ASSERT(init_filename.text[init_filename.len] == 0);
char *fullpath_str = gb_path_get_full_name(heap_allocator(), cast(char *)&init_filename[0]); char *fullpath_str = gb_path_get_full_name(heap_allocator(), cast(char *)&init_filename[0]);
String init_fullpath = string_trim_whitespace(make_string_c(fullpath_str)); String init_fullpath = string_trim_whitespace(make_string_c(fullpath_str));
TokenPos init_pos = {}; TokenPos init_pos = {};
ImportedFile init_imported_file = {ImportedFile_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_file_count = 0;
if (!build_context.generate_docs) { if (!build_context.generate_docs) {
String s = get_fullpath_core(heap_allocator(), str_lit("_preload.odin")); String s = get_fullpath_core(heap_allocator(), str_lit("runtime"));
ImportedFile runtime_file = {ImportedFile_Shared, s, s, init_pos}; ImportedPackage runtime_package = {ImportedPackage_Runtime, s, s, init_pos};
array_add(&p->imports, runtime_file); array_add(&p->imports, runtime_package);
shared_file_count++;
}
if (!build_context.generate_docs) {
String s = get_fullpath_core(heap_allocator(), str_lit("_soft_numbers.odin"));
ImportedFile runtime_file = {ImportedFile_Shared, s, s, init_pos};
array_add(&p->imports, runtime_file);
shared_file_count++; shared_file_count++;
} }
array_add(&p->imports, init_imported_file); 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
+23 -11
View File
@@ -3,6 +3,8 @@ struct Scope;
struct Type; struct Type;
struct Entity; struct Entity;
struct DeclInfo; struct DeclInfo;
struct AstFile;
struct AstPackage;
enum ParseFileError { enum ParseFileError {
@@ -23,23 +25,23 @@ struct CommentGroup {
}; };
enum ImportedFileKind { enum ImportedPackageKind {
ImportedFile_Normal, ImportedPackage_Normal,
ImportedFile_Shared, ImportedPackage_Runtime,
ImportedFile_Init, ImportedPackage_Init,
}; };
struct ImportedFile { struct ImportedPackage {
ImportedFileKind kind; ImportedPackageKind kind;
String path; String path;
String rel_path; String rel_path;
TokenPos pos; // import TokenPos pos; // import
isize index; isize index;
}; };
struct AstFile { struct AstFile {
isize id; AstPackage * package;
// isize id;
String fullpath; String fullpath;
gbArena arena; gbArena arena;
Tokenizer tokenizer; Tokenizer tokenizer;
@@ -47,6 +49,8 @@ struct AstFile {
isize curr_token_index; isize curr_token_index;
Token curr_token; Token curr_token;
Token prev_token; // previous non-comment Token prev_token; // previous non-comment
Token package_token;
String package_name;
// >= 0: In Expression // >= 0: In Expression
// < 0: In Control Clause // < 0: In Control Clause
@@ -58,8 +62,6 @@ struct AstFile {
isize when_level; isize when_level;
Array<AstNode *> decls; Array<AstNode *> decls;
ImportedFileKind file_kind;
bool is_global_scope;
Array<AstNode *> imports_and_exports; // 'import' 'using import' 'export' Array<AstNode *> imports_and_exports; // 'import' 'using import' 'export'
@@ -81,10 +83,19 @@ struct AstFile {
}; };
struct AstPackage {
ImportedPackageKind kind;
String name;
String fullpath;
Map<AstFile *> files; // Key: String (names)
};
struct Parser { struct Parser {
String init_fullpath; String init_fullpath;
Map<AstPackage *> packages; // Key: String (fullpath)
Array<AstFile *> files; Array<AstFile *> files;
Array<ImportedFile> imports; Array<ImportedPackage> imports;
isize total_token_count; isize total_token_count;
isize total_line_count; isize total_line_count;
gbMutex file_add_mutex; gbMutex file_add_mutex;
@@ -526,3 +537,4 @@ gb_inline bool is_ast_node_when_stmt(AstNode *node) {
return node->kind == AstNode_WhenStmt; return node->kind == AstNode_WhenStmt;
} }
+4
View File
@@ -82,6 +82,10 @@ gb_inline String make_string_c(char *text) {
return make_string(cast(u8 *)cast(void *)text, gb_strlen(text)); return make_string(cast(u8 *)cast(void *)text, gb_strlen(text));
} }
gb_inline String16 make_string16_c(wchar_t *text) {
return make_string16(text, string16_len(text));
}
String substring(String const &s, isize lo, isize hi) { String substring(String const &s, isize lo, isize hi) {
isize max = s.len; isize max = s.len;
GB_ASSERT_MSG(lo <= hi && hi <= max, "%td..%td..%td", lo, hi, max); GB_ASSERT_MSG(lo <= hi && hi <= max, "%td..%td..%td", lo, hi, max);
+1
View File
@@ -85,6 +85,7 @@ TOKEN_KIND(Token__KeywordBegin, ""), \
TOKEN_KIND(Token_import, "import"), \ TOKEN_KIND(Token_import, "import"), \
TOKEN_KIND(Token_export, "export"), \ TOKEN_KIND(Token_export, "export"), \
TOKEN_KIND(Token_foreign, "foreign"), \ TOKEN_KIND(Token_foreign, "foreign"), \
TOKEN_KIND(Token_package, "package"), \
TOKEN_KIND(Token_type, "type"), \ TOKEN_KIND(Token_type, "type"), \
TOKEN_KIND(Token_when, "when"), \ TOKEN_KIND(Token_when, "when"), \
TOKEN_KIND(Token_if, "if"), \ TOKEN_KIND(Token_if, "if"), \