From a43b89f36e988df8268ee92ea54017806b3226bb Mon Sep 17 00:00:00 2001 From: gingerBill Date: Sun, 29 Oct 2017 11:35:21 +0000 Subject: [PATCH] #alias type declarations; core library additions; `_global` import name for the global scope --- core/math.odin | 10 +- core/opengl_constants.odin | 24 +++++ core/os.odin | 14 ++- core/os_linux.odin | 2 +- core/os_windows.odin | 10 +- core/os_x.odin | 2 +- core/strings.odin | 10 +- core/sys/windows.odin | 201 +++++++++++++++++++++++++++++++++---- core/utf16.odin | 33 +++++- src/check_decl.cpp | 36 +++++-- src/check_expr.cpp | 19 +++- src/check_type.cpp | 6 ++ src/checker.cpp | 12 +++ src/entity.cpp | 1 + src/gb/gb.h | 2 +- src/ir.cpp | 10 +- src/ir_print.cpp | 3 + src/parser.cpp | 21 +++- 18 files changed, 367 insertions(+), 49 deletions(-) diff --git a/core/math.odin b/core/math.odin index a113bcd87..23586cce7 100644 --- a/core/math.odin +++ b/core/math.odin @@ -37,6 +37,13 @@ foreign __llvm_core { cos :: proc(θ: f32) -> f32 #link_name "llvm.cos.f32" ---; cos :: proc(θ: f64) -> f64 #link_name "llvm.cos.f64" ---; + // asin :: proc(x: f32) -> f32 #link_name "llvm.asin.f32" ---; + // asin :: proc(x: f64) -> f64 #link_name "llvm.asin.f64" ---; + + // acos :: proc(x: f32) -> f32 #link_name "llvm.acos.f32" ---; + // acos :: proc(x: f64) -> f64 #link_name "llvm.acos.f64" ---; + + pow :: proc(x, power: f32) -> f32 #link_name "llvm.pow.f32" ---; pow :: proc(x, power: f64) -> f64 #link_name "llvm.pow.f64" ---; @@ -47,9 +54,8 @@ foreign __llvm_core { tan :: proc(θ: f32) -> f32 #inline do return sin(θ)/cos(θ); tan :: proc(θ: f64) -> f64 #inline do return sin(θ)/cos(θ); +lerp :: proc(a, b: $T, t: $E) -> (x: T) do return a*(1-t) + b*t; -lerp :: proc(a, b, t: f32) -> (x: f32) do return a*(1-t) + b*t; -lerp :: proc(a, b, t: f64) -> (x: f64) do return a*(1-t) + b*t; unlerp :: proc(a, b, x: f32) -> (t: f32) do return (x-a)/(b-a); unlerp :: proc(a, b, x: f64) -> (t: f64) do return (x-a)/(b-a); diff --git a/core/opengl_constants.odin b/core/opengl_constants.odin index 31ed3e6aa..9b768409f 100644 --- a/core/opengl_constants.odin +++ b/core/opengl_constants.odin @@ -1381,3 +1381,27 @@ DEBUG_LOGGED_MESSAGES_ARB :: 0x9145; DEBUG_SEVERITY_HIGH_ARB :: 0x9146; DEBUG_SEVERITY_MEDIUM_ARB :: 0x9147; DEBUG_SEVERITY_LOW_ARB :: 0x9148; + + +SHADER_BINARY_FORMAT_SPIR_V :: 0x9551; +SPIR_V_BINARY :: 0x9552; +PARAMETER_BUFFER :: 0x80EE; +PARAMETER_BUFFER_BINDING :: 0x80EF; +CONTEXT_FLAG_NO_ERROR_BIT :: 0x00000008; +VERTICES_SUBMITTED :: 0x82EE; +PRIMITIVES_SUBMITTED :: 0x82EF; +VERTEX_SHADER_INVOCATIONS :: 0x82F0; +TESS_CONTROL_SHADER_PATCHES :: 0x82F1; +TESS_EVALUATION_SHADER_INVOCATIONS :: 0x82F2; +GEOMETRY_SHADER_PRIMITIVES_EMITTED :: 0x82F3; +FRAGMENT_SHADER_INVOCATIONS :: 0x82F4; +COMPUTE_SHADER_INVOCATIONS :: 0x82F5; +CLIPPING_INPUT_PRIMITIVES :: 0x82F6; +CLIPPING_OUTPUT_PRIMITIVES :: 0x82F7; +POLYGON_OFFSET_CLAMP :: 0x8E1B; +SPIR_V_EXTENSIONS :: 0x9553; +NUM_SPIR_V_EXTENSIONS :: 0x9554; +TEXTURE_MAX_ANISOTROPY :: 0x84FE; +MAX_TEXTURE_MAX_ANISOTROPY :: 0x84FF; +TRANSFORM_FEEDBACK_OVERFLOW :: 0x82EC; +TRANSFORM_FEEDBACK_STREAM_OVERFLOW :: 0x82ED; diff --git a/core/os.odin b/core/os.odin index a2a75f83a..f982dd270 100644 --- a/core/os.odin +++ b/core/os.odin @@ -2,6 +2,8 @@ when ODIN_OS == "windows" do export "core:os_windows.odin"; when ODIN_OS == "osx" do export "core:os_x.odin"; when ODIN_OS == "linux" do export "core:os_linux.odin"; +import "mem.odin"; + write_string :: proc(fd: Handle, str: string) -> (int, Errno) { return write(fd, cast([]u8)str); } @@ -35,8 +37,8 @@ read_entire_file :: proc(name: string) -> (data: []u8, success: bool) { return data[0..bytes_read], true; } -write_entire_file :: proc(name: string, data: []u8) -> (sucess: bool) { - fd, err := open(name, O_WRONLY|O_CREAT, 0); +write_entire_file :: proc(name: string, data: []u8) -> (success: bool) { + fd, err := open(name, O_WRONLY|O_CREATE, 0); if err != 0 { return false; } @@ -45,3 +47,11 @@ write_entire_file :: proc(name: string, data: []u8) -> (sucess: bool) { bytes_written, write_err := write(fd, data); return write_err != 0; } + +write :: proc(fd: Handle, data: rawptr, len: int) -> (int, Errno) { + return write(fd, mem.slice_ptr(cast(^u8)data, len)); +} + +read :: proc(fd: Handle, data: rawptr, len: int) -> (int, Errno) { + return read(fd, mem.slice_ptr(cast(^u8)data, len)); +} diff --git a/core/os_linux.odin b/core/os_linux.odin index 0a7c6a6c9..d3af6e48d 100644 --- a/core/os_linux.odin +++ b/core/os_linux.odin @@ -12,7 +12,7 @@ Errno :: i32; O_RDONLY :: 0x00000; O_WRONLY :: 0x00001; O_RDWR :: 0x00002; -O_CREAT :: 0x00040; +O_CREATE :: 0x00040; O_EXCL :: 0x00080; O_NOCTTY :: 0x00100; O_TRUNC :: 0x00200; diff --git a/core/os_windows.odin b/core/os_windows.odin index e8b22a0e4..9910a0b75 100644 --- a/core/os_windows.odin +++ b/core/os_windows.odin @@ -12,7 +12,7 @@ INVALID_HANDLE: Handle : -1; O_RDONLY :: 0x00000; O_WRONLY :: 0x00001; O_RDWR :: 0x00002; -O_CREAT :: 0x00040; +O_CREATE :: 0x00040; O_EXCL :: 0x00080; O_NOCTTY :: 0x00100; O_TRUNC :: 0x00200; @@ -66,7 +66,7 @@ open :: proc(path: string, mode: int = O_RDONLY, perm: u32 = 0) -> (Handle, Errn case O_RDWR: access = win32.FILE_GENERIC_READ | win32.FILE_GENERIC_WRITE; } - if mode&O_CREAT != 0 { + if mode&O_CREATE != 0 { access |= win32.FILE_GENERIC_WRITE; } if mode&O_APPEND != 0 { @@ -83,11 +83,11 @@ open :: proc(path: string, mode: int = O_RDONLY, perm: u32 = 0) -> (Handle, Errn create_mode: u32; switch { - case mode&(O_CREAT|O_EXCL) == (O_CREAT | O_EXCL): + case mode&(O_CREATE|O_EXCL) == (O_CREATE | O_EXCL): create_mode = win32.CREATE_NEW; - case mode&(O_CREAT|O_TRUNC) == (O_CREAT | O_TRUNC): + case mode&(O_CREATE|O_TRUNC) == (O_CREATE | O_TRUNC): create_mode = win32.CREATE_ALWAYS; - case mode&O_CREAT == O_CREAT: + case mode&O_CREATE == O_CREATE: create_mode = win32.OPEN_ALWAYS; case mode&O_TRUNC == O_TRUNC: create_mode = win32.TRUNCATE_EXISTING; diff --git a/core/os_x.odin b/core/os_x.odin index e0612d459..eba27fff2 100644 --- a/core/os_x.odin +++ b/core/os_x.odin @@ -12,7 +12,7 @@ Errno :: int; O_RDONLY :: 0x00000; O_WRONLY :: 0x00001; O_RDWR :: 0x00002; -O_CREAT :: 0x00040; +O_CREATE :: 0x00040; O_EXCL :: 0x00080; O_NOCTTY :: 0x00100; O_TRUNC :: 0x00200; diff --git a/core/strings.odin b/core/strings.odin index e51fcb345..f8697e46e 100644 --- a/core/strings.odin +++ b/core/strings.odin @@ -14,9 +14,9 @@ new_c_string :: proc(s: string) -> ^u8 { return &c[0]; } -to_odin_string :: proc(c: ^u8) -> string { - if c == nil do return ""; - len := 0; - for (c+len)^ != 0 do len+=1; - return string(mem.slice_ptr(c, len)); +to_odin_string :: proc(str: ^u8) -> string { + if str == nil do return ""; + end := str; + for end^ != 0 do end+=1; + return string(mem.slice_ptr(str, end-str)); } diff --git a/core/sys/windows.odin b/core/sys/windows.odin index d597d95c0..1f4751029 100644 --- a/core/sys/windows.odin +++ b/core/sys/windows.odin @@ -17,11 +17,15 @@ Hbrush :: Handle; Hgdiobj :: Handle; Hmodule :: Handle; Hmonitor :: Handle; +Hrawinput :: Handle; +HKL :: Handle; Wparam :: uint; Lparam :: int; Lresult :: int; Wnd_Proc :: proc(Hwnd, u32, Wparam, Lparam) -> Lresult #cc_c; +Long_Ptr :: int; + Bool :: i32; FALSE: Bool : 0; TRUE: Bool : 1; @@ -42,6 +46,19 @@ Wnd_Class_Ex_A :: struct #ordered { sm: Hicon, } +Wnd_Class_Ex_W :: struct #ordered { + size, style: u32, + wnd_proc: Wnd_Proc, + cls_extra, wnd_extra: i32, + instance: Hinstance, + icon: Hicon, + cursor: Hcursor, + background: Hbrush, + menu_name, class_name: ^u16, + sm: Hicon, +} + + Msg :: struct #ordered { hwnd: Hwnd, message: u32, @@ -167,6 +184,59 @@ Critical_Section_Debug :: struct #ordered { List_Entry :: struct #ordered {flink, blink: ^List_Entry}; +Raw_Input_Device :: struct #ordered { + usage_page: u16, + usage: u16, + flags: u32, + wnd_target: Hwnd, +} + +Raw_Input_Header :: struct #ordered { + kind: u32, + size: u32, + device: Handle, + wparam: Wparam, +} + +Raw_HID :: struct #ordered { + size_hid: u32, + count: u32, + raw_data: [1]u8, +} + +Raw_Keyboard :: struct #ordered { + make_code: u16, + flags: u16, + reserved: u16, + vkey: u16, + message: u32, + extra_information: u32, +} + +Raw_Mouse :: struct #ordered { + flags: u16, + using data: struct #raw_union { + buttons: u32, + using _: struct #ordered { + button_flags: u16, + button_data: u16, + }, + }, + raw_buttons: u32, + last_x: i32, + last_y: i32, + extra_information: u32, +} + +Raw_Input :: struct #ordered { + using header: Raw_Input_Header, + data: struct #raw_union { + mouse: Raw_Mouse, + keyboard: Raw_Keyboard, + hid: Raw_HID, + }, +} + MAPVK_VK_TO_VSC :: 0; MAPVK_VSC_TO_VK :: 1; @@ -199,26 +269,30 @@ WS_BORDER :: 0x00800000; WS_CAPTION :: 0x00C00000; WS_VISIBLE :: 0x10000000; WS_POPUP :: 0x80000000; +WS_MAXIMIZE :: 0x01000000; +WS_MINIMIZE :: 0x20000000; WS_OVERLAPPEDWINDOW :: WS_OVERLAPPED|WS_CAPTION|WS_SYSMENU|WS_THICKFRAME|WS_MINIMIZEBOX|WS_MAXIMIZEBOX; WS_POPUPWINDOW :: WS_POPUP | WS_BORDER | WS_SYSMENU; -WM_DESTROY :: 0x0002; -WM_SIZE :: 0x0005; -WM_CLOSE :: 0x0010; +WM_ACTIVATE :: 0x0006; WM_ACTIVATEAPP :: 0x001C; -WM_QUIT :: 0x0012; +WM_CHAR :: 0x0102; +WM_CLOSE :: 0x0010; +WM_CREATE :: 0x0001; +WM_DESTROY :: 0x0002; +WM_INPUT :: 0x00ff; WM_KEYDOWN :: 0x0100; WM_KEYUP :: 0x0101; +WM_KILLFOCUS :: 0x0008; +WM_QUIT :: 0x0012; +WM_SETCURSOR :: 0x0020; +WM_SETFOCUS :: 0x0007; +WM_SIZE :: 0x0005; WM_SIZING :: 0x0214; WM_SYSKEYDOWN :: 0x0104; WM_SYSKEYUP :: 0x0105; -WM_WINDOWPOSCHANGED :: 0x0047; -WM_SETCURSOR :: 0x0020; -WM_CHAR :: 0x0102; -WM_ACTIVATE :: 0x0006; -WM_SETFOCUS :: 0x0007; -WM_KILLFOCUS :: 0x0008; WM_USER :: 0x0400; +WM_WINDOWPOSCHANGED :: 0x0047; WM_MOUSEWHEEL :: 0x020A; WM_MOUSEMOVE :: 0x0200; @@ -248,7 +322,12 @@ COLOR_BACKGROUND :: Hbrush(int(1)); INVALID_SET_FILE_POINTER :: ~u32(0); HEAP_ZERO_MEMORY :: 0x00000008; INFINITE :: 0xffffffff; +GWL_EXSTYLE :: -20; +GWLP_HINSTANCE :: -6; +GWLP_ID :: -12; GWL_STYLE :: -16; +GWLP_USERDATA :: -21; +GWLP_WNDPROC :: -4; Hwnd_TOP :: Hwnd(uint(0)); BI_RGB :: 0; @@ -267,8 +346,63 @@ SWP_NOSIZE :: 0x0001; SWP_NOMOVE :: 0x0002; +// Raw Input +RID_HEADER :: 0x10000005; +RID_INPUT :: 0x10000003; + + +RIDEV_APPKEYS :: 0x00000400; +RIDEV_CAPTUREMOUSE :: 0x00000200; +RIDEV_DEVNOTIFY :: 0x00002000; +RIDEV_EXCLUDE :: 0x00000010; +RIDEV_EXINPUTSINK :: 0x00001000; +RIDEV_INPUTSINK :: 0x00000100; +RIDEV_NOHOTKEYS :: 0x00000200; +RIDEV_NOLEGACY :: 0x00000030; +RIDEV_PAGEONLY :: 0x00000020; +RIDEV_REMOVE :: 0x00000001; + + +RIM_TYPEMOUSE :: 0; +RIM_TYPEKEYBOARD :: 1; +RIM_TYPEHID :: 2; + + +MOUSE_ATTRIBUTES_CHANGED :: 0x04; +MOUSE_MOVE_RELATIVE :: 0; +MOUSE_MOVE_ABSOLUTE :: 1; +MOUSE_VIRTUAL_DESKTOP :: 0x02; + + + +RI_MOUSE_BUTTON_1_DOWN :: 0x0001; +RI_MOUSE_BUTTON_1_UP :: 0x0002; +RI_MOUSE_BUTTON_2_DOWN :: 0x0004; +RI_MOUSE_BUTTON_2_UP :: 0x0008; +RI_MOUSE_BUTTON_3_DOWN :: 0x0010; +RI_MOUSE_BUTTON_3_UP :: 0x0020; +RI_MOUSE_BUTTON_4_DOWN :: 0x0040; +RI_MOUSE_BUTTON_4_UP :: 0x0080; +RI_MOUSE_BUTTON_5_DOWN :: 0x0100; +RI_MOUSE_BUTTON_5_UP :: 0x0200; +RI_MOUSE_LEFT_BUTTON_DOWN :: 0x0001; +RI_MOUSE_LEFT_BUTTON_UP :: 0x0002; +RI_MOUSE_MIDDLE_BUTTON_DOWN :: 0x0010; +RI_MOUSE_MIDDLE_BUTTON_UP :: 0x0020; +RI_MOUSE_RIGHT_BUTTON_DOWN :: 0x0004; +RI_MOUSE_RIGHT_BUTTON_UP :: 0x0008; +RI_MOUSE_WHEEL :: 0x0400; + + +RI_KEY_MAKE :: 0x00; +RI_KEY_BREAK :: 0x01; +RI_KEY_E0 :: 0x02; +RI_KEY_E1 :: 0x04; +RI_KEY_TERMSRV_SET_LED :: 0x08; +RI_KEY_TERMSRV_SHADOW :: 0x10; + // Windows OpenGL PFD_TYPE_RGBA :: 0; @@ -302,6 +436,7 @@ foreign kernel32 { get_last_error :: proc() -> i32 #cc_std #link_name "GetLastError" ---; exit_process :: proc(exit_code: u32) #cc_std #link_name "ExitProcess" ---; get_module_handle_a :: proc(module_name: ^u8) -> Hinstance #cc_std #link_name "GetModuleHandleA" ---; + get_module_handle_w :: proc(module_name: ^u16) -> Hinstance #cc_std #link_name "GetModuleHandleW" ---; sleep :: proc(ms: i32) -> i32 #cc_std #link_name "Sleep" ---; query_performance_frequency :: proc(result: ^i64) -> i32 #cc_std #link_name "QueryPerformanceFrequency" ---; query_performance_counter :: proc(result: ^i64) -> i32 #cc_std #link_name "QueryPerformanceCounter" ---; @@ -394,11 +529,14 @@ foreign kernel32 { foreign user32 { get_desktop_window :: proc() -> Hwnd #cc_std #link_name "GetDesktopWindow" ---; show_cursor :: proc(show : Bool) #cc_std #link_name "ShowCursor" ---; - get_cursor_pos :: proc(p: ^Point) -> i32 #cc_std #link_name "GetCursorPos" ---; - screen_to_client :: proc(h: Hwnd, p: ^Point) -> i32 #cc_std #link_name "ScreenToClient" ---; + get_cursor_pos :: proc(p: ^Point) -> Bool #cc_std #link_name "GetCursorPos" ---; + set_cursor_pos :: proc(x, y: i32) -> Bool #cc_std #link_name "SetCursorPos" ---; + screen_to_client :: proc(h: Hwnd, p: ^Point) -> Bool #cc_std #link_name "ScreenToClient" ---; + client_to_screen :: proc(h: Hwnd, p: ^Point) -> Bool #cc_std #link_name "ClientToScreen" ---; post_quit_message :: proc(exit_code: i32) #cc_std #link_name "PostQuitMessage" ---; set_window_text_a :: proc(hwnd: Hwnd, c_string: ^u8) -> Bool #cc_std #link_name "SetWindowTextA" ---; register_class_ex_a :: proc(wc: ^Wnd_Class_Ex_A) -> i16 #cc_std #link_name "RegisterClassExA" ---; + register_class_ex_w :: proc(wc: ^Wnd_Class_Ex_W) -> i16 #cc_std #link_name "RegisterClassExW" ---; create_window_ex_a :: proc(ex_style: u32, class_name, title: ^u8, @@ -407,13 +545,24 @@ foreign user32 { parent: Hwnd, menu: Hmenu, instance: Hinstance, param: rawptr) -> Hwnd #cc_std #link_name "CreateWindowExA" ---; + create_window_ex_w :: proc(ex_style: u32, + class_name, title: ^u16, + style: u32, + x, y, w, h: i32, + parent: Hwnd, menu: Hmenu, instance: Hinstance, + param: rawptr) -> Hwnd #cc_std #link_name "CreateWindowExW" ---; + show_window :: proc(hwnd: Hwnd, cmd_show: i32) -> Bool #cc_std #link_name "ShowWindow" ---; translate_message :: proc(msg: ^Msg) -> Bool #cc_std #link_name "TranslateMessage" ---; dispatch_message_a :: proc(msg: ^Msg) -> Lresult #cc_std #link_name "DispatchMessageA" ---; + dispatch_message_w :: proc(msg: ^Msg) -> Lresult #cc_std #link_name "DispatchMessageW" ---; update_window :: proc(hwnd: Hwnd) -> Bool #cc_std #link_name "UpdateWindow" ---; get_message_a :: proc(msg: ^Msg, hwnd: Hwnd, msg_filter_min, msg_filter_max : u32) -> Bool #cc_std #link_name "GetMessageA" ---; + get_message_w :: proc(msg: ^Msg, hwnd: Hwnd, msg_filter_min, msg_filter_max : u32) -> Bool #cc_std #link_name "GetMessageW" ---; peek_message_a :: proc(msg: ^Msg, hwnd: Hwnd, - msg_filter_min, msg_filter_max, remove_msg: u32) -> Bool #cc_std #link_name "PeekMessageA" ---; + msg_filter_min, msg_filter_max, remove_msg: u32) -> Bool #cc_std #link_name "PeekMessageA" ---; + peek_message_w :: proc(msg: ^Msg, hwnd: Hwnd, + msg_filter_min, msg_filter_max, remove_msg: u32) -> Bool #cc_std #link_name "PeekMessageW" ---; post_message :: proc(hwnd: Hwnd, msg, wparam, lparam : u32) -> Bool #cc_std #link_name "PostMessageA" ---; @@ -435,8 +584,10 @@ foreign user32 { set_window_placement :: proc(wnd: Hwnd, wndpl: ^Window_Placement) -> Bool #cc_std #link_name "SetWindowPlacement" ---; get_window_rect :: proc(wnd: Hwnd, rect: ^Rect) -> Bool #cc_std #link_name "GetWindowRect" ---; - get_window_long_ptr_a :: proc(wnd: Hwnd, index: i32) -> i64 #cc_std #link_name "GetWindowLongPtrA" ---; - set_window_long_ptr_a :: proc(wnd: Hwnd, index: i32, new: i64) -> i64 #cc_std #link_name "SetWindowLongPtrA" ---; + get_window_long_ptr_a :: proc(wnd: Hwnd, index: i32) -> Long_Ptr #cc_std #link_name "GetWindowLongPtrA" ---; + set_window_long_ptr_a :: proc(wnd: Hwnd, index: i32, new: Long_Ptr) -> Long_Ptr #cc_std #link_name "SetWindowLongPtrA" ---; + get_window_long_ptr_w :: proc(wnd: Hwnd, index: i32) -> Long_Ptr #cc_std #link_name "GetWindowLongPtrW" ---; + set_window_long_ptr_w :: proc(wnd: Hwnd, index: i32, new: Long_Ptr) -> Long_Ptr #cc_std #link_name "SetWindowLongPtrW" ---; get_window_text :: proc(wnd: Hwnd, str: ^u8, maxCount: i32) -> i32 #cc_std #link_name "GetWindowText" ---; @@ -445,10 +596,23 @@ foreign user32 { get_dc :: proc(h: Hwnd) -> Hdc #cc_std #link_name "GetDC" ---; release_dc :: proc(wnd: Hwnd, hdc: Hdc) -> i32 #cc_std #link_name "ReleaseDC" ---; - map_virtual_key :: proc(scancode : u32, map_type : u32) -> u32 #cc_std #link_name "MapVirtualKeyA" ---; + map_virtual_key_a :: proc(scancode : u32, map_type : u32) -> u32 #cc_std #link_name "MapVirtualKeyA" ---; + map_virtual_key_w :: proc(scancode : u32, map_type : u32) -> u32 #cc_std #link_name "MapVirtualKeyW" ---; get_key_state :: proc(v_key: i32) -> i16 #cc_std #link_name "GetKeyState" ---; get_async_key_state :: proc(v_key: i32) -> i16 #cc_std #link_name "GetAsyncKeyState" ---; + + set_foreground_window :: proc(h: Hwnd) -> Bool #cc_std #link_name "SetForegroundWindow" ---; + set_focus :: proc(h: Hwnd) -> Hwnd #cc_std #link_name "SetFocus" ---; + + + + register_raw_input_devices :: proc(raw_input_device: ^Raw_Input_Device, num_devices, size: u32) -> Bool #cc_std #link_name "RegisterRawInputDevices" ---; + + get_raw_input_data :: proc(raw_input: Hrawinput, command: u32, data: rawptr, size: ^u32, size_header: u32) -> u32 #cc_std #link_name "GetRawInputData" ---; + + map_virtual_key_ex_w :: proc(code, map_type: u32, hkl: HKL) #cc_std #link_name "MapVirtualKeyExW" ---; + map_virtual_key_ex_a :: proc(code, map_type: u32, hkl: HKL) #cc_std #link_name "MapVirtualKeyExA" ---; } foreign gdi32 { @@ -493,7 +657,6 @@ is_key_down :: proc(key: Key_Code) -> bool #inline { return get_async_key_state( - MAX_PATH :: 0x00000104; HANDLE_FLAG_INHERIT :: 1; @@ -582,10 +745,14 @@ Rgb_Quad :: struct #ordered {blue, green, red, reserved: u8} Key_Code :: enum i32 { + Unknown = 0x00, + Lbutton = 0x01, Rbutton = 0x02, Cancel = 0x03, Mbutton = 0x04, + Xbutton1 = 0x05, + Xbutton2 = 0x06, Back = 0x08, Tab = 0x09, Clear = 0x0C, diff --git a/core/utf16.odin b/core/utf16.odin index b8caededd..762079c1e 100644 --- a/core/utf16.odin +++ b/core/utf16.odin @@ -1,3 +1,5 @@ +import "utf8.odin" + REPLACEMENT_CHAR :: '\uFFFD'; MAX_RUNE :: '\U0010FFFF'; @@ -27,7 +29,7 @@ encode_surrogate_pair :: proc(r: rune) -> (r1, r2: rune) { return _surr1 + (r>>10)&0x3ff, _surr2 + r&0x3ff; } -encode :: proc(d: []u16, s: []rune) { +encode :: proc(d: []u16, s: []rune) -> int { n := len(s); for r in s do if r >= _surr_self do n += 1; @@ -51,4 +53,33 @@ encode :: proc(d: []u16, s: []rune) { n += 1; } } + return n; +} + + +encode :: proc(d: []u16, s: string) -> int { + n := utf8.rune_count(s); + for r in s do if r >= _surr_self do n += 1; + + max_n := min(len(d), n); + n = 0; + + for r in s { + switch r { + case 0.._surr1, _surr3.._surr_self: + d[n] = u16(r); + n += 1; + + case _surr_self..MAX_RUNE: + r1, r2 := encode_surrogate_pair(r); + d[n] = u16(r1); + d[n+1] = u16(r2); + n += 2; + + case: + d[n] = u16(REPLACEMENT_CHAR); + n += 1; + } + } + return n; } diff --git a/src/check_decl.cpp b/src/check_decl.cpp index 121c10774..0baf43349 100644 --- a/src/check_decl.cpp +++ b/src/check_decl.cpp @@ -170,8 +170,26 @@ void check_init_constant(Checker *c, Entity *e, Operand *operand) { e->Constant.value = operand->value; } -void check_type_decl(Checker *c, Entity *e, AstNode *type_expr, Type *def) { +AstNode *remove_type_alias(AstNode *node) { + for (;;) { + if (node == nullptr) { + return nullptr; + } + if (node->kind == AstNode_ParenExpr) { + node = node->ParenExpr.expr; + } else if (node->kind == AstNode_AliasType) { + node = node->AliasType.type; + } else { + return node; + } + } +} + +void check_type_decl(Checker *c, Entity *e, AstNode *type_expr, Type *def, bool is_alias) { GB_ASSERT(e->type == nullptr); + AstNode *te = remove_type_alias(type_expr); + + e->type = t_invalid; String name = e->token.string; Type *named = make_type_named(c->allocator, name, nullptr, e); named->Named.type_name = e; @@ -180,12 +198,14 @@ void check_type_decl(Checker *c, Entity *e, AstNode *type_expr, Type *def) { } e->type = named; - // gb_printf_err("%.*s %p\n", LIT(e->token.string), e); - - Type *bt = check_type(c, type_expr, named); + Type *bt = check_type(c, te, named); named->Named.base = base_type(bt); - if (named->Named.base == t_invalid) { - // gb_printf("check_type_decl: %s\n", type_to_string(named)); + if (is_alias) { + if (is_type_named(bt)) { + e->type = bt; + } else { + warning(type_expr, "Type declaration will not be an alias type"); + } } } @@ -232,7 +252,7 @@ void check_const_decl(Checker *c, Entity *e, AstNode *type_expr, AstNode *init, error(e->token, "A type declaration cannot have an type parameter"); } d->type_expr = d->init_expr; - check_type_decl(c, e, d->type_expr, named_type); + check_type_decl(c, e, d->type_expr, named_type, false); return; } @@ -673,7 +693,7 @@ void check_entity_decl(Checker *c, Entity *e, DeclInfo *d, Type *named_type) { check_const_decl(c, e, d->type_expr, d->init_expr, named_type); break; case Entity_TypeName: - check_type_decl(c, e, d->type_expr, named_type); + check_type_decl(c, e, d->type_expr, named_type, d->type_expr->kind == AstNode_AliasType); break; case Entity_Procedure: check_proc_decl(c, e, d); diff --git a/src/check_expr.cpp b/src/check_expr.cpp index cdce6297a..2f3bc4fdf 100644 --- a/src/check_expr.cpp +++ b/src/check_expr.cpp @@ -57,7 +57,7 @@ ExprKind check_expr_base (Checker *c, Operand *operand, AstNode * void check_expr_with_type_hint (Checker *c, Operand *o, AstNode *e, Type *t); Type * check_type (Checker *c, AstNode *expression, Type *named_type = nullptr); Type * make_optional_ok_type(gbAllocator a, Type *value); -void check_type_decl (Checker *c, Entity *e, AstNode *type_expr, Type *def); +void check_type_decl (Checker *c, Entity *e, AstNode *type_expr, Type *def, bool alias); Entity * check_selector (Checker *c, Operand *operand, AstNode *node, Type *type_hint); Entity * check_ident (Checker *c, Operand *o, AstNode *n, Type *named_type, Type *type_hint, bool allow_import_name); Entity * find_polymorphic_struct_entity(Checker *c, Type *original_type, isize param_count, Array ordered_operands); @@ -1421,6 +1421,14 @@ void check_unary_expr(Checker *c, Operand *o, Token op, AstNode *node) { if (is_type_unsigned(type)) { precision = cast(i32)(8 * type_size_of(c->allocator, type)); } + if (op.kind == Token_Xor && is_type_untyped(type)) { + gbString err_str = expr_to_string(node); + error(op, "Bitwise not cannot be applied to untyped constants `%s`", err_str); + gb_string_free(err_str); + o->mode = Addressing_Invalid; + return; + } + o->value = exact_unary_operator_value(op.kind, o->value, precision); if (is_type_typed(type)) { @@ -5353,7 +5361,7 @@ ExprKind check_expr_base_internal(Checker *c, Operand *o, AstNode *node, Type *t for_array(i, cl->elems) { AstNode *elem = cl->elems[i]; if (elem->kind != AstNode_FieldValue) { - error(elem, "Mixture of `field = value` and value elements in a structure literal is not allowed"); + error(elem, "Mixture of `field = value` and value elements in a literal is not allowed"); continue; } ast_node(fv, FieldValue, elem); @@ -5416,7 +5424,7 @@ ExprKind check_expr_base_internal(Checker *c, Operand *o, AstNode *node, Type *t for_array(index, cl->elems) { AstNode *elem = cl->elems[index]; if (elem->kind == AstNode_FieldValue) { - error(elem, "Mixture of `field = value` and value elements in a structure literal is not allowed"); + error(elem, "Mixture of `field = value` and value elements in a literal is not allowed"); continue; } if (index >= field_count) { @@ -6316,6 +6324,11 @@ gbString write_expr_to_string(gbString str, AstNode *node) { str = write_expr_to_string(str, ht->type); case_end; + case_ast_node(ht, AliasType, node); + str = gb_string_appendc(str, "#alias "); + str = write_expr_to_string(str, ht->type); + case_end; + case_ast_node(pt, PolyType, node); str = gb_string_append_rune(str, '$'); diff --git a/src/check_type.cpp b/src/check_type.cpp index e6cddf62e..95b876ef8 100644 --- a/src/check_type.cpp +++ b/src/check_type.cpp @@ -2131,6 +2131,12 @@ bool check_type_internal(Checker *c, AstNode *e, Type **type, Type *named_type) return check_type_internal(c, ht->type, type, named_type); case_end; + case_ast_node(at, AliasType, e); + error(e, "Invalid use of `#alias`"); + // NOTE(bill): Treat it as a HelperType to remove errors + return check_type_internal(c, at->type, type, named_type); + case_end; + case_ast_node(pt, PolyType, e); AstNode *ident = pt->type; if (ident->kind != AstNode_Ident) { diff --git a/src/checker.cpp b/src/checker.cpp index f78249b2f..d6bbf754d 100644 --- a/src/checker.cpp +++ b/src/checker.cpp @@ -1716,7 +1716,19 @@ void init_preload(Checker *c) { t_map_header = e->type; } + + { + String _global = str_lit("_global"); + + Entity *e = make_entity_import_name(c->allocator, c->global_scope->parent, make_token_ident(_global), t_invalid, + str_lit(""), _global, + c->global_scope); + + add_entity(c, c->global_scope, nullptr, e); + } + c->done_preload = true; + } diff --git a/src/entity.cpp b/src/entity.cpp index e03adeab8..de0922650 100644 --- a/src/entity.cpp +++ b/src/entity.cpp @@ -156,6 +156,7 @@ bool is_entity_exported(Entity *e) { return name[0] != '_'; } + gb_global u64 global_entity_id = 0; Entity *alloc_entity(gbAllocator a, EntityKind kind, Scope *scope, Token token, Type *type) { diff --git a/src/gb/gb.h b/src/gb/gb.h index 48da7ae41..dfd701b8d 100644 --- a/src/gb/gb.h +++ b/src/gb/gb.h @@ -7954,7 +7954,7 @@ gbFileTime gb_file_last_write_time(char const *filepath) { time_t result = 0; struct stat file_stat; - if (stat(filepath, &file_stat)) { + if (stat(filepath, &file_stat) == 0) { result = file_stat.st_mtime; } diff --git a/src/ir.cpp b/src/ir.cpp index 853960d08..9b018a2ea 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -119,6 +119,7 @@ struct irProcedure { u64 tags; bool is_foreign; bool is_export; + bool is_entry_point; irValue * return_ptr; Array params; @@ -3743,6 +3744,12 @@ void ir_check_type_and_gen_for_proc_lit(irModule *m, String prefix_name, Type *t void ir_gen_global_type_name(irModule *m, Entity *e, String name) { if (e->type == nullptr) return; + if (e->kind == Entity_TypeName && e->type->kind == Type_Named) { + if (e != e->type->Named.type_name) { + // NOTE(bill): Is alias + return; + } + } Type *bt = base_type(e->type); @@ -8267,7 +8274,6 @@ void ir_gen_tree(irGen *s) { switch (e->kind) { case Entity_TypeName: - GB_ASSERT(e->type->kind == Type_Named); ir_gen_global_type_name(m, e, name); break; @@ -8374,6 +8380,7 @@ void ir_gen_tree(irGen *s) { irProcedure *proc = &p->Proc; proc->tags = ProcTag_no_inline; // TODO(bill): is no_inline a good idea? + proc->is_entry_point = true; e->Procedure.link_name = name; ir_begin_procedure_body(proc); @@ -8444,6 +8451,7 @@ void ir_gen_tree(irGen *s) { irProcedure *proc = &p->Proc; proc->tags = ProcTag_no_inline; // TODO(bill): is no_inline a good idea? + proc->is_entry_point = true; e->Procedure.link_name = name; ir_begin_procedure_body(proc); diff --git a/src/ir_print.cpp b/src/ir_print.cpp index f60764b94..edf2665c7 100644 --- a/src/ir_print.cpp +++ b/src/ir_print.cpp @@ -1678,6 +1678,9 @@ void ir_print_proc(irFileBuffer *f, irModule *m, irProcedure *proc) { ir_write_string(f, "dllexport "); } } + // if (!proc->is_export && !proc->is_foreign && !proc->is_entry_point) { + // ir_write_string(f, "internal "); + // } } TypeProc *proc_type = &proc->type->Proc; diff --git a/src/parser.cpp b/src/parser.cpp index 56e768bc3..94a4e7585 100644 --- a/src/parser.cpp +++ b/src/parser.cpp @@ -407,6 +407,10 @@ AST_NODE_KIND(_TypeBegin, "", i32) \ Token token; \ AstNode *type; \ }) \ + AST_NODE_KIND(AliasType, "alias type", struct { \ + Token token; \ + AstNode *type; \ + }) \ AST_NODE_KIND(PolyType, "polymorphic type", struct { \ Token token; \ AstNode *type; \ @@ -611,6 +615,7 @@ Token ast_node_token(AstNode *node) { case AstNode_TypeType: return node->TypeType.token; case AstNode_HelperType: return node->HelperType.token; + case AstNode_AliasType: return node->AliasType.token; case AstNode_PolyType: return node->PolyType.token; case AstNode_ProcType: return node->ProcType.token; case AstNode_PointerType: return node->PointerType.token; @@ -857,6 +862,9 @@ AstNode *clone_ast_node(gbAllocator a, AstNode *node) { case AstNode_HelperType: n->HelperType.type = clone_ast_node(a, n->HelperType.type); break; + case AstNode_AliasType: + n->AliasType.type = clone_ast_node(a, n->AliasType.type); + break; case AstNode_ProcType: n->ProcType.params = clone_ast_node(a, n->ProcType.params); n->ProcType.results = clone_ast_node(a, n->ProcType.results); @@ -1411,6 +1419,13 @@ AstNode *ast_helper_type(AstFile *f, Token token, AstNode *type) { return result; } +AstNode *ast_alias_type(AstFile *f, Token token, AstNode *type) { + AstNode *result = make_ast_node(f, AstNode_AliasType); + result->AliasType.token = token; + result->AliasType.type = type; + return result; +} + AstNode *ast_poly_type(AstFile *f, Token token, AstNode *type, AstNode *specialization) { AstNode *result = make_ast_node(f, AstNode_PolyType); @@ -2256,8 +2271,10 @@ AstNode *parse_operand(AstFile *f, bool lhs) { if (allow_token(f, Token_type)) { return ast_helper_type(f, token, parse_type(f)); } - Token name = expect_token(f, Token_Ident); - if (name.string == "run") { + Token name = expect_token(f, Token_Ident); + if (name.string == "alias") { + return ast_alias_type(f, token, parse_type(f)); + } else if (name.string == "run") { AstNode *expr = parse_expr(f, false); operand = ast_run_expr(f, token, name, expr); if (unparen_expr(expr)->kind != AstNode_CallExpr) {