2024-06-15 03:37:50 -05:00
# HERE SHALL THE DOCUMENTATION RESIDE
2024-06-20 04:18:36 -05:00
## Enforced Political Views
2024-06-15 03:38:16 -05:00
2024-06-20 04:18:36 -05:00
- worse is better
- less is more
- embrace `unsafe {}`
- adhere `macro_rules!`
- pessimization == death (put in `std::pin::Pin` and left with hungry crabs)
- importing external dependencies == death (`fn(dependencies) -> ExecutionStrategy`)
- above sell not be disputed, discussed, or questioned
## What hblang is
Holey-Bytes-Language (hblang for short) (*.hb) is the only true language targeting hbvm byte code. hblang is low level, manually managed, and procedural. Its rumored to be better then writing hbasm and you should probably use it for complex applications.
## What hblang isnt't
hblang knows what it isn't, because it knows what it is, hblang computes this by sub...
2024-09-03 10:51:28 -05:00
2024-06-20 04:18:36 -05:00
## Examples
Examples are also used in tests. To add an example that runs during testing add:
2024-06-15 03:46:53 -05:00
< pre >
2024-06-15 03:49:02 -05:00
#### <name>
2024-06-15 03:48:42 -05:00
```hb
< example& gt
```
2024-06-15 03:46:53 -05:00
< / pre >
and also:
```rs
< name > => README;
```
to the `run_tests` macro at the bottom of the `src/codegen.rs` .
2024-06-20 04:18:36 -05:00
### Tour Examples
Following examples incrementally introduce language features and syntax.
#### main_fn
2024-06-15 03:37:50 -05:00
```hb
2024-06-20 04:18:36 -05:00
main := fn(): int {
return 1;
2024-06-15 03:37:50 -05:00
}
2024-06-20 04:18:36 -05:00
```
2024-06-15 03:37:50 -05:00
2024-06-20 04:18:36 -05:00
#### arithmetic
```hb
2024-06-15 03:37:50 -05:00
main := fn(): int {
2024-09-14 04:26:54 -05:00
return 10 - 20 / 2 + 4 * (2 + 2) - 4 * 4 + (1 < < 0 ) + -1
2024-06-20 04:18:36 -05:00
}
```
#### functions
```hb
main := fn(): int {
2024-07-19 14:04:22 -05:00
return add_one(10) + add_two(20)
2024-06-20 04:18:36 -05:00
}
add_two := fn(x: int): int {
2024-07-19 14:04:22 -05:00
return x + 2
2024-06-20 04:18:36 -05:00
}
add_one := fn(x: int): int {
2024-07-19 14:04:22 -05:00
return x + 1
2024-06-15 03:37:50 -05:00
}
```
2024-06-25 12:46:48 -05:00
#### comments
```hb
// commant is an item
main := fn(): int {
// comment is a statement
2024-09-01 14:05:17 -05:00
2024-07-19 14:04:22 -05:00
foo(/* comment is an exprression /* if you are crazy */ * /)
return 0
2024-06-25 12:46:48 -05:00
}
2024-07-19 14:04:22 -05:00
foo := fn(comment: void): void return /* comment evaluates to void */
2024-06-25 12:46:48 -05:00
// comments might be formatted in the future
```
2024-06-15 03:37:50 -05:00
#### if_statements
```hb
main := fn(): int {
2024-07-19 14:04:22 -05:00
return fib(10)
2024-06-15 03:37:50 -05:00
}
fib := fn(x: int): int {
if x < = 2 {
2024-07-19 14:04:22 -05:00
return 1
2024-06-15 03:37:50 -05:00
} else {
2024-07-19 14:04:22 -05:00
return fib(x - 1) + fib(x - 2)
2024-06-15 03:37:50 -05:00
}
}
```
2024-06-20 04:18:36 -05:00
#### variables
2024-06-15 03:37:50 -05:00
```hb
main := fn(): int {
2024-07-19 14:04:22 -05:00
ඞ := 1
b := 2
ඞ += 1
return ඞ - b
2024-06-15 03:37:50 -05:00
}
```
2024-06-20 04:18:36 -05:00
#### loops
2024-06-15 03:37:50 -05:00
```hb
main := fn(): int {
2024-07-19 14:04:22 -05:00
return fib(10)
2024-06-15 03:37:50 -05:00
}
2024-06-20 04:18:36 -05:00
fib := fn(n: int): int {
2024-07-19 14:04:22 -05:00
a := 0
b := 1
2024-09-06 11:50:28 -05:00
loop if n == 0 break else {
2024-07-19 14:04:22 -05:00
c := a + b
a = b
b = c
n -= 1
2024-06-20 04:18:36 -05:00
}
2024-07-19 14:04:22 -05:00
return a
2024-06-15 03:37:50 -05:00
}
```
2024-06-20 04:18:36 -05:00
#### pointers
2024-06-15 03:37:50 -05:00
```hb
main := fn(): int {
2024-07-19 14:04:22 -05:00
a := 1
b := & a
modify(b)
drop(a)
return *b - 2
2024-06-20 04:18:36 -05:00
}
2024-06-15 03:37:50 -05:00
2024-06-20 04:18:36 -05:00
modify := fn(a: ^int): void {
2024-07-19 14:04:22 -05:00
*a = 2
return
2024-06-15 03:37:50 -05:00
}
2024-06-20 04:18:36 -05:00
drop := fn(a: int): void {
2024-07-19 14:04:22 -05:00
return
2024-06-15 03:37:50 -05:00
}
```
#### structs
```hb
Ty := struct {
2024-09-14 05:27:53 -05:00
// comment
2024-06-15 03:37:50 -05:00
a: int,
b: int,
}
Ty2 := struct {
ty: Ty,
c: int,
}
2024-09-28 14:56:39 -05:00
useless := struct {}
2024-06-15 03:37:50 -05:00
main := fn(): int {
2024-09-28 14:56:39 -05:00
// `packed` structs have no padding (all fields are alighred to 1)
2024-09-22 11:17:30 -05:00
if @sizeof (packed struct {a: u8, b: u16}) != 3 {
return 9001
}
2024-09-28 14:56:39 -05:00
finst := Ty2.{ty: .{a: 4, b: 1}, c: 3}
2024-10-12 06:07:49 -05:00
inst := odher_pass(finst)
if inst.c == 3 {
return pass(& inst.ty)
}
return 0
2024-06-15 03:37:50 -05:00
}
pass := fn(t: ^Ty): int {
2024-10-12 06:07:49 -05:00
.{a, b} := *t
return a - b
2024-06-15 03:37:50 -05:00
}
odher_pass := fn(t: Ty2): Ty2 {
2024-07-19 14:04:22 -05:00
return t
2024-06-15 03:37:50 -05:00
}
```
2024-06-20 04:18:36 -05:00
#### struct_operators
2024-06-15 03:37:50 -05:00
```hb
2024-06-20 04:18:36 -05:00
Point := struct {
x: int,
y: int,
2024-06-15 03:37:50 -05:00
}
2024-06-20 04:18:36 -05:00
Rect := struct {
a: Point,
b: Point,
2024-06-15 03:37:50 -05:00
}
2024-06-20 04:18:36 -05:00
main := fn(): int {
2024-07-19 14:04:22 -05:00
a := Point.(1, 2)
b := Point.(3, 4)
2024-06-20 04:18:36 -05:00
2024-07-19 14:04:22 -05:00
d := Rect.(a + b, b - a)
2024-09-20 05:03:24 -05:00
zp := Point.(0, 0)
d2 := Rect.(zp - b, a)
2024-07-19 14:04:22 -05:00
d2 += d
2024-06-20 04:18:36 -05:00
2024-07-19 14:04:22 -05:00
c := d2.a + d2.b
return c.x + c.y
2024-06-15 03:37:50 -05:00
}
```
2024-06-20 04:18:36 -05:00
#### global_variables
2024-06-15 03:37:50 -05:00
```hb
2024-07-19 14:04:22 -05:00
global_var := 10
2024-06-20 04:18:36 -05:00
2024-07-19 14:04:22 -05:00
complex_global_var := fib(global_var) - 5
2024-06-20 04:18:36 -05:00
fib := fn(n: int): int {
if 2 > n {
2024-07-19 14:04:22 -05:00
return n
2024-06-20 04:18:36 -05:00
}
2024-07-19 14:04:22 -05:00
return fib(n - 1) + fib(n - 2)
2024-06-20 04:18:36 -05:00
}
2024-06-15 03:37:50 -05:00
main := fn(): int {
2024-09-08 05:00:07 -05:00
complex_global_var += 5
2024-07-19 14:04:22 -05:00
return complex_global_var
2024-06-15 03:37:50 -05:00
}
2024-06-20 04:18:36 -05:00
```
note: values of global variables are evaluated at compile time
2024-06-15 03:37:50 -05:00
2024-06-20 04:18:36 -05:00
#### directives
```hb
2024-07-19 14:04:22 -05:00
foo := @use ("foo.hb")
2024-06-15 03:37:50 -05:00
2024-06-20 04:18:36 -05:00
main := fn(): int {
2024-07-19 14:04:22 -05:00
byte := @as (u8, 10)
same_type_as_byte := @as (@TypeOf(byte), 30)
wide_uint := @as (u32, 40)
truncated_uint := @as (u8, @intcast (wide_uint))
size_of_Type_in_bytes := @sizeof (foo.Type)
align_of_Type_in_bytes := @alignof (foo.Type)
hardcoded_pointer := @as (^u8, @bitcast (10))
2024-09-17 11:11:07 -05:00
ecall_that_returns_int := @as (int, @eca (1, foo.Type.(10, 20), 5, 6))
2024-09-01 19:38:11 -05:00
return @inline (foo.foo)
2024-06-15 03:37:50 -05:00
}
2024-07-08 04:00:35 -05:00
2024-09-18 03:07:40 -05:00
// in module: foo.hb
2024-07-08 04:00:35 -05:00
Type := struct {
brah: int,
blah: int,
}
2024-09-01 19:38:11 -05:00
foo := fn(): int return 0
2024-06-20 04:18:36 -05:00
```
2024-06-15 03:37:50 -05:00
2024-07-08 04:00:35 -05:00
- `@use(<string>)` : imports a module based of string, the string is passed to a loader that can be customized, default loader uses following syntax:
- `((rel:|)(<path>)|git:<git-addr>:<path>)` : `rel:` and `''` prefixes both mean module is located at `path` relavive to the current file, `git:` takes a git url without `https://` passed as `git-addr` , `path` then refers to file within the repository
2024-06-20 04:18:36 -05:00
- `@TypeOf(<expr>)` : results into literal type of whatever the type of `<expr>` is, `<expr>` is not included in final binary
- `@as(<ty>, <expr>)` : hint to the compiler that `@TypeOf(<expr>) == <ty>`
- `@intcast(<expr>)` : needs to be used when conversion of `@TypeOf(<expr>)` would loose precision (widening of integers is implicit)
- `@sizeof(<ty>), @alignof(<ty>)` : I think explaining this would insult your intelligence
- `@bitcast(<expr>)` : tell compiler to assume `@TypeOf(<expr>)` is whatever is inferred, so long as size and alignment did not change
2024-09-01 19:38:11 -05:00
- `@eca(<ty>, ...<expr>)` : invoke `eca` instruction, where `<ty>` is the type this will return and `<expr>...` are arguments passed to the call
- `@inline(<func>, ...<args>)` : equivalent to `<func>(...<args>)` but function is guaranteed to inline, compiler will otherwise never inline
2024-06-15 03:37:50 -05:00
2024-07-02 07:49:05 -05:00
#### c_strings
```hb
2024-07-07 06:42:48 -05:00
str_len := fn(str: ^u8): int {
2024-07-19 14:04:22 -05:00
len := 0
2024-07-07 06:42:48 -05:00
loop if *str == 0 break else {
2024-07-19 14:04:22 -05:00
len += 1
str += 1
2024-07-02 07:49:05 -05:00
}
2024-07-19 14:04:22 -05:00
return len
2024-07-02 07:49:05 -05:00
}
2024-07-07 06:42:48 -05:00
main := fn(): int {
// when string ends with '\0' its a C string and thus type is '^u8'
2024-09-04 11:43:08 -05:00
some_str := "abඞ\n\r\t\{35}\{36373839}\0"
2024-07-19 14:04:22 -05:00
len := str_len(some_str)
some_other_str := "fff\0"
lep := str_len(some_other_str)
return lep + len
2024-07-07 06:42:48 -05:00
}
2024-07-02 07:49:05 -05:00
```
2024-07-08 04:00:35 -05:00
#### struct_patterns
```hb
2024-07-19 14:04:22 -05:00
.{fib, fib_iter, Fiber} := @use ("fibs.hb")
2024-07-08 04:00:35 -05:00
main := fn(): int {
2024-07-19 14:04:22 -05:00
.{a, b} := Fiber.{a: 10, b: 10}
return fib(a) - fib_iter(b)
2024-07-08 04:00:35 -05:00
}
// in module: fibs.hb
2024-07-19 14:04:22 -05:00
Fiber := struct {a: u8, b: u8}
2024-07-08 04:00:35 -05:00
fib := fn(n: int): int if n < 2 {
2024-07-19 14:04:22 -05:00
return n
2024-07-08 04:00:35 -05:00
} else {
2024-07-19 14:04:22 -05:00
return fib(n - 1) + fib(n - 2)
}
2024-07-08 04:00:35 -05:00
fib_iter := fn(n: int): int {
2024-07-19 14:04:22 -05:00
a := 0
b := 1
2024-07-08 04:00:35 -05:00
loop if n == 0 break else {
2024-07-19 14:04:22 -05:00
c := a + b
a = b
b = c
n -= 1
2024-07-08 04:00:35 -05:00
}
2024-07-19 14:04:22 -05:00
return a
2024-07-08 04:00:35 -05:00
}
```
2024-07-08 11:08:58 -05:00
#### arrays
```hb
main := fn(): int {
2024-09-16 14:46:02 -05:00
addr := @as (u16, 0x1FF)
msg := [u8].(0, 0, @as (u8, addr & 0xFF), @as (u8, addr >> 8 & 0xFF))
_force_stack := & msg
2024-07-19 14:04:22 -05:00
arr := [int].(1, 2, 4)
2024-09-16 14:46:02 -05:00
return pass(& arr) + msg[3]
2024-07-08 11:08:58 -05:00
}
pass := fn(arr: ^[int; 3]): int {
2024-07-19 14:04:22 -05:00
return arr[0] + arr[1] + arr[arr[1]]
2024-07-08 11:08:58 -05:00
}
```
2024-09-01 19:38:11 -05:00
#### inline
```hb
main := fn(): int {
return @inline (foo, 1, 2, 3) - 6
}
foo := fn(a: int, b: int, c: int): int {
return a + b + c
}
```
2024-09-09 12:36:53 -05:00
#### idk
```hb
2024-09-12 11:42:21 -05:00
_edge_case := @as (int, idk)
2024-09-09 12:36:53 -05:00
main := fn(): int {
big_array := @as ([u8; 128], idk)
i := 0
loop if i >= 128 break else {
big_array[i] = 69
i += 1
}
return big_array[42]
}
```
2024-09-17 08:47:23 -05:00
#### wide_ret
```hb
OemIdent := struct {
dos_version: [u8; 8],
dos_version_name: [u8; 8],
}
2024-09-17 10:59:03 -05:00
Stru := struct {
a: u16,
b: u16,
}
small_struct := fn(): Stru {
return .{a: 0, b: 0}
}
2024-09-17 08:47:23 -05:00
main := fn(major: int, minor: int): OemIdent {
2024-09-17 10:59:03 -05:00
small_struct()
2024-09-17 08:47:23 -05:00
ver := [u8].(0, 0, 0, 0, 0, 0, 0, 0)
return OemIdent.(ver, ver)
}
```
2024-06-20 04:18:36 -05:00
### Incomplete Examples
2024-06-15 03:37:50 -05:00
2024-10-13 06:30:00 -05:00
#### wired_mem_swap
```hb
Color := struct {x: int}
put_trisquare := fn(pos: Vec2(int), size: Vec2(int), color: Color): void {
step := Vec2(int).(1, 1)
if size.x < 0 {
step.x = -1
}
if size.y < 0 {
step.y = -1
}
target := pos + size
loop if pos.x == target.x break else {
put_vline(pos.x, pos.y, target.y, color)
pos.x += step.x
}
return
}
put_vline := fn(x: int, y0: int, y1: int, color: Color): void {
return
}
Vec2 := fn($Expr: type): type {
return struct {x: Expr, y: Expr}
}
MemSwap := fn($Expr: type): type {
return struct {a: Expr, b: Expr}
}
memswap := fn($Expr: type, a: ^Expr, b: ^Expr): void {
MemSwap(Expr).(b, a) = MemSwap(Expr).(*a, *b)
return
}
main := fn(): int {
put_trisquare(.(0, 0), .(0, 0), .(0))
a := 10
b := 50
//memswap(int, a, b)
return a
}
```
2024-07-19 05:00:55 -05:00
#### comptime_pointers
```hb
main := fn(): int {
2024-07-19 14:04:22 -05:00
$integer := 7
modify(& integer)
return integer
2024-07-19 05:00:55 -05:00
}
modify := fn($num: ^int): void {
2024-07-19 14:04:22 -05:00
$: *num = 0
2024-07-19 05:00:55 -05:00
}
```
2024-06-20 04:18:36 -05:00
#### generic_types
2024-06-15 03:37:50 -05:00
```hb
2024-06-24 10:26:00 -05:00
MALLOC_SYS_CALL := 69
FREE_SYS_CALL := 96
2024-09-17 11:11:07 -05:00
malloc := fn(size: uint, align: uint): ^void return @eca (MALLOC_SYS_CALL, size, align)
free := fn(ptr: ^void, size: uint, align: uint): void return @eca (FREE_SYS_CALL, ptr, size, align)
2024-06-24 10:26:00 -05:00
2024-06-20 04:18:36 -05:00
Vec := fn($Elem: type): type {
return struct {
data: ^Elem,
len: uint,
cap: uint,
2024-07-19 14:04:22 -05:00
}
2024-06-20 04:18:36 -05:00
}
2024-07-19 14:04:22 -05:00
new := fn($Elem: type): Vec(Elem) return Vec(Elem).{data: @bitcast (0), len: 0, cap: 0}
2024-06-24 10:26:00 -05:00
deinit := fn($Elem: type, vec: ^Vec(Elem)): void {
2024-06-24 10:45:58 -05:00
free(@bitcast(vec.data), vec.cap * @sizeof (Elem), @alignof (Elem));
2024-07-19 14:04:22 -05:00
*vec = new(Elem)
2024-07-19 06:51:38 -05:00
return
2024-06-24 10:26:00 -05:00
}
push := fn($Elem: type, vec: ^Vec(Elem), value: Elem): ^Elem {
if vec.len == vec.cap {
if vec.cap == 0 {
2024-07-19 14:04:22 -05:00
vec.cap = 1
2024-06-24 10:26:00 -05:00
} else {
2024-07-19 14:04:22 -05:00
vec.cap *= 2
2024-06-24 10:26:00 -05:00
}
2024-07-19 14:04:22 -05:00
new_alloc := @as (^Elem, @bitcast (malloc(vec.cap * @sizeof (Elem), @alignof (Elem))))
if new_alloc == 0 return 0
src_cursor := vec.data
dst_cursor := new_alloc
end := vec.data + vec.len
2024-06-24 10:26:00 -05:00
loop if src_cursor == end break else {
2024-07-19 14:04:22 -05:00
*dst_cursor = *src_cursor
src_cursor += 1
dst_cursor += 1
2024-06-24 10:26:00 -05:00
}
2024-06-24 10:45:58 -05:00
if vec.len != 0 {
2024-07-19 14:04:22 -05:00
free(@bitcast(vec.data), vec.len * @sizeof (Elem), @alignof (Elem))
2024-06-24 10:45:58 -05:00
}
2024-07-19 14:04:22 -05:00
vec.data = new_alloc
2024-06-24 10:26:00 -05:00
}
slot := vec.data + vec.len;
2024-07-19 14:04:22 -05:00
*slot = value
vec.len += 1
return slot
2024-06-24 10:26:00 -05:00
}
2024-06-15 03:37:50 -05:00
main := fn(): int {
2024-07-19 14:04:22 -05:00
vec := new(int)
push(int, & vec, 69)
res := *vec.data
deinit(int, & vec)
return res
2024-06-15 03:37:50 -05:00
}
```
2024-06-24 10:26:00 -05:00
#### generic_functions
```hb
2024-07-19 14:04:22 -05:00
add := fn($T: type, a: T, b: T): T return a + b
2024-06-24 10:26:00 -05:00
main := fn(): int {
2024-07-19 14:04:22 -05:00
return add(u32, 2, 2) - add(int, 1, 3)
2024-06-24 10:26:00 -05:00
}
```
2024-06-20 04:18:36 -05:00
#### fb_driver
2024-06-15 03:37:50 -05:00
```hb
2024-07-19 14:04:22 -05:00
arm_fb_ptr := fn(): int return 100
x86_fb_ptr := fn(): int return 100
2024-06-20 04:18:36 -05:00
check_platform := fn(): int {
2024-07-19 14:04:22 -05:00
return x86_fb_ptr()
2024-06-15 03:37:50 -05:00
}
2024-06-20 04:18:36 -05:00
set_pixel := fn(x: int, y: int, width: int): int {
2024-09-08 10:11:33 -05:00
return y * width + x
2024-06-20 04:18:36 -05:00
}
2024-06-15 03:37:50 -05:00
2024-06-20 04:18:36 -05:00
main := fn(): int {
2024-07-19 14:04:22 -05:00
fb_ptr := check_platform()
width := 100
height := 30
x := 0
y := 0
2024-09-15 13:14:56 -05:00
//t := 0
2024-09-08 10:11:33 -05:00
i := 0
2024-07-19 14:04:22 -05:00
loop {
2024-09-15 13:14:56 -05:00
if x < height {
//t += set_pixel(x, y, height)
2024-07-19 14:04:22 -05:00
x += 1
2024-09-15 13:14:56 -05:00
i += 1
2024-07-19 14:04:22 -05:00
} else {
x = 0
y += 1
2024-09-15 13:14:56 -05:00
if set_pixel(x, y, height) != i return 0
if y == width break
2024-07-19 14:04:22 -05:00
}
}
2024-09-15 13:14:56 -05:00
return i
2024-06-15 03:37:50 -05:00
}
```
2024-06-20 04:18:36 -05:00
### Purely Testing Examples
2024-09-01 15:07:45 -05:00
#### comptime_min_reg_leak
```hb
2024-09-01 16:14:48 -05:00
a := @use ("math.hb").min(100, 50)
main := fn(): int {
return a
}
// in module: math.hb
2024-09-01 15:07:45 -05:00
SIZEOF_INT := 32
SHIFT := SIZEOF_INT - 1
min := fn(a: int, b: int): int {
c := a - b
return b + (c & c >> SHIFT)
}
```
2024-06-15 03:37:50 -05:00
#### different_types
```hb
Color := struct {
r: u8,
g: u8,
b: u8,
a: u8,
}
Point := struct {
x: u32,
y: u32,
}
Pixel := struct {
color: Color,
point: Point,
}
main := fn(): int {
pixel := Pixel.{
color: Color.{
r: 255,
g: 0,
b: 0,
a: 255,
},
point: Point.{
x: 0,
y: 2,
},
2024-07-19 14:04:22 -05:00
}
soupan := 1
2024-07-07 05:15:48 -05:00
if *(& pixel.point.x + soupan) != 2 {
2024-07-19 14:04:22 -05:00
return 0
2024-06-15 03:37:50 -05:00
}
if *(& pixel.point.y - 1) != 0 {
2024-07-19 14:04:22 -05:00
return 64
2024-06-15 03:37:50 -05:00
}
return pixel.point.x + pixel.point.y + pixel.color.r
2024-07-19 14:04:22 -05:00
+ pixel.color.g + pixel.color.b + pixel.color.a
2024-06-15 03:37:50 -05:00
}
```
2024-07-18 10:55:55 -05:00
#### struct_return_from_module_function
```hb
2024-07-19 14:04:22 -05:00
bar := @use ("bar.hb")
2024-07-18 10:55:55 -05:00
main := fn(): int {
2024-07-19 14:04:22 -05:00
return 7 - bar.foo().x - bar.foo().y - bar.foo().z
2024-07-18 10:55:55 -05:00
}
// in module: bar.hb
2024-07-20 11:52:24 -05:00
foo := fn(): Foo {
2024-07-19 14:04:22 -05:00
return .{x: 3, y: 2, z: 2}
2024-07-18 10:55:55 -05:00
}
2024-07-20 11:52:24 -05:00
Foo := struct {x: int, y: u32, z: u32}
2024-07-18 10:55:55 -05:00
```
2024-07-21 03:29:58 -05:00
#### sort_something_viredly
```hb
main := fn(): int {
foo := sqrt
return 0
}
sqrt := fn(x: int): int {
temp := 0
g := 0
b := 32768
bshift := 15
loop if b == 0 break else {
bshift -= 1
temp = b + (g < < 1 )
temp < < = bshift
if x >= temp {
g += b
x -= temp
}
b >>= 1
}
return g
}
```
2024-09-01 14:07:19 -05:00
#### hex_octal_binary_literals
```hb
main := fn(): int {
hex := 0xFF
decimal := 255
octal := 0o377
binary := 0b11111111
if hex == decimal & octal == decimal & binary == decimal {
return 0
}
return 1
}
2024-09-01 15:07:45 -05:00
```
2024-09-01 16:14:48 -05:00
#### structs_in_registers
```hb
ColorBGRA := struct {b: u8, g: u8, r: u8, a: u8}
MAGENTA := ColorBGRA.{b: 205, g: 0, r: 205, a: 255}
main := fn(): int {
color := MAGENTA
return color.r
}
```
#### comptime_function_from_another_file
```hb
stn := @use ("stn.hb")
CONST_A := 100
CONST_B := 50
a := stn.math.min(CONST_A, CONST_B)
main := fn(): int {
return a
}
// in module: stn.hb
math := @use ("math.hb")
// in module: math.hb
SIZEOF_INT := 32
SHIFT := SIZEOF_INT - 1
min := fn(a: int, b: int): int {
c := a - b
return b + (c & c >> SHIFT)
}
```
2024-09-01 20:21:39 -05:00
2024-09-03 10:51:28 -05:00
### Just Testing Optimizations
#### const_folding_with_arg
```hb
main := fn(arg: int): int {
// reduces to 0
return arg + 0 - arg * 1 + arg + 1 + arg + 2 + arg + 3 - arg * 3 - 6
}
```
2024-09-05 18:17:54 -05:00
#### branch_assignments
```hb
main := fn(arg: int): int {
if arg == 1 {
arg = 1
} else if arg == 0 {
arg = 2
} else {
arg = 3
}
return arg
}
```
2024-09-01 20:21:39 -05:00
#### inline_test
```hb
Point := struct {x: int, y: int}
Buffer := struct {}
2024-09-01 20:37:49 -05:00
Transform := Point
2024-09-01 20:21:39 -05:00
ColorBGRA := Point
line := fn(buffer: Buffer, p0: Point, p1: Point, color: ColorBGRA, thickness: int): void {
if true {
if p0.x > p1.x {
@inline (line_low, buffer, p1, p0, color)
} else {
@inline (line_low, buffer, p0, p1, color)
}
} else {
if p0.y > p1.y {
2024-09-15 13:14:56 -05:00
// blah, test leading new line on directives
2024-09-01 20:21:39 -05:00
@inline (line_high, buffer, p1, p0, color)
} else {
@inline (line_high, buffer, p0, p1, color)
}
}
return
}
line_low := fn(buffer: Buffer, p0: Point, p1: Point, color: ColorBGRA): void {
return
}
line_high := fn(buffer: Buffer, p0: Point, p1: Point, color: ColorBGRA): void {
return
}
2024-09-01 20:37:49 -05:00
screenidx := @use ("screen.hb").screenidx
rect_line := fn(buffer: Buffer, pos: Point, tr: Transform, color: ColorBGRA, thickness: int): void {
t := 0
y := 0
x := 0
loop if t == thickness break else {
y = pos.y
x = pos.x
loop if y == pos.y + tr.x break else {
a := 1 + @inline (screenidx, 10)
a = 1 + @inline (screenidx, 2)
y += 1
}
t += 1
}
return
}
2024-09-01 21:45:42 -05:00
random := @use ("random.hb")
example := fn(): void {
loop {
random_x := @inline (random.integer, 0, 1024)
random_y := random.integer(0, 768)
2024-09-04 09:54:34 -05:00
a := @inline (screenidx, random_x)
2024-09-01 21:45:42 -05:00
break
}
return
}
2024-09-01 20:21:39 -05:00
main := fn(): int {
line(.(), .(0, 0), .(0, 0), .(0, 0), 10)
2024-09-01 20:37:49 -05:00
rect_line(.(), .(0, 0), .(0, 0), .(0, 0), 10)
2024-09-01 21:45:42 -05:00
example()
return 0
2024-09-01 20:21:39 -05:00
}
2024-09-01 20:37:49 -05:00
// in module: screen.hb
screenidx := fn(orange: int): int {
return orange
}
2024-09-01 21:45:42 -05:00
// in module: random.hb
integer := fn(min: int, max: int): int {
2024-09-17 11:11:07 -05:00
rng := @as (int, @eca (3, 4))
2024-09-01 21:45:42 -05:00
if min != 0 | max != 0 {
return rng % (max - min + 1) + min
}
return rng
}
2024-09-01 20:21:39 -05:00
```
2024-09-04 09:54:34 -05:00
2024-10-12 15:03:53 -05:00
#### inlined_generic_functions
```hb
abs := fn($Expr: type, x: Expr): Expr {
mask := x >> @bitcast (@sizeof(Expr) - 1)
return (x ^ mask) - mask
}
main := fn(): int {
return @inline (abs, int, -10)
}
```
2024-09-04 09:54:34 -05:00
#### some_generic_code
```hb
some_func := fn($Elem: type): void {
return
}
main := fn(): void {
2024-09-04 11:48:25 -05:00
some_func(u8)
2024-09-04 09:54:34 -05:00
return
}
```
2024-09-05 19:42:07 -05:00
#### integer_inference_issues
```hb
.{integer_range} := @use ("random.hb")
main := fn(): void {
a := integer_range(0, 1000)
return
}
// in module: random.hb
integer_range := fn(min: uint, max: int): uint {
2024-09-17 11:11:07 -05:00
return @eca (3, 4) % (@bitcast(max) - min + 1) + min
2024-09-05 19:42:07 -05:00
}
```
2024-09-06 11:50:28 -05:00
#### exhaustive_loop_testing
```hb
2024-09-06 15:00:23 -05:00
main := fn(): int {
if multiple_breaks(0) != 3 {
2024-09-06 11:50:28 -05:00
return 1
}
if multiple_breaks(4) != 10 {
return 2
}
2024-09-15 13:14:56 -05:00
if state_change_in_break(0) != 0 {
return 3
}
2024-09-06 11:50:28 -05:00
2024-09-15 13:14:56 -05:00
if state_change_in_break(4) != 10 {
return 4
}
2024-09-06 11:50:28 -05:00
2024-09-15 13:14:56 -05:00
if continue_and_state_change(10) != 10 {
return 5
}
2024-09-06 11:50:28 -05:00
2024-09-15 13:14:56 -05:00
if continue_and_state_change(3) != 0 {
return 6
}
2024-09-06 11:50:28 -05:00
return 0
}
multiple_breaks := fn(arg: int): int {
loop if arg < 10 {
arg += 1
2024-09-07 20:12:57 -05:00
if arg == 3 break
2024-09-06 11:50:28 -05:00
} else break
return arg
}
2024-09-15 13:14:56 -05:00
state_change_in_break := fn(arg: int): int {
loop if arg < 10 {
if arg == 3 {
arg = 0
break
}
arg += 1
} else break
return arg
}
continue_and_state_change := fn(arg: int): int {
loop if arg < 10 {
if arg == 2 {
arg = 4
continue
}
if arg == 3 {
arg = 0
break
}
arg += 1
} else break
return arg
}
2024-09-06 11:50:28 -05:00
```
2024-09-08 10:11:33 -05:00
#### writing_into_string
```hb
outl := fn(): void {
2024-09-08 10:25:33 -05:00
msg := "whahaha\0"
2024-09-08 10:11:33 -05:00
@as (u8, 0)
return
}
inl := fn(): void {
2024-09-08 10:25:33 -05:00
msg := "luhahah\0"
2024-09-08 10:11:33 -05:00
return
}
main := fn(): void {
outl()
inl()
return
}
```
2024-09-09 15:17:54 -05:00
#### request_page
```hb
request_page := fn(page_count: u8): ^u8 {
msg := "\{00}\{01}xxxxxxxx\0"
msg_page_count := msg + 1;
*msg_page_count = page_count
2024-09-17 11:11:07 -05:00
return @eca (3, 2, msg, 12)
2024-09-09 15:17:54 -05:00
}
create_back_buffer := fn(total_pages: int): ^u32 {
if total_pages < = 0xFF {
return @bitcast (request_page(total_pages))
}
ptr := request_page(255)
remaining := total_pages - 0xFF
loop if remaining < = 0 break else {
if remaining < 0xFF {
request_page(remaining)
} else {
request_page(0xFF)
}
remaining -= 0xFF
}
return @bitcast (ptr)
}
main := fn(): void {
2024-09-09 15:52:34 -05:00
create_back_buffer(400)
2024-09-09 15:17:54 -05:00
return
}
```
2024-09-09 18:15:18 -05:00
#### tests_ptr_to_ptr_copy
```hb
main := fn(): int {
back_buffer := @as ([u8; 1024 * 10], idk)
n := 0
loop if n >= 1024 break else {
back_buffer[n] = 64
n += 1
}
n = 1
loop if n >= 10 break else {
*(@as(^[u8; 1024], @bitcast(&back_buffer)) + n) = * @as (^[u8; 1024], @bitcast (& back_buffer))
n += 1
}
return back_buffer[1024 * 2]
}
```
2024-09-28 08:13:32 -05:00
#### pointer_opts
```hb
main := fn(): int {
mem := &0;
*mem = 1;
*mem = 2
b := *mem + *mem
clobber(mem)
b -= *mem
return b
}
clobber := fn(cb: ^int): void {
*cb = 4
return
}
```