Change to globals are PascalCase, locals are snake_case
This commit is contained in:
@@ -116,7 +116,7 @@ Stuff that helped me a lot programming the compiler. Hopefully they also will be
|
|||||||
- [ ] Dynamic arrays
|
- [ ] Dynamic arrays
|
||||||
- [ ] Hash tables
|
- [ ] Hash tables
|
||||||
|
|
||||||
- [ ] Generics
|
- [ ] Generics / Parametric polymorphism
|
||||||
|
|
||||||
- [ ] Language constructs
|
- [ ] Language constructs
|
||||||
- [x] If
|
- [x] If
|
||||||
|
|||||||
@@ -235,7 +235,7 @@ lex_init(Allocator *token_string_arena, Allocator *map_allocator, Lexer *l){
|
|||||||
keyword_false = l->intern("false"_s);
|
keyword_false = l->intern("false"_s);
|
||||||
keyword_return = l->intern("return"_s);
|
keyword_return = l->intern("return"_s);
|
||||||
keyword_switch = l->intern("switch"_s);
|
keyword_switch = l->intern("switch"_s);
|
||||||
keyword_assert = l->intern("assert"_s);
|
keyword_assert = l->intern("Assert"_s);
|
||||||
keyword_if = l->intern("if"_s);
|
keyword_if = l->intern("if"_s);
|
||||||
keyword_elif = l->intern("elif"_s);
|
keyword_elif = l->intern("elif"_s);
|
||||||
keyword_pass = l->intern("pass"_s);
|
keyword_pass = l->intern("pass"_s);
|
||||||
|
|||||||
@@ -56,9 +56,28 @@ For modules it's a bit different cause they should be distributed as valid.
|
|||||||
|
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
|
|
||||||
@todo
|
- [ ] Basic
|
||||||
- [ ] Split Bc into builder and interpreter
|
- [ ] Fix . operator lookups
|
||||||
- [ ] Implement functions in the bytecode
|
|
||||||
|
|
||||||
|
- [ ] Builtin data structures
|
||||||
|
- [ ] Fix length_of etc. they should be function calls not operators
|
||||||
|
- [ ] Strings probably should have len() instead of string.len
|
||||||
|
- [ ] Slices
|
||||||
|
- [ ] Some way to take slice of data
|
||||||
|
- [ ] Tuples
|
||||||
|
- [ ] Dynamic arrays
|
||||||
|
- [ ] Hash tables
|
||||||
|
|
||||||
|
- [ ] Bytecode interpreter
|
||||||
|
- [ ] Ir
|
||||||
|
- [ ] Interpreter
|
||||||
|
- [ ] Code generation
|
||||||
|
|
||||||
|
- [ ] Parametric Polymorphism
|
||||||
|
|
||||||
|
|
||||||
|
- [ ] Improvements
|
||||||
|
|
||||||
- [ ] Probably need to give Ast_Expr a Value field, then I can express Type nicely
|
- [ ] Probably need to give Ast_Expr a Value field, then I can express Type nicely
|
||||||
- [ ] I would love for String, slice, Any etc. to have their struct declarations in source files, I also would want for stuff like string.str to work without weird special cases
|
- [ ] I would love for String, slice, Any etc. to have their struct declarations in source files, I also would want for stuff like string.str to work without weird special cases
|
||||||
@@ -66,30 +85,25 @@ For modules it's a bit different cause they should be distributed as valid.
|
|||||||
|
|
||||||
- [ ] #test construct that would gather all tests and run them on start of program or something
|
- [ ] #test construct that would gather all tests and run them on start of program or something
|
||||||
- [ ] Foreign import that would link library
|
- [ ] Foreign import that would link library
|
||||||
- [ ] Builtin dynamic arrays
|
|
||||||
- [ ] Kilobyte, Megabyte, Gigabyte
|
- [ ] Kilobyte, Megabyte, Gigabyte
|
||||||
- [ ] Cast from array to pointer?
|
- [ ] Cast from array to pointer?
|
||||||
- [ ] Fix field access, cant cast, cant index
|
- [ ] Fix field access, cant cast, cant index
|
||||||
- [ ] Add parent_scope to Ast_Type, Add name to Ast_Type?
|
- [ ] Add parent_scope to Ast_Type, Add name to Ast_Type?
|
||||||
- [ ] Some way to take slice of data
|
|
||||||
- [ ] Optional function renaming in codegen
|
- [ ] Optional function renaming in codegen
|
||||||
- [ ] Using in structs to embed members, then casting offsets to that embedded member
|
- [ ] Using in structs to embed members, then casting offsets to that embedded member
|
||||||
|
|
||||||
- [ ] Comma notation when declaring variables thing1, thing2: S32 :: probably want to unify it with var unpacking
|
- [ ] Comma notation when declaring variables thing1, thing2: S32 :: probably want to unify it with var unpacking
|
||||||
- [ ] Add single line lambda expressions
|
- [ ] Add single line lambda expressions
|
||||||
- [ ] Ternary operator
|
- [ ] Ternary operator
|
||||||
- [ ] Disable ability to parse inner structs, functions, constants etc. ?
|
|
||||||
- [ ] Write up on order independent declarations
|
- [ ] Write up on order independent declarations
|
||||||
|
|
||||||
- [ ] Consider changing syntax of scopes to use braces { }
|
|
||||||
- [ ] Order independent declarations in structs ?
|
|
||||||
- [ ] constructor => thing :: (i: S32) -> {i = i, thing = 10}
|
- [ ] constructor => thing :: (i: S32) -> {i = i, thing = 10}
|
||||||
- [ ] Casting to basic types by call S64(x)
|
- [ ] Casting to basic types by call S64(x)
|
||||||
- [ ] Default values in structs??? Should compound stmts bring values from default values?? Maybe not? Whats the alternative
|
- [ ] Default values in structs??? Should compound stmts bring values from default values?? Maybe not? Whats the alternative
|
||||||
|
|
||||||
@ideas
|
@ideas
|
||||||
- [ ] Var args using Any array - args: []Any - delete vargs
|
- [ ] Var args using Any array - args: []Any - delete vargs
|
||||||
- [ ] [Using] keyword that brings in the struct enviroment into current scope etc.
|
|
||||||
- [ ] Constant arrays that evaluate fully at compile time
|
- [ ] Constant arrays that evaluate fully at compile time
|
||||||
- [ ] Rust like enum where you associate values(other structs) with keys
|
- [ ] Rust like enum where you associate values(other structs) with keys
|
||||||
- [ ] Compound that zeros values - .{} , Compound that assumes defaults from struct definition - {}
|
- [ ] Compound that zeros values - .{} , Compound that assumes defaults from struct definition - {}
|
||||||
@@ -100,6 +114,8 @@ For modules it's a bit different cause they should be distributed as valid.
|
|||||||
|
|
||||||
## Done
|
## Done
|
||||||
|
|
||||||
|
- [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
|
- [x] Fix language_basics.kl string index error
|
||||||
- [x] Type as a parameter to a function, alloc :: (size: U64, type: Type)
|
- [x] Type as a parameter to a function, alloc :: (size: U64, type: Type)
|
||||||
- [x] Add token information to instructions
|
- [x] Add token information to instructions
|
||||||
@@ -119,7 +135,7 @@ For modules it's a bit different cause they should be distributed as valid.
|
|||||||
- [x] slices should be properly displayed in debugger
|
- [x] slices should be properly displayed in debugger
|
||||||
- [x] Imports inside of import shouldn't spill outside
|
- [x] Imports inside of import shouldn't spill outside
|
||||||
- [x] Scope
|
- [x] Scope
|
||||||
- [x] #assert that handles constants at compile time and vars at runtime
|
- [x] #Assert that handles constants at compile time and vars at runtime
|
||||||
- [x] Hex 0x42
|
- [x] Hex 0x42
|
||||||
- [x] Rewrite where # happen,
|
- [x] Rewrite where # happen,
|
||||||
- [x] elif
|
- [x] elif
|
||||||
@@ -136,6 +152,7 @@ For modules it's a bit different cause they should be distributed as valid.
|
|||||||
- [x] Emitting #line
|
- [x] Emitting #line
|
||||||
- [x] Making sure debugger works
|
- [x] Making sure debugger works
|
||||||
- [x] We need ++ -- operators
|
- [x] We need ++ -- operators
|
||||||
|
- [x] Order independent declarations in structs ? NO MORE
|
||||||
- [x] Arrays with size passed
|
- [x] Arrays with size passed
|
||||||
- [x] Values inited to 0 by default
|
- [x] Values inited to 0 by default
|
||||||
- [x] Some way to call foreign functions
|
- [x] Some way to call foreign functions
|
||||||
|
|||||||
@@ -635,9 +635,9 @@ resolve_stmt(Ast *ast, Ast_Type *ret){
|
|||||||
|
|
||||||
CASE(CONSTANT_ASSERT, Builtin){
|
CASE(CONSTANT_ASSERT, Builtin){
|
||||||
Operand op = resolve_and_require_bool("Assert condition is not boolean", node->expr, AST_CAN_BE_NULL);
|
Operand op = resolve_and_require_bool("Assert condition is not boolean", node->expr, AST_CAN_BE_NULL);
|
||||||
if(!op.is_const) compiler_error(node->pos, "#assert expression required to be constant");
|
if(!op.is_const) compiler_error(node->pos, "#Assert expression required to be constant");
|
||||||
if(op.bool_val == false){
|
if(op.bool_val == false){
|
||||||
compiler_error(node->pos, "#assert condition not met :: %.*s", (int)node->assert_message.len, node->assert_message.str);
|
compiler_error(node->pos, "#Assert condition not met :: %.*s", (int)node->assert_message.len, node->assert_message.str);
|
||||||
}
|
}
|
||||||
BREAK();
|
BREAK();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,15 +15,15 @@ main :: (): int
|
|||||||
static_array: [8]int
|
static_array: [8]int
|
||||||
|
|
||||||
// We can get size of array using length_of builtin
|
// We can get size of array using length_of builtin
|
||||||
#assert(length_of(static_array) == 8)
|
#Assert(length_of(static_array) == 8)
|
||||||
|
|
||||||
// Accessing values is like in C
|
// Accessing values is like in C
|
||||||
// Variables are zeroed by default
|
// Variables are zeroed by default
|
||||||
assert(static_array[1] == 0)
|
Assert(static_array[1] == 0)
|
||||||
|
|
||||||
element2 := static_array[2]
|
element2 := static_array[2]
|
||||||
element0: int = static_array[0]
|
element0: int = static_array[0]
|
||||||
assert(element0 == 0 && element2 == 0)
|
Assert(element0 == 0 && element2 == 0)
|
||||||
|
|
||||||
// We can loop through arrays
|
// We can loop through arrays
|
||||||
// this implicitly defines 'it' variable
|
// this implicitly defines 'it' variable
|
||||||
@@ -31,16 +31,16 @@ main :: (): int
|
|||||||
*it = 1
|
*it = 1
|
||||||
|
|
||||||
// We set all variables to 1 so
|
// We set all variables to 1 so
|
||||||
assert(static_array[6] == 1)
|
Assert(static_array[6] == 1)
|
||||||
|
|
||||||
// This is how slice is defined, no [] index in between brackets
|
// This is how slice is defined, no [] index in between brackets
|
||||||
// slice is array pointer + length
|
// slice is array pointer + length
|
||||||
// Other then that it works exactly like regular array
|
// Other then that it works exactly like regular array
|
||||||
slice: []int = static_array
|
slice: []int = static_array
|
||||||
|
|
||||||
// We can't do a compile time assert anymore
|
// We can't do a compile time Assert anymore
|
||||||
assert(length_of(slice) == 8)
|
Assert(length_of(slice) == 8)
|
||||||
assert(slice[4] == 1)
|
Assert(slice[4] == 1)
|
||||||
|
|
||||||
// After we loop and reassign slice values
|
// After we loop and reassign slice values
|
||||||
// old static_array gets changed
|
// old static_array gets changed
|
||||||
@@ -50,4 +50,4 @@ main :: (): int
|
|||||||
// example in a single line
|
// example in a single line
|
||||||
for slice;; *it = 2
|
for slice;; *it = 2
|
||||||
|
|
||||||
assert(static_array[2] == 2)
|
Assert(static_array[2] == 2)
|
||||||
@@ -1,4 +1,5 @@
|
|||||||
#import "base.kl"
|
#import "base.kl"
|
||||||
|
Arena :: #import "arena.kl"
|
||||||
#import "os_windows.kl"
|
#import "os_windows.kl"
|
||||||
#import "kernel32.kl"
|
#import "kernel32.kl"
|
||||||
#import "gdi32.kl"
|
#import "gdi32.kl"
|
||||||
@@ -18,7 +19,7 @@ Bitmap :: struct
|
|||||||
size: Vec2I
|
size: Vec2I
|
||||||
data: *U32
|
data: *U32
|
||||||
|
|
||||||
create_bitmap :: (size: Vec2I, bottom_up: Bool = true): Windows_Bitmap
|
CreateBitmap :: (size: Vec2I, bottom_up: Bool = true): Windows_Bitmap
|
||||||
result: Windows_Bitmap = {size = size}
|
result: Windows_Bitmap = {size = size}
|
||||||
if bottom_up == false
|
if bottom_up == false
|
||||||
result.size.y = -result.size.y
|
result.size.y = -result.size.y
|
||||||
@@ -42,11 +43,11 @@ create_bitmap :: (size: Vec2I, bottom_up: Bool = true): Windows_Bitmap
|
|||||||
return result
|
return result
|
||||||
|
|
||||||
|
|
||||||
app_is_running := true
|
AppIsRunning := true
|
||||||
window_procedure :: (hwnd: HWND, msg: UINT, wparam: WPARAM, lparam: LPARAM): LRESULT
|
WindowProc :: (hwnd: HWND, msg: UINT, wparam: WPARAM, lparam: LPARAM): LRESULT
|
||||||
if msg == WM_DESTROY
|
if msg == WM_DESTROY
|
||||||
PostQuitMessage(0)
|
PostQuitMessage(0)
|
||||||
app_is_running = false
|
AppIsRunning = false
|
||||||
return 0
|
return 0
|
||||||
else;; return DefWindowProcW(hwnd, msg, wparam, lparam)
|
else;; return DefWindowProcW(hwnd, msg, wparam, lparam)
|
||||||
|
|
||||||
@@ -54,15 +55,15 @@ WinMain :: (hInstance: HINSTANCE, hPrevInstance: HINSTANCE, lpCmdLine: LPSTR, nS
|
|||||||
if good_scheduling := false, timeBeginPeriod(1) == TIMERR_NOERROR
|
if good_scheduling := false, timeBeginPeriod(1) == TIMERR_NOERROR
|
||||||
good_scheduling = true
|
good_scheduling = true
|
||||||
|
|
||||||
arena: Arena
|
arena: Arena.Arena
|
||||||
|
|
||||||
window_name := string_to_string16(&arena, "Have a wonderful day! 豈 更 車 賈 滑 串 句 龜 ")
|
window_name := StringToString16(&arena, "Have a wonderful day! 豈 更 車 賈 滑 串 句 龜 ")
|
||||||
w := WNDCLASSW{
|
w := WNDCLASSW{
|
||||||
lpfnWndProc = window_procedure,
|
lpfnWndProc = WindowProc,
|
||||||
hInstance = hInstance,
|
hInstance = hInstance,
|
||||||
lpszClassName = window_name.str,
|
lpszClassName = window_name.str,
|
||||||
}
|
}
|
||||||
assert(RegisterClassW(&w) != 0)
|
Assert(RegisterClassW(&w) != 0)
|
||||||
|
|
||||||
screen_size: Vec2I = {1280, 720}
|
screen_size: Vec2I = {1280, 720}
|
||||||
window := CreateWindowExW(
|
window := CreateWindowExW(
|
||||||
@@ -73,17 +74,17 @@ WinMain :: (hInstance: HINSTANCE, hPrevInstance: HINSTANCE, lpCmdLine: LPSTR, nS
|
|||||||
dwStyle = WS_OVERLAPPEDWINDOW,
|
dwStyle = WS_OVERLAPPEDWINDOW,
|
||||||
hInstance = hInstance
|
hInstance = hInstance
|
||||||
)
|
)
|
||||||
assert(window != 0)
|
Assert(window != 0)
|
||||||
ShowWindow(window, nShowCmd)
|
ShowWindow(window, nShowCmd)
|
||||||
|
|
||||||
window_dc := GetDC(window)
|
window_dc := GetDC(window)
|
||||||
bitmap := create_bitmap(screen_size)
|
bitmap := CreateBitmap(screen_size)
|
||||||
|
|
||||||
requested_time_per_frame := 1.0 / 60.0
|
requested_time_per_frame := 1.0 / 60.0
|
||||||
frame_start_time := time()
|
frame_start_time := Time()
|
||||||
frame_number: S64
|
frame_number: S64
|
||||||
total_time: F64
|
total_time: F64
|
||||||
for app_is_running
|
for AppIsRunning
|
||||||
msg: MSG
|
msg: MSG
|
||||||
for PeekMessageW(&msg, window, 0, 0, PM_REMOVE) > 0
|
for PeekMessageW(&msg, window, 0, 0, PM_REMOVE) > 0
|
||||||
TranslateMessage(&msg)
|
TranslateMessage(&msg)
|
||||||
@@ -97,7 +98,7 @@ WinMain :: (hInstance: HINSTANCE, hPrevInstance: HINSTANCE, lpCmdLine: LPSTR, nS
|
|||||||
BitBlt(window_dc, 0, 0, (bitmap.size.x)->int, (bitmap.size.y)->int, bitmap.hdc, 0, 0, SRCCOPY)
|
BitBlt(window_dc, 0, 0, (bitmap.size.x)->int, (bitmap.size.y)->int, bitmap.hdc, 0, 0, SRCCOPY)
|
||||||
|
|
||||||
|
|
||||||
frame_time := time() - frame_start_time
|
frame_time := Time() - frame_start_time
|
||||||
if frame_time < requested_time_per_frame
|
if frame_time < requested_time_per_frame
|
||||||
if good_scheduling
|
if good_scheduling
|
||||||
time_to_sleep := (requested_time_per_frame - frame_time) * 1000
|
time_to_sleep := (requested_time_per_frame - frame_time) * 1000
|
||||||
@@ -106,9 +107,9 @@ WinMain :: (hInstance: HINSTANCE, hPrevInstance: HINSTANCE, lpCmdLine: LPSTR, nS
|
|||||||
// @check if time_to_sleep_dword truncates down
|
// @check if time_to_sleep_dword truncates down
|
||||||
Sleep(time_to_sleep_dword)
|
Sleep(time_to_sleep_dword)
|
||||||
|
|
||||||
new_frame_time := time()
|
new_frame_time := Time()
|
||||||
for new_frame_time < requested_time_per_frame
|
for new_frame_time < requested_time_per_frame
|
||||||
new_frame_time = time() - frame_start_time
|
new_frame_time = Time() - frame_start_time
|
||||||
|
|
||||||
frame_time = new_frame_time
|
frame_time = new_frame_time
|
||||||
frame_number += 1
|
frame_number += 1
|
||||||
|
|||||||
@@ -21,10 +21,10 @@ main :: (): int
|
|||||||
string_val: String = "String type"
|
string_val: String = "String type"
|
||||||
cstring_val: *char = "CString type"
|
cstring_val: *char = "CString type"
|
||||||
|
|
||||||
assert(s64val == 0 && s32val == 0 && s16val == 0 && s8val == 0 && intval == 0 && u64val == 0 && u32val == 0 && u16val == 0 && u8val == 0 && f64val == 0 && f32val == 0)
|
Assert(s64val == 0 && s32val == 0 && s16val == 0 && s8val == 0 && intval == 0 && u64val == 0 && u32val == 0 && u16val == 0 && u8val == 0 && f64val == 0 && f32val == 0)
|
||||||
// @todo: Fix error here !!
|
// @todo: Fix error here !!
|
||||||
// assert(string_val[0] == 'S) //'
|
// Assert(string_val[0] == 'S) //'
|
||||||
assert(cstring_val[0] == 'C')
|
Assert(cstring_val[0] == 'C')
|
||||||
|
|
||||||
// This is how we can assign variables
|
// This is how we can assign variables
|
||||||
// There is no need for prefixes, compiler figures
|
// There is no need for prefixes, compiler figures
|
||||||
@@ -43,8 +43,8 @@ main :: (): int
|
|||||||
this_is_f64_by_default = 15.1255
|
this_is_f64_by_default = 15.1255
|
||||||
|
|
||||||
// @todo: Add type_of operator!!!
|
// @todo: Add type_of operator!!!
|
||||||
// assert(type_of(this_is_string_by_default) == String)
|
// Assert(type_of(this_is_string_by_default) == String)
|
||||||
// assert(type_of(this_is_s64_by_default) == S64)
|
// Assert(type_of(this_is_s64_by_default) == S64)
|
||||||
|
|
||||||
// There are also constant bindings in the language.
|
// There are also constant bindings in the language.
|
||||||
// You can bind all sorts of constants to names this way.
|
// You can bind all sorts of constants to names this way.
|
||||||
@@ -59,8 +59,8 @@ main :: (): int
|
|||||||
combining_types := this_is_s64_by_default->F64 + this_is_f64_by_default
|
combining_types := this_is_s64_by_default->F64 + this_is_f64_by_default
|
||||||
|
|
||||||
|
|
||||||
assert(signed_variable == 10 && unsigned_variable == 10)
|
Assert(signed_variable == 10 && unsigned_variable == 10)
|
||||||
assert(INT_VALUE == 10)
|
Assert(INT_VALUE == 10)
|
||||||
assert(FLOAT_VALUE == 124.125)
|
Assert(FLOAT_VALUE == 124.125)
|
||||||
assert(this_is_f64_by_default == 15.1255)
|
Assert(this_is_f64_by_default == 15.1255)
|
||||||
assert(combining_types == 15.1255 + 20)
|
Assert(combining_types == 15.1255 + 20)
|
||||||
|
|||||||
@@ -16,10 +16,10 @@ main :: (): int
|
|||||||
if type_info.type == S64
|
if type_info.type == S64
|
||||||
// We can use size_of and align_of operators
|
// We can use size_of and align_of operators
|
||||||
// to figure out the type alignment and it's size
|
// to figure out the type alignment and it's size
|
||||||
assert(type_info.size == size_of(S64))
|
Assert(type_info.size == size_of(S64))
|
||||||
assert(type_info.align == align_of(S64))
|
Assert(type_info.align == align_of(S64))
|
||||||
|
|
||||||
else;; assert(false, "We expected S64 here! What a boomer!")
|
else;; Assert(false, "We expected S64 here! What a boomer!")
|
||||||
|
|
||||||
//
|
//
|
||||||
// @todo: This should work
|
// @todo: This should work
|
||||||
@@ -41,12 +41,12 @@ main :: (): int
|
|||||||
elif any_value.type == int
|
elif any_value.type == int
|
||||||
value: *int = any_value.data
|
value: *int = any_value.data
|
||||||
*value = 30
|
*value = 30
|
||||||
elif any_value.type == char;; assert(false, "No bueno")
|
elif any_value.type == char;; Assert(false, "No bueno")
|
||||||
|
|
||||||
assert(value_to_be_wrapped == 20)
|
Assert(value_to_be_wrapped == 20)
|
||||||
|
|
||||||
letter := get_first_letter_of_type(value_to_be_wrapped)
|
letter := get_first_letter_of_type(value_to_be_wrapped)
|
||||||
assert(letter == 'I')
|
Assert(letter == 'I')
|
||||||
|
|
||||||
get_first_letter_of_type :: (a: Any): U8
|
get_first_letter_of_type :: (a: Any): U8
|
||||||
type_info := get_type_info(a.type)
|
type_info := get_type_info(a.type)
|
||||||
|
|||||||
@@ -1,15 +1,15 @@
|
|||||||
main :: (): int
|
main :: (): int
|
||||||
// Types can be evaluated at compile time for equality
|
// Types can be evaluated at compile time for equality
|
||||||
#assert(int == int)
|
#Assert(int == int)
|
||||||
#assert(int != char)
|
#Assert(int != char)
|
||||||
#assert(*char == *char)
|
#Assert(*char == *char)
|
||||||
|
|
||||||
// They can also be evaluated at runtime, they basically get
|
// They can also be evaluated at runtime, they basically get
|
||||||
// replaced with type ids, which are just unique integers assigned
|
// replaced with type ids, which are just unique integers assigned
|
||||||
// to each type
|
// to each type
|
||||||
assert(int == int)
|
Assert(int == int)
|
||||||
assert(int != char)
|
Assert(int != char)
|
||||||
assert(*char == *char)
|
Assert(*char == *char)
|
||||||
|
|
||||||
// We can assign types to compile time variable constants
|
// We can assign types to compile time variable constants
|
||||||
New_Type :: int
|
New_Type :: int
|
||||||
@@ -17,19 +17,19 @@ main :: (): int
|
|||||||
// This is a loose association
|
// This is a loose association
|
||||||
thing: int = 10
|
thing: int = 10
|
||||||
new_type_thing: New_Type = thing
|
new_type_thing: New_Type = thing
|
||||||
#assert(New_Type == int)
|
#Assert(New_Type == int)
|
||||||
|
|
||||||
// to force typechecker to treat
|
// to force typechecker to treat$
|
||||||
// both of these types as different we need to add a #strict directive
|
// both of these types as different we need to add a #strict directive
|
||||||
Strict_Type :: #strict int
|
Strict_Type :: #strict int
|
||||||
|
|
||||||
// new_strict_type_thing: Strict_Type = thing // This produces a compile time type error
|
// new_strict_type_thing: Strict_Type = thing // This produces a compile time type error
|
||||||
// But this works
|
// But this works
|
||||||
strict_thing: Strict_Type = 10
|
strict_thing: Strict_Type = 10
|
||||||
#assert(Strict_Type != int)
|
#Assert(Strict_Type != int)
|
||||||
|
|
||||||
// If we want to use those types together we need to cast
|
// If we want to use those types together we need to cast
|
||||||
assert(new_type_thing + strict_thing->int != 0)
|
Assert(new_type_thing + strict_thing->int != 0)
|
||||||
|
|
||||||
// We can also assign types to runtime variables, there is a special type for that
|
// We can also assign types to runtime variables, there is a special type for that
|
||||||
some_type: Type = int
|
some_type: Type = int
|
||||||
|
|||||||
@@ -1,74 +1,31 @@
|
|||||||
Os :: #import "os_windows.kl"
|
OS :: #import "os_windows.kl"
|
||||||
|
#import "arena.kl"
|
||||||
SizeU :: U64
|
SizeU :: U64
|
||||||
arena_di: U64
|
|
||||||
|
|
||||||
ADDITIONAL_COMMIT_SIZE :: 1024*1024
|
ClampTopSizeU :: (val: SizeU, max: SizeU): SizeU
|
||||||
DEFAULT_RESERVE_SIZE :: 1024*1024*1024
|
|
||||||
DEFAULT_ALIGNMENT :: 8
|
|
||||||
|
|
||||||
Arena :: struct
|
|
||||||
di: U64 // @debug_id
|
|
||||||
memory: Os.Memory
|
|
||||||
alignment: U64
|
|
||||||
len: U64
|
|
||||||
|
|
||||||
clamp_top_sizeu :: (val: SizeU, max: SizeU): SizeU
|
|
||||||
if val > max
|
if val > max
|
||||||
return max
|
return max
|
||||||
return val
|
return val
|
||||||
|
|
||||||
get_align_offset :: (size: SizeU, align: SizeU): SizeU
|
GetAlignOffset :: (size: SizeU, align: SizeU): SizeU
|
||||||
mask := align - 1
|
mask := align - 1
|
||||||
val := size & mask
|
val := size & mask
|
||||||
if val != 0
|
if val != 0
|
||||||
val = align - val
|
val = align - val
|
||||||
return val
|
return val
|
||||||
|
|
||||||
align_up :: (size: SizeU, align: SizeU): SizeU
|
AlignUp :: (size: SizeU, align: SizeU): SizeU
|
||||||
result := size + get_align_offset(size, align)
|
result := size + GetAlignOffset(size, align)
|
||||||
return result
|
return result
|
||||||
|
|
||||||
arena_init :: (a: *Arena)
|
|
||||||
a.memory = Os.reserve(DEFAULT_RESERVE_SIZE)
|
|
||||||
a.alignment = DEFAULT_ALIGNMENT
|
|
||||||
a.di = arena_di++
|
|
||||||
// a.allocator.proc = arena_allocator_proc
|
|
||||||
|
|
||||||
arena_push_size :: (a: *Arena, size: SizeU): *void
|
|
||||||
generous_size := size + a.alignment
|
|
||||||
if a.len + generous_size > a.memory.commit
|
|
||||||
if a.memory.reserve == 0
|
|
||||||
arena_init(a)
|
|
||||||
result := Os.commit(&a.memory, generous_size + ADDITIONAL_COMMIT_SIZE)
|
|
||||||
assert(result == true)
|
|
||||||
a.len = align_up(a.len, a.alignment)
|
|
||||||
assert(a.memory.reserve > a.len + a.memory.commit)
|
|
||||||
result: *void = a.memory.data + a.len
|
|
||||||
a.len += size
|
|
||||||
return result
|
|
||||||
|
|
||||||
// @todo: Make this compile time thing!!!
|
|
||||||
// This probably will wait till polymorphism stuff
|
|
||||||
// something like this:
|
|
||||||
// arena_push_type :: (a: *Arena, type: $T): *T
|
|
||||||
//
|
|
||||||
arena_push_type :: (a: *Arena, type: Type): *void
|
|
||||||
type_info := get_type_info(type)
|
|
||||||
assert(type_info != 0)
|
|
||||||
return arena_push_size(a, type_info.size->SizeU)
|
|
||||||
|
|
||||||
arena_release :: (a: *Arena)
|
|
||||||
Os.release(&a.memory)
|
|
||||||
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// Unicode
|
// Unicode
|
||||||
//
|
//
|
||||||
question_mark16 :: 0x003f
|
QuestionMark16 :: 0x003f
|
||||||
String32 :: struct;; str: *U32; len: S64
|
String32 :: struct;; str: *U32; len: S64
|
||||||
String16 :: struct;; str: *U16; len: S64
|
String16 :: struct;; str: *U16; len: S64
|
||||||
|
|
||||||
utf8_to_utf32 :: (c: *U8, max_advance: S64): U32, S64
|
Utf8ToUtf32 :: (c: *U8, max_advance: S64): U32, S64
|
||||||
out_str: U32
|
out_str: U32
|
||||||
advance: S64
|
advance: S64
|
||||||
if (c[0] & 0b10000000) == 0
|
if (c[0] & 0b10000000) == 0
|
||||||
@@ -100,7 +57,7 @@ utf8_to_utf32 :: (c: *U8, max_advance: S64): U32, S64
|
|||||||
|
|
||||||
return out_str, advance
|
return out_str, advance
|
||||||
|
|
||||||
utf32_to_utf16 :: (codepoint: U32): [2]U16, S64
|
Utf32ToUtf16 :: (codepoint: U32): [2]U16, S64
|
||||||
str: [2]U16
|
str: [2]U16
|
||||||
len := 0
|
len := 0
|
||||||
if codepoint < 0x10000
|
if codepoint < 0x10000
|
||||||
@@ -114,24 +71,24 @@ utf32_to_utf16 :: (codepoint: U32): [2]U16, S64
|
|||||||
|
|
||||||
return str, len
|
return str, len
|
||||||
|
|
||||||
string_to_string16 :: (arena: *Arena, in: String): String16
|
StringToString16 :: (arena: *Arena, in: String): String16
|
||||||
in_str := &in[0]
|
in_str := &in[0]
|
||||||
// @Note(Krzosa): Should be more then enough space
|
// @Note(Krzosa): Should be more then enough space
|
||||||
alloc_size := (length_of(in)*2)+1
|
alloc_size := (length_of(in)*2)+1
|
||||||
result := String16{str = arena_push_size(arena, alloc_size->U64)}
|
result := String16{str = PushSize(arena, alloc_size->U64)}
|
||||||
for i := 0, i < length_of(in)
|
for i := 0, i < length_of(in)
|
||||||
s32, s32_len := utf8_to_utf32(in_str + i, length_of(in) - i)
|
s32, s32_len := Utf8ToUtf32(in_str + i, length_of(in) - i)
|
||||||
if s32_len != 0
|
if s32_len != 0
|
||||||
i += s32_len
|
i += s32_len
|
||||||
s16, s16_len := utf32_to_utf16(s32)
|
s16, s16_len := Utf32ToUtf16(s32)
|
||||||
if s16_len != 0
|
if s16_len != 0
|
||||||
for j := 0, j < s16_len, j++
|
for j := 0, j < s16_len, j++
|
||||||
result.str[result.len++] = s16[j]
|
result.str[result.len++] = s16[j]
|
||||||
else
|
else
|
||||||
result.str[result.len++] = question_mark16
|
result.str[result.len++] = QuestionMark16
|
||||||
break
|
break
|
||||||
else
|
else
|
||||||
result.str[result.len++] = question_mark16
|
result.str[result.len++] = QuestionMark16
|
||||||
break
|
break
|
||||||
|
|
||||||
result.str[result.len] = 0
|
result.str[result.len] = 0
|
||||||
@@ -139,14 +96,14 @@ string_to_string16 :: (arena: *Arena, in: String): String16
|
|||||||
|
|
||||||
test_unicode :: (arena: *Arena)
|
test_unicode :: (arena: *Arena)
|
||||||
string := " 豈 更 車 賈 滑 串 句 龜 龜 契 金 喇 奈 懶 癩 羅 蘿 螺 裸 邏 樂 洛 烙 珞 落 酪 駱 亂 卵 欄 爛 蘭 鸞 嵐 濫 藍 襤 拉 臘 蠟 廊 朗 浪 狼 郎 來 冷 勞 擄 櫓 爐 盧 老 蘆 虜 路 露 魯 鷺 碌 祿 綠 菉 錄 鹿 論 壟 弄 籠 聾 牢 磊 賂 雷 壘 屢 樓 淚 漏 累 縷 陋 勒 肋 凜 凌 稜 綾 菱 陵 讀 拏 樂 諾 丹 寧 怒 率 異 北 磻 便 復 不 泌 數 索 參 塞 省 葉 說 殺 辰 沈 拾 若 掠 略 亮 兩 凉 梁 糧 良 諒 量 勵 ..."
|
string := " 豈 更 車 賈 滑 串 句 龜 龜 契 金 喇 奈 懶 癩 羅 蘿 螺 裸 邏 樂 洛 烙 珞 落 酪 駱 亂 卵 欄 爛 蘭 鸞 嵐 濫 藍 襤 拉 臘 蠟 廊 朗 浪 狼 郎 來 冷 勞 擄 櫓 爐 盧 老 蘆 虜 路 露 魯 鷺 碌 祿 綠 菉 錄 鹿 論 壟 弄 籠 聾 牢 磊 賂 雷 壘 屢 樓 淚 漏 累 縷 陋 勒 肋 凜 凌 稜 綾 菱 陵 讀 拏 樂 諾 丹 寧 怒 率 異 北 磻 便 復 不 泌 數 索 參 塞 省 葉 說 殺 辰 沈 拾 若 掠 略 亮 兩 凉 梁 糧 良 諒 量 勵 ..."
|
||||||
string_result := string_to_string16(arena, string)
|
string_result := StringToString16(arena, string)
|
||||||
print(string_result)
|
print(string_result)
|
||||||
|
|
||||||
s32, s32_len := utf8_to_utf32('A', 1)
|
s32, s32_len := Utf8ToUtf32('A', 1)
|
||||||
assert(s32 == 'A', "Invalid decode")
|
assert(s32 == 'A', "Invalid decode")
|
||||||
|
|
||||||
s32_2, s32_len_2 := utf8_to_utf32('ć', 2)
|
s32_2, s32_len_2 := Utf8ToUtf32('ć', 2)
|
||||||
assert(s32_2 == 0x107, "Invalid decode")
|
assert(s32_2 == 0x107, "Invalid decode")
|
||||||
|
|
||||||
s32_3, s32_len_3 := utf8_to_utf32('ó', 2)
|
s32_3, s32_len_3 := Utf8ToUtf32('ó', 2)
|
||||||
assert(s32_3 == 0xF3, "Invalid decode")
|
assert(s32_3 == 0xF3, "Invalid decode")
|
||||||
|
|||||||
@@ -7,14 +7,14 @@ Memory :: struct
|
|||||||
reserve: SizeU
|
reserve: SizeU
|
||||||
data : *U8
|
data : *U8
|
||||||
|
|
||||||
process_heap: HANDLE
|
ProcessHeap: HANDLE
|
||||||
allocate :: (size: U64): *void
|
Allocate :: (size: U64): *void
|
||||||
if process_heap == 0
|
if ProcessHeap == 0
|
||||||
process_heap = GetProcessHeap()
|
ProcessHeap = GetProcessHeap()
|
||||||
return HeapAlloc(process_heap, 0, size)
|
return HeapAlloc(ProcessHeap, 0, size)
|
||||||
|
|
||||||
reserve :: (size: SizeU): Memory
|
Reserve :: (size: SizeU): Memory
|
||||||
result := Memory{reserve=align_up(size, PAGE_SIZE)}
|
result := Memory{reserve=AlignUp(size, PAGE_SIZE)}
|
||||||
result.data = VirtualAlloc(
|
result.data = VirtualAlloc(
|
||||||
flProtect = PAGE_READWRITE,
|
flProtect = PAGE_READWRITE,
|
||||||
dwSize = result.reserve,
|
dwSize = result.reserve,
|
||||||
@@ -22,10 +22,10 @@ reserve :: (size: SizeU): Memory
|
|||||||
lpAddress = 0)->*U8
|
lpAddress = 0)->*U8
|
||||||
return result
|
return result
|
||||||
|
|
||||||
commit :: (m: *Memory, size: SizeU): Bool
|
Commit :: (m: *Memory, size: SizeU): Bool
|
||||||
commit_size := align_up(size, PAGE_SIZE)
|
commit_size := AlignUp(size, PAGE_SIZE)
|
||||||
total_commit := m.commit + commit_size
|
total_commit := m.commit + commit_size
|
||||||
clamped_commit := clamp_top_sizeu(total_commit, m.reserve)
|
clamped_commit := ClampTopSizeU(total_commit, m.reserve)
|
||||||
adjusted_commit := clamped_commit - m.commit
|
adjusted_commit := clamped_commit - m.commit
|
||||||
if adjusted_commit != 0
|
if adjusted_commit != 0
|
||||||
result := VirtualAlloc(
|
result := VirtualAlloc(
|
||||||
@@ -38,28 +38,28 @@ commit :: (m: *Memory, size: SizeU): Bool
|
|||||||
return true
|
return true
|
||||||
return false
|
return false
|
||||||
|
|
||||||
release :: (m: *Memory)
|
Release :: (m: *Memory)
|
||||||
result := VirtualFree(m.data->*void, 0, MEM_RELEASE)
|
result := VirtualFree(m.data->*void, 0, MEM_RELEASE)
|
||||||
if result != 0
|
if result != 0
|
||||||
m.data = 0
|
m.data = 0
|
||||||
m.commit = 0
|
m.commit = 0
|
||||||
m.reserve = 0
|
m.reserve = 0
|
||||||
|
|
||||||
write_console :: (string: String16)
|
WriteConsole :: (string: String16)
|
||||||
handle := GetStdHandle(STD_OUTPUT_HANDLE)
|
handle := GetStdHandle(STD_OUTPUT_HANDLE)
|
||||||
WriteConsoleW(handle, string.str->*void, string.len->DWORD, 0, 0)
|
WriteConsoleW(handle, string.str->*void, string.len->DWORD, 0, 0)
|
||||||
|
|
||||||
performance_frequency: F64
|
PerformanceFrequency: F64
|
||||||
time :: (): F64
|
Time :: (): F64
|
||||||
query: LARGE_INTEGER
|
query: LARGE_INTEGER
|
||||||
if !performance_frequency
|
if !PerformanceFrequency
|
||||||
err := QueryPerformanceFrequency(&query)
|
err := QueryPerformanceFrequency(&query)
|
||||||
assert(err != 0)
|
Assert(err != 0)
|
||||||
performance_frequency = query->F64
|
PerformanceFrequency = query->F64
|
||||||
|
|
||||||
err := QueryPerformanceCounter(&query)
|
err := QueryPerformanceCounter(&query)
|
||||||
assert(err != 0)
|
Assert(err != 0)
|
||||||
result := query->F64 / performance_frequency
|
result := query->F64 / PerformanceFrequency
|
||||||
return result
|
return result
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -67,7 +67,7 @@ time :: (): F64
|
|||||||
* Written by Lukás Chmela
|
* Written by Lukás Chmela
|
||||||
* Released under GPLv3.
|
* Released under GPLv3.
|
||||||
*/
|
*/
|
||||||
itoa :: (value: S64, result: *U8, base: S64): *U8
|
Itoa :: (value: S64, result: *U8, base: S64): *U8
|
||||||
// check that the base if valid
|
// check that the base if valid
|
||||||
if (base < 2) || (base > 36)
|
if (base < 2) || (base > 36)
|
||||||
*result = 0 // '
|
*result = 0 // '
|
||||||
@@ -94,14 +94,14 @@ itoa :: (value: S64, result: *U8, base: S64): *U8
|
|||||||
return result
|
return result
|
||||||
|
|
||||||
|
|
||||||
print :: (string: String, args: ..)
|
Print :: (string: String, args: ..)
|
||||||
buffer: [1024]U8
|
buffer: [1024]U8
|
||||||
buffer_len: S64
|
buffer_len: S64
|
||||||
|
|
||||||
arg_counter := 0
|
arg_counter := 0
|
||||||
for i := 0, i < length_of(string), i+=1
|
for i := 0, i < length_of(string), i+=1
|
||||||
if string[i] == '%'
|
if string[i] == '%'
|
||||||
assert(arg_counter < length_of(args), "Passing too many [%] to a print lambda")
|
Assert(arg_counter < length_of(args), "Passing too many [%] to a print lambda")
|
||||||
arg := args[arg_counter++]
|
arg := args[arg_counter++]
|
||||||
|
|
||||||
if arg.type == S64
|
if arg.type == S64
|
||||||
@@ -110,6 +110,6 @@ print :: (string: String, args: ..)
|
|||||||
p := itoa(value, &itoa_buff[0], 10)
|
p := itoa(value, &itoa_buff[0], 10)
|
||||||
for *p != 0
|
for *p != 0
|
||||||
buffer[buffer_len++] = *p++
|
buffer[buffer_len++] = *p++
|
||||||
else;; assert(false)
|
else;; Assert(false)
|
||||||
else
|
else
|
||||||
buffer[buffer_len++] = string[i]
|
buffer[buffer_len++] = string[i]
|
||||||
Reference in New Issue
Block a user