From 7cdf37eaf6ec9b4f2f4adf527eea55c7bc716472 Mon Sep 17 00:00:00 2001 From: Laytan Laats Date: Mon, 3 Jul 2023 01:22:36 +0200 Subject: [PATCH 01/21] exit with code 1 on `odin test` failure --- src/llvm_backend.cpp | 44 ++++++++++++++++++++++++++++++++------------ 1 file changed, 32 insertions(+), 12 deletions(-) diff --git a/src/llvm_backend.cpp b/src/llvm_backend.cpp index 12abe7b16..6a4046d8d 100644 --- a/src/llvm_backend.cpp +++ b/src/llvm_backend.cpp @@ -1825,25 +1825,45 @@ gb_internal lbProcedure *lb_create_main_procedure(lbModule *m, lbProcedure *star TEMPORARY_ALLOCATOR_GUARD(); auto args = array_make(temporary_allocator(), 1); args[0] = lb_addr_load(p, all_tests_slice); - lb_emit_call(p, runner, args); + lbValue result = lb_emit_call(p, runner, args); + + lbBlock *block_success = lb_create_block(p, "success"); + lbBlock *block_failure = lb_create_block(p, "failure"); + + lbValue result_success = lb_emit_comp(p, Token_CmpEq, result, lb_const_bool(m, t_bool, true)); + lb_emit_if(p, result_success, block_success, block_failure); + + lbValue exit_runner = lb_find_package_value(m, str_lit("os"), str_lit("exit")); + + lb_start_block(p, block_success); + { + auto exit_args = array_make(temporary_allocator(), 1); + exit_args[0] = lb_const_int(m, t_int, 0); + lb_emit_call(p, exit_runner, exit_args); + } + + lb_start_block(p, block_failure); + { + auto exit_args = array_make(temporary_allocator(), 1); + exit_args[0] = lb_const_int(m, t_int, 1); + lb_emit_call(p, exit_runner, exit_args); + } } else { if (m->info->entry_point != nullptr) { lbValue entry_point = lb_find_procedure_value_from_entity(m, m->info->entry_point); lb_emit_call(p, entry_point, {}, ProcInlining_no_inline); } - } + if (call_cleanup) { + lbValue cleanup_runtime_value = {cleanup_runtime->value, cleanup_runtime->type}; + lb_emit_call(p, cleanup_runtime_value, {}, ProcInlining_none); + } - if (call_cleanup) { - lbValue cleanup_runtime_value = {cleanup_runtime->value, cleanup_runtime->type}; - lb_emit_call(p, cleanup_runtime_value, {}, ProcInlining_none); - } - - - if (is_dll_main) { - LLVMBuildRet(p->builder, LLVMConstInt(lb_type(m, t_i32), 1, false)); - } else { - LLVMBuildRet(p->builder, LLVMConstInt(lb_type(m, t_i32), 0, false)); + if (is_dll_main) { + LLVMBuildRet(p->builder, LLVMConstInt(lb_type(m, t_i32), 1, false)); + } else { + LLVMBuildRet(p->builder, LLVMConstInt(lb_type(m, t_i32), 0, false)); + } } lb_end_procedure_body(p); From 7b89f258189f817bcc177bbc4426c48f3ccd9127 Mon Sep 17 00:00:00 2001 From: ramn Date: Sat, 8 Jul 2023 23:46:51 +0200 Subject: [PATCH 02/21] Fix #2637 where testing.expect_value can't compare nils --- core/testing/testing.odin | 5 +++-- tests/issues/run.bat | 1 + tests/issues/run.sh | 1 + tests/issues/test_issue_2637.odin | 13 +++++++++++++ 4 files changed, 18 insertions(+), 2 deletions(-) create mode 100644 tests/issues/test_issue_2637.odin diff --git a/core/testing/testing.odin b/core/testing/testing.odin index 0ceb58e33..1d738bbd1 100644 --- a/core/testing/testing.odin +++ b/core/testing/testing.odin @@ -4,6 +4,7 @@ import "core:fmt" import "core:io" import "core:time" import "core:intrinsics" +import "core:reflect" // IMPORTANT NOTE: Compiler requires this layout Test_Signature :: proc(^T) @@ -89,7 +90,7 @@ expect :: proc(t: ^T, ok: bool, msg: string = "", loc := #caller_location) -> bo return ok } expect_value :: proc(t: ^T, value, expected: $T, loc := #caller_location) -> bool where intrinsics.type_is_comparable(T) { - ok := value == expected + ok := value == expected || reflect.is_nil(value) && reflect.is_nil(expected) if !ok { errorf(t, "expected %v, got %v", expected, value, loc=loc) } @@ -100,4 +101,4 @@ expect_value :: proc(t: ^T, value, expected: $T, loc := #caller_location) -> boo set_fail_timeout :: proc(t: ^T, duration: time.Duration, loc := #caller_location) { _fail_timeout(t, duration, loc) -} \ No newline at end of file +} diff --git a/tests/issues/run.bat b/tests/issues/run.bat index 105d474e3..63d722e09 100644 --- a/tests/issues/run.bat +++ b/tests/issues/run.bat @@ -14,6 +14,7 @@ set COMMON=-collection:tests=..\.. ..\..\..\odin build ..\test_issue_2113.odin %COMMON% -file -debug || exit /b ..\..\..\odin test ..\test_issue_2466.odin %COMMON% -file || exit /b ..\..\..\odin test ..\test_issue_2615.odin %COMMON% -file || exit /b +..\..\..\odin test ..\test_issue_2637.odin %COMMON% -file || exit /b @echo off diff --git a/tests/issues/run.sh b/tests/issues/run.sh index c4c53e7e1..7d2101dc6 100755 --- a/tests/issues/run.sh +++ b/tests/issues/run.sh @@ -17,6 +17,7 @@ $ODIN test ../test_issue_2087.odin $COMMON -file $ODIN build ../test_issue_2113.odin $COMMON -file -debug $ODIN test ../test_issue_2466.odin $COMMON -file $ODIN test ../test_issue_2615.odin $COMMON -file +$ODIN test ../test_issue_2637.odin $COMMON -file if [[ $($ODIN build ../test_issue_2395.odin $COMMON -file 2>&1 >/dev/null | grep -c "$NO_NIL_ERR") -eq 2 ]] ; then echo "SUCCESSFUL 1/1" else diff --git a/tests/issues/test_issue_2637.odin b/tests/issues/test_issue_2637.odin new file mode 100644 index 000000000..c170fc444 --- /dev/null +++ b/tests/issues/test_issue_2637.odin @@ -0,0 +1,13 @@ +// Tests issue #2637 https://github.com/odin-lang/Odin/issues/2637 +package test_issues + +import "core:testing" + +Foo :: Maybe(string) + +@(test) +test_expect_value_succeeds_with_nil :: proc(t: ^testing.T) { + x: Foo + testing.expect(t, x == nil) // Succeeds + testing.expect_value(t, x, nil) // Fails, "expected nil, got nil" +} From 5f53d815d113e06bf4612592506db8564d3dc88b Mon Sep 17 00:00:00 2001 From: ramn Date: Sun, 9 Jul 2023 00:15:01 +0200 Subject: [PATCH 03/21] fix: make -vet not complain --- core/testing/testing.odin | 2 ++ 1 file changed, 2 insertions(+) diff --git a/core/testing/testing.odin b/core/testing/testing.odin index 1d738bbd1..1ba05315c 100644 --- a/core/testing/testing.odin +++ b/core/testing/testing.odin @@ -6,6 +6,8 @@ import "core:time" import "core:intrinsics" import "core:reflect" +_ :: reflect // alias reflect to nothing to force visibility for -vet + // IMPORTANT NOTE: Compiler requires this layout Test_Signature :: proc(^T) From 363b701925ffdbbab6255934e5076c516fa57ce6 Mon Sep 17 00:00:00 2001 From: Zac Nowicki Date: Sun, 9 Jul 2023 08:29:28 -0400 Subject: [PATCH 04/21] Improve Mutex struct documentation --- core/sync/primitives.odin | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/core/sync/primitives.odin b/core/sync/primitives.odin index b8bcfad70..fdb86d835 100644 --- a/core/sync/primitives.odin +++ b/core/sync/primitives.odin @@ -7,10 +7,21 @@ current_thread_id :: proc "contextless" () -> int { return _current_thread_id() } -// A Mutex is a mutual exclusion lock -// The zero value for a Mutex is an unlocked mutex +// A Mutex is a [mutual exclusion lock](https://en.wikipedia.org/wiki/Mutual_exclusion). +// It can be used to prevent more than one thread from executing the same piece of code, +// and thus prevent access to same piece of memory by multiple threads, at the same time. // -// A Mutex must not be copied after first use +// A Mutex's zero value represents an initial, *unlocked* state. +// +// If another thread tries to take the lock while another thread holds it, it will pause +// until the lock is released. Code or memory that is "surrounded" by a mutex lock is said +// to be "guarded by a mutex". +// +// A Mutex must not be copied after first use (e.g., after locking it the first time). +// This is because, in order to coordinate with other threads, all threads must watch +// the same memory address to know when the lock has been released. Trying to use a +// copy of the lock at a different memory address will result in broken and unsafe +// behavior. For this reason, Mutexes are marked as `#no_copy`. Mutex :: struct #no_copy { impl: _Mutex, } From f0f8177a19e6975c309e5e3e720d8848e6819c96 Mon Sep 17 00:00:00 2001 From: ryuukk <44361234+ryuukk@users.noreply.github.com> Date: Mon, 10 Jul 2023 05:56:26 +0200 Subject: [PATCH 05/21] Add definitions for network byte order conversion procs --- core/sys/windows/ws2_32.odin | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/core/sys/windows/ws2_32.odin b/core/sys/windows/ws2_32.odin index 631ef4241..c8bec05a6 100644 --- a/core/sys/windows/ws2_32.odin +++ b/core/sys/windows/ws2_32.odin @@ -206,4 +206,12 @@ foreign ws2_32 { optval: ^c_char, optlen: ^c_int, ) -> c_int --- + // https://learn.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-ntohl + ntohl :: proc(netlong: c_ulong) -> c_ulong --- + // https://learn.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-ntohs + ntohs :: proc(netshort: c_ushort) -> c_ushort --- + // https://learn.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-htonl + htonl :: proc(hostlong: c_ulong) -> c_ulong --- + // https://learn.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-htons + htons :: proc(hostshort: c_ushort) -> c_ushort --- } From ccd5685cee52e09b49e6dbb9a3e1f122ef8ef632 Mon Sep 17 00:00:00 2001 From: ryuukk <44361234+ryuukk@users.noreply.github.com> Date: Mon, 10 Jul 2023 05:57:12 +0200 Subject: [PATCH 06/21] Fix doc links --- core/sys/windows/ws2_32.odin | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/core/sys/windows/ws2_32.odin b/core/sys/windows/ws2_32.odin index c8bec05a6..c09b714ca 100644 --- a/core/sys/windows/ws2_32.odin +++ b/core/sys/windows/ws2_32.odin @@ -206,12 +206,12 @@ foreign ws2_32 { optval: ^c_char, optlen: ^c_int, ) -> c_int --- - // https://learn.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-ntohl + // [MS-Docs](https://learn.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-ntohl) ntohl :: proc(netlong: c_ulong) -> c_ulong --- - // https://learn.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-ntohs + // [MS-Docs](https://learn.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-ntohs) ntohs :: proc(netshort: c_ushort) -> c_ushort --- - // https://learn.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-htonl + // [MS-Docs](https://learn.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-htonl) htonl :: proc(hostlong: c_ulong) -> c_ulong --- - // https://learn.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-htons + // [MS-Docs](https://learn.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-htons) htons :: proc(hostshort: c_ushort) -> c_ushort --- } From bc43a8d38dcd4ad778ebf405308e4dc9058c0834 Mon Sep 17 00:00:00 2001 From: ryuukk <44361234+ryuukk@users.noreply.github.com> Date: Mon, 10 Jul 2023 06:02:38 +0200 Subject: [PATCH 07/21] Add CopyFileW --- core/sys/windows/kernel32.odin | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/core/sys/windows/kernel32.odin b/core/sys/windows/kernel32.odin index beed3a7e5..fcd9e55ed 100644 --- a/core/sys/windows/kernel32.odin +++ b/core/sys/windows/kernel32.odin @@ -159,6 +159,11 @@ foreign kernel32 { WaitForSingleObject :: proc(hHandle: HANDLE, dwMilliseconds: DWORD) -> DWORD --- Sleep :: proc(dwMilliseconds: DWORD) --- GetProcessId :: proc(handle: HANDLE) -> DWORD --- + CopyFileW :: proc( + lpExistingFileName: LPCWSTR, + lpNewFileName: LPCWSTR, + bFailIfExists: BOOL, + ) -> BOOL --- CopyFileExW :: proc( lpExistingFileName: LPCWSTR, lpNewFileName: LPCWSTR, From f141078073ef086dfb21f9c3c3de4d43205de69f Mon Sep 17 00:00:00 2001 From: Pix Date: Mon, 10 Jul 2023 22:24:16 +0800 Subject: [PATCH 08/21] GetGestureDetecetd should return a Gestures bit_set not a Gesture. --- vendor/raylib/raylib.odin | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vendor/raylib/raylib.odin b/vendor/raylib/raylib.odin index 2bedf77c4..4236839f0 100644 --- a/vendor/raylib/raylib.odin +++ b/vendor/raylib/raylib.odin @@ -1133,7 +1133,7 @@ foreign lib { SetGesturesEnabled :: proc(flags: Gestures) --- // Enable a set of gestures using flags IsGestureDetected :: proc(gesture: Gesture) -> bool --- // Check if a gesture have been detected - GetGestureDetected :: proc() -> Gesture --- // Get latest detected gesture + GetGestureDetected :: proc() -> Gestures --- // Get latest detected gesture GetGestureHoldDuration :: proc() -> f32 --- // Get gesture hold time in milliseconds GetGestureDragVector :: proc() -> Vector2 --- // Get gesture drag vector GetGestureDragAngle :: proc() -> f32 --- // Get gesture drag angle From 20e5e95ff85cd0d590fa152aec3d8942c0d665e2 Mon Sep 17 00:00:00 2001 From: ryuukk <44361234+ryuukk@users.noreply.github.com> Date: Tue, 11 Jul 2023 03:45:08 +0200 Subject: [PATCH 09/21] Deprecate htons, htonl, ntohl, ntohs --- core/sys/windows/ws2_32.odin | 2 ++ 1 file changed, 2 insertions(+) diff --git a/core/sys/windows/ws2_32.odin b/core/sys/windows/ws2_32.odin index c09b714ca..6e5c37345 100644 --- a/core/sys/windows/ws2_32.odin +++ b/core/sys/windows/ws2_32.odin @@ -211,7 +211,9 @@ foreign ws2_32 { // [MS-Docs](https://learn.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-ntohs) ntohs :: proc(netshort: c_ushort) -> c_ushort --- // [MS-Docs](https://learn.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-htonl) + @(deprecated("Use endian specific integers instead, https://odin-lang.org/docs/overview/#basic-types")) htonl :: proc(hostlong: c_ulong) -> c_ulong --- // [MS-Docs](https://learn.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-htons) + @(deprecated("Use endian specific integers instead, https://odin-lang.org/docs/overview/#basic-types")) htons :: proc(hostshort: c_ushort) -> c_ushort --- } From e1fae5b9027ad6e79b949639ed403593e1591356 Mon Sep 17 00:00:00 2001 From: ryuukk <44361234+ryuukk@users.noreply.github.com> Date: Tue, 11 Jul 2023 03:51:28 +0200 Subject: [PATCH 10/21] Fix attribute --- core/sys/windows/ws2_32.odin | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/sys/windows/ws2_32.odin b/core/sys/windows/ws2_32.odin index 6e5c37345..7b9cf1b89 100644 --- a/core/sys/windows/ws2_32.odin +++ b/core/sys/windows/ws2_32.odin @@ -211,9 +211,9 @@ foreign ws2_32 { // [MS-Docs](https://learn.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-ntohs) ntohs :: proc(netshort: c_ushort) -> c_ushort --- // [MS-Docs](https://learn.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-htonl) - @(deprecated("Use endian specific integers instead, https://odin-lang.org/docs/overview/#basic-types")) + @(deprecated="Use endian specific integers instead, https://odin-lang.org/docs/overview/#basic-types") htonl :: proc(hostlong: c_ulong) -> c_ulong --- // [MS-Docs](https://learn.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-htons) - @(deprecated("Use endian specific integers instead, https://odin-lang.org/docs/overview/#basic-types")) + @(deprecated="Use endian specific integers instead, https://odin-lang.org/docs/overview/#basic-types") htons :: proc(hostshort: c_ushort) -> c_ushort --- } From 46f408cc9f86bbc840864c26675d7ccfd242242c Mon Sep 17 00:00:00 2001 From: Zac Nowicki Date: Tue, 11 Jul 2023 07:43:16 -0400 Subject: [PATCH 11/21] Fixup link format --- core/sync/primitives.odin | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/sync/primitives.odin b/core/sync/primitives.odin index fdb86d835..5e71f6336 100644 --- a/core/sync/primitives.odin +++ b/core/sync/primitives.odin @@ -7,7 +7,7 @@ current_thread_id :: proc "contextless" () -> int { return _current_thread_id() } -// A Mutex is a [mutual exclusion lock](https://en.wikipedia.org/wiki/Mutual_exclusion). +// A Mutex is a [[mutual exclusion lock; https://en.wikipedia.org/wiki/Mutual_exclusion]] // It can be used to prevent more than one thread from executing the same piece of code, // and thus prevent access to same piece of memory by multiple threads, at the same time. // From 52700d6a840d5635cf8ebc3f9ebf516f9c47f615 Mon Sep 17 00:00:00 2001 From: Laytan Laats Date: Tue, 11 Jul 2023 19:30:44 +0200 Subject: [PATCH 12/21] use lb_emit_select instead of lb_emit_if for exit check --- src/llvm_backend.cpp | 26 ++++---------------------- 1 file changed, 4 insertions(+), 22 deletions(-) diff --git a/src/llvm_backend.cpp b/src/llvm_backend.cpp index 6a4046d8d..90716dde0 100644 --- a/src/llvm_backend.cpp +++ b/src/llvm_backend.cpp @@ -1827,30 +1827,12 @@ gb_internal lbProcedure *lb_create_main_procedure(lbModule *m, lbProcedure *star args[0] = lb_addr_load(p, all_tests_slice); lbValue result = lb_emit_call(p, runner, args); - lbBlock *block_success = lb_create_block(p, "success"); - lbBlock *block_failure = lb_create_block(p, "failure"); - - lbValue result_success = lb_emit_comp(p, Token_CmpEq, result, lb_const_bool(m, t_bool, true)); - lb_emit_if(p, result_success, block_success, block_failure); - lbValue exit_runner = lb_find_package_value(m, str_lit("os"), str_lit("exit")); - - lb_start_block(p, block_success); - { - auto exit_args = array_make(temporary_allocator(), 1); - exit_args[0] = lb_const_int(m, t_int, 0); - lb_emit_call(p, exit_runner, exit_args); - } - - lb_start_block(p, block_failure); - { - auto exit_args = array_make(temporary_allocator(), 1); - exit_args[0] = lb_const_int(m, t_int, 1); - lb_emit_call(p, exit_runner, exit_args); - } + auto exit_args = array_make(temporary_allocator(), 1); + exit_args[0] = lb_emit_select(p, result, lb_const_int(m, t_int, 0), lb_const_int(m, t_int, 1)); + lb_emit_call(p, exit_runner, exit_args, ProcInlining_none); } else { - if (m->info->entry_point != nullptr) { - lbValue entry_point = lb_find_procedure_value_from_entity(m, m->info->entry_point); + if (m->info->entry_point != nullptr) { lbValue entry_point = lb_find_procedure_value_from_entity(m, m->info->entry_point); lb_emit_call(p, entry_point, {}, ProcInlining_no_inline); } From 3cce9721257f921b81bd757c453fecb8b5308227 Mon Sep 17 00:00:00 2001 From: Laytan Laats Date: Tue, 11 Jul 2023 19:33:14 +0200 Subject: [PATCH 13/21] fix indentation --- src/llvm_backend.cpp | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/llvm_backend.cpp b/src/llvm_backend.cpp index 90716dde0..938c9b2ac 100644 --- a/src/llvm_backend.cpp +++ b/src/llvm_backend.cpp @@ -1832,19 +1832,20 @@ gb_internal lbProcedure *lb_create_main_procedure(lbModule *m, lbProcedure *star exit_args[0] = lb_emit_select(p, result, lb_const_int(m, t_int, 0), lb_const_int(m, t_int, 1)); lb_emit_call(p, exit_runner, exit_args, ProcInlining_none); } else { - if (m->info->entry_point != nullptr) { lbValue entry_point = lb_find_procedure_value_from_entity(m, m->info->entry_point); + if (m->info->entry_point != nullptr) { + lbValue entry_point = lb_find_procedure_value_from_entity(m, m->info->entry_point); lb_emit_call(p, entry_point, {}, ProcInlining_no_inline); } if (call_cleanup) { - lbValue cleanup_runtime_value = {cleanup_runtime->value, cleanup_runtime->type}; - lb_emit_call(p, cleanup_runtime_value, {}, ProcInlining_none); + lbValue cleanup_runtime_value = {cleanup_runtime->value, cleanup_runtime->type}; + lb_emit_call(p, cleanup_runtime_value, {}, ProcInlining_none); } if (is_dll_main) { - LLVMBuildRet(p->builder, LLVMConstInt(lb_type(m, t_i32), 1, false)); + LLVMBuildRet(p->builder, LLVMConstInt(lb_type(m, t_i32), 1, false)); } else { - LLVMBuildRet(p->builder, LLVMConstInt(lb_type(m, t_i32), 0, false)); + LLVMBuildRet(p->builder, LLVMConstInt(lb_type(m, t_i32), 0, false)); } } From 8068a3899d8a92b35ad89a2bcfb7f34e5eb9487e Mon Sep 17 00:00:00 2001 From: hchac Date: Tue, 11 Jul 2023 16:23:54 -0400 Subject: [PATCH 14/21] Don't gitignore folders named odin. --- .gitignore | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 824e0c203..3528af624 100644 --- a/.gitignore +++ b/.gitignore @@ -270,6 +270,7 @@ bin/ # - Linux/MacOS odin +!odin/ odin.dSYM *.bin demo.bin @@ -286,4 +287,4 @@ shared/ *.sublime-workspace examples/bug/ build.sh -!core/debug/ \ No newline at end of file +!core/debug/ From c6957e4e313b7c46e687c2869d5681a7f59ec500 Mon Sep 17 00:00:00 2001 From: Eric Johnson Date: Tue, 11 Jul 2023 13:41:12 -0700 Subject: [PATCH 15/21] Fix small doc mistakes in arena.odin --- core/mem/virtual/arena.odin | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/core/mem/virtual/arena.odin b/core/mem/virtual/arena.odin index e73a39660..cfd35ab05 100644 --- a/core/mem/virtual/arena.odin +++ b/core/mem/virtual/arena.odin @@ -242,7 +242,7 @@ arena_growing_bootstrap_new_by_name :: proc($T: typeid, $field_name: string, min return arena_growing_bootstrap_new_by_offset(T, offset_of_by_string(T, field_name), minimum_block_size) } -// Ability to bootstrap allocate a struct with an arena within the struct itself using the growing variant strategy. +// Ability to bootstrap allocate a struct with an arena within the struct itself using the static variant strategy. @(require_results) arena_static_bootstrap_new_by_offset :: proc($T: typeid, offset_to_arena: uintptr, reserved: uint) -> (ptr: ^T, err: Allocator_Error) { bootstrap: Arena @@ -258,7 +258,7 @@ arena_static_bootstrap_new_by_offset :: proc($T: typeid, offset_to_arena: uintpt return } -// Ability to bootstrap allocate a struct with an arena within the struct itself using the growing variant strategy. +// Ability to bootstrap allocate a struct with an arena within the struct itself using the static variant strategy. @(require_results) arena_static_bootstrap_new_by_name :: proc($T: typeid, $field_name: string, reserved: uint) -> (ptr: ^T, err: Allocator_Error) { return arena_static_bootstrap_new_by_offset(T, offset_of_by_string(T, field_name), reserved) @@ -271,7 +271,7 @@ arena_allocator :: proc(arena: ^Arena) -> mem.Allocator { return mem.Allocator{arena_allocator_proc, arena} } -// The allocator procedured by an `Allocator` produced by `arena_allocator` +// The allocator procedure used by an `Allocator` produced by `arena_allocator` arena_allocator_proc :: proc(allocator_data: rawptr, mode: mem.Allocator_Mode, size, alignment: int, old_memory: rawptr, old_size: int, @@ -328,7 +328,7 @@ arena_allocator_proc :: proc(allocator_data: rawptr, mode: mem.Allocator_Mode, -// An `Arena_Temp` is a way to produce temporary watermarks to reset a arena to a previous state. +// An `Arena_Temp` is a way to produce temporary watermarks to reset an arena to a previous state. // All uses of an `Arena_Temp` must be handled by ending them with `arena_temp_end` or ignoring them with `arena_temp_ignore`. Arena_Temp :: struct { arena: ^Arena, From 635d671ee7facfa1a2026a544dd1b6d1f3a6422a Mon Sep 17 00:00:00 2001 From: Brennen Shaughnessy Date: Sat, 15 Jul 2023 15:59:58 -0400 Subject: [PATCH 16/21] Fixed typo in GGPO bindings --- vendor/ggpo/ggpo.odin | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vendor/ggpo/ggpo.odin b/vendor/ggpo/ggpo.odin index d17c33638..b38f4fb65 100644 --- a/vendor/ggpo/ggpo.odin +++ b/vendor/ggpo/ggpo.odin @@ -50,7 +50,7 @@ Player :: struct { player_num: c.int, using u: struct #raw_union { local: struct {}, - remove: struct { + remote: struct { ip_address: [32]byte, port: u16, }, From dcf3023d93de612575acd9794b039e2514c010c0 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Mon, 17 Jul 2023 12:06:48 +0100 Subject: [PATCH 17/21] Fix bug caused by incorrect assert --- src/llvm_backend_expr.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/llvm_backend_expr.cpp b/src/llvm_backend_expr.cpp index c30170553..c9d30af7a 100644 --- a/src/llvm_backend_expr.cpp +++ b/src/llvm_backend_expr.cpp @@ -4171,7 +4171,7 @@ gb_internal lbAddr lb_build_addr_compound_lit(lbProcedure *p, Ast *expr) { // HACK TODO(bill): THIS IS A MASSIVE HACK!!!! if (is_type_union(ft) && !are_types_identical(fet, ft) && !is_type_untyped(fet)) { - GB_ASSERT_MSG(union_variant_index(ft, fet) > 0, "%s", type_to_string(fet)); + GB_ASSERT_MSG(union_variant_index(ft, fet) >= 0, "%s", type_to_string(fet)); lb_emit_store_union_variant(p, gep, field_expr, fet); } else { From 921530dd01e940600692caba0b19185399daa2e0 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Mon, 17 Jul 2023 12:43:56 +0100 Subject: [PATCH 18/21] Fix to allow procedure groups on objective-c types --- src/check_decl.cpp | 124 +++++++++--------- src/check_expr.cpp | 178 ++++++++++++++++---------- src/checker.cpp | 48 +++++++ src/llvm_backend_expr.cpp | 3 +- src/types.cpp | 2 +- vendor/darwin/Metal/MetalClasses.odin | 4 +- 6 files changed, 233 insertions(+), 126 deletions(-) diff --git a/src/check_decl.cpp b/src/check_decl.cpp index b651e33e6..2b2fb867c 100644 --- a/src/check_decl.cpp +++ b/src/check_decl.cpp @@ -757,6 +757,66 @@ gb_internal String handle_link_name(CheckerContext *ctx, Token token, String lin return link_name; } +gb_internal void check_objc_methods(CheckerContext *ctx, Entity *e, AttributeContext const &ac) { + if (!(ac.objc_name.len || ac.objc_is_class_method || ac.objc_type)) { + return; + } + if (ac.objc_name.len == 0 && ac.objc_is_class_method) { + error(e->token, "@(objc_name) is required with @(objc_is_class_method)"); + } else if (ac.objc_type == nullptr) { + error(e->token, "@(objc_name) requires that @(objc_type) to be set"); + } else if (ac.objc_name.len == 0 && ac.objc_type) { + error(e->token, "@(objc_name) is required with @(objc_type)"); + } else { + Type *t = ac.objc_type; + if (t->kind == Type_Named) { + Entity *tn = t->Named.type_name; + + GB_ASSERT(tn->kind == Entity_TypeName); + + if (tn->scope != e->scope) { + error(e->token, "@(objc_name) attribute may only be applied to procedures and types within the same scope"); + } else { + mutex_lock(&global_type_name_objc_metadata_mutex); + defer (mutex_unlock(&global_type_name_objc_metadata_mutex)); + + if (!tn->TypeName.objc_metadata) { + tn->TypeName.objc_metadata = create_type_name_obj_c_metadata(); + } + auto *md = tn->TypeName.objc_metadata; + mutex_lock(md->mutex); + defer (mutex_unlock(md->mutex)); + + if (!ac.objc_is_class_method) { + bool ok = true; + for (TypeNameObjCMetadataEntry const &entry : md->value_entries) { + if (entry.name == ac.objc_name) { + error(e->token, "Previous declaration of @(objc_name=\"%.*s\")", LIT(ac.objc_name)); + ok = false; + break; + } + } + if (ok) { + array_add(&md->value_entries, TypeNameObjCMetadataEntry{ac.objc_name, e}); + } + } else { + bool ok = true; + for (TypeNameObjCMetadataEntry const &entry : md->type_entries) { + if (entry.name == ac.objc_name) { + error(e->token, "Previous declaration of @(objc_name=\"%.*s\")", LIT(ac.objc_name)); + ok = false; + break; + } + } + if (ok) { + array_add(&md->type_entries, TypeNameObjCMetadataEntry{ac.objc_name, e}); + } + } + } + } + } +} + gb_internal void check_proc_decl(CheckerContext *ctx, Entity *e, DeclInfo *d) { GB_ASSERT(e->type == nullptr); if (d->proc_lit->kind != Ast_ProcLit) { @@ -840,62 +900,7 @@ gb_internal void check_proc_decl(CheckerContext *ctx, Entity *e, DeclInfo *d) { } e->Procedure.optimization_mode = cast(ProcedureOptimizationMode)ac.optimization_mode; - if (ac.objc_name.len || ac.objc_is_class_method || ac.objc_type) { - if (ac.objc_name.len == 0 && ac.objc_is_class_method) { - error(e->token, "@(objc_name) is required with @(objc_is_class_method)"); - } else if (ac.objc_type == nullptr) { - error(e->token, "@(objc_name) requires that @(objc_type) to be set"); - } else if (ac.objc_name.len == 0 && ac.objc_type) { - error(e->token, "@(objc_name) is required with @(objc_type)"); - } else { - Type *t = ac.objc_type; - if (t->kind == Type_Named) { - Entity *tn = t->Named.type_name; - - GB_ASSERT(tn->kind == Entity_TypeName); - - if (tn->scope != e->scope) { - error(e->token, "@(objc_name) attribute may only be applied to procedures and types within the same scope"); - } else { - mutex_lock(&global_type_name_objc_metadata_mutex); - defer (mutex_unlock(&global_type_name_objc_metadata_mutex)); - - if (!tn->TypeName.objc_metadata) { - tn->TypeName.objc_metadata = create_type_name_obj_c_metadata(); - } - auto *md = tn->TypeName.objc_metadata; - mutex_lock(md->mutex); - defer (mutex_unlock(md->mutex)); - - if (!ac.objc_is_class_method) { - bool ok = true; - for (TypeNameObjCMetadataEntry const &entry : md->value_entries) { - if (entry.name == ac.objc_name) { - error(e->token, "Previous declaration of @(objc_name=\"%.*s\")", LIT(ac.objc_name)); - ok = false; - break; - } - } - if (ok) { - array_add(&md->value_entries, TypeNameObjCMetadataEntry{ac.objc_name, e}); - } - } else { - bool ok = true; - for (TypeNameObjCMetadataEntry const &entry : md->type_entries) { - if (entry.name == ac.objc_name) { - error(e->token, "Previous declaration of @(objc_name=\"%.*s\")", LIT(ac.objc_name)); - ok = false; - break; - } - } - if (ok) { - array_add(&md->type_entries, TypeNameObjCMetadataEntry{ac.objc_name, e}); - } - } - } - } - } - } + check_objc_methods(ctx, e, ac); if (ac.require_target_feature.len != 0 && ac.enable_target_feature.len != 0) { error(e->token, "Attributes @(require_target_feature=...) and @(enable_target_feature=...) cannot be used together"); @@ -1241,7 +1246,7 @@ gb_internal void check_global_variable_decl(CheckerContext *ctx, Entity *&e, Ast check_rtti_type_disallowed(e->token, e->type, "A variable declaration is using a type, %s, which has been disallowed"); } -gb_internal void check_proc_group_decl(CheckerContext *ctx, Entity *&pg_entity, DeclInfo *d) { +gb_internal void check_proc_group_decl(CheckerContext *ctx, Entity *pg_entity, DeclInfo *d) { GB_ASSERT(pg_entity->kind == Entity_ProcGroup); auto *pge = &pg_entity->ProcGroup; String proc_group_name = pg_entity->token.string; @@ -1366,6 +1371,11 @@ gb_internal void check_proc_group_decl(CheckerContext *ctx, Entity *&pg_entity, } } + AttributeContext ac = {}; + check_decl_attributes(ctx, d->attributes, proc_group_attribute, &ac); + check_objc_methods(ctx, pg_entity, ac); + + } gb_internal void check_entity_decl(CheckerContext *ctx, Entity *e, DeclInfo *d, Type *named_type) { diff --git a/src/check_expr.cpp b/src/check_expr.cpp index b662c231f..bb953ee2e 100644 --- a/src/check_expr.cpp +++ b/src/check_expr.cpp @@ -6328,9 +6328,46 @@ gb_internal CallArgumentData check_call_arguments_proc_group(CheckerContext *c, print_argument_types(); } + if (procs.count == 0) { + procs = proc_group_entities_cloned(c, *operand); + } if (procs.count > 0) { error_line("Did you mean to use one of the following:\n"); } + isize max_name_length = 0; + isize max_type_length = 0; + for (Entity *proc : procs) { + Type *t = base_type(proc->type); + if (t == t_invalid) continue; + String prefix = {}; + String prefix_sep = {}; + if (proc->pkg) { + prefix = proc->pkg->name; + prefix_sep = str_lit("."); + } + String name = proc->token.string; + max_name_length = gb_max(max_name_length, prefix.len + prefix_sep.len + name.len); + + + + gbString pt; + if (t->Proc.node != nullptr) { + pt = expr_to_string(t->Proc.node); + } else { + pt = type_to_string(t); + } + + max_type_length = gb_max(max_type_length, gb_string_length(pt)); + gb_string_free(pt); + } + + isize max_spaces = gb_max(max_name_length, max_type_length); + char *spaces = gb_alloc_array(temporary_allocator(), char, max_spaces+1); + for (isize i = 0; i < max_spaces; i++) { + spaces[i] = ' '; + } + spaces[max_spaces] = 0; + for (Entity *proc : procs) { TokenPos pos = proc->token.pos; Type *t = base_type(proc->type); @@ -6350,12 +6387,23 @@ gb_internal CallArgumentData check_call_arguments_proc_group(CheckerContext *c, prefix_sep = str_lit("."); } String name = proc->token.string; + isize len = prefix.len + prefix_sep.len + name.len; + + int name_padding = cast(int)gb_max(max_name_length - len, 0); + int type_padding = cast(int)gb_max(max_type_length - gb_string_length(pt), 0); char const *sep = "::"; if (proc->kind == Entity_Variable) { sep = ":="; } - error_line("\t%.*s%.*s%.*s %s %s at %s\n", LIT(prefix), LIT(prefix_sep), LIT(name), sep, pt, token_pos_to_string(pos)); + error_line("\t%.*s%.*s%.*s %.*s%s %s %.*sat %s\n", + LIT(prefix), LIT(prefix_sep), LIT(name), + name_padding, spaces, + sep, + pt, + type_padding, spaces, + token_pos_to_string(pos) + ); } if (procs.count > 0) { error_line("\n"); @@ -9315,13 +9363,13 @@ gb_internal ExprKind check_selector_call_expr(CheckerContext *c, Operand *o, Ast ExprKind kind = check_expr_base(c, &x, se->expr, nullptr); c->allow_arrow_right_selector_expr = allow_arrow_right_selector_expr; - if (x.mode == Addressing_Invalid || x.type == t_invalid) { + if (x.mode == Addressing_Invalid || (x.type == t_invalid && x.mode != Addressing_ProcGroup)) { o->mode = Addressing_Invalid; o->type = t_invalid; o->expr = node; return kind; } - if (!is_type_proc(x.type)) { + if (!is_type_proc(x.type) && x.mode != Addressing_ProcGroup) { gbString type_str = type_to_string(x.type); error(se->call, "Selector call expressions expect a procedure type for the call, got '%s'", type_str); gb_string_free(type_str); @@ -9344,76 +9392,76 @@ gb_internal ExprKind check_selector_call_expr(CheckerContext *c, Operand *o, Ast first_arg->state_flags |= StateFlag_SelectorCallExpr; } - Type *pt = base_type(x.type); - GB_ASSERT(pt->kind == Type_Proc); - Type *first_type = nullptr; - String first_arg_name = {}; - if (pt->Proc.param_count > 0) { - Entity *f = pt->Proc.params->Tuple.variables[0]; - first_type = f->type; - first_arg_name = f->token.string; - } - if (first_arg_name.len == 0) { - first_arg_name = str_lit("_"); - } + if (e->kind != Entity_ProcGroup) { + Type *pt = base_type(x.type); + GB_ASSERT_MSG(pt->kind == Type_Proc, "%.*s %.*s %s", LIT(e->token.string), LIT(entity_strings[e->kind]), type_to_string(x.type)); + Type *first_type = nullptr; + String first_arg_name = {}; + if (pt->Proc.param_count > 0) { + Entity *f = pt->Proc.params->Tuple.variables[0]; + first_type = f->type; + first_arg_name = f->token.string; + } + if (first_arg_name.len == 0) { + first_arg_name = str_lit("_"); + } - if (first_type == nullptr) { - error(se->call, "Selector call expressions expect a procedure type for the call with at least 1 parameter"); - o->mode = Addressing_Invalid; - o->type = t_invalid; - o->expr = node; - return Expr_Stmt; - } + if (first_type == nullptr) { + error(se->call, "Selector call expressions expect a procedure type for the call with at least 1 parameter"); + o->mode = Addressing_Invalid; + o->type = t_invalid; + o->expr = node; + return Expr_Stmt; + } - Operand y = {}; - y.mode = first_arg->tav.mode; - y.type = first_arg->tav.type; - y.value = first_arg->tav.value; + Operand y = {}; + y.mode = first_arg->tav.mode; + y.type = first_arg->tav.type; + y.value = first_arg->tav.value; - if (check_is_assignable_to(c, &y, first_type)) { - // Do nothing, it's valid - } else { - Operand z = y; - z.type = type_deref(y.type); - if (check_is_assignable_to(c, &z, first_type)) { - // NOTE(bill): AST GENERATION HACK! - Token op = {Token_Pointer}; - first_arg = ast_deref_expr(first_arg->file(), first_arg, op); - } else if (y.mode == Addressing_Variable) { - Operand w = y; - w.type = alloc_type_pointer(y.type); - if (check_is_assignable_to(c, &w, first_type)) { + if (check_is_assignable_to(c, &y, first_type)) { + // Do nothing, it's valid + } else { + Operand z = y; + z.type = type_deref(y.type); + if (check_is_assignable_to(c, &z, first_type)) { // NOTE(bill): AST GENERATION HACK! - Token op = {Token_And}; - first_arg = ast_unary_expr(first_arg->file(), op, first_arg); + Token op = {Token_Pointer}; + first_arg = ast_deref_expr(first_arg->file(), first_arg, op); + } else if (y.mode == Addressing_Variable) { + Operand w = y; + w.type = alloc_type_pointer(y.type); + if (check_is_assignable_to(c, &w, first_type)) { + // NOTE(bill): AST GENERATION HACK! + Token op = {Token_And}; + first_arg = ast_unary_expr(first_arg->file(), op, first_arg); + } + } + } + + if (ce->args.count > 0) { + bool fail = false; + bool first_is_field_value = (ce->args[0]->kind == Ast_FieldValue); + for (Ast *arg : ce->args) { + bool mix = false; + if (first_is_field_value) { + mix = arg->kind != Ast_FieldValue; + } else { + mix = arg->kind == Ast_FieldValue; + } + if (mix) { + fail = true; + break; + } + } + if (!fail && first_is_field_value) { + Token op = {Token_Eq}; + AstFile *f = first_arg->file(); + first_arg = ast_field_value(f, ast_ident(f, make_token_ident(first_arg_name)), first_arg, op); } } } - if (ce->args.count > 0) { - bool fail = false; - bool first_is_field_value = (ce->args[0]->kind == Ast_FieldValue); - for (Ast *arg : ce->args) { - bool mix = false; - if (first_is_field_value) { - mix = arg->kind != Ast_FieldValue; - } else { - mix = arg->kind == Ast_FieldValue; - } - if (mix) { - fail = true; - break; - } - } - if (!fail && first_is_field_value) { - Token op = {Token_Eq}; - AstFile *f = first_arg->file(); - first_arg = ast_field_value(f, ast_ident(f, make_token_ident(first_arg_name)), first_arg, op); - } - } - - - auto modified_args = slice_make(heap_allocator(), ce->args.count+1); modified_args[0] = first_arg; slice_copy(&modified_args, ce->args, 1); diff --git a/src/checker.cpp b/src/checker.cpp index 396a04d7a..2a2cb5c42 100644 --- a/src/checker.cpp +++ b/src/checker.cpp @@ -2935,6 +2935,54 @@ gb_internal DECL_ATTRIBUTE_PROC(foreign_block_decl_attribute) { return false; } +gb_internal DECL_ATTRIBUTE_PROC(proc_group_attribute) { + if (name == ATTRIBUTE_USER_TAG_NAME) { + ExactValue ev = check_decl_attribute_value(c, value); + if (ev.kind != ExactValue_String) { + error(elem, "Expected a string value for '%.*s'", LIT(name)); + } + return true; + } else if (name == "objc_name") { + ExactValue ev = check_decl_attribute_value(c, value); + if (ev.kind == ExactValue_String) { + if (string_is_valid_identifier(ev.value_string)) { + ac->objc_name = ev.value_string; + } else { + error(elem, "Invalid identifier for '%.*s', got '%.*s'", LIT(name), LIT(ev.value_string)); + } + } else { + error(elem, "Expected a string value for '%.*s'", LIT(name)); + } + return true; + } else if (name == "objc_is_class_method") { + ExactValue ev = check_decl_attribute_value(c, value); + if (ev.kind == ExactValue_Bool) { + ac->objc_is_class_method = ev.value_bool; + } else { + error(elem, "Expected a boolean value for '%.*s'", LIT(name)); + } + return true; + } else if (name == "objc_type") { + if (value == nullptr) { + error(elem, "Expected a type for '%.*s'", LIT(name)); + } else { + Type *objc_type = check_type(c, value); + if (objc_type != nullptr) { + if (!has_type_got_objc_class_attribute(objc_type)) { + gbString t = type_to_string(objc_type); + error(value, "'%.*s' expected a named type with the attribute @(obj_class=), got type %s", LIT(name), t); + gb_string_free(t); + } else { + ac->objc_type = objc_type; + } + } + } + return true; + } + return false; +} + + gb_internal DECL_ATTRIBUTE_PROC(proc_decl_attribute) { if (name == ATTRIBUTE_USER_TAG_NAME) { ExactValue ev = check_decl_attribute_value(c, value); diff --git a/src/llvm_backend_expr.cpp b/src/llvm_backend_expr.cpp index c9d30af7a..5e6831fc2 100644 --- a/src/llvm_backend_expr.cpp +++ b/src/llvm_backend_expr.cpp @@ -4519,8 +4519,9 @@ gb_internal lbAddr lb_build_addr_internal(lbProcedure *p, Ast *expr) { Selection sel = lookup_field(type, selector, false); GB_ASSERT(sel.entity != nullptr); if (sel.pseudo_field) { - GB_ASSERT(sel.entity->kind == Entity_Procedure); + GB_ASSERT(sel.entity->kind == Entity_Procedure || sel.entity->kind == Entity_ProcGroup); Entity *e = entity_of_node(sel_node); + GB_ASSERT(e->kind == Entity_Procedure); return lb_addr(lb_find_value_from_entity(p->module, e)); } diff --git a/src/types.cpp b/src/types.cpp index 385ca926d..847aea9f3 100644 --- a/src/types.cpp +++ b/src/types.cpp @@ -3081,7 +3081,7 @@ gb_internal Selection lookup_field_with_selection(Type *type_, String field_name mutex_lock(md->mutex); defer (mutex_unlock(md->mutex)); for (TypeNameObjCMetadataEntry const &entry : md->value_entries) { - GB_ASSERT(entry.entity->kind == Entity_Procedure); + GB_ASSERT(entry.entity->kind == Entity_Procedure || entry.entity->kind == Entity_ProcGroup); if (entry.name == field_name) { sel.entity = entry.entity; sel.pseudo_field = true; diff --git a/vendor/darwin/Metal/MetalClasses.odin b/vendor/darwin/Metal/MetalClasses.odin index 17f22e1d3..9239182db 100644 --- a/vendor/darwin/Metal/MetalClasses.odin +++ b/vendor/darwin/Metal/MetalClasses.odin @@ -5388,8 +5388,8 @@ Device_newBufferWithLength :: #force_inline proc "c" (self: ^Device, length: NS. @(objc_type=Device, objc_name="newBuffer") Device_newBuffer :: proc{ - Device_newBufferWithBytes, - Device_newBufferWithBytesNoCopy, + // Device_newBufferWithBytes, + // Device_newBufferWithBytesNoCopy, Device_newBufferWithSlice, Device_newBufferWithSliceNoCopy, Device_newBufferWithLength, From 88485d5467653d2768a925b90b0345b9a9bb62a9 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Mon, 17 Jul 2023 12:57:33 +0100 Subject: [PATCH 19/21] Improve scoring for polymorphic procedures --- src/check_expr.cpp | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/src/check_expr.cpp b/src/check_expr.cpp index bb953ee2e..87b6e52d8 100644 --- a/src/check_expr.cpp +++ b/src/check_expr.cpp @@ -6258,14 +6258,18 @@ gb_internal CallArgumentData check_call_arguments_proc_group(CheckerContext *c, } isize index = i; + ValidIndexAndScore item = {}; + item.score = data.score; + if (data.gen_entity != nullptr) { array_add(&proc_entities, data.gen_entity); index = proc_entities.count-1; + + // prefer non-polymorphic procedures over polymorphic + item.score += assign_score_function(1); } - ValidIndexAndScore item = {}; item.index = index; - item.score = data.score; array_add(&valids, item); } } @@ -6348,8 +6352,6 @@ gb_internal CallArgumentData check_call_arguments_proc_group(CheckerContext *c, String name = proc->token.string; max_name_length = gb_max(max_name_length, prefix.len + prefix_sep.len + name.len); - - gbString pt; if (t->Proc.node != nullptr) { pt = expr_to_string(t->Proc.node); @@ -6417,8 +6419,8 @@ gb_internal CallArgumentData check_call_arguments_proc_group(CheckerContext *c, error(operand->expr, "Ambiguous procedure group call '%s' that match with the given arguments", expr_name); print_argument_types(); - for (isize i = 0; i < valids.count; i++) { - Entity *proc = proc_entities[valids[i].index]; + for (auto const &valid : valids) { + Entity *proc = proc_entities[valid.index]; GB_ASSERT(proc != nullptr); TokenPos pos = proc->token.pos; Type *t = base_type(proc->type); GB_ASSERT(t->kind == Type_Proc); From 0f28857c59346ab6239527d51403899ffbf6885e Mon Sep 17 00:00:00 2001 From: gingerBill Date: Mon, 17 Jul 2023 13:03:58 +0100 Subject: [PATCH 20/21] Improve type inference for procedure group stuff --- src/check_expr.cpp | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/src/check_expr.cpp b/src/check_expr.cpp index 87b6e52d8..98154f33d 100644 --- a/src/check_expr.cpp +++ b/src/check_expr.cpp @@ -6136,7 +6136,6 @@ gb_internal CallArgumentData check_call_arguments_proc_group(CheckerContext *c, { // NOTE(bill, 2019-07-13): This code is used to improve the type inference for procedure groups // where the same positional parameter has the same type value (and ellipsis) - bool proc_arg_count_all_equal = true; isize proc_arg_count = -1; for (Entity *p : procs) { Type *pt = base_type(p->type); @@ -6144,15 +6143,12 @@ gb_internal CallArgumentData check_call_arguments_proc_group(CheckerContext *c, if (proc_arg_count < 0) { proc_arg_count = pt->Proc.param_count; } else { - if (proc_arg_count != pt->Proc.param_count) { - proc_arg_count_all_equal = false; - break; - } + proc_arg_count = gb_min(proc_arg_count, pt->Proc.param_count); } } } - if (proc_arg_count >= 0 && proc_arg_count_all_equal) { + if (proc_arg_count >= 0) { lhs_count = proc_arg_count; if (lhs_count > 0) { lhs = gb_alloc_array(heap_allocator(), Entity *, lhs_count); From 1b3657122cb69b96ec54dd878e4fbdbb00641bcc Mon Sep 17 00:00:00 2001 From: gingerBill Date: Mon, 17 Jul 2023 16:02:18 +0100 Subject: [PATCH 21/21] Uncomment procedures in procedure group --- vendor/darwin/Metal/MetalClasses.odin | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/vendor/darwin/Metal/MetalClasses.odin b/vendor/darwin/Metal/MetalClasses.odin index 9239182db..17f22e1d3 100644 --- a/vendor/darwin/Metal/MetalClasses.odin +++ b/vendor/darwin/Metal/MetalClasses.odin @@ -5388,8 +5388,8 @@ Device_newBufferWithLength :: #force_inline proc "c" (self: ^Device, length: NS. @(objc_type=Device, objc_name="newBuffer") Device_newBuffer :: proc{ - // Device_newBufferWithBytes, - // Device_newBufferWithBytesNoCopy, + Device_newBufferWithBytes, + Device_newBufferWithBytesNoCopy, Device_newBufferWithSlice, Device_newBufferWithSliceNoCopy, Device_newBufferWithLength,