From: Brendan Hansen Date: Sat, 24 Dec 2022 03:22:39 +0000 (-0600) Subject: bugfixes X-Git-Url: https://git.brendanfh.com/?a=commitdiff_plain;h=3fc9228dc2bf7e21d99c16434a6d50f86f444987;p=onyx.git bugfixes --- diff --git a/compiler/include/astnodes.h b/compiler/include/astnodes.h index 3ad01782..f6bb55b9 100644 --- a/compiler/include/astnodes.h +++ b/compiler/include/astnodes.h @@ -1625,7 +1625,7 @@ struct Context { // present in this list when generating CTags. bh_arr(AstNode *) tag_locations; - b32 cycle_almost_detected : 1; + u32 cycle_almost_detected : 2; b32 cycle_detected : 1; }; diff --git a/compiler/src/checker.c b/compiler/src/checker.c index 23462ce0..12171d00 100644 --- a/compiler/src/checker.c +++ b/compiler/src/checker.c @@ -2161,7 +2161,9 @@ CheckStatus check_insert_directive(AstDirectiveInsert** pinsert) { AstCodeBlock* code_block = (AstCodeBlock *) insert->code_expr; code_block = (AstCodeBlock *) strip_aliases((AstNode *) code_block); - assert(code_block->kind == Ast_Kind_Code_Block); + if (code_block->kind != Ast_Kind_Code_Block) { + ERROR(insert->token->pos, "Expected compile-time known expression of type 'Code'."); + } AstNode* cloned_block = ast_clone(context.ast_alloc, code_block->code); cloned_block->next = insert->next; diff --git a/compiler/src/onyx.c b/compiler/src/onyx.c index 82982019..f7ff50d7 100644 --- a/compiler/src/onyx.c +++ b/compiler/src/onyx.c @@ -672,10 +672,10 @@ static i32 onyx_compile() { if (ent->macro_attempts > highest_watermark) { entity_heap_insert_existing(&context.entities, ent); - if (context.cycle_almost_detected) { + if (context.cycle_almost_detected == 3) { dump_cycles(); } else { - context.cycle_almost_detected = 1; + context.cycle_almost_detected += 1; } } } diff --git a/compiler/src/symres.c b/compiler/src/symres.c index 341a1288..ea997211 100644 --- a/compiler/src/symres.c +++ b/compiler/src/symres.c @@ -362,7 +362,7 @@ static SymresStatus symres_field_access(AstFieldAccess** fa) { } } else if (force_a_lookup) { - if (context.cycle_detected || context.cycle_almost_detected) { + if (context.cycle_detected || context.cycle_almost_detected >= 2) { onyx_report_error((*fa)->token->pos, Error_Critical, "'%b' does not exist here. This is a bad error message.", (*fa)->token->text, (*fa)->token->length); @@ -909,7 +909,7 @@ static SymresStatus symres_directive_solidify(AstDirectiveSolidify** psolid) { static SymresStatus symres_directive_defined(AstDirectiveDefined** pdefined) { AstDirectiveDefined* defined = *pdefined; - b32 has_to_be_resolved = context.cycle_almost_detected; + b32 has_to_be_resolved = context.cycle_almost_detected >= 1; onyx_errors_disable(); resolved_a_symbol = 0; diff --git a/core/container/array.onyx b/core/container/array.onyx index c5aa3020..6c3655e3 100644 --- a/core/container/array.onyx +++ b/core/container/array.onyx @@ -244,6 +244,8 @@ Untyped_Array :: struct { // Things that work with slices and arrays +use core.intrinsics.types {type_is_struct} + transplant :: (arr: [] $T, old_index: i32, new_index: i32) -> bool { if old_index < 0 || old_index >= arr.count do return false; if new_index < 0 || new_index >= arr.count do return false; @@ -477,32 +479,44 @@ map :: #match #locked { macro (arr: [] $T, data: $R, f: (T, R) -> T) do for ^it: arr do *it = f(*it, data);, } -every :: #match #locked { - macro (arr: [] $T, predicate: (T) -> bool) -> bool { - every :: every - return every(arr, #(predicate(it))); - }, +every :: #match #local {} - macro (arr: [] $T, predicate_body: Code) -> bool { - for arr { - if !(#unquote predicate_body) do return false; - } - return true; +#overload +every :: macro (arr: [] $T, predicate: (T) -> bool) -> bool { + every :: every + return every(arr, #(predicate(it))); +} + +#overload +every :: macro (arr: [] $T, predicate_body: Code) -> bool { + for arr { + if !(#unquote predicate_body) do return false; } + return true; } -some :: #match #locked { - macro (arr: [] $T, predicate: (T) -> bool) -> bool { - some :: some - return every(arr, #(predicate(it))); - }, +some :: #match #local {} - macro (arr: [] $T, predicate_body: Code) -> bool { - for arr { - if #unquote predicate_body do return true; - } - return false; +#overload +some :: macro (arr: [] $T, predicate: (T) -> bool) -> bool { + some :: some + return every(arr, #(predicate(it))); +} + +#overload +some :: macro (arr: [] $T/type_is_struct, predicate_body: Code) -> bool { + for ^ arr { + if #unquote predicate_body do return true; } + return false; +} + +#overload +some :: macro (arr: [] $T, predicate_body: Code) -> bool { + for arr { + if #unquote predicate_body do return true; + } + return false; } fill :: (arr: [] $T, value: T) { @@ -540,7 +554,7 @@ find :: (arr: [] $T, value: T) -> i32 { } #overload -find :: macro (arr: [] $T, pred: Code) -> i32 { +find :: macro (arr: [] $T/type_is_struct, pred: Code) -> i32 { for i: arr.count { it := ^arr[i]; if #unquote pred do return i; @@ -549,6 +563,16 @@ find :: macro (arr: [] $T, pred: Code) -> i32 { return -1; } +#overload +find :: macro (arr: [] $T, pred: Code) -> i32 { + for i: arr.count { + it := arr[i]; + if #unquote pred do return i; + } + + return -1; +} + find_ptr :: (arr: [] $T, value: T) -> ^T { for ^it: arr { if value == *it do return it; @@ -563,9 +587,18 @@ first :: #match #locked { return first(arr, #(predicate(it))); }, + macro (arr: [] $T/type_is_struct, predicate_body: Code) -> ^T { + for ^ arr { + if #unquote predicate_body do return it; + } + + return null; + }, + macro (arr: [] $T, predicate_body: Code) -> ^T { // This is to preserve the semantics that "it" is - // not a pointer (same as contains) + // not a pointer (same as contains), when T is not a + // structure. for ^it_ptr: arr { it := *it_ptr; if #unquote predicate_body do return it_ptr; diff --git a/core/hash/hash.onyx b/core/hash/hash.onyx index 433f553b..95ee4f2c 100644 --- a/core/hash/hash.onyx +++ b/core/hash/hash.onyx @@ -1,7 +1,14 @@ package core.hash to_u32 :: #match { + // Does this need to have a higher precedence value? + // Because if I wanted to have a custom type as the key + // of a map that only looks at some of the members of the + // struct to determine its hash, that would not be possible + // as any pointer would match this case instead of the actual + // one defined for the type... (key: rawptr) -> u32 { return 0xcbf29ce7 ^ cast(u32) key; }, + (key: i8) -> u32 { return ~~ key; }, (key: i16) -> u32 { return 0x9ce7 ^ cast(u32) key; }, (key: i32) -> u32 { return 0xcbf29ce7 ^ cast(u32) key; }, diff --git a/core/misc/any_utils.onyx b/core/misc/any_utils.onyx index 53551454..a0019143 100644 --- a/core/misc/any_utils.onyx +++ b/core/misc/any_utils.onyx @@ -11,8 +11,12 @@ use runtime.info { get_struct_member } -use core { iter, array } +use core { iter, array, string } +// Either to_any or as_any will work. I prefer `as_any` because +// much of the rest of the standard library uses `as_...` for +// conversion. +as_any :: to_any to_any :: macro (x: ^$T) => any.{x, T}; any_as :: (a: any, $T: type_expr) -> ^T { @@ -57,6 +61,27 @@ any_selector :: (v: any, member_name: str) -> any { return .{null, void}; } +// This selector works with selecting "foo.bar.joe" +any_nested_selector :: (v: any, member_name: str) -> any { + t := get_type_info(v.type); + if t.kind != .Struct do return .{}; + + part_name, next_name := string.bisect(member_name, #char "."); + + member := get_struct_member(v.type, part_name); + if member { + if next_name { + return any_nested_selector(any.{cast(^u8) v.data + member.offset, member.type}, next_name); + } + + return any.{ + cast(^u8, v.data) + member.offset, member.type + }; + } + + return .{null, void}; +} + any_to_map :: (v: any) -> (Map(str, any), success: bool) { vals := v; if get_type_info(vals.type).kind == .Pointer { diff --git a/core/std.onyx b/core/std.onyx index 7d226994..ae198e29 100644 --- a/core/std.onyx +++ b/core/std.onyx @@ -46,10 +46,8 @@ package core #load "./test/testing" #load "./misc/arg_parse" -#load "./misc/any_utils" #load "./misc/method_ops" -#local runtime :: package runtime #if runtime.runtime == .Wasi || runtime.runtime == .Onyx { #load "./os/file" #load "./os/os" @@ -85,6 +83,7 @@ package core #load "./encoding/base64" #load "./encoding/csv" + #load "./misc/any_utils" } #if runtime.Multi_Threading_Enabled { diff --git a/interpreter/include/ovm_debug.h b/interpreter/include/ovm_debug.h index a6b53e9f..07501a54 100644 --- a/interpreter/include/ovm_debug.h +++ b/interpreter/include/ovm_debug.h @@ -284,6 +284,8 @@ typedef struct debug_state_t { bh_arena tmp_arena; bh_allocator tmp_alloc; + char *listen_path; + debug_info_t *info; struct ovm_engine_t *ovm_engine; diff --git a/interpreter/include/ovm_wasm.h b/interpreter/include/ovm_wasm.h index 71bb19c1..0dac195e 100644 --- a/interpreter/include/ovm_wasm.h +++ b/interpreter/include/ovm_wasm.h @@ -9,9 +9,11 @@ struct wasm_config_t { bool debug_enabled; + char *listen_path; }; void wasm_config_enable_debug(wasm_config_t *config, bool enabled); +void wasm_config_set_listen_path(wasm_config_t *config, char *listen_path); struct wasm_engine_t { wasm_config_t *config; diff --git a/interpreter/src/debug/debug_thread.c b/interpreter/src/debug/debug_thread.c index eee4ec60..17695647 100644 --- a/interpreter/src/debug/debug_thread.c +++ b/interpreter/src/debug/debug_thread.c @@ -465,8 +465,8 @@ void *__debug_thread_entry(void * data) { struct sockaddr_un local_addr, remote_addr; local_addr.sun_family = AF_UNIX; - strcpy(local_addr.sun_path, "/tmp/ovm-debug.0000"); // TODO: Make this dynamic so mulitple servers can exist at a time. - unlink(local_addr.sun_path); // TODO: Remove this line for the same reason. + strcpy(local_addr.sun_path, debug->listen_path); // TODO: Make this dynamic so mulitple servers can exist at a time. + unlink(local_addr.sun_path); // TODO: Remove this line for the same reason. int len = strlen(local_addr.sun_path) + sizeof(local_addr.sun_family); bind(debug->listen_socket_fd, (struct sockaddr *)&local_addr, len); diff --git a/interpreter/src/vm/vm.c b/interpreter/src/vm/vm.c index a877ab80..3ae33763 100644 --- a/interpreter/src/vm/vm.c +++ b/interpreter/src/vm/vm.c @@ -741,7 +741,7 @@ static void __ovm_debug_hook(ovm_engine_t *engine, ovm_state_t *state) { #define OVMI_FUNC_NAME(n) ovmi_exec_debug_##n #define OVMI_DISPATCH_NAME ovmi_debug_dispatch -#define OVMI_DEBUG_HOOK if (state->debug) __ovm_debug_hook(state->engine, state) +#define OVMI_DEBUG_HOOK __ovm_debug_hook(state->engine, state) #define OVMI_EXCEPTION_HOOK __ovm_trigger_exception(state) #include "./vm_instrs.h" diff --git a/interpreter/src/wasm/config.c b/interpreter/src/wasm/config.c index 07ea4741..bd8801e3 100644 --- a/interpreter/src/wasm/config.c +++ b/interpreter/src/wasm/config.c @@ -4,6 +4,7 @@ wasm_config_t *wasm_config_new() { wasm_config_t *config = malloc(sizeof(*config)); config->debug_enabled = false; + config->listen_path = "/tmp/ovm-debug.0000"; return config; } @@ -15,4 +16,7 @@ void wasm_config_enable_debug(wasm_config_t *config, bool enabled) { config->debug_enabled = enabled; } +void wasm_config_set_listen_path(wasm_config_t *config, char *listen_path) { + config->listen_path = listen_path; +} diff --git a/interpreter/src/wasm/engine.c b/interpreter/src/wasm/engine.c index db4fbeab..666779a7 100644 --- a/interpreter/src/wasm/engine.c +++ b/interpreter/src/wasm/engine.c @@ -23,6 +23,8 @@ wasm_engine_t *wasm_engine_new_with_config(wasm_config_t *config) { engine->engine->debug = debug; debug_host_init(engine->engine->debug, engine->engine); + debug->listen_path = config->listen_path; + debug_host_start(engine->engine->debug); } diff --git a/scripts/onyx-pkg.onyx b/scripts/onyx-pkg.onyx index fb816806..d7d39f5a 100644 --- a/scripts/onyx-pkg.onyx +++ b/scripts/onyx-pkg.onyx @@ -42,22 +42,24 @@ main :: (args: [] cstr) { command_procedures := runtime.info.get_procedures_with_tag(Command); defer delete(^command_procedures); - for command_procedures { - if it.tag.command == command { - if it.tag.require_config_file { - if !load_config_file() { - eprintf("Failed to open {}.\n", global_arguments.config_file); - os.exit(1); - } - loaded_config_file = true; - } + command_tag := array.first(command_procedures, #(it.tag.command == command)); + if !command_tag { + run_help_command(arguments); + return; + } - assert(it.type == #type ([] cstr) -> void, "BAD TYPE FOR COMMAND PROCEDURE!"); - (*cast(^([] cstr) -> void) ^it.func)(arguments); - break; + if command_tag.tag.require_config_file { + if !load_config_file() { + eprintf("Failed to open {}.\n", global_arguments.config_file); + os.exit(1); } + + loaded_config_file = true; } + + assert(command_tag.type == #type ([] cstr) -> void, "BAD TYPE FOR COMMAND PROCEDURE!"); + (*cast(^([] cstr) -> void) ^command_tag.func)(arguments); } Command :: struct { @@ -334,7 +336,7 @@ run_sync_command :: (args: [] cstr) { package-or-url Git repository name or package name on disk to remove. """ } -run_rebuild_command :: (args: [] cstr) { +run_rebuild_command :: (args: [] cstr) { if args.count < 1 { eprintf("Expected package name."); return; @@ -446,6 +448,11 @@ run_test_command :: (args: [] cstr) { } } +#tag Command.{ "new", "Create a new project from an installed template." } +run_new_command :: (args: [] cstr) { + +} + #local { #if runtime.compiler_os == .Linux { @@ -741,6 +748,8 @@ Git :: struct { version_str := tprintf("v{}", version); full_dest := tprintf("{}/{}", config.config.lib_source_directory, ".cloned"); + os.remove_directory(full_dest); + // Use 'git clone' to clone the bare minimum amount to get the released version. git_proc := os.process_spawn(git_path, .["clone", "--depth", "1", "-b", version_str, repo, full_dest]); result := os.process_wait(^git_proc); diff --git a/shared/lib/linux_x86_64/lib/libovmwasm.so b/shared/lib/linux_x86_64/lib/libovmwasm.so index 0cfe7fce..2ba9dcba 100755 Binary files a/shared/lib/linux_x86_64/lib/libovmwasm.so and b/shared/lib/linux_x86_64/lib/libovmwasm.so differ