mirror of
https://github.com/odin-lang/Odin.git
synced 2026-04-19 13:00:28 +00:00
Parallelization of the Parser
~66% reduction (unoptimized build) ~30% reduction (optimized build)
This commit is contained in:
@@ -338,7 +338,7 @@ union_type :: proc() {
|
||||
|
||||
parametric_polymorphism :: proc() {
|
||||
print_value :: proc(value: $T) {
|
||||
fmt.printf("print_value: %v %v\n", value, value);
|
||||
fmt.printf("print_value: %T %v\n", value, value);
|
||||
}
|
||||
|
||||
v1: int = 1;
|
||||
@@ -496,10 +496,12 @@ parametric_polymorphism :: proc() {
|
||||
return -1;
|
||||
}
|
||||
|
||||
get_hash :: proc(s: string) -> u32 { // djb2
|
||||
hash: u32 = 0x1505;
|
||||
for i in 0..len(s) do hash = (hash<<5) + hash + u32(s[i]);
|
||||
return hash;
|
||||
get_hash :: proc(s: string) -> u32 { // fnv32a
|
||||
h: u32 = 0x811c9dc5;
|
||||
for i in 0..len(s) {
|
||||
h = (h ~ u32(s[i])) * 0x01000193;
|
||||
}
|
||||
return h;
|
||||
}
|
||||
|
||||
|
||||
@@ -586,6 +588,7 @@ threading_example :: proc() {
|
||||
|
||||
|
||||
main :: proc() {
|
||||
when false {
|
||||
if true {
|
||||
fmt.println("\ngeneral_stuff:"); general_stuff();
|
||||
fmt.println("\nnested_struct_declarations:"); nested_struct_declarations();
|
||||
@@ -595,4 +598,5 @@ main :: proc() {
|
||||
}
|
||||
fmt.println("\nthreading_example:"); threading_example();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -19,6 +19,9 @@ struct BuildContext {
|
||||
bool generate_docs;
|
||||
i32 optimization_level;
|
||||
bool show_timings;
|
||||
|
||||
gbAffinity affinity;
|
||||
isize thread_count;
|
||||
};
|
||||
|
||||
|
||||
@@ -205,18 +208,22 @@ String odin_root_dir(void) {
|
||||
|
||||
#if defined(GB_SYSTEM_WINDOWS)
|
||||
String path_to_fullpath(gbAllocator a, String s) {
|
||||
gbTempArenaMemory tmp = gb_temp_arena_memory_begin(&string_buffer_arena);
|
||||
String16 string16 = string_to_string16(string_buffer_allocator, s);
|
||||
String result = {0};
|
||||
String result = {};
|
||||
gb_mutex_lock(&string_buffer_mutex);
|
||||
{
|
||||
gbTempArenaMemory tmp = gb_temp_arena_memory_begin(&string_buffer_arena);
|
||||
String16 string16 = string_to_string16(string_buffer_allocator, s);
|
||||
|
||||
DWORD len = GetFullPathNameW(&string16[0], 0, nullptr, nullptr);
|
||||
if (len != 0) {
|
||||
wchar_t *text = gb_alloc_array(string_buffer_allocator, wchar_t, len+1);
|
||||
GetFullPathNameW(&string16[0], len, text, nullptr);
|
||||
text[len] = 0;
|
||||
result = string16_to_string(a, make_string16(text, len));
|
||||
DWORD len = GetFullPathNameW(&string16[0], 0, nullptr, nullptr);
|
||||
if (len != 0) {
|
||||
wchar_t *text = gb_alloc_array(string_buffer_allocator, wchar_t, len+1);
|
||||
GetFullPathNameW(&string16[0], len, text, nullptr);
|
||||
text[len] = 0;
|
||||
result = string16_to_string(a, make_string16(text, len));
|
||||
}
|
||||
gb_temp_arena_memory_end(tmp);
|
||||
}
|
||||
gb_temp_arena_memory_end(tmp);
|
||||
gb_mutex_unlock(&string_buffer_mutex);
|
||||
return result;
|
||||
}
|
||||
#elif defined(GB_SYSTEM_OSX) || defined(GB_SYSTEM_UNIX)
|
||||
@@ -271,6 +278,12 @@ String const ODIN_VERSION = str_lit("0.6.0");
|
||||
|
||||
void init_build_context(void) {
|
||||
BuildContext *bc = &build_context;
|
||||
|
||||
gb_affinity_init(&bc->affinity);
|
||||
if (bc->thread_count == 0) {
|
||||
bc->thread_count = gb_max(bc->affinity.thread_count, 1);
|
||||
}
|
||||
|
||||
bc->ODIN_VENDOR = str_lit("odin");
|
||||
bc->ODIN_VERSION = ODIN_VERSION;
|
||||
bc->ODIN_ROOT = odin_root_dir();
|
||||
|
||||
@@ -2279,6 +2279,8 @@ void check_parsed_files(Checker *c) {
|
||||
scope->file = f;
|
||||
if (f->tokenizer.fullpath == c->parser->init_fullpath) {
|
||||
scope->is_init = true;
|
||||
} else if (f->file_kind == ImportedFile_Init) {
|
||||
scope->is_init = true;
|
||||
}
|
||||
|
||||
if (scope->is_global) {
|
||||
|
||||
34
src/gb/gb.h
34
src/gb/gb.h
@@ -957,7 +957,7 @@ gb_mutex_init(&m);
|
||||
|
||||
|
||||
|
||||
#define GB_THREAD_PROC(name) void name(void *data)
|
||||
#define GB_THREAD_PROC(name) isize name(struct gbThread *thread)
|
||||
typedef GB_THREAD_PROC(gbThreadProc);
|
||||
|
||||
typedef struct gbThread {
|
||||
@@ -968,7 +968,9 @@ typedef struct gbThread {
|
||||
#endif
|
||||
|
||||
gbThreadProc *proc;
|
||||
void * data;
|
||||
void * user_data;
|
||||
isize user_index;
|
||||
isize return_value;
|
||||
|
||||
gbSemaphore semaphore;
|
||||
isize stack_size;
|
||||
@@ -4672,22 +4674,32 @@ void gb_thread_destory(gbThread *t) {
|
||||
|
||||
gb_inline void gb__thread_run(gbThread *t) {
|
||||
gb_semaphore_release(&t->semaphore);
|
||||
t->proc(t->data);
|
||||
t->return_value = t->proc(t);
|
||||
}
|
||||
|
||||
#if defined(GB_SYSTEM_WINDOWS)
|
||||
gb_inline DWORD __stdcall gb__thread_proc(void *arg) { gb__thread_run(cast(gbThread *)arg); return 0; }
|
||||
gb_inline DWORD __stdcall gb__thread_proc(void *arg) {
|
||||
gbThread *t = cast(gbThread *)arg;
|
||||
gb__thread_run(t);
|
||||
t->is_running = false;
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
gb_inline void * gb__thread_proc(void *arg) { gb__thread_run(cast(gbThread *)arg); return NULL; }
|
||||
gb_inline void * gb__thread_proc(void *arg) {
|
||||
gbThread *t = cast(gbThread *)arg;
|
||||
gb__thread_run(t);
|
||||
t->is_running = false;
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
gb_inline void gb_thread_start(gbThread *t, gbThreadProc *proc, void *data) { gb_thread_start_with_stack(t, proc, data, 0); }
|
||||
gb_inline void gb_thread_start(gbThread *t, gbThreadProc *proc, void *user_data) { gb_thread_start_with_stack(t, proc, user_data, 0); }
|
||||
|
||||
gb_inline void gb_thread_start_with_stack(gbThread *t, gbThreadProc *proc, void *data, isize stack_size) {
|
||||
gb_inline void gb_thread_start_with_stack(gbThread *t, gbThreadProc *proc, void *user_data, isize stack_size) {
|
||||
GB_ASSERT(!t->is_running);
|
||||
GB_ASSERT(proc != NULL);
|
||||
t->proc = proc;
|
||||
t->data = data;
|
||||
t->user_data = user_data;
|
||||
t->stack_size = stack_size;
|
||||
|
||||
#if defined(GB_SYSTEM_WINDOWS)
|
||||
@@ -4698,8 +4710,9 @@ gb_inline void gb_thread_start_with_stack(gbThread *t, gbThreadProc *proc, void
|
||||
pthread_attr_t attr;
|
||||
pthread_attr_init(&attr);
|
||||
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
|
||||
if (stack_size != 0)
|
||||
if (stack_size != 0) {
|
||||
pthread_attr_setstacksize(&attr, stack_size);
|
||||
}
|
||||
pthread_create(&t->posix_handle, &attr, gb__thread_proc, t);
|
||||
pthread_attr_destroy(&attr);
|
||||
}
|
||||
@@ -5401,7 +5414,8 @@ gb_inline gbTempArenaMemory gb_temp_arena_memory_begin(gbArena *arena) {
|
||||
}
|
||||
|
||||
gb_inline void gb_temp_arena_memory_end(gbTempArenaMemory tmp) {
|
||||
GB_ASSERT(tmp.arena->total_allocated >= tmp.original_count);
|
||||
GB_ASSERT_MSG(tmp.arena->total_allocated >= tmp.original_count,
|
||||
"%td >= %td", tmp.arena->total_allocated, tmp.original_count);
|
||||
GB_ASSERT(tmp.arena->temp_count > 0);
|
||||
tmp.arena->total_allocated = tmp.original_count;
|
||||
tmp.arena->temp_count--;
|
||||
|
||||
64
src/main.cpp
64
src/main.cpp
@@ -172,6 +172,7 @@ enum BuildFlagKind {
|
||||
|
||||
BuildFlag_OptimizationLevel,
|
||||
BuildFlag_ShowTimings,
|
||||
BuildFlag_ThreadCount,
|
||||
|
||||
BuildFlag_COUNT,
|
||||
};
|
||||
@@ -202,9 +203,9 @@ void add_flag(Array<BuildFlag> *build_flags, BuildFlagKind kind, String name, Bu
|
||||
bool parse_build_flags(Array<String> args) {
|
||||
Array<BuildFlag> build_flags = {};
|
||||
array_init(&build_flags, heap_allocator(), BuildFlag_COUNT);
|
||||
add_flag(&build_flags, BuildFlag_OptimizationLevel, str_lit("opt"), BuildFlagParam_Integer);
|
||||
add_flag(&build_flags, BuildFlag_ShowTimings, str_lit("show-timings"), BuildFlagParam_None);
|
||||
|
||||
add_flag(&build_flags, BuildFlag_OptimizationLevel, str_lit("opt"), BuildFlagParam_Integer);
|
||||
add_flag(&build_flags, BuildFlag_ShowTimings, str_lit("show-timings"), BuildFlagParam_None);
|
||||
add_flag(&build_flags, BuildFlag_ThreadCount, str_lit("thread-count"), BuildFlagParam_Integer);
|
||||
|
||||
|
||||
Array<String> flag_args = args;
|
||||
@@ -291,27 +292,64 @@ bool parse_build_flags(Array<String> args) {
|
||||
}
|
||||
}
|
||||
if (ok) {
|
||||
switch (bf.kind) {
|
||||
case BuildFlag_OptimizationLevel:
|
||||
if (value.kind == ExactValue_Integer) {
|
||||
build_context.optimization_level = cast(i32)i128_to_i64(value.value_integer);
|
||||
} else {
|
||||
switch (bf.param_kind) {
|
||||
case BuildFlagParam_None:
|
||||
if (value.kind != ExactValue_Invalid) {
|
||||
gb_printf_err("%.*s expected no value, got %.*s", LIT(name), LIT(param));
|
||||
bad_flags = true;
|
||||
ok = false;
|
||||
}
|
||||
break;
|
||||
case BuildFlagParam_Boolean:
|
||||
if (value.kind != ExactValue_Bool) {
|
||||
gb_printf_err("%.*s expected a boolean, got %.*s", LIT(name), LIT(param));
|
||||
bad_flags = true;
|
||||
ok = false;
|
||||
}
|
||||
break;
|
||||
case BuildFlagParam_Integer:
|
||||
if (value.kind != ExactValue_Integer) {
|
||||
gb_printf_err("%.*s expected an integer, got %.*s", LIT(name), LIT(param));
|
||||
bad_flags = true;
|
||||
ok = false;
|
||||
}
|
||||
break;
|
||||
case BuildFlag_ShowTimings:
|
||||
if (value.kind == ExactValue_Invalid) {
|
||||
build_context.show_timings = true;
|
||||
} else {
|
||||
gb_printf_err("%.*s expected no value, got %.*s", LIT(name), LIT(param));
|
||||
case BuildFlagParam_Float:
|
||||
if (value.kind != ExactValue_Float) {
|
||||
gb_printf_err("%.*s expected a floating pointer number, got %.*s", LIT(name), LIT(param));
|
||||
bad_flags = true;
|
||||
ok = false;
|
||||
}
|
||||
break;
|
||||
case BuildFlagParam_String:
|
||||
if (value.kind != ExactValue_String) {
|
||||
gb_printf_err("%.*s expected a string, got %.*s", LIT(name), LIT(param));
|
||||
bad_flags = true;
|
||||
ok = false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (ok) switch (bf.kind) {
|
||||
case BuildFlag_OptimizationLevel:
|
||||
GB_ASSERT(value.kind == ExactValue_Integer);
|
||||
build_context.optimization_level = cast(i32)i128_to_i64(value.value_integer);
|
||||
break;
|
||||
case BuildFlag_ShowTimings:
|
||||
GB_ASSERT(value.kind == ExactValue_Invalid);
|
||||
build_context.show_timings = true;
|
||||
break;
|
||||
case BuildFlag_ThreadCount: {
|
||||
GB_ASSERT(value.kind == ExactValue_Integer);
|
||||
isize count = cast(isize)i128_to_i64(value.value_integer);
|
||||
if (count <= 0) {
|
||||
gb_printf_err("%.*s expected a positive non-zero number, got %.*s", LIT(name), LIT(param));
|
||||
build_context.thread_count = 0;
|
||||
} else {
|
||||
build_context.thread_count = count;
|
||||
}
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
242
src/parser.cpp
242
src/parser.cpp
@@ -20,6 +20,21 @@ struct CommentGroup {
|
||||
};
|
||||
|
||||
|
||||
enum ImportedFileKind {
|
||||
ImportedFile_Normal,
|
||||
ImportedFile_Shared,
|
||||
ImportedFile_Init,
|
||||
};
|
||||
|
||||
struct ImportedFile {
|
||||
ImportedFileKind kind;
|
||||
String path;
|
||||
String rel_path;
|
||||
TokenPos pos; // import
|
||||
isize index;
|
||||
};
|
||||
|
||||
|
||||
struct AstFile {
|
||||
i32 id;
|
||||
gbArena arena;
|
||||
@@ -38,6 +53,7 @@ struct AstFile {
|
||||
bool allow_type;
|
||||
|
||||
Array<AstNode *> decls;
|
||||
ImportedFileKind file_kind;
|
||||
bool is_global_scope;
|
||||
|
||||
AstNode * curr_proc;
|
||||
@@ -58,16 +74,12 @@ struct AstFile {
|
||||
TokenPos fix_prev_pos;
|
||||
};
|
||||
|
||||
struct ImportedFile {
|
||||
String path;
|
||||
String rel_path;
|
||||
TokenPos pos; // import
|
||||
};
|
||||
|
||||
struct Parser {
|
||||
String init_fullpath;
|
||||
Array<AstFile> files;
|
||||
Array<ImportedFile> imports;
|
||||
isize curr_import_index;
|
||||
gbAtomic32 import_index;
|
||||
isize total_token_count;
|
||||
isize total_line_count;
|
||||
@@ -4748,18 +4760,19 @@ ParseFileError init_ast_file(AstFile *f, String fullpath) {
|
||||
}
|
||||
TokenizerInitError err = init_tokenizer(&f->tokenizer, fullpath);
|
||||
if (err == TokenizerInit_None) {
|
||||
array_init(&f->tokens, heap_allocator());
|
||||
{
|
||||
for (;;) {
|
||||
Token token = tokenizer_get_token(&f->tokenizer);
|
||||
if (token.kind == Token_Invalid) {
|
||||
return ParseFile_InvalidToken;
|
||||
}
|
||||
array_add(&f->tokens, token);
|
||||
isize file_size = f->tokenizer.end - f->tokenizer.start;
|
||||
isize init_token_cap = gb_max(next_pow2(file_size/2), 16);
|
||||
array_init(&f->tokens, heap_allocator(), gb_max(init_token_cap, 16));
|
||||
|
||||
if (token.kind == Token_EOF) {
|
||||
break;
|
||||
}
|
||||
for (;;) {
|
||||
Token token = tokenizer_get_token(&f->tokenizer);
|
||||
if (token.kind == Token_Invalid) {
|
||||
return ParseFile_InvalidToken;
|
||||
}
|
||||
array_add(&f->tokens, token);
|
||||
|
||||
if (token.kind == Token_EOF) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4821,7 +4834,6 @@ void destroy_parser(Parser *p) {
|
||||
|
||||
// NOTE(bill): Returns true if it's added
|
||||
bool try_add_import_path(Parser *p, String path, String rel_path, TokenPos pos) {
|
||||
|
||||
gb_mutex_lock(&p->mutex);
|
||||
defer (gb_mutex_unlock(&p->mutex));
|
||||
|
||||
@@ -4839,10 +4851,12 @@ bool try_add_import_path(Parser *p, String path, String rel_path, TokenPos pos)
|
||||
}
|
||||
}
|
||||
|
||||
ImportedFile item;
|
||||
item.path = path;
|
||||
ImportedFile item = {};
|
||||
item.kind = ImportedFile_Normal;
|
||||
item.path = path;
|
||||
item.rel_path = rel_path;
|
||||
item.pos = pos;
|
||||
item.pos = pos;
|
||||
item.index = p->imports.count;
|
||||
array_add(&p->imports, item);
|
||||
|
||||
|
||||
@@ -4979,80 +4993,168 @@ void parse_file(Parser *p, AstFile *f) {
|
||||
|
||||
|
||||
|
||||
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 = {};
|
||||
file.file_kind = imported_file.kind;
|
||||
if (file.file_kind == ImportedFile_Shared) {
|
||||
file.is_global_scope = true;
|
||||
}
|
||||
|
||||
ParseFileError err = init_ast_file(&file, import_path);
|
||||
|
||||
if (err != ParseFile_None) {
|
||||
if (err == ParseFile_EmptyFile) {
|
||||
if (import_path == p->init_fullpath) {
|
||||
gb_printf_err("Initial file is empty - %.*s\n", LIT(p->init_fullpath));
|
||||
gb_exit(1);
|
||||
}
|
||||
return ParseFile_None;
|
||||
}
|
||||
|
||||
if (pos.line != 0) {
|
||||
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));
|
||||
switch (err) {
|
||||
case ParseFile_WrongExtension:
|
||||
gb_printf_err("Invalid file extension: File must have the extension `.odin`");
|
||||
break;
|
||||
case ParseFile_InvalidFile:
|
||||
gb_printf_err("Invalid file or cannot be found");
|
||||
break;
|
||||
case ParseFile_Permission:
|
||||
gb_printf_err("File permissions problem");
|
||||
break;
|
||||
case ParseFile_NotFound:
|
||||
gb_printf_err("File cannot be found (`%.*s`)", LIT(import_path));
|
||||
break;
|
||||
case ParseFile_InvalidToken:
|
||||
gb_printf_err("Invalid token found in file");
|
||||
break;
|
||||
}
|
||||
gb_printf_err("\n");
|
||||
return err;
|
||||
}
|
||||
parse_file(p, &file);
|
||||
|
||||
{
|
||||
gb_mutex_lock(&p->mutex);
|
||||
file.id = imported_file.index;
|
||||
array_add(&p->files, file);
|
||||
p->total_line_count += file.tokenizer.line_count;
|
||||
gb_mutex_unlock(&p->mutex);
|
||||
}
|
||||
|
||||
|
||||
return ParseFile_None;
|
||||
}
|
||||
|
||||
GB_THREAD_PROC(parse_worker_file_proc) {
|
||||
if (thread == nullptr) return 0;
|
||||
auto *p = cast(Parser *)thread->user_data;
|
||||
isize index = thread->user_index;
|
||||
ImportedFile imported_file = p->imports[index];
|
||||
ParseFileError err = parse_import(p, imported_file);
|
||||
return cast(isize)err;
|
||||
}
|
||||
|
||||
|
||||
struct ParserThreadWork {
|
||||
Parser *parser;
|
||||
isize import_index;
|
||||
};
|
||||
|
||||
ParseFileError parse_files(Parser *p, String init_filename) {
|
||||
GB_ASSERT(init_filename.text[init_filename.len] == 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));
|
||||
TokenPos init_pos = {};
|
||||
ImportedFile init_imported_file = {init_fullpath, init_fullpath, init_pos};
|
||||
ImportedFile init_imported_file = {ImportedFile_Init, init_fullpath, init_fullpath, init_pos};
|
||||
|
||||
isize shared_file_count = 0;
|
||||
if (!build_context.generate_docs) {
|
||||
String s = get_fullpath_core(heap_allocator(), str_lit("_preload.odin"));
|
||||
ImportedFile runtime_file = {s, s, init_pos};
|
||||
ImportedFile runtime_file = {ImportedFile_Shared, s, s, init_pos};
|
||||
array_add(&p->imports, runtime_file);
|
||||
shared_file_count++;
|
||||
}
|
||||
if (!build_context.generate_docs) {
|
||||
String s = get_fullpath_core(heap_allocator(), str_lit("_soft_numbers.odin"));
|
||||
ImportedFile runtime_file = {s, s, init_pos};
|
||||
ImportedFile runtime_file = {ImportedFile_Shared, s, s, init_pos};
|
||||
array_add(&p->imports, runtime_file);
|
||||
shared_file_count++;
|
||||
}
|
||||
|
||||
array_add(&p->imports, init_imported_file);
|
||||
p->init_fullpath = init_fullpath;
|
||||
|
||||
for_array(i, p->imports) {
|
||||
ImportedFile imported_file = p->imports[i];
|
||||
String import_path = imported_file.path;
|
||||
String import_rel_path = imported_file.rel_path;
|
||||
TokenPos pos = imported_file.pos;
|
||||
AstFile file = {};
|
||||
|
||||
ParseFileError err = init_ast_file(&file, import_path);
|
||||
#if 1
|
||||
isize thread_count = gb_max(build_context.thread_count, 1);
|
||||
if (thread_count > 1) {
|
||||
Array<gbThread> worker_threads = {};
|
||||
array_init_count(&worker_threads, heap_allocator(), thread_count);
|
||||
defer (array_free(&worker_threads));
|
||||
|
||||
if (err != ParseFile_None) {
|
||||
if (err == ParseFile_EmptyFile) {
|
||||
if (import_path == init_fullpath) {
|
||||
gb_printf_err("Initial file is empty - %.*s\n", LIT(init_fullpath));
|
||||
gb_exit(1);
|
||||
}
|
||||
return ParseFile_None;
|
||||
}
|
||||
|
||||
if (pos.line != 0) {
|
||||
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));
|
||||
switch (err) {
|
||||
case ParseFile_WrongExtension:
|
||||
gb_printf_err("Invalid file extension: File must have the extension `.odin`");
|
||||
break;
|
||||
case ParseFile_InvalidFile:
|
||||
gb_printf_err("Invalid file or cannot be found");
|
||||
break;
|
||||
case ParseFile_Permission:
|
||||
gb_printf_err("File permissions problem");
|
||||
break;
|
||||
case ParseFile_NotFound:
|
||||
gb_printf_err("File cannot be found (`%.*s`)", LIT(import_path));
|
||||
break;
|
||||
case ParseFile_InvalidToken:
|
||||
gb_printf_err("Invalid token found in file");
|
||||
break;
|
||||
}
|
||||
gb_printf_err("\n");
|
||||
return err;
|
||||
for_array(i, p->imports) {
|
||||
gbThread *t = &worker_threads[i];
|
||||
gb_thread_init(t);
|
||||
}
|
||||
parse_file(p, &file);
|
||||
|
||||
{
|
||||
gb_mutex_lock(&p->mutex);
|
||||
file.id = p->files.count;
|
||||
array_add(&p->files, file);
|
||||
p->total_line_count += file.tokenizer.line_count;
|
||||
gb_mutex_unlock(&p->mutex);
|
||||
// NOTE(bill): Make sure that these are in parsed in this order
|
||||
for (isize i = 0; i < shared_file_count; i++) {
|
||||
ParseFileError err = parse_import(p, p->imports[i]);
|
||||
if (err != ParseFile_None) {
|
||||
return err;
|
||||
}
|
||||
p->curr_import_index++;
|
||||
}
|
||||
|
||||
for (;;) {
|
||||
bool are_any_alive = false;
|
||||
for_array(i, worker_threads) {
|
||||
gbThread *t = &worker_threads[i];
|
||||
if (gb_thread_is_running(t)) {
|
||||
are_any_alive = true;
|
||||
} else if (p->curr_import_index < p->imports.count) {
|
||||
if (t->return_value != 0) {
|
||||
for_array(i, worker_threads) {
|
||||
gb_thread_destory(&worker_threads[i]);
|
||||
}
|
||||
return cast(ParseFileError)t->return_value;
|
||||
}
|
||||
t->user_index = p->curr_import_index++;
|
||||
gb_thread_start(t, parse_worker_file_proc, p);
|
||||
are_any_alive = true;
|
||||
}
|
||||
}
|
||||
if (!are_any_alive && p->curr_import_index >= p->imports.count) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
for_array(i, worker_threads) {
|
||||
gb_thread_destory(&worker_threads[i]);
|
||||
}
|
||||
} else {
|
||||
for_array(i, p->imports) {
|
||||
ParseFileError err = parse_import(p, p->imports[i]);
|
||||
if (err != ParseFile_None) {
|
||||
return err;
|
||||
}
|
||||
}
|
||||
}
|
||||
#else
|
||||
for_array(i, p->imports) {
|
||||
ParseFileError err = parse_import(p, p->imports[i]);
|
||||
if (err != ParseFile_None) {
|
||||
return err;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
for_array(i, p->files) {
|
||||
p->total_token_count += p->files[i].tokens.count;
|
||||
|
||||
@@ -1,10 +1,12 @@
|
||||
gb_global gbArena string_buffer_arena = {};
|
||||
gb_global gbArena string_buffer_arena = {};
|
||||
gb_global gbAllocator string_buffer_allocator = {};
|
||||
gb_global gbMutex string_buffer_mutex = {};
|
||||
|
||||
void init_string_buffer_memory(void) {
|
||||
// NOTE(bill): This should be enough memory for file systems
|
||||
gb_arena_init_from_allocator(&string_buffer_arena, heap_allocator(), gb_megabytes(1));
|
||||
string_buffer_allocator = gb_arena_allocator(&string_buffer_arena);
|
||||
gb_mutex_init(&string_buffer_mutex);
|
||||
}
|
||||
|
||||
|
||||
@@ -104,9 +106,8 @@ gb_inline bool str_eq_ignore_case(String a, String b) {
|
||||
return false;
|
||||
}
|
||||
|
||||
int string_compare(String x, String y) {
|
||||
if (!(x.len == y.len &&
|
||||
x.text == y.text)) {
|
||||
int string_compare(String const &x, String const &y) {
|
||||
if (x.len != y.len || x.text != y.text) {
|
||||
isize n, fast, offset, curr_block;
|
||||
isize *la, *lb;
|
||||
isize pos;
|
||||
@@ -148,26 +149,34 @@ GB_COMPARE_PROC(string_cmp_proc) {
|
||||
return string_compare(x, y);
|
||||
}
|
||||
|
||||
gb_inline bool str_eq(String a, String b) { return a.len == b.len ? gb_memcompare(a.text, b.text, a.len) == 0 : false; }
|
||||
gb_inline bool str_ne(String a, String b) { return !str_eq(a, b); }
|
||||
gb_inline bool str_lt(String a, String b) { return string_compare(a, b) < 0; }
|
||||
gb_inline bool str_gt(String a, String b) { return string_compare(a, b) > 0; }
|
||||
gb_inline bool str_le(String a, String b) { return string_compare(a, b) <= 0; }
|
||||
gb_inline bool str_ge(String a, String b) { return string_compare(a, b) >= 0; }
|
||||
gb_inline bool str_eq(String const &a, String const &b) {
|
||||
if (a.len != b.len) return false;
|
||||
for (isize i = 0; i < a.len; i++) {
|
||||
if (a.text[i] != b.text[i]) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
gb_inline bool str_ne(String const &a, String const &b) { return !str_eq(a, b); }
|
||||
gb_inline bool str_lt(String const &a, String const &b) { return string_compare(a, b) < 0; }
|
||||
gb_inline bool str_gt(String const &a, String const &b) { return string_compare(a, b) > 0; }
|
||||
gb_inline bool str_le(String const &a, String const &b) { return string_compare(a, b) <= 0; }
|
||||
gb_inline bool str_ge(String const &a, String const &b) { return string_compare(a, b) >= 0; }
|
||||
|
||||
bool operator == (String a, String b) { return str_eq(a, b); }
|
||||
bool operator != (String a, String b) { return str_ne(a, b); }
|
||||
bool operator < (String a, String b) { return str_lt(a, b); }
|
||||
bool operator > (String a, String b) { return str_gt(a, b); }
|
||||
bool operator <= (String a, String b) { return str_le(a, b); }
|
||||
bool operator >= (String a, String b) { return str_ge(a, b); }
|
||||
gb_inline bool operator == (String const &a, String const &b) { return str_eq(a, b); }
|
||||
gb_inline bool operator != (String const &a, String const &b) { return str_ne(a, b); }
|
||||
gb_inline bool operator < (String const &a, String const &b) { return str_lt(a, b); }
|
||||
gb_inline bool operator > (String const &a, String const &b) { return str_gt(a, b); }
|
||||
gb_inline bool operator <= (String const &a, String const &b) { return str_le(a, b); }
|
||||
gb_inline bool operator >= (String const &a, String const &b) { return str_ge(a, b); }
|
||||
|
||||
template <isize N> bool operator == (String a, char const (&b)[N]) { return str_eq(a, make_string(cast(u8 *)b, N-1)); }
|
||||
template <isize N> bool operator != (String a, char const (&b)[N]) { return str_ne(a, make_string(cast(u8 *)b, N-1)); }
|
||||
template <isize N> bool operator < (String a, char const (&b)[N]) { return str_lt(a, make_string(cast(u8 *)b, N-1)); }
|
||||
template <isize N> bool operator > (String a, char const (&b)[N]) { return str_gt(a, make_string(cast(u8 *)b, N-1)); }
|
||||
template <isize N> bool operator <= (String a, char const (&b)[N]) { return str_le(a, make_string(cast(u8 *)b, N-1)); }
|
||||
template <isize N> bool operator >= (String a, char const (&b)[N]) { return str_ge(a, make_string(cast(u8 *)b, N-1)); }
|
||||
template <isize N> bool operator == (String const &a, char const (&b)[N]) { return str_eq(a, make_string(cast(u8 *)b, N-1)); }
|
||||
template <isize N> bool operator != (String const &a, char const (&b)[N]) { return str_ne(a, make_string(cast(u8 *)b, N-1)); }
|
||||
template <isize N> bool operator < (String const &a, char const (&b)[N]) { return str_lt(a, make_string(cast(u8 *)b, N-1)); }
|
||||
template <isize N> bool operator > (String const &a, char const (&b)[N]) { return str_gt(a, make_string(cast(u8 *)b, N-1)); }
|
||||
template <isize N> bool operator <= (String const &a, char const (&b)[N]) { return str_le(a, make_string(cast(u8 *)b, N-1)); }
|
||||
template <isize N> bool operator >= (String const &a, char const (&b)[N]) { return str_ge(a, make_string(cast(u8 *)b, N-1)); }
|
||||
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user