From f388e3f91590769a28361b78ec9d7c679f839bfa Mon Sep 17 00:00:00 2001 From: Krzosa Karol Date: Tue, 27 Sep 2022 22:42:46 +0200 Subject: [PATCH] Begin raymarcher example and math module, fixing parsing bugs --- core_main.cpp | 15 +- core_parsing.cpp | 4 +- core_typechecking.cpp | 3 +- .../drawing_to_screen_using_windows_api.kl | 2 +- examples/raymarcher.kl | 164 ++++++++++++++++++ modules/math.kl | 64 +++++++ modules/os_windows.kl | 1 + 7 files changed, 244 insertions(+), 9 deletions(-) create mode 100644 examples/raymarcher.kl create mode 100644 modules/math.kl diff --git a/core_main.cpp b/core_main.cpp index 7e3f226..b5151ce 100644 --- a/core_main.cpp +++ b/core_main.cpp @@ -57,7 +57,6 @@ For modules it's a bit different cause they should be distributed as valid. ------------------------------------------------------------------------------- - [ ] Basic - - [ ] Calculate size and alignment of struct data types - [ ] Pass size and alignment calculations to C ? - [ ] Fix . operator lookups - [ ] Combining casts with . operator @@ -72,9 +71,13 @@ For modules it's a bit different cause they should be distributed as valid. - [ ] Hash tables - [ ] C Codegen - - [ ] Function renaming to prevent colissions + - [ ] Function renaming to prevent colissions, we can't really touch other stuff cause I want it to be easily debuggable -- [ ] Using language construct +- [ ] Programming constructs + - [ ] Using language construct + - [ ] Function polimorphism + - [ ] Operator Overloading + - [ ] Named loops and breaking out of them - [ ] Bytecode interpreter - [ ] Ir @@ -83,7 +86,8 @@ For modules it's a bit different cause they should be distributed as valid. - [ ] Parametric Polymorphism -- [ ] Conditional compilation #if +- [ ] Conditional compilation #if (maybe just do something like a conditional load or import?) #import "windows.kl" when os == "windows" + - [ ] Any - [ ] Assigning to any values like ints etc. should work perhaps? But what type they should have? @@ -123,6 +127,7 @@ For modules it's a bit different cause they should be distributed as valid. ## Done +- [x] Calculate size and alignment of struct data types - [x] Consider changing syntax of scopes to use braces { } NO - [x] Disable ability to parse inner structs, functions, constants etc. ? - [x] Fix language_basics.kl string index error @@ -261,6 +266,4 @@ int main(int argument_count, char **arguments){ compile_file(it.absolute_path, COMPILE_AND_RUN); } } - - __debugbreak(); } diff --git a/core_parsing.cpp b/core_parsing.cpp index f776c42..105f9b2 100644 --- a/core_parsing.cpp +++ b/core_parsing.cpp @@ -180,7 +180,9 @@ parse_expr_call(Ast_Expr *left, Token_Kind close_kind){ Ast_Call_Item *item_comp = ast_new(Ast_Call_Item, AST_CALL_ITEM, token_get(), AST_EXPR); item_comp->item = parse_expr(); if(token_match(TK_Assign)){ - assert(is_flag_set(item_comp->item->flags, AST_ATOM)); + if(!is_flag_set(item_comp->item->flags, AST_ATOM)){ + compiler_error(item_comp->pos, "Invalid value specifier, it's required to be a simple identifier/index"); + } if(item_comp->item->kind != AST_IDENT){ item_comp->index = item_comp->item; diff --git a/core_typechecking.cpp b/core_typechecking.cpp index c8e1f5c..b217d81 100644 --- a/core_typechecking.cpp +++ b/core_typechecking.cpp @@ -1287,8 +1287,9 @@ resolve_expr(Ast_Expr *ast, Resolve_Flag flags, Ast_Type *compound_context){ else { Operand name = resolve_expr(node->name, inherit_flag(flags, AST_CANT_BE_NULL)); - if(name.type->kind != TYPE_LAMBDA) + if(name.type->kind != TYPE_LAMBDA){ compiler_error(node->pos, "Calling %Q which is not a [Lambda]", typestring(name.type)); + } Scratch scratch; Array items = {scratch}; diff --git a/examples/drawing_to_screen_using_windows_api.kl b/examples/drawing_to_screen_using_windows_api.kl index 302d57a..5a86440 100644 --- a/examples/drawing_to_screen_using_windows_api.kl +++ b/examples/drawing_to_screen_using_windows_api.kl @@ -59,7 +59,7 @@ WinMain :: (hInstance: HINSTANCE, hPrevInstance: HINSTANCE, lpCmdLine: LPSTR, nS arena: Arena.Arena - window_name := StringToString16(&arena, "Have a wonderful day! 豈 更 車 賈 滑 串 句 龜 ") + window_name := StringToString16(&arena, "Have a wonderful day! 你好世界 ") w := WNDCLASSW{ lpfnWndProc = WindowProc, hInstance = hInstance, diff --git a/examples/raymarcher.kl b/examples/raymarcher.kl new file mode 100644 index 0000000..5c5e6eb --- /dev/null +++ b/examples/raymarcher.kl @@ -0,0 +1,164 @@ +#import "math.kl" + +Epsilon :: 0.00001 +Screen : *U32 +X : S64 +Y : S64 + +SphereSDF :: (pos: Vec3): F32 + result := Vec3_Length(pos) - 1.0 + return result + +Raymarcher_Update :: () + up := Vec3{0, 1, 0} + forward := Vec3{0, 0, -1} + side := Vec3_Normalize(Vec3_Cross(forward, up)) + + bug := Vec3_Dot(side, forward, d, e) + Xf := 1 / X->F32 + Yf := 1 / Y->F32 + ratio := X->F32 / Y->F32 + for y := 0, y < Y, y+=1 + for x := 0, x < X, x+=1 + uv := Vec3{x->F32 * Xf * 2 - 1, y->F32 * Yf * 2 - 1, 1.0} + uv.x *= ratio + dir := Vec3_Normalize(Vec3{Vec3_Dot(side, uv), Vec3_Dot(up, uv), Vec3_Dot(forward, uv)}) + pos := Vec3{0, 0, 5} + + t: F32 + end: F32 = 100.0 + hit := true + for i := 0, i < 255, i+=1 + p := Vec3_Add(pos, Vec3_MulF32(dir, t)) + + distance := SphereSDF(p) + if distance < Epsilon + break + + t += distance + if distance >= end + hit = false + break + + if hit + Screen[x + y*X] = Vec3_ConvertToARGB({1, uv.y, 0}) + + + + +///////////////////////////////////// +// +// Windows specific code +// + +#import "base.kl" +#import "arena.kl" +#import "os_windows.kl" +#import "kernel32.kl" +#import "gdi32.kl" +#import "user32.kl" +#import "winmm.kl" + +Windows_Bitmap :: struct + size: Vec2I + data: *U32 + hdc: HDC + dib: HBITMAP + +CreateBitmap :: (size: Vec2I, bottom_up: Bool = true): Windows_Bitmap + result: Windows_Bitmap = {size = size} + if bottom_up == false + result.size.y = -result.size.y + + header_size: U32 = SizeOf(BITMAPINFOHEADER) + Assert(header_size == 40) + bminfo := BITMAPINFO{ + BITMAPINFOHEADER{ + biSize = header_size, + biWidth = size.x->LONG, + biHeight = size.y->LONG, + biPlanes = 1, + biBitCount = 32, + biCompression = BI_RGB, + biXPelsPerMeter = 1, + biYPelsPerMeter = 1, + } + } + + hdc := GetDC(0) + result.dib = CreateDIBSection(hdc, &bminfo, DIB_RGB_COLORS, (&result.data)->**void, 0, 0) + result.hdc = CreateCompatibleDC(hdc) + return result + + +AppIsRunning := true +WindowProc :: (hwnd: HWND, msg: UINT, wparam: WPARAM, lparam: LPARAM): LRESULT + if msg == WM_DESTROY + PostQuitMessage(0) + AppIsRunning = false + return 0 + else;; return DefWindowProcW(hwnd, msg, wparam, lparam) + +WinMain :: (hInstance: HINSTANCE, hPrevInstance: HINSTANCE, lpCmdLine: LPSTR, nShowCmd: int): int + if good_scheduling := false, timeBeginPeriod(1) == TIMERR_NOERROR + good_scheduling = true + + arena: Arena + + window_name := StringToString16(&arena, "Have a wonderful day! 你好世界 ") + w := WNDCLASSW{ + lpfnWndProc = WindowProc, + hInstance = hInstance, + lpszClassName = window_name.str, + } + Assert(RegisterClassW(&w) != 0) + + screen_size: Vec2I = {1280, 720} + window := CreateWindowExW( + dwExStyle = 0, hWndParent = 0, hMenu = 0, lpParam = 0, + X = CW_USEDEFAULT, Y = CW_USEDEFAULT, nWidth = screen_size.x->int, nHeight = screen_size.y->int, + lpClassName = window_name.str, + lpWindowName = window_name.str, + dwStyle = WS_OVERLAPPEDWINDOW, + hInstance = hInstance + ) + Assert(window != 0) + ShowWindow(window, nShowCmd) + + window_dc := GetDC(window) + bitmap := CreateBitmap(screen_size) + + requested_time_per_frame := 1.0 / 60.0 + frame_start_time := Time() + frame_number: S64 + total_time: F64 + for AppIsRunning + msg: MSG + for PeekMessageW(&msg, window, 0, 0, PM_REMOVE) > 0 + TranslateMessage(&msg) + DispatchMessageW(&msg) + + Screen = bitmap.data; X = bitmap.size.x; Y = bitmap.size.y + Raymarcher_Update() + + + SelectObject(bitmap.hdc, bitmap.dib) + BitBlt(window_dc, 0, 0, (bitmap.size.x)->int, (bitmap.size.y)->int, bitmap.hdc, 0, 0, SRCCOPY) + + + frame_time := Time() - frame_start_time + if frame_time < requested_time_per_frame + if good_scheduling + time_to_sleep := (requested_time_per_frame - frame_time) * 1000 + if time_to_sleep > 0 + time_to_sleep_dword := time_to_sleep->DWORD + // @check if time_to_sleep_dword truncates down + Sleep(time_to_sleep_dword) + + new_frame_time := Time() + for new_frame_time < requested_time_per_frame + new_frame_time = Time() - frame_start_time + + frame_time = new_frame_time + frame_number += 1 + total_time += frame_time \ No newline at end of file diff --git a/modules/math.kl b/modules/math.kl new file mode 100644 index 0000000..607f237 --- /dev/null +++ b/modules/math.kl @@ -0,0 +1,64 @@ +sqrtf :: #foreign (value: F32): F32 + +Vec2I :: struct;; x: S64; y: S64 +Vec2 :: struct;; x: F32; y: F32 +Vec3 :: struct;; x: F32; y: F32; z: F32 + +Vec3_Length :: (a: Vec3): F32 + result := sqrtf(a.x*a.x + a.y*a.y + a.z*a.z) + return result + +Vec3_Cross :: (a: Vec3, b: Vec3): Vec3 + result := Vec3{ + a.y * b.z - a.z * b.y, + a.z * b.x - a.x * b.z, + a.x * b.y - a.y * b.x, + } + return result + +Vec3_Normalize :: (a: Vec3): Vec3 + length := Vec3_Length(a) + result := Vec3{ + a.x / length, + a.y / length, + a.z / length, + } + return result + +Vec3_ConvertToARGB :: (a: Vec3): U32 + a.x = F32_Clamp(0, a.x, 1) + a.y = F32_Clamp(0, a.y, 1) + a.z = F32_Clamp(0, a.z, 1) + r := (a.x * 255)->U32 << 16 + g := (a.y * 255)->U32 << 8 + b := (a.z * 255)->U32 << 0 + result := r | g | b + return result + +Vec3_Dot :: (a: Vec3, b: Vec3): F32 + result := a.x*b.x + a.y*b.y + a.z*b.z + return result +Vec3_Mul :: (a: Vec3, b: Vec3): Vec3 + result := Vec3{a.x*b.x, a.y*b.y, a.z*b.z} + return result +Vec3_MulF32 :: (a: Vec3, b: F32): Vec3 + result := Vec3{a.x*b, a.y*b, a.z*b} + return result +Vec3_Add :: (a: Vec3, b: Vec3): Vec3 + result := Vec3{a.x+b.x, a.y+b.y, a.z+b.z} + return result +Vec3_Div :: (a: Vec3, b: Vec3): Vec3 + result := Vec3{a.x/b.x, a.y/b.y, a.z/b.z} + return result +Vec3_Sub :: (a: Vec3, b: Vec3): Vec3 + result := Vec3{a.x-b.x, a.y-b.y, a.z-b.z} + return result + +F32_Clamp :: (min: F32, value: F32, max: F32): F32 + if value > max;; return max + if value < min;; return min + return value + +F32_Absolute :: (val: F32): F32 + if val < 0;; return -val + return val diff --git a/modules/os_windows.kl b/modules/os_windows.kl index 55805d5..78eb2a8 100644 --- a/modules/os_windows.kl +++ b/modules/os_windows.kl @@ -34,6 +34,7 @@ Commit :: (m: *Memory, size: SizeU): Bool flAllocationType = MEM_COMMIT, flProtect = PAGE_READWRITE, ) + Assert(result != 0) m.commit += adjusted_commit return true return false