From 96e033b22caff96924d2e0d72bd3d7166ec7ad02 Mon Sep 17 00:00:00 2001 From: matias Date: Thu, 25 Aug 2022 21:12:45 -0400 Subject: [PATCH 01/13] Add Extended Window Styles (WS_EX) Featuring frequently used styles such as: `WS_EX_APPWINDOW`, `WS_EX_NOREDIRECTIONBITMAP`, `WS_EX_ACCEPTFILES`, `WS_EX_TOOLWINDOW`, `WS_EX_TOPMOST`, `WS_EX_NOACTIVATE`, `WS_EX_LAYERED`, and more. --- core/sys/windows/types.odin | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/core/sys/windows/types.odin b/core/sys/windows/types.odin index edf6e593e..88a8af890 100644 --- a/core/sys/windows/types.odin +++ b/core/sys/windows/types.odin @@ -978,6 +978,35 @@ WS_TILEDWINDOW : UINT : WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_THICKF WS_VISIBLE : UINT : 0x1000_0000 WS_VSCROLL : UINT : 0x0020_0000 +WS_EX_ACCEPTFILES : UINT : 0x0000_0010 +WS_EX_APPWINDOW : UINT : 0x0004_0000 +WS_EX_CLIENTEDGE : UINT : 0x0000_0200 +WS_EX_COMPOSITED : UINT : 0x0200_0000 +WS_EX_CONTEXTHELP : UINT : 0x0000_0400 +WS_EX_CONTROLPARENT : UINT : 0x0001_0000 +WS_EX_DLGMODALFRAME : UINT : 0x0000_0001 +WS_EX_DRAGDETECT : UINT : 0x0000_0002 // undocumented +WS_EX_LAYERED : UINT : 0x0008_0000 +WS_EX_LAYOUTRTL : UINT : 0x0040_0000 +WS_EX_LEFT : UINT : 0x0000_0000 +WS_EX_LEFTSCROLLBAR : UINT : 0x0000_4000 +WS_EX_LTRREADING : UINT : 0x0000_0000 +WS_EX_MDICHILD : UINT : 0x0000_0040 +WS_EX_NOACTIVATE : UINT : 0x0800_0000 +WS_EX_NOINHERITLAYOUT : UINT : 0x0010_0000 +WS_EX_NOPARENTNOTIFY : UINT : 0x0000_0004 +WS_EX_NOREDIRECTIONBITMAP : UINT : 0x0020_0000 +WS_EX_OVERLAPPEDWINDOW : UINT : WS_EX_WINDOWEDGE | WS_EX_CLIENTEDGE +WS_EX_PALETTEWINDOW : UINT : WS_EX_WINDOWEDGE | WS_EX_TOOLWINDOW | WS_EX_TOPMOST +WS_EX_RIGHT : UINT : 0x0000_1000 +WS_EX_RIGHTSCROLLBAR : UINT : 0x0000_0000 +WS_EX_RTLREADING : UINT : 0x0000_2000 +WS_EX_STATICEDGE : UINT : 0x0002_0000 +WS_EX_TOOLWINDOW : UINT : 0x0000_0080 +WS_EX_TOPMOST : UINT : 0x0000_0008 +WS_EX_TRANSPARENT : UINT : 0x0000_0020 +WS_EX_WINDOWEDGE : UINT : 0x0000_0100 + PBS_SMOOTH :: 0x01 PBS_VERTICAL :: 0x04 From eb4891bcc89436a52643d5daac4e6237b1619f96 Mon Sep 17 00:00:00 2001 From: SyndaKai Date: Wed, 31 Aug 2022 04:28:46 -0400 Subject: [PATCH 02/13] Fix for SDL `GetPreferredLocales` --- vendor/sdl2/sdl2.odin | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vendor/sdl2/sdl2.odin b/vendor/sdl2/sdl2.odin index 24ecc38e6..a89394d4b 100644 --- a/vendor/sdl2/sdl2.odin +++ b/vendor/sdl2/sdl2.odin @@ -200,7 +200,7 @@ Locale :: struct { @(default_calling_convention="c", link_prefix="SDL_") foreign lib { - GetPreferredLocales :: proc() -> ^Locale --- + GetPreferredLocales :: proc() -> [^]Locale --- } // misc From b0a09f7b9e17825ed45e212108c464e6d6d4bca3 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Wed, 31 Aug 2022 11:02:36 +0100 Subject: [PATCH 03/13] Fix typo --- core/mem/virtual/growing_arena.odin | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/mem/virtual/growing_arena.odin b/core/mem/virtual/growing_arena.odin index f1067071b..ee3220cfa 100644 --- a/core/mem/virtual/growing_arena.odin +++ b/core/mem/virtual/growing_arena.odin @@ -13,7 +13,7 @@ Growing_Arena :: struct { DEFAULT_MINIMUM_BLOCK_SIZE :: 1<<20 // 1 MiB should be enough -growing_arena_init :: proc(arena: ^Static_Arena, reserved: uint = DEFAULT_MINIMUM_BLOCK_SIZE) -> (err: Allocator_Error) { +growing_arena_init :: proc(arena: ^Growing_Arena, reserved: uint = DEFAULT_MINIMUM_BLOCK_SIZE) -> (err: Allocator_Error) { arena.block = memory_block_alloc(0, reserved, {}) or_return arena.total_used = 0 arena.total_reserved = arena.block.reserved From ca76d5345241cbd2b7522ec40aee1bf29b23f3f4 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Wed, 31 Aug 2022 11:07:31 +0100 Subject: [PATCH 04/13] Fix more typos --- core/mem/virtual/growing_arena.odin | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/mem/virtual/growing_arena.odin b/core/mem/virtual/growing_arena.odin index ee3220cfa..0fb826c07 100644 --- a/core/mem/virtual/growing_arena.odin +++ b/core/mem/virtual/growing_arena.odin @@ -14,9 +14,9 @@ Growing_Arena :: struct { DEFAULT_MINIMUM_BLOCK_SIZE :: 1<<20 // 1 MiB should be enough growing_arena_init :: proc(arena: ^Growing_Arena, reserved: uint = DEFAULT_MINIMUM_BLOCK_SIZE) -> (err: Allocator_Error) { - arena.block = memory_block_alloc(0, reserved, {}) or_return + arena.curr_block = memory_block_alloc(0, reserved, {}) or_return arena.total_used = 0 - arena.total_reserved = arena.block.reserved + arena.total_reserved = arena.curr_block.reserved return } From 15aaf7dfa009d9a048b4029932831628999638c2 Mon Sep 17 00:00:00 2001 From: Phil Date: Fri, 26 Aug 2022 12:35:12 -0700 Subject: [PATCH 05/13] add sort_with_indices family of procs --- core/slice/sort.odin | 28 ++++++ core/slice/sort_private.odin | 177 +++++++++++++++++++++++++++++++++++ 2 files changed, 205 insertions(+) diff --git a/core/slice/sort.odin b/core/slice/sort.odin index b6e455056..779ba37fd 100644 --- a/core/slice/sort.odin +++ b/core/slice/sort.odin @@ -38,6 +38,20 @@ sort :: proc(data: $T/[]$E) where ORD(E) { } } +// sort sorts a slice +// This sort is not guaranteed to be stable +sort_with_indices :: proc(data: $T/[]$E, indices: []int) where ORD(E) { + when size_of(E) != 0 { + if n := len(data); n > 1 { + assert(len(data) == len(indices)) + for _, idx in indices { + indices[idx] = idx + } + _quick_sort_general_with_indices(data, indices, 0, n, _max_depth(n), struct{}{}, .Ordered) + } + } +} + // sort_by sorts a slice with a given procedure to test whether two values are ordered "i < j" // This sort is not guaranteed to be stable sort_by :: proc(data: $T/[]$E, less: proc(i, j: E) -> bool) { @@ -48,6 +62,20 @@ sort_by :: proc(data: $T/[]$E, less: proc(i, j: E) -> bool) { } } +// sort_by sorts a slice with a given procedure to test whether two values are ordered "i < j" +// This sort is not guaranteed to be stable +sort_by_with_indices :: proc(data: $T/[]$E, indices: []int, less: proc(i, j: E) -> bool) { + when size_of(E) != 0 { + if n := len(data); n > 1 { + assert(len(data) == len(indices)) + for _, idx in indices { + indices[idx] = idx + } + _quick_sort_general_with_indices(data, indices, 0, n, _max_depth(n), less, .Less) + } + } +} + sort_by_cmp :: proc(data: $T/[]$E, cmp: proc(i, j: E) -> Ordering) { when size_of(E) != 0 { if n := len(data); n > 1 { diff --git a/core/slice/sort_private.odin b/core/slice/sort_private.odin index d93d74bf9..86a6f5928 100644 --- a/core/slice/sort_private.odin +++ b/core/slice/sort_private.odin @@ -198,3 +198,180 @@ _stable_sort_general :: proc(data: $T/[]$E, call: $P, $KIND: Sort_Kind) where (O } } } + +_quick_sort_general_with_indices :: proc(data: $T/[]$E, indices: []int, a, b, max_depth: int, call: $P, $KIND: Sort_Kind) where (ORD(E) && KIND == .Ordered) || (KIND != .Ordered) #no_bounds_check { + less :: #force_inline proc(a, b: E, call: P) -> bool { + when KIND == .Ordered { + return a < b + } else when KIND == .Less { + return call(a, b) + } else when KIND == .Cmp { + return call(a, b) == .Less + } else { + #panic("unhandled Sort_Kind") + } + } + + insertion_sort :: proc(data: $T/[]$E, indices: []int, a, b: int, call: P) #no_bounds_check { + for i in a+1.. a && less(data[j], data[j-1], call); j -= 1 { + swap(data, j, j-1) + swap(indices, j, j-1) + } + } + } + + heap_sort :: proc(data: $T/[]$E, indices: []int, a, b: int, call: P) #no_bounds_check { + sift_down :: proc(data: T, indices: []int, lo, hi, first: int, call: P) #no_bounds_check { + root := lo + for { + child := 2*root + 1 + if child >= hi { + break + } + if child+1 < hi && less(data[first+child], data[first+child+1], call) { + child += 1 + } + if !less(data[first+root], data[first+child], call) { + return + } + swap(data, first+root, first+child) + swap(indices, first+root, first+child) + root = child + } + } + + + first, lo, hi := a, 0, b-a + + for i := (hi-1)/2; i >= 0; i -= 1 { + sift_down(data, indices, i, hi, first, call) + } + + for i := hi-1; i >= 0; i -= 1 { + swap(data, first, first+i) + swap(indices, first, first+i) + sift_down(data, indices, lo, i, first, call) + } + } + + median3 :: proc(data: T, indices: []int, m1, m0, m2: int, call: P) #no_bounds_check { + if less(data[m1], data[m0], call) { + swap(data, m1, m0) + swap(indices, m1, m0) + } + if less(data[m2], data[m1], call) { + swap(data, m2, m1) + swap(indices, m2, m1) + if less(data[m1], data[m0], call) { + swap(data, m1, m0) + swap(indices, m1, m0) + } + } + } + + do_pivot :: proc(data: T, indices: []int, lo, hi: int, call: P) -> (midlo, midhi: int) #no_bounds_check { + m := int(uint(lo+hi)>>1) + if hi-lo > 40 { + s := (hi-lo)/8 + median3(data, indices, lo, lo+s, lo+s*2, call) + median3(data, indices, m, m-s, m+s, call) + median3(data, indices, hi-1, hi-1-s, hi-1-s*2, call) + } + median3(data, indices, lo, m, hi-1, call) + + pivot := lo + a, c := lo+1, hi-1 + + + for ; a < c && less(data[a], data[pivot], call); a += 1 { + } + b := a + + for { + for ; b < c && !less(data[pivot], data[b], call); b += 1 { // data[b] <= pivot + } + for ; b < c && less(data[pivot], data[c-1], call); c -=1 { // data[c-1] > pivot + } + if b >= c { + break + } + + swap(data, b, c-1) + swap(indices, b, c-1) + b += 1 + c -= 1 + } + + protect := hi-c < 5 + if !protect && hi-c < (hi-lo)/4 { + dups := 0 + if !less(data[pivot], data[hi-1], call) { + swap(data, c, hi-1) + swap(indices, c, hi-1) + c += 1 + dups += 1 + } + if !less(data[b-1], data[pivot], call) { + b -= 1 + dups += 1 + } + + if !less(data[m], data[pivot], call) { + swap(data, m, b-1) + swap(indices, m, b-1) + b -= 1 + dups += 1 + } + protect = dups > 1 + } + if protect { + for { + for ; a < b && !less(data[b-1], data[pivot], call); b -= 1 { + } + for ; a < b && less(data[a], data[pivot], call); a += 1 { + } + if a >= b { + break + } + swap(data, a, b-1) + swap(indices, a, b-1) + a += 1 + b -= 1 + } + } + swap(data, pivot, b-1) + swap(indices, pivot, b-1) + return b-1, c + } + + assert(len(data) == len(indices)) + + a, b, max_depth := a, b, max_depth + + for b-a > 12 { // only use shell sort for lengths <= 12 + if max_depth == 0 { + heap_sort(data, indices, a, b, call) + return + } + max_depth -= 1 + mlo, mhi := do_pivot(data, indices, a, b, call) + if mlo-a < b-mhi { + _quick_sort_general_with_indices(data, indices, a, mlo, max_depth, call, KIND) + a = mhi + } else { + _quick_sort_general_with_indices(data, indices, mhi, b, max_depth, call, KIND) + b = mlo + } + } + if b-a > 1 { + // Shell short with gap 6 + for i in a+6.. Date: Wed, 31 Aug 2022 14:14:06 -0700 Subject: [PATCH 06/13] fix ease.odin compile error from missing comma --- core/math/ease/ease.odin | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/math/ease/ease.odin b/core/math/ease/ease.odin index 0bd7c3641..c3917707f 100644 --- a/core/math/ease/ease.odin +++ b/core/math/ease/ease.odin @@ -356,7 +356,7 @@ Flux_Tween :: struct($T: typeid) { flux_init :: proc($T: typeid, value_capacity := 8) -> Flux_Map(T) where intrinsics.type_is_float(T) { return { values = make(map[^T]Flux_Tween(T), value_capacity), - keys_to_be_deleted = make([dynamic]^T, 0, value_capacity) + keys_to_be_deleted = make([dynamic]^T, 0, value_capacity), } } From f3f51bd6436b82293fb9a1acad3eeb2165385aae Mon Sep 17 00:00:00 2001 From: Lucas Perlind Date: Thu, 1 Sep 2022 22:53:14 +1000 Subject: [PATCH 07/13] Kernel32: Add more window bindings and improve consistency --- core/sys/windows/kernel32.odin | 36 +++++++++++++++++++++------------- core/sys/windows/types.odin | 28 ++++++++++++++++++++++++++ core/sys/windows/winerror.odin | 2 ++ 3 files changed, 52 insertions(+), 14 deletions(-) diff --git a/core/sys/windows/kernel32.odin b/core/sys/windows/kernel32.odin index f055b6908..5174e6df7 100644 --- a/core/sys/windows/kernel32.odin +++ b/core/sys/windows/kernel32.odin @@ -24,6 +24,8 @@ foreign kernel32 { lpMode: LPDWORD) -> BOOL --- SetConsoleMode :: proc(hConsoleHandle: HANDLE, dwMode: DWORD) -> BOOL --- + SetConsoleCursorPosition :: proc(hConsoleHandle: HANDLE, + dwCursorPosition: COORD) -> BOOL --- GetFileInformationByHandle :: proc(hFile: HANDLE, lpFileInformation: LPBY_HANDLE_FILE_INFORMATION) -> BOOL --- SetHandleInformation :: proc(hObject: HANDLE, @@ -94,6 +96,15 @@ foreign kernel32 { dwCreationFlags: DWORD, lpThreadId: LPDWORD, ) -> HANDLE --- + CreateRemoteThread :: proc( + hProcess: HANDLE, + lpThreadAttributes: LPSECURITY_ATTRIBUTES, + dwStackSize: SIZE_T, + lpStartAddress: proc "stdcall" (rawptr) -> DWORD, + lpParameter: LPVOID, + dwCreationFlags: DWORD, + lpThreadId: LPDWORD, + ) -> HANDLE --- SwitchToThread :: proc() -> BOOL --- ResumeThread :: proc(thread: HANDLE) -> DWORD --- GetThreadPriority :: proc(thread: HANDLE) -> c_int --- @@ -326,6 +337,15 @@ foreign kernel32 { SetEndOfFile :: proc(hFile: HANDLE) -> BOOL --- CreatePipe :: proc(hReadPipe, hWritePipe: ^HANDLE, lpPipeAttributes: LPSECURITY_ATTRIBUTES, nSize: DWORD) -> BOOL --- + + ConnectNamedPipe :: proc(hNamedPipe: HANDLE, lpOverlapped: LPOVERLAPPED,) -> BOOL --- + DisconnectNamedPipe :: proc(hNamedPipe: HANDLE,) -> BOOL --- + WaitNamedPipeW :: proc(lpNamedPipeName: LPCWSTR, nTimeOut: DWORD,) -> BOOL --- + + SetConsoleCtrlHandler :: proc(HandlerRoutine: PHANDLER_ROUTINE, Add: BOOL) -> BOOL --- + GenerateConsoleCtrlEvent :: proc(dwCtrlEvent: DWORD, dwProcessGroupId: DWORD) -> BOOL --- + FreeConsole :: proc() -> BOOL --- + GetConsoleWindow :: proc() -> HWND --- } @@ -780,17 +800,5 @@ foreign kernel32 { ) -> BOOL --- } -@(default_calling_convention="stdcall") -foreign kernel32 { - @(link_name="SetConsoleCtrlHandler") set_console_ctrl_handler :: proc(handler: Handler_Routine, add: BOOL) -> BOOL --- -} - -Handler_Routine :: proc(dwCtrlType: Control_Event) -> BOOL - -Control_Event :: enum DWORD { - control_c = 0, - _break = 1, - close = 2, - logoff = 5, - shutdown = 6, -} +HandlerRoutine :: proc "stdcall" (dwCtrlType: DWORD) -> BOOL +PHANDLER_ROUTINE :: HandlerRoutine diff --git a/core/sys/windows/types.odin b/core/sys/windows/types.odin index edf6e593e..0a03baaa2 100644 --- a/core/sys/windows/types.odin +++ b/core/sys/windows/types.odin @@ -1628,6 +1628,8 @@ CONDITION_VARIABLE_INIT :: CONDITION_VARIABLE{} SRWLOCK_INIT :: SRWLOCK{} DETACHED_PROCESS: DWORD : 0x00000008 +CREATE_NEW_CONSOLE: DWORD : 0x00000010 +CREATE_NO_WINDOW: DWORD : 0x08000000 CREATE_NEW_PROCESS_GROUP: DWORD : 0x00000200 CREATE_UNICODE_ENVIRONMENT: DWORD : 0x00000400 STARTF_USESTDHANDLES: DWORD : 0x00000100 @@ -1689,6 +1691,7 @@ PIPE_WAIT: DWORD : 0x00000000 PIPE_TYPE_BYTE: DWORD : 0x00000000 PIPE_REJECT_REMOTE_CLIENTS: DWORD : 0x00000008 PIPE_READMODE_BYTE: DWORD : 0x00000000 +PIPE_ACCEPT_REMOTE_CLIENTS: DWORD : 0x00000000 FD_SETSIZE :: 64 @@ -3265,3 +3268,28 @@ IFileSaveDialogVtbl :: struct { GetProperties: proc "stdcall" (this: ^IFileSaveDialog, ppStore: ^^IPropertyStore) -> HRESULT, ApplyProperties: proc "stdcall" (this: ^IFileSaveDialog, psi: ^IShellItem, pStore: ^IPropertyStore, hwnd: HWND, pSink: ^IFileOperationProgressSink) -> HRESULT, } + +ENABLE_ECHO_INPUT : DWORD : 0x0004 +ENABLE_INSERT_MODE : DWORD : 0x0020 +ENABLE_LINE_INPUT : DWORD : 0x0002 +ENABLE_MOUSE_INPUT : DWORD : 0x0010 +ENABLE_PROCESSED_INPUT : DWORD : 0x0001 +ENABLE_QUICK_EDIT_MODE : DWORD : 0x0040 +ENABLE_WINDOW_INPUT : DWORD : 0x0008 +ENABLE_VIRTUAL_TERMINAL_INPUT : DWORD : 0x0200 +ENABLE_PROCESSED_OUTPUT : DWORD : 0x0001 +ENABLE_WRAP_AT_EOL_OUTPUT : DWORD : 0x0002 +ENABLE_VIRTUAL_TERMINAL_PROCESSING : DWORD : 0x0004 +DISABLE_NEWLINE_AUTO_RETURN : DWORD : 0x0008 +ENABLE_LVB_GRID_WORLDWIDE : DWORD : 0x0010 + +CTRL_C_EVENT : DWORD : 0 +CTRL_BREAK_EVENT : DWORD : 1 +CTRL_CLOSE_EVENT : DWORD : 2 +CTRL_LOGOFF_EVENT : DWORD : 5 +CTRL_SHUTDOWN_EVENT : DWORD : 6 + +COORD :: struct { + X: SHORT, + Y: SHORT, +} diff --git a/core/sys/windows/winerror.odin b/core/sys/windows/winerror.odin index 7bd0bfe9f..f552b9a53 100644 --- a/core/sys/windows/winerror.odin +++ b/core/sys/windows/winerror.odin @@ -42,6 +42,8 @@ ERROR_TIMEOUT : DWORD : 1460 ERROR_DATATYPE_MISMATCH : DWORD : 1629 ERROR_UNSUPPORTED_TYPE : DWORD : 1630 ERROR_NOT_SAME_OBJECT : DWORD : 1656 +ERROR_PIPE_CONNECTED : DWORD : 0x80070217 +ERROR_PIPE_BUSY : DWORD : 231 E_NOTIMPL :: HRESULT(-0x7fff_bfff) // 0x8000_4001 From ed73441a4c2a3828626709d807b70bbd53b7a161 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Thu, 1 Sep 2022 15:11:53 +0100 Subject: [PATCH 08/13] Fix code generation related to Objective-C related `x->y()` calls --- src/check_expr.cpp | 5 ++++- src/llvm_backend_proc.cpp | 5 ++--- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/src/check_expr.cpp b/src/check_expr.cpp index 9c2d20781..54dc081cf 100644 --- a/src/check_expr.cpp +++ b/src/check_expr.cpp @@ -8769,7 +8769,10 @@ ExprKind check_selector_call_expr(CheckerContext *c, Operand *o, Ast *node, Type Ast *first_arg = x.expr->SelectorExpr.expr; GB_ASSERT(first_arg != nullptr); - first_arg->state_flags |= StateFlag_SelectorCallExpr; + Entity *e = entity_of_node(se->expr); + if (!(e != nullptr && (e->kind == Entity_Procedure || e->kind == Entity_ProcGroup))) { + first_arg->state_flags |= StateFlag_SelectorCallExpr; + } Type *pt = base_type(x.type); GB_ASSERT(pt->kind == Type_Proc); diff --git a/src/llvm_backend_proc.cpp b/src/llvm_backend_proc.cpp index f85d8397c..d9f4e0c0d 100644 --- a/src/llvm_backend_proc.cpp +++ b/src/llvm_backend_proc.cpp @@ -2867,9 +2867,9 @@ lbValue lb_build_call_expr_internal(lbProcedure *p, Ast *expr) { return y; } - Ast *pexpr = unparen_expr(ce->proc); + Ast *proc_expr = unparen_expr(ce->proc); if (proc_mode == Addressing_Builtin) { - Entity *e = entity_of_node(pexpr); + Entity *e = entity_of_node(proc_expr); BuiltinProcId id = BuiltinProc_Invalid; if (e != nullptr) { id = cast(BuiltinProcId)e->Builtin.id; @@ -2881,7 +2881,6 @@ lbValue lb_build_call_expr_internal(lbProcedure *p, Ast *expr) { // NOTE(bill): Regular call lbValue value = {}; - Ast *proc_expr = unparen_expr(ce->proc); Entity *proc_entity = entity_of_node(proc_expr); if (proc_entity != nullptr) { From b82b91ea08696535d48decef8b993f53d47087af Mon Sep 17 00:00:00 2001 From: gingerBill Date: Thu, 1 Sep 2022 15:15:51 +0100 Subject: [PATCH 09/13] Fix #1974 by erring on untyped parameters to `intrinsics.objc_send` --- src/check_builtin.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/check_builtin.cpp b/src/check_builtin.cpp index e55a2e024..6af1c3d44 100644 --- a/src/check_builtin.cpp +++ b/src/check_builtin.cpp @@ -341,6 +341,13 @@ bool check_builtin_objc_procedure(CheckerContext *c, Operand *operand, Ast *call for (isize i = 2+arg_offset; i < ce->args.count; i++) { Operand x = {}; check_expr(c, &x, ce->args[i]); + if (is_type_untyped(x.type)) { + gbString e = expr_to_string(x.expr); + gbString t = type_to_string(x.type); + error(x.expr, "'%.*s' expects typed parameters, got %s of type %s", LIT(builtin_name), e, t); + gb_string_free(t); + gb_string_free(e); + } param_types[i-arg_offset] = x.type; } From 19ae6122c774d16c3b6cc851debf14a437e71e57 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Thu, 1 Sep 2022 16:11:03 +0100 Subject: [PATCH 10/13] Fix #2002 (allow `array *= matrix`) --- src/llvm_backend_stmt.cpp | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/src/llvm_backend_stmt.cpp b/src/llvm_backend_stmt.cpp index 175c4c537..9ea4ad34b 100644 --- a/src/llvm_backend_stmt.cpp +++ b/src/llvm_backend_stmt.cpp @@ -1959,8 +1959,18 @@ void lb_build_assign_stmt(lbProcedure *p, AstAssignStmt *as) { } else { lbAddr lhs = lb_build_addr(p, as->lhs[0]); lbValue value = lb_build_expr(p, as->rhs[0]); - Type *lhs_type = lb_addr_type(lhs); + + // NOTE(bill): Allow for the weird edge case of: + // array *= matrix + if (op == Token_Mul && is_type_matrix(value.type) && is_type_array(lhs_type)) { + lbValue old_value = lb_addr_load(p, lhs); + Type *type = old_value.type; + lbValue new_value = lb_emit_vector_mul_matrix(p, old_value, value, type); + lb_addr_store(p, lhs, new_value); + return; + } + if (is_type_array(lhs_type)) { lb_build_assign_stmt_array(p, op, lhs, value); return; From 902a6db0e1e5304e687dbf71ef2a099ed7c52cd7 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Thu, 1 Sep 2022 16:15:09 +0100 Subject: [PATCH 11/13] Fix #2000 - allow #soa array iteration by pointer --- src/llvm_backend_stmt.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/llvm_backend_stmt.cpp b/src/llvm_backend_stmt.cpp index 9ea4ad34b..a080fc09d 100644 --- a/src/llvm_backend_stmt.cpp +++ b/src/llvm_backend_stmt.cpp @@ -646,7 +646,7 @@ void lb_build_range_stmt_struct_soa(lbProcedure *p, AstRangeStmt *rs, Scope *sco lbAddr array = lb_build_addr(p, expr); - if (is_type_pointer(type_deref(lb_addr_type(array)))) { + if (is_type_pointer(lb_addr_type(array))) { array = lb_addr(lb_addr_load(p, array)); } lbValue count = lb_soa_struct_len(p, lb_addr_load(p, array)); From 3e3b9ae2df0e9892eb369c9ba92d017da4942c10 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Thu, 1 Sep 2022 16:33:44 +0100 Subject: [PATCH 12/13] Fix #1994 Returning to err: Maybe(Error) raises compiler 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 7d81d1407..023e7b363 100644 --- a/src/llvm_backend_expr.cpp +++ b/src/llvm_backend_expr.cpp @@ -1924,7 +1924,7 @@ lbValue lb_emit_conv(lbProcedure *p, lbValue value, Type *t) { } if (dst->Union.variants.count == 1) { Type *vt = dst->Union.variants[0]; - if (internal_check_is_assignable_to(src, vt)) { + if (internal_check_is_assignable_to(src_type, vt)) { value = lb_emit_conv(p, value, vt); lbAddr parent = lb_add_local_generated(p, t, true); lb_emit_store_union_variant(p, parent.addr, value, vt); From 36473b2774d8c6d08d2c1c73c5d35e3f58458cd9 Mon Sep 17 00:00:00 2001 From: Jeroen van Rijn Date: Thu, 1 Sep 2022 18:04:48 +0200 Subject: [PATCH 13/13] Add test for core:slice. --- tests/core/build.bat | 7 +- tests/core/slice/test_core_slice.odin | 97 +++++++++++++++++++++++++++ 2 files changed, 103 insertions(+), 1 deletion(-) create mode 100644 tests/core/slice/test_core_slice.odin diff --git a/tests/core/build.bat b/tests/core/build.bat index 77ff38038..94f8e0fd8 100644 --- a/tests/core/build.bat +++ b/tests/core/build.bat @@ -69,4 +69,9 @@ echo --- echo --- echo Running core:text/i18n tests echo --- -%PATH_TO_ODIN% run text\i18n %COMMON% -out:test_core_i18n.exe \ No newline at end of file +%PATH_TO_ODIN% run text\i18n %COMMON% -out:test_core_i18n.exe + +echo --- +echo Running core:slice tests +echo --- +%PATH_TO_ODIN% run slice %COMMON% -out:test_core_slice.exe \ No newline at end of file diff --git a/tests/core/slice/test_core_slice.odin b/tests/core/slice/test_core_slice.odin new file mode 100644 index 000000000..12577ab20 --- /dev/null +++ b/tests/core/slice/test_core_slice.odin @@ -0,0 +1,97 @@ +package test_core_slice + +import "core:slice" +import "core:testing" +import "core:fmt" +import "core:os" +import "core:math/rand" + +TEST_count := 0 +TEST_fail := 0 + +when ODIN_TEST { + expect :: testing.expect + log :: testing.log +} else { + expect :: proc(t: ^testing.T, condition: bool, message: string, loc := #caller_location) { + TEST_count += 1 + if !condition { + TEST_fail += 1 + fmt.printf("[%v] %v\n", loc, message) + return + } + } + log :: proc(t: ^testing.T, v: any, loc := #caller_location) { + fmt.printf("[%v] ", loc) + fmt.printf("log: %v\n", v) + } +} + +main :: proc() { + t := testing.T{} + test_sort_with_indices(&t) + + fmt.printf("%v/%v tests successful.\n", TEST_count - TEST_fail, TEST_count) + if TEST_fail > 0 { + os.exit(1) + } +} + +@test +test_sort_with_indices :: proc(t: ^testing.T) { + seed := rand.uint64() + fmt.printf("Random seed: %v\n", seed) + + // Test sizes are all prime. + test_sizes :: []int{7, 13, 347, 1031, 10111, 100003} + + for test_size in test_sizes { + fmt.printf("Sorting %v random u64 values along with index.\n", test_size) + + r := rand.create(seed) + + vals := make([]u64, test_size) + f_idx := make([]int, test_size) // Forward index, will be sorted + r_idx := make([]int, test_size) // Reverse index + + defer { + delete(vals) + delete(f_idx) + delete(r_idx) + } + + // Set up test values + for _, i in vals { + vals[i] = rand.uint64(&r) + f_idx[i] = i + } + + // Sort + slice.sort_with_indices(vals, f_idx) + + // Verify sorted test values + rand.init(&r, seed) + + for v, i in f_idx { + r_idx[v] = i + } + + last: u64 + for v, i in vals { + if i > 0 { + val_pass := v >= last + expect(t, val_pass, "Expected values to have been sorted.") + if !val_pass { + break + } + } + + idx_pass := vals[r_idx[i]] == rand.uint64(&r) + expect(t, idx_pass, "Expected index to have been sorted.") + if !idx_pass { + break + } + last = v + } + } +} \ No newline at end of file