Begin raymarcher example and math module, fixing parsing bugs

This commit is contained in:
Krzosa Karol
2022-09-27 22:42:46 +02:00
parent 7ab1b24bbe
commit f388e3f915
7 changed files with 244 additions and 9 deletions

View File

@@ -57,7 +57,6 @@ For modules it's a bit different cause they should be distributed as valid.
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
- [ ] Basic - [ ] Basic
- [ ] Calculate size and alignment of struct data types
- [ ] Pass size and alignment calculations to C ? - [ ] Pass size and alignment calculations to C ?
- [ ] Fix . operator lookups - [ ] Fix . operator lookups
- [ ] Combining casts with . operator - [ ] Combining casts with . operator
@@ -72,9 +71,13 @@ For modules it's a bit different cause they should be distributed as valid.
- [ ] Hash tables - [ ] Hash tables
- [ ] C Codegen - [ ] 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
- [ ] Programming constructs
- [ ] Using language construct - [ ] Using language construct
- [ ] Function polimorphism
- [ ] Operator Overloading
- [ ] Named loops and breaking out of them
- [ ] Bytecode interpreter - [ ] Bytecode interpreter
- [ ] Ir - [ ] Ir
@@ -83,7 +86,8 @@ For modules it's a bit different cause they should be distributed as valid.
- [ ] Parametric Polymorphism - [ ] 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 - [ ] Any
- [ ] Assigning to any values like ints etc. should work perhaps? But what type they should have? - [ ] 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 ## Done
- [x] Calculate size and alignment of struct data types
- [x] Consider changing syntax of scopes to use braces { } NO - [x] Consider changing syntax of scopes to use braces { } NO
- [x] Disable ability to parse inner structs, functions, constants etc. ? - [x] Disable ability to parse inner structs, functions, constants etc. ?
- [x] Fix language_basics.kl string index error - [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); compile_file(it.absolute_path, COMPILE_AND_RUN);
} }
} }
__debugbreak();
} }

View File

@@ -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); Ast_Call_Item *item_comp = ast_new(Ast_Call_Item, AST_CALL_ITEM, token_get(), AST_EXPR);
item_comp->item = parse_expr(); item_comp->item = parse_expr();
if(token_match(TK_Assign)){ 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){ if(item_comp->item->kind != AST_IDENT){
item_comp->index = item_comp->item; item_comp->index = item_comp->item;

View File

@@ -1287,8 +1287,9 @@ resolve_expr(Ast_Expr *ast, Resolve_Flag flags, Ast_Type *compound_context){
else { else {
Operand name = resolve_expr(node->name, inherit_flag(flags, AST_CANT_BE_NULL)); 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)); compiler_error(node->pos, "Calling %Q which is not a [Lambda]", typestring(name.type));
}
Scratch scratch; Scratch scratch;
Array<Ast_Call_Item *> items = {scratch}; Array<Ast_Call_Item *> items = {scratch};

View File

@@ -59,7 +59,7 @@ WinMain :: (hInstance: HINSTANCE, hPrevInstance: HINSTANCE, lpCmdLine: LPSTR, nS
arena: Arena.Arena arena: Arena.Arena
window_name := StringToString16(&arena, "Have a wonderful day! 豈 更 車 賈 滑 串 句 龜 ") window_name := StringToString16(&arena, "Have a wonderful day! 你好世界 ")
w := WNDCLASSW{ w := WNDCLASSW{
lpfnWndProc = WindowProc, lpfnWndProc = WindowProc,
hInstance = hInstance, hInstance = hInstance,

164
examples/raymarcher.kl Normal file
View File

@@ -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

64
modules/math.kl Normal file
View File

@@ -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

View File

@@ -34,6 +34,7 @@ Commit :: (m: *Memory, size: SizeU): Bool
flAllocationType = MEM_COMMIT, flAllocationType = MEM_COMMIT,
flProtect = PAGE_READWRITE, flProtect = PAGE_READWRITE,
) )
Assert(result != 0)
m.commit += adjusted_commit m.commit += adjusted_commit
return true return true
return false return false