holey-bytes/lang/README.md

2011 lines
37 KiB
Markdown
Raw Normal View History

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...
## 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
#### &lt;name&gt
2024-06-15 03:48:42 -05:00
```hb
&lt;example&gt
```
2024-06-15 03:46:53 -05:00
</pre>
and also:
```rs
2024-10-27 13:55:11 -05:00
<name>;
2024-06-15 03:46:53 -05:00
```
2024-10-27 13:55:11 -05:00
to the `run_tests` macro at the bottom of the `src/son.rs`.
2024-06-15 03:46:53 -05:00
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-10-25 07:51:33 -05:00
main := fn(): uint {
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-10-25 07:51:33 -05:00
main := fn(): uint {
return 10 - 20 / 2 + 4 * (2 + 2) - 4 * 4 + (true << 0) + -1
2024-06-20 04:18:36 -05:00
}
```
2024-11-17 09:25:39 -06:00
2024-10-29 07:36:12 -05:00
#### floating_point_arithmetic
```hb
main := fn(): f32 {
return 10. - 20. / 2. + 4. * (2. + 2.) - 4. * 4. + -1.
}
```
2024-06-20 04:18:36 -05:00
#### functions
```hb
2024-10-25 07:51:33 -05:00
main := fn(): uint {
2024-07-19 14:04:22 -05:00
return add_one(10) + add_two(20)
2024-06-20 04:18:36 -05:00
}
2024-10-25 07:51:33 -05:00
add_two := fn(x: uint): uint {
2024-07-19 14:04:22 -05:00
return x + 2
2024-06-20 04:18:36 -05:00
}
2024-10-25 07:51:33 -05:00
add_one := fn(x: uint): uint {
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
2024-10-25 07:51:33 -05:00
main := fn(): uint {
2024-06-25 12:46:48 -05:00
// 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
2024-10-25 07:51:33 -05:00
main := fn(): uint {
2024-07-19 14:04:22 -05:00
return fib(10)
2024-06-15 03:37:50 -05:00
}
2024-10-25 07:51:33 -05:00
fib := fn(x: uint): uint {
2024-06-15 03:37:50 -05:00
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
2024-10-25 07:51:33 -05:00
main := fn(): uint {
2024-07-19 14:04:22 -05:00
ඞ := 1
b := 2
ඞ += 1
return ඞ - b
2024-06-15 03:37:50 -05:00
}
```
2024-11-17 09:25:39 -06:00
#### hex_octal_binary_literals
```hb
main := fn(): uint {
hex := 0xFF
decimal := 255
octal := 0o377
binary := 0b11111111
ascii := '\n'
2024-11-17 09:25:39 -06:00
if hex == decimal & octal == decimal & binary == decimal {
return 0
}
2024-11-17 09:25:39 -06:00
return 1
}
```
2024-06-20 04:18:36 -05:00
#### loops
2024-06-15 03:37:50 -05:00
```hb
2024-10-25 07:51:33 -05:00
main := fn(): uint {
2024-07-19 14:04:22 -05:00
return fib(10)
2024-06-15 03:37:50 -05:00
}
2024-10-25 07:51:33 -05:00
fib := fn(n: uint): uint {
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
2024-10-25 07:51:33 -05:00
main := fn(): uint {
2024-07-19 14:04:22 -05:00
a := 1
b := &a
2024-10-13 08:22:16 -05:00
boundary := 1000
b = b + boundary - 2
b = b - (boundary - 2)
2024-07-19 14:04:22 -05:00
modify(b)
drop(a)
return *b - 2
2024-06-20 04:18:36 -05:00
}
2024-06-15 03:37:50 -05:00
2024-10-25 07:51:33 -05:00
modify := fn(a: ^uint): void {
2024-07-19 14:04:22 -05:00
*a = 2
return
2024-06-15 03:37:50 -05:00
}
2024-10-25 07:51:33 -05:00
drop := fn(a: uint): void {
2024-07-19 14:04:22 -05:00
return
2024-06-15 03:37:50 -05:00
}
```
2024-11-17 09:25:39 -06:00
#### structs
```hb
Ty := struct {
// comment
a: uint,
}
Ty2 := struct {
ty: Ty,
c: uint = 3,
2024-11-17 09:25:39 -06:00
}
useless := struct {}
main := fn(): uint {
// `packed` structs have no padding (all fields are alighred to 1)
if @sizeof(packed struct {a: u8, b: u16}) != 3 {
return 9001
}
finst := Ty2.{ty: .{a: 4}}
2024-11-17 09:25:39 -06:00
inst := odher_pass(finst)
if inst.c == 3 {
return pass(&inst.ty)
}
return 0
}
pass := fn(t: ^Ty): uint {
return t.a
}
odher_pass := fn(t: Ty2): Ty2 {
return t
}
```
#### tuples
```hb
main := fn(): uint {
tupl := .(1, 1)
return tupl[0] - tupl[1]
}
```
2024-11-24 07:47:38 -06:00
#### struct_scopes
```hb
$zr := 0
Struct := struct {
a: uint,
b: uint,
$zero := Self.(zr, zr)
$new := fn(a: uint, b: uint): Self return .(a, b)
$swap := fn(s: ^Self): void {
2024-11-24 09:43:45 -06:00
_ = diff(*s)
2024-11-24 07:47:38 -06:00
t := s.a
s.a = s.b
s.b = t
}
$diff := fn(s: Self): uint return s.a - s.b
}
main := fn(): uint {
z := Struct.zero
z += Struct.new(1, 2)
z.swap()
return z.diff()
}
```
2024-11-17 09:25:39 -06:00
#### enums
```hb
Enum := enum {
A,
B,
C,
$default := Self.A
}
2024-11-17 09:25:39 -06:00
some_enum := fn(): Enum return .A
main := fn(): uint {
e := some_enum()
match e {
Enum.default => return 0,
2024-11-17 09:25:39 -06:00
_ => return 100,
}
}
```
#### unions
```hb
Union := union {
i: u32,
f: f32,
$sconst := 0
$new := fn(i: u32): Self {
return .{i}
}
}
main := fn(): uint {
v := Union.{f: 0}
u := Union.new(Union.sconst)
return v.i + u.i
}
```
2024-10-30 14:20:03 -05:00
#### nullable_types
```hb
2024-10-31 04:56:59 -05:00
main := fn(): uint {
2024-10-30 14:20:03 -05:00
a := &1
b := @as(?^uint, null)
if decide() b = a
if b == null return 9001
c := @as(?uint, *b)
if decide() c = null
if c != null return 42
2024-10-31 04:36:18 -05:00
d := @as(?u16, null)
2024-10-31 04:56:59 -05:00
if decide() d = 1
2024-10-31 04:36:18 -05:00
if d == null return 69
sf := new_foo()
if sf == null return 999
str := "foo\0"
use_foo(sf, str)
f := no_foo()
2024-10-31 04:56:59 -05:00
if decide() f = .(a, 1)
if f == null return 34
bar := new_bar(a)
2024-10-31 05:03:58 -05:00
if decide() bar = null
if bar != null return 420
2024-11-03 03:15:03 -06:00
g := @as(?^uint, null)
g = a
_rd := *g
2024-10-31 04:56:59 -05:00
return d - *f.a
2024-10-30 14:20:03 -05:00
}
2024-10-31 04:56:59 -05:00
Foo := struct {a: ^uint, b: uint}
no_foo := fn(): ?Foo return null
new_foo := fn(): ?Foo return .(&0, 0)
use_foo := fn(foo: Foo, str: ^u8): void {
}
2024-10-31 04:56:59 -05:00
2024-10-31 05:03:58 -05:00
Bar := struct {a: ?^uint, b: uint}
new_bar := fn(a: ?^uint): ?Bar return .(a, 1)
2024-10-31 05:03:58 -05:00
2024-11-11 15:14:54 -06:00
decide := fn(): bool return !false
2024-10-30 14:20:03 -05:00
```
2024-11-13 09:18:21 -06:00
#### inline_return_stack
```hb
$fun := fn(): [uint; 3] {
res := [uint].(0, 1, 2)
return res
}
main := fn(): uint {
vl := fun()
return vl[0]
}
```
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 {
2024-10-25 07:51:33 -05:00
x: uint,
y: uint,
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-10-17 08:48:22 -05:00
Color := packed struct {b: u8, g: u8, r: u8, a: u8}
2024-10-25 07:51:33 -05:00
main := fn(): uint {
2024-10-17 08:48:22 -05:00
i := Color.(0, 0, 0, 0)
i += .(1, 1, 1, 1)
if i.r + i.g + i.b + i.a != 4 return 1008
if Point.(1, 1) != Point.(1, 1) return 1009
if Point.(1, 2) == Point.(1, 1) return 1010
if Point.(1, 2) < Point.(1, 1) return 1011
if Point.(1, 1) > Point.(2, 1) return 1012
2024-10-17 08:48:22 -05:00
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)
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
2024-10-25 07:51:33 -05:00
fib := fn(n: uint): uint {
2024-06-20 04:18:36 -05:00
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
2024-10-25 07:51:33 -05:00
main := fn(): uint {
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-11-08 03:57:58 -06:00
#### constants
```hb
main := fn(): u32 {
2024-11-17 13:04:53 -06:00
return SOME_CONST + 35
2024-11-08 03:57:58 -06:00
}
2024-11-17 13:04:53 -06:00
$SOME_CONST := 34
2024-11-08 03:57:58 -06: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-10-25 07:51:33 -05:00
main := fn(): uint {
if false {
@error("unexpected '\0", u8, "', wah now?\0")
}
byte := @as(@ChildOf(^u8), 10)
_ = sum(byte, byte)
2024-07-19 14:04:22 -05:00
same_type_as_byte := @as(@TypeOf(byte), 30)
wide_uint := @as(u32, 40)
_ = sum(wide_uint, wide_uint)
2024-07-19 14:04:22 -05:00
truncated_uint := @as(u8, @intcast(wide_uint))
2024-10-29 08:24:31 -05:00
widened_float := @as(f64, @floatcast(1.))
int_from_float := @as(int, @fti(1.))
2024-11-15 16:18:40 -06:00
float_from_int := @as(f64, @itf(1))
2024-07-19 14:04:22 -05:00
size_of_Type_in_bytes := @sizeof(foo.Type)
align_of_Type_in_bytes := @alignof(foo.Type)
hardcoded_pointer := @as(^u8, @bitcast(10))
2024-10-25 07:51:33 -05:00
ecall_that_returns_uint := @as(uint, @eca(1, foo.Type.(10, 20), 5, 6))
2024-10-21 12:57:55 -05:00
embedded_array := @as([u8; 15], @embed("text.txt"))
two_fields := @len(foo.Type)
string_length := @len("foo\0")
the_struct_kind := @kindof(foo.Type)
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
$sum := fn(a: @Any(), b: @TypeOf(a)): @TypeOf(a) return a + b
// in module: foo.hb
2024-07-08 04:00:35 -05:00
Type := struct {
2024-10-25 07:51:33 -05:00
brah: uint,
blah: uint,
2024-07-08 04:00:35 -05:00
}
2024-09-01 19:38:11 -05:00
2024-10-25 07:51:33 -05:00
foo := fn(): uint return 0
2024-10-13 13:01:18 -05:00
// in module: text.txt
arbitrary text
2024-06-20 04:18:36 -05:00
```
2024-06-15 03:37:50 -05:00
2024-10-27 13:55:11 -05:00
- `@use(<string>)`: imports a module based on relative path, cycles are allowed when importing
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
2024-10-27 13:55:11 -05:00
- `@as(<ty>, <expr>)`: hint to the compiler that `@TypeOf(<expr>) == <ty>`
2024-06-20 04:18:36 -05:00
- `@intcast(<expr>)`: needs to be used when conversion of `@TypeOf(<expr>)` would loose precision (widening of integers is implicit)
2024-10-27 13:55:11 -05:00
- `@sizeof(<ty>), @alignof(<ty>)`: get size and align of a type in bytes
- `@bitcast(<expr>)`: tell compiler to assume `@TypeOf(<expr>)` is whatever is inferred, so long as size matches
- `@eca(...<expr>)`: invoke `eca` instruction, where return type is inferred and `<expr>...` are arguments passed to the call in the standard call convention
- `@embed(<string>)`: include relative file as an array of bytes
2024-09-01 19:38:11 -05:00
- `@inline(<func>, ...<args>)`: equivalent to `<func>(...<args>)` but function is guaranteed to inline, compiler will otherwise never inline
- `@len(<ty>)`: reports a length of the type of indexing purposes or length ot a string constant
- `@kindof(<ty>)`: gives an u8 integer describing the kind of type as an index to array `[Builtin, Struct, Tuple, Enum, Union, Ptr, Slice, Opt, Func, Template, Global, Const, Module]`
- `@Any()`: generic parameter based on inference, TBD: this will ake arguments in the future that restrict what is accepted
- `@error(...<expr>)`: emit compiler error, if reachable, and use arguments to construct a message, can display strings and types
- `@ChildOf(<ty>)`: returns the child type of the `<ty>`, works for pointers and optionals (`@ChildOf(?u8) == u8`)
2024-06-15 03:37:50 -05:00
2024-07-02 07:49:05 -05:00
#### c_strings
```hb
2024-10-25 07:51:33 -05:00
str_len := fn(str: ^u8): uint {
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
2024-10-25 07:51:33 -05:00
main := fn(): uint {
2024-07-07 06:42:48 -05:00
// 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
2024-10-25 07:51:33 -05:00
main := fn(): uint {
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
2024-10-25 07:51:33 -05:00
fib := fn(n: uint): uint 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
2024-10-25 07:51:33 -05:00
fib_iter := fn(n: uint): uint {
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
2024-10-25 07:51:33 -05:00
main := fn(): uint {
addr := @as(u16, 0x1FF)
2024-10-21 11:57:23 -05:00
msg := [u8].(0, 0, @intcast(addr), @intcast(addr >> 8))
_force_stack := &msg
2024-10-25 07:51:33 -05:00
arr := [uint].(1, 2, 4)
return pass(&arr) + msg[3]
2024-07-08 11:08:58 -05:00
}
2024-10-25 07:51:33 -05:00
pass := fn(arr: ^[uint; 3]): uint {
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
2024-10-25 07:51:33 -05:00
main := fn(): uint {
2024-11-12 10:11:39 -06:00
some_eca()
2024-11-10 12:35:48 -06:00
return @inline(foo, 1, 2, 3) - bar(3)
2024-09-01 19:38:11 -05:00
}
2024-11-12 10:11:39 -06:00
$some_eca := fn(): void return @eca(8)
2024-11-10 12:35:48 -06:00
// only for functions with no control flow (if, loop)
$bar := fn(a: uint): uint return a * 2
gb := 0
2024-10-25 07:51:33 -05:00
foo := fn(a: uint, b: uint, c: uint): uint {
2024-10-22 09:53:48 -05:00
if false | gb != 0 return 1
2024-09-01 19:38:11 -05:00
return a + b + c
}
```
#### idk
```hb
2024-10-25 07:51:33 -05:00
_edge_case := @as(uint, idk)
2024-09-12 11:42:21 -05:00
2024-10-25 07:51:33 -05:00
main := fn(): uint {
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-10-22 00:20:08 -05:00
#### generic_functions
```hb
2024-11-23 08:28:02 -06:00
add := fn($T: type, a: T, b: T): T {
if T != void {
return a + b
}
}
2024-10-22 00:20:08 -05:00
2024-10-25 07:51:33 -05:00
main := fn(): uint {
2024-11-23 08:28:02 -06:00
add(void, {
}, {
})
2024-10-25 07:51:33 -05:00
return add(u32, 2, 2) - add(uint, 1, 3)
2024-10-22 00:20:08 -05:00
}
```
#### generic_types
```hb
malloc_sys_call := 69
free_sys_call := 96
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)
Vec := fn($Elem: type): type return struct {
data: ^Elem,
len: uint,
cap: uint,
new := fn(): Self return .{data: @bitcast(@alignof(Elem)), len: 0, cap: 0}
deinit := fn(vec: ^Self): void {
free(@bitcast(vec.data), vec.cap * @sizeof(Elem), @alignof(Elem));
*vec = new()
return
}
push := fn(vec: ^Self, value: Elem): ?^Elem {
if vec.len == vec.cap {
if vec.cap == 0 {
vec.cap = 1
} else {
vec.cap *= 2
}
new_alloc := @as(?^Elem, @bitcast(malloc(vec.cap * @sizeof(Elem), @alignof(Elem))))
if new_alloc == null return null
src_cursor := vec.data
dst_cursor := @as(^Elem, new_alloc)
end := vec.data + vec.len
loop if src_cursor == end break else {
*dst_cursor = *src_cursor
src_cursor += 1
dst_cursor += 1
}
if vec.len != 0 {
free(@bitcast(vec.data), vec.len * @sizeof(Elem), @alignof(Elem))
}
vec.data = new_alloc
}
slot := vec.data + vec.len;
*slot = value
vec.len += 1
return slot
}
}
main := fn(): uint {
vec := Vec(uint).new()
_ = vec.push(35)
defer vec.deinit()
vec2 := Vec(u8).new()
_ = vec2.push(34)
defer vec2.deinit()
return *vec.data + *vec2.data
}
```
2024-11-03 03:15:03 -06:00
#### die
```hb
fun := fn(): never die
2024-11-03 03:15:03 -06:00
main := fn(): never {
// simply emmits 'un' instruction that immediately terminates the execution
2024-11-03 03:23:17 -06:00
// the expresion has similar properties to 'return' but does not accept a value
fun()
2024-11-03 03:15:03 -06:00
}
```
2024-11-24 11:50:55 -06:00
#### defer
```hb
main := fn(): uint {
i := 0
loop {
defer i += 1
if i == 10 break
if i % 3 == 0 {
continue
}
}
return i - 11
}
```
#### unrolled_loops
```hb
Nums := struct {a: uint, b: u32, c: u16, d: u8}
main := fn(): uint {
nums := Nums.(1, 2, 3, 4)
i := 0
sum := 0
$loop if i == @len(Nums) break else {
sum += nums[i]
i += 1
}
return sum - 10
}
```
2024-06-20 04:18:36 -05:00
### Incomplete Examples
2024-06-15 03:37:50 -05:00
#### comptime_pointers
```hb
2024-10-25 07:51:33 -05:00
main := fn(): uint {
2024-07-19 14:04:22 -05:00
$integer := 7
modify(&integer)
return integer
}
2024-10-25 07:51:33 -05:00
modify := fn($num: ^uint): void {
2024-07-19 14:04:22 -05:00
$: *num = 0
}
```
2024-06-20 04:18:36 -05:00
#### fb_driver
2024-06-15 03:37:50 -05:00
```hb
2024-10-25 07:51:33 -05:00
arm_fb_ptr := fn(): uint return 100
x86_fb_ptr := fn(): uint return 100
2024-06-20 04:18:36 -05:00
2024-10-25 07:51:33 -05:00
check_platform := fn(): uint {
2024-07-19 14:04:22 -05:00
return x86_fb_ptr()
2024-06-15 03:37:50 -05:00
}
2024-10-25 07:51:33 -05:00
set_pixel := fn(x: uint, y: uint, width: uint): uint {
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-10-25 07:51:33 -05:00
main := fn(): uint {
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
#### method_receiver_by_value
```hb
$log := fn(ptr: ^u8): void return @eca(37, ptr)
Struct := struct {
ptr: ^u8,
print := fn(self: Self, rhs: Self): void {
log(self.ptr)
log(rhs.ptr)
}
}
Struct2 := struct {
ptr: ^u8,
print2 := fn(self: ^Self, rhs: ^Self): void {
log(self.ptr)
log(rhs.ptr)
}
}
main := fn(): void {
lhs := Struct.("Hello, World!\0")
rhs := Struct.("Goodbye, World!\0")
lhs.print(rhs)
lhs2 := Struct2.("Hello, World!\0")
rhs2 := Struct2.("Goodbye, World!\0")
lhs2.print2(&rhs2)
}
```
#### comparing_floating_points
```hb
main := fn(): uint {
if box(1) < box(0) return 1
if box(1) <= box(0) return 2
if box(0) > box(1) return 3
if box(0) >= box(1) return 4
return 0
}
box := fn(v: f32): f32 return v
box2 := fn(v: f64): f64 return v
```
2024-11-24 04:26:38 -06:00
#### pointer_comparison
```hb
main := fn(): int {
a := 10
b := 20
if &a == &a {
return 10
} else {
return 20
}
}
```
2024-11-17 09:25:39 -06:00
#### wrong_dead_code_elimination
```hb
Color := struct {b: u8}
main := fn(): void {
color := Color.(0)
n := @as(u8, 1)
loop {
if color.b == 255 | color.b == 0 {
n = -n
}
color.b += n
}
}
```
2024-11-14 13:25:52 -06:00
#### different_function_destinations
```hb
Stru := struct {a: uint, b: uint}
new_stru := fn(): Stru return .(0, 0)
glob_stru := Stru.(1, 1)
main := fn(): uint {
glob_stru = new_stru()
if glob_stru.a != 0 return 300
glob_stru = .(1, 1)
glob_stru = @inline(new_stru)
if glob_stru.a != 0 return 200
glob_stru = .(1, 1)
strus := [Stru].(glob_stru, glob_stru, glob_stru)
i := 0
loop if i == 3 break else {
strus[i] = new_stru()
i += 1
}
if strus[2].a != 0 return 100
strus = [Stru].(glob_stru, glob_stru, glob_stru)
i = 0
loop if i == 3 break else {
strus[i] = @inline(new_stru)
i += 1
}
if strus[2].a != 0 return 10
return 0
}
```
2024-11-12 14:10:42 -06:00
#### triggering_store_in_divergent_branch
```hb
opaque := fn(): uint {
return 1 << 31
}
main := fn(): void {
a := 0
loop if a >= opaque() break else {
valid := true
b := 0
loop if b >= opaque() break else {
if b == 1 << 16 {
valid = false
break
}
b += 1
}
if valid == false continue
a += 1
}
}
```
#### very_nested_loops
```hb
2024-11-16 13:52:34 -06:00
$H := 3
$W := 3
2024-11-16 13:52:34 -06:00
main := fn(): int {
y := @as(int, 0)
loop if y == H break else {
x := @as(int, 0)
loop if x == W break else {
c_r := @as(f64, @itf(x))
c_i := @as(f64, @itf(y))
2024-11-16 13:52:34 -06:00
if c_i * c_r >= 10.0 return 0
x += 1
}
2024-11-16 13:52:34 -06:00
y += 1
}
2024-11-16 13:52:34 -06:00
return 1
}
Color := struct {r: u8, g: u8, b: u8, a: u8}
Vec := struct {x: uint, y: uint}
put_pixel := fn(pos: Vec, color: Color): void {
}
```
2024-11-11 02:06:34 -06:00
#### generic_type_mishap
```hb
opaque := fn($Expr: type, ptr: ^?Expr): void {
}
process := fn($Expr: type): void {
optional := @as(?Expr, null)
timer := 1000
loop if timer > 0 {
opaque(Expr, &optional)
if optional != null return {
}
timer -= 1
}
return
}
main := fn(): void process(uint)
```
2024-11-10 10:32:24 -06:00
#### storing_into_nullable_struct
```hb
2024-11-10 13:30:35 -06:00
StructA := struct {b: StructB, c: ^uint, d: uint}
2024-11-10 13:30:35 -06:00
StructB := struct {g: ^uint, c: StructC}
StructC := struct {c: uint}
some_index := fn(): ?uint return 0
heap := [u8].(0, 1, 2)
optionala := fn(): ?StructA {
i := some_index()
if i == null die
return .(.(&0, .(1)), &0, heap[i])
}
2024-11-10 10:32:24 -06:00
Struct := struct {inner: uint}
optional := fn(): ?Struct {
return .(10)
}
do_stuff := fn(arg: uint): uint {
return arg
2024-11-10 10:32:24 -06:00
}
2024-11-10 13:30:35 -06:00
just_read := fn(s: StructA): void {
}
main := fn(): uint {
a := optionala()
if a == null {
return 10
2024-11-10 10:32:24 -06:00
}
2024-11-10 13:30:35 -06:00
a.b.c = .(0)
just_read(a)
innera := do_stuff(a.b.c.c)
2024-11-10 11:59:29 -06:00
val := optional()
if val == null {
return 20
}
val.inner = 100
inner := do_stuff(val.inner)
return innera + inner
2024-11-10 10:32:24 -06:00
}
```
2024-11-09 08:14:03 -06:00
#### scheduling_block_did_dirty
```hb
Struct := struct {
pad: uint,
pad2: uint,
}
file := [u8].(255)
opaque := fn(x: uint): uint {
return file[x]
}
constructor := fn(x: uint): Struct {
a := opaque(x)
return .(a, a)
}
main := fn(): void {
something := constructor(0)
return
}
```
2024-11-09 03:28:53 -06:00
#### null_check_returning_small_global
```hb
2024-11-17 13:04:53 -06:00
magic := 127
2024-11-09 03:28:53 -06:00
get := fn(file: ^u8): ?uint {
2024-11-17 13:04:53 -06:00
if *file == magic {
return magic
2024-11-09 03:28:53 -06:00
} else {
return null
}
}
some_file := [u8].(127, 255, 255, 255, 255, 255)
foo := fn(): ?uint {
gotten := get(&some_file[0])
if gotten == null {
return null
} else if gotten == 4 {
return 2
2024-11-17 13:04:53 -06:00
} else if gotten == magic {
2024-11-09 03:28:53 -06:00
return 0
}
return null
}
main := fn(): uint {
f := foo()
if f == null return 100
return f
}
```
#### null_check_in_the_loop
```hb
A := struct {
x_change: u8,
y_change: u8,
left: u8,
middle: u8,
right: u8,
}
return_fn := fn(): ?A {
return A.(0, 0, 0, 0, 0)
}
main := fn(): int {
loop {
ret := return_fn()
if ret != null {
return 1
}
}
}
```
#### stack_provenance
```hb
main := fn(): uint {
return *dangle()
}
dangle := fn(): ^uint return &0
```
#### advanced_floating_point_arithmetic
```hb
2024-11-17 13:04:53 -06:00
sin_table := [f32].(0.0, 0.02454122852291229, 0.04906767432741801, 0.07356456359966743, 0.0980171403295606, 0.1224106751992162, 0.1467304744553617, 0.1709618887603012, 0.1950903220161282, 0.2191012401568698, 0.2429801799032639, 0.2667127574748984, 0.2902846772544623, 0.3136817403988915, 0.3368898533922201, 0.3598950365349881, 0.3826834323650898, 0.4052413140049899, 0.4275550934302821, 0.4496113296546065, 0.4713967368259976, 0.492898192229784, 0.5141027441932217, 0.5349976198870972, 0.5555702330196022, 0.5758081914178453, 0.5956993044924334, 0.6152315905806268, 0.6343932841636455, 0.6531728429537768, 0.6715589548470183, 0.6895405447370668, 0.7071067811865475, 0.7242470829514669, 0.7409511253549591, 0.7572088465064845, 0.773010453362737, 0.7883464276266062, 0.8032075314806448, 0.8175848131515837, 0.8314696123025452, 0.844853565249707, 0.8577286100002721, 0.8700869911087113, 0.8819212643483549, 0.8932243011955153, 0.9039892931234433, 0.9142097557035307, 0.9238795325112867, 0.9329927988347388, 0.9415440651830208, 0.9495281805930367, 0.9569403357322089, 0.9637760657954398, 0.970031253194544, 0.9757021300385286, 0.9807852804032304, 0.9852776423889412, 0.989176509964781, 0.99247953459871, 0.9951847266721968, 0.9972904566786902, 0.9987954562051724, 0.9996988186962042, 1.0, 0.9996988186962042, 0.9987954562051724, 0.9972904566786902, 0.9951847266721969, 0.99247953459871, 0.989176509964781, 0.9852776423889412, 0.9807852804032304, 0.9757021300385286, 0.970031253194544, 0.9637760657954398, 0.9569403357322089, 0.9495281805930367, 0.9415440651830208, 0.9329927988347388, 0.9238795325112867, 0.9142097557035307, 0.9039892931234434, 0.8932243011955152, 0.881921264348355, 0.8700869911087115, 0.8577286100002721, 0.8448535652497072, 0.8314696123025455, 0.8175848131515837, 0.8032075314806449, 0.7883464276266063, 0.7730104533627371, 0.7572088465064847, 0.740951125354959, 0.7242470829514669, 0.7071067811865476, 0.6895405447370671, 0.6715589548470186, 0.6531728429537766, 0.6343932841636455, 0.6152315905806269, 0.5956993044924335, 0.5758081914178454, 0.5555702330196022, 0.5349976198870972, 0.5141027441932218, 0.4928981922297841, 0.4713967368259979, 0.4496113296546069, 0.427555093430282, 0.4052413140049899, 0.3826834323650899, 0.3598950365349883, 0.3368898533922203, 0.3136817403988914, 0.2902846772544624, 0.2667127574748985, 0.2429801799032641, 0.21910124015687, 0.1950903220161286, 0.1709618887603012, 0.1467304744553618, 0.1224106751992163, 0.09801714032956083, 0.07356456359966773, 0.04906767432741797, 0.02454122852291233, 0.0, -0.02454122852291208, -0.04906767432741772, -0.0735645635996675, -0.09801714032956059, -0.1224106751992161, -0.1467304744553616, -0.170961888760301, -0.1950903220161284, -0.2191012401568698, -0.2429801799032638, -0.2667127574748983, -0.2902846772544621, -0.3136817403988912, -0.3368898533922201, -0.3598950365349881, -0.3826834323650897, -0.4052413140049897, -0.4275550934302818, -0.4496113296546067, -0.4713967368259976, -0.4928981922297839, -0.5141027441932216, -0.5349976198870969, -0.555570233019602, -0.5758081914178453, -0.5956993044924332, -0.6152315905806267, -0.6343932841636453, -0.6531728429537765, -0.6715589548470184, -0.6895405447370668, -0.7071067811865475, -0.7242470829514668, -0.7409511253549589, -0.7572088465064842, -0.7730104533627367, -0.7883464276266059, -0.8032075314806451, -0.8175848131515838, -0.8314696123025452, -0.844853565249707, -0.857728610000272, -0.8700869911087113, -0.8819212643483549, -0.8932243011955152, -0.9039892931234431, -0.9142097557035305, -0.9238795325112865, -0.932992798834739, -0.9415440651830208, -0.9495281805930367, -0.9569403357322088, -0.9637760657954398, -0.970031253194544, -0.9757021300385285, -0.9807852804032303, -0.9852776423889411, -0.9891765099647809, -0.9924795345987101, -0.9951847266721969, -0.9972904566786902, -0.9987954562051724, -0.9996988186962042, -1.0, -0.9996988186962042, -0.9987954562051724, -0.9972904566786902, -0.9951847266721969, -0.9924795345987101, -0.9891765099647809, -0.9852776423889412, -0.9807852804032304, -0.9757021300385286, -0.970031253194544, -0.96377606579
sin := fn(theta: f32): f32 {
PI := 3.14159265358979323846
TABLE_SIZE := @as(i32, 256)
si := @fti(theta * 0.5 * @itf(TABLE_SIZE) / PI)
d := theta - @itf(si) * 2.0 * PI / @itf(TABLE_SIZE)
ci := si + TABLE_SIZE / 4 & TABLE_SIZE - 1
si &= TABLE_SIZE - 1
2024-11-17 13:04:53 -06:00
return sin_table[@bitcast(si)] + (sin_table[@bitcast(ci)] - 0.5 * sin_table[@bitcast(si)] * d) * d
}
main := fn(): int {
// expected result: 826
return @fti(sin(1000.0) * 1000.0)
}
```
2024-11-07 09:39:15 -06:00
#### nullable_structure
```hb
Structure := struct {}
2024-11-07 09:42:57 -06:00
BigStructure := struct {a: uint, b: uint}
2024-11-07 10:02:22 -06:00
MidStructure := struct {a: u8}
2024-11-07 09:39:15 -06:00
returner_fn := fn(): ?Structure {
2024-11-07 09:42:57 -06:00
return .()
}
returner_bn := fn(): ?BigStructure {
return .(0, 0)
2024-11-07 09:39:15 -06:00
}
2024-11-07 10:02:22 -06:00
returner_cn := fn(): ?MidStructure {
return .(0)
}
2024-11-07 09:39:15 -06:00
main := fn(): int {
ret := returner_fn()
2024-11-07 10:02:22 -06:00
bet := returner_bn()
cet := returner_cn()
if ret != null & bet != null & cet != null {
2024-11-07 09:39:15 -06:00
return 1
}
return 0
}
```
2024-11-04 12:18:37 -06:00
#### needless_unwrap
```hb
main := fn(): uint {
always_nn := @as(?^uint, &0)
ptr1 := @unwrap(always_nn)
2024-11-04 12:18:37 -06:00
always_n := @as(?^uint, null)
ptr2 := @unwrap(always_n)
return *ptr1 + *ptr2
2024-11-04 12:18:37 -06:00
}
```
2024-11-05 12:07:04 -06:00
#### optional_from_eca
```hb
main := fn(): uint {
a := @as(?uint, @eca(0, 0, 0, 0))
if a == null {
die
}
return a
}
```
2024-11-06 09:17:03 -06:00
#### returning_optional_issues
```hb
2024-11-17 13:04:53 -06:00
bmp := 0
2024-11-06 09:17:03 -06:00
get_format := fn(): ?uint {
2024-11-17 13:04:53 -06:00
return bmp
2024-11-06 09:17:03 -06:00
}
main := fn(): uint {
fmt := get_format()
if fmt == null {
return 1
} else {
return fmt
}
}
```
2024-11-04 05:38:47 -06:00
#### inlining_issues
```hb
main := fn(): void {
@use("main.hb").put_filled_rect(.(&.(0), 100, 100), .(0, 0), .(0, 0), .(1))
}
// in module: memory.hb
SetMsg := packed struct {a: u8, count: u32, size: u32, src: ^u8, dest: ^u8}
set := fn($Expr: type, src: ^Expr, dest: ^Expr, count: uint): void {
return @eca(8, 2, &SetMsg.(5, @intcast(count), @intcast(@sizeof(Expr)), @bitcast(src), @bitcast(dest)), @sizeof(SetMsg))
}
// in module: main.hb
Color := struct {r: u8}
Vec2 := fn($Ty: type): type return struct {x: Ty, y: Ty}
memory := @use("memory.hb")
Surface := struct {
buf: ^Color,
width: uint,
height: uint,
}
indexptr := fn(surface: Surface, x: uint, y: uint): ^Color {
return surface.buf + y * surface.width + x
}
put_filled_rect := fn(surface: Surface, pos: Vec2(uint), tr: Vec2(uint), color: Color): void {
top_start_idx := @inline(indexptr, surface, pos.x, pos.y)
bottom_start_idx := @inline(indexptr, surface, pos.x, pos.y + tr.y - 1)
rows_to_fill := tr.y
loop if rows_to_fill <= 1 break else {
@inline(memory.set, Color, &color, top_start_idx, @bitcast(tr.x))
@inline(memory.set, Color, &color, bottom_start_idx, @bitcast(tr.x))
top_start_idx += surface.width
bottom_start_idx -= surface.width
rows_to_fill -= 2
}
if rows_to_fill == 1 {
@inline(memory.set, Color, &color, top_start_idx, @bitcast(tr.x))
}
return
}
```
#### only_break_loop
```hb
memory := @use("memory.hb")
bar := fn(): int {
loop if memory.inb(0x64) != 0 return 1
}
foo := fn(): void {
loop if (memory.inb(0x64) & 2) == 0 break
memory.outb(0x60, 0x0)
}
main := fn(): int {
@inline(foo)
return @inline(bar)
}
// in module: memory.hb
inb := fn(f: int): int return f
outb := fn(f: int, g: int): void {
}
```
#### reading_idk
```hb
main := fn(): int {
a := @as(int, idk)
return a
}
```
#### nonexistent_ident_import
```hb
main := @use("foo.hb").main
// in module: foo.hb
foo := fn(): void {
return
}
foo := fn(): void {
return
}
main := @use("bar.hb").mian
// in module: bar.hb
main := fn(): void {
return
}
```
2024-10-25 17:34:22 -05:00
#### big_array_crash
```hb
2024-11-17 13:04:53 -06:00
sin_table := [int].(0, 174, 348, 523, 697, 871, 1045, 1218, 1391, 1564, 1736, 1908, 2079, 2249, 2419, 2588, 2756, 2923, 3090, 3255, 3420, 3583, 3746, 3907, 4067, 4226, 4384, 4540, 4695, 4848, 5000, 5150, 5299, 5446, 5591, 5735, 5877, 6018, 6156, 6293, 6427, 6560, 6691, 6819, 6946, 7071, 7193, 7313, 7431, 7547, 7660, 7771, 7880, 7986, 8090, 8191, 8290, 8386, 8480, 8571, 8660, 8746, 8829, 8910, 8987, 9063, 9135, 9205, 9271, 9335, 9396, 9455, 9510, 9563, 9612, 9659, 9702, 9743, 9781, 9816, 9848, 9877, 9902, 9925, 9945, 9961, 9975, 9986, 9993, 9998, 10000)
2024-10-25 17:34:22 -05:00
2024-11-17 13:04:53 -06:00
main := fn(): int return sin_table[10]
2024-10-25 17:34:22 -05:00
```
2024-10-24 06:25:30 -05:00
#### returning_global_struct
```hb
Color := struct {r: u8, g: u8, b: u8, a: u8}
white := Color.(255, 255, 255, 255)
random_color := fn(): Color {
return white
}
2024-10-25 07:51:33 -05:00
main := fn(): uint {
2024-10-24 06:25:30 -05:00
val := random_color()
2024-10-25 07:51:33 -05:00
return @as(uint, val.r) + val.g + val.b + val.a
2024-10-24 06:25:30 -05:00
}
```
2024-10-24 06:58:58 -05:00
#### small_struct_bitcast
```hb
Color := struct {r: u8, g: u8, b: u8, a: u8}
white := Color.(255, 255, 255, 255)
2024-11-11 15:34:42 -06:00
u32_to_color := fn(v: u32): Color return @bitcast(u32_to_u32(@bitcast(v)))
2024-10-24 07:08:17 -05:00
u32_to_u32 := fn(v: u32): u32 return v
2024-10-25 07:51:33 -05:00
main := fn(): uint {
return u32_to_color(@bitcast(white)).r
}
```
#### small_struct_assignment
```hb
Color := struct {r: u8, g: u8, b: u8, a: u8}
white := Color.(255, 255, 255, 255)
black := Color.(0, 0, 0, 0)
2024-10-25 07:51:33 -05:00
main := fn(): uint {
f := black
f = white
return f.a
2024-10-24 06:58:58 -05:00
}
```
2024-10-24 09:26:28 -05:00
#### intcast_store
```hb
SetMsg := packed struct {a: u8, count: u32, size: u32, src: ^u8, dest: ^u8}
set := fn($Expr: type, src: ^Expr, dest: ^Expr, count: uint): u32 {
l := SetMsg.(5, @intcast(count), @intcast(@sizeof(Expr)), @bitcast(src), @bitcast(dest))
return l.count
}
2024-10-25 07:51:33 -05:00
main := fn(): uint {
return set(uint, &0, &0, 1024)
2024-10-24 09:26:28 -05:00
}
2024-10-24 12:57:36 -05:00
```
#### string_flip
```hb
2024-10-25 07:51:33 -05:00
U := struct {u: uint}
main := fn(): uint {
2024-10-24 12:57:36 -05:00
arr := @as([U; 2 * 2], idk)
2024-10-24 09:26:28 -05:00
2024-10-24 12:57:36 -05:00
i := 0
loop if i == 2 * 2 break else {
arr[i] = .(i)
i += 1
}
i = 0
loop if i == 2 / 2 break else {
j := 0
loop if j == 2 break else {
a := i * 2 + j
b := (2 - i - 1) * 2 + j
tmp := arr[a]
arr[a] = arr[b]
arr[b] = tmp
j += 1
}
i += 1
}
return arr[2].u
2024-10-24 12:57:36 -05:00
}
2024-10-24 09:26:28 -05:00
```
2024-11-12 05:54:36 -06:00
#### memory_swap
```hb
U := struct {u: uint, v: uint, g: uint}
main := fn(): uint {
a := decide(0)
b := decide(1)
c := a
a = b
b = c
return b.u + a.u
}
decide := fn(u: uint): U return .(u, 0, 0)
```
#### wide_ret
```hb
OemIdent := struct {
dos_version: [u8; 8],
dos_version_name: [u8; 8],
}
Stru := struct {
a: u16,
b: u16,
}
small_struct := fn(): Stru {
return .{a: 0, b: 0}
}
2024-10-25 07:51:33 -05:00
maina := fn(major: uint, minor: uint): OemIdent {
_f := small_struct()
ver := [u8].(0, 0, 0, 3, 1, 0, 0, 0)
return OemIdent.(ver, ver)
}
2024-10-25 07:51:33 -05:00
main := fn(): uint {
m := maina(0, 0)
return m.dos_version[3] - m.dos_version_name[4]
}
```
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)
2024-10-25 07:51:33 -05:00
main := fn(): uint {
2024-09-01 16:14:48 -05:00
return a
}
// in module: math.hb
2024-11-17 13:04:53 -06:00
sizeof_uint := 32
shift := sizeof_uint - 1
2024-10-25 07:51:33 -05:00
min := fn(a: uint, b: uint): uint {
2024-09-01 15:07:45 -05:00
c := a - b
2024-11-17 13:04:53 -06:00
return b + (c & c >> shift)
2024-09-01 15:07:45 -05:00
}
```
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,
2024-10-25 07:51:33 -05:00
pouint: Point,
2024-06-15 03:37:50 -05:00
}
2024-10-25 07:51:33 -05:00
main := fn(): uint {
2024-06-15 03:37:50 -05:00
pixel := Pixel.{
color: Color.{
r: 255,
g: 0,
b: 0,
a: 255,
},
2024-10-25 07:51:33 -05:00
pouint: Point.{
2024-06-15 03:37:50 -05:00
x: 0,
y: 2,
},
2024-07-19 14:04:22 -05:00
}
soupan := 1
2024-10-25 07:51:33 -05:00
if *(&pixel.pouint.x + soupan) != 2 {
2024-07-19 14:04:22 -05:00
return 0
2024-06-15 03:37:50 -05:00
}
2024-10-25 07:51:33 -05:00
if *(&pixel.pouint.y - 1) != 0 {
2024-07-19 14:04:22 -05:00
return 64
2024-06-15 03:37:50 -05:00
}
2024-10-25 07:51:33 -05:00
return pixel.pouint.x + pixel.pouint.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
2024-10-25 07:51:33 -05:00
main := fn(): uint {
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
2024-10-25 07:51:33 -05:00
Foo := struct {x: uint, y: u32, z: u32}
2024-07-18 10:55:55 -05:00
```
#### sort_something_viredly
```hb
2024-10-25 07:51:33 -05:00
main := fn(): uint {
return sqrt(100)
}
2024-10-25 07:51:33 -05:00
sqrt := fn(x: uint): uint {
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-10-27 13:13:25 -05:00
#### struct_in_register
2024-09-01 16:14:48 -05:00
```hb
ColorBGRA := struct {b: u8, g: u8, r: u8, a: u8}
2024-11-17 13:04:53 -06:00
magenta := ColorBGRA.{b: 205, g: 0, r: 205, a: 255}
2024-09-01 16:14:48 -05:00
2024-10-25 07:51:33 -05:00
main := fn(): uint {
2024-11-17 13:04:53 -06:00
color := magenta
2024-09-01 16:14:48 -05:00
return color.r
}
```
#### comptime_function_from_another_file
```hb
stn := @use("stn.hb")
2024-11-17 13:04:53 -06:00
const_a := 100
const_b := 50
a := stn.math.min(const_a, const_b)
2024-09-01 16:14:48 -05:00
2024-10-25 07:51:33 -05:00
main := fn(): uint {
2024-09-01 16:14:48 -05:00
return a
}
// in module: stn.hb
math := @use("math.hb")
// in module: math.hb
2024-11-17 13:04:53 -06:00
sizeof_uint := 32
shift := sizeof_uint - 1
2024-10-25 07:51:33 -05:00
min := fn(a: uint, b: uint): uint {
2024-09-01 16:14:48 -05:00
c := a - b
2024-11-17 13:04:53 -06:00
return b + (c & c >> shift)
2024-09-01 16:14:48 -05:00
}
```
2024-09-01 20:21:39 -05:00
#### inline_test
```hb
2024-10-25 07:51:33 -05:00
fna := fn(a: uint, b: uint, c: uint): uint return a + b + c
2024-09-01 20:21:39 -05:00
2024-10-25 07:51:33 -05:00
scalar_values := fn(): uint {
2024-10-24 02:43:07 -05:00
return @inline(fna, 1, @inline(fna, 2, 3, 4), -10)
2024-09-01 20:21:39 -05:00
}
2024-10-25 07:51:33 -05:00
A := struct {a: uint}
AB := struct {a: A, b: uint}
2024-09-01 20:21:39 -05:00
2024-10-25 07:51:33 -05:00
mangle := fn(a: A, ab: AB): uint {
2024-10-24 02:43:07 -05:00
return a.a + ab.a.a - ab.b
2024-09-01 20:21:39 -05:00
}
2024-10-25 07:51:33 -05:00
structs := fn(): uint {
2024-10-24 02:43:07 -05:00
return @inline(mangle, .(0), .(.(@inline(mangle, .(20), .(.(5), 5))), 20))
2024-09-01 21:45:42 -05:00
}
2024-10-25 07:51:33 -05:00
main := fn(): uint {
2024-10-24 02:43:07 -05:00
if scalar_values() != 0 return 1
if structs() != 0 return structs()
2024-10-24 02:43:07 -05:00
return 0
2024-09-01 21:45:42 -05:00
}
2024-09-01 20:21:39 -05:00
```
2024-09-04 09:54:34 -05:00
#### inlined_generic_functions
```hb
abs := fn($Expr: type, x: Expr): Expr {
mask := x >> @bitcast(@sizeof(Expr) - 1)
return (x ^ mask) - mask
}
2024-10-25 07:51:33 -05:00
main := fn(): uint {
return @inline(abs, uint, -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
2024-10-25 07:51:33 -05:00
integer_range := fn(min: uint, max: uint): 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
2024-10-25 08:45:00 -05:00
#### signed_to_unsigned_upcast
```hb
main := fn(): uint return @as(i32, 1)
```
2024-09-08 10:11:33 -05:00
#### writing_into_string
```hb
outl := fn(): void {
msg := "whahaha\0"
_u := @as(u8, 0)
2024-09-08 10:11:33 -05:00
return
}
inl := fn(): void {
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 {
2024-10-22 00:20:08 -05:00
return @bitcast(request_page(@intcast(total_pages)))
2024-09-09 15:17:54 -05:00
}
ptr := request_page(255)
remaining := total_pages - 0xFF
loop if remaining <= 0 break else {
if remaining < 0xFF {
2024-11-03 15:27:37 -06:00
_ = request_page(@intcast(remaining))
2024-09-09 15:17:54 -05:00
} else {
2024-11-03 15:27:37 -06:00
_ = request_page(0xFF)
2024-09-09 15:17:54 -05:00
}
remaining -= 0xFF
}
return @bitcast(ptr)
}
main := fn(): void {
2024-10-22 00:20:08 -05:00
_f := 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
2024-10-25 07:51:33 -05:00
main := fn(): uint {
2024-09-09 18:15:18 -05:00
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 {
2024-11-11 15:34:42 -06:00
*(@as(^[u8; 1024], @bitcast(&back_buffer)) + n) = *@bitcast(&back_buffer)
2024-09-09 18:15:18 -05:00
n += 1
}
return back_buffer[1024 * 2]
}
```
2024-09-28 08:13:32 -05:00
#### global_variable_wiredness
```hb
ports := false
inb := fn(): uint return 0
main := fn(): void {
if ports {
ports = inb() == 0x0
}
}
```
2024-10-18 01:43:50 -05:00
### Just Testing Optimizations
#### elide_stack_offsets_for_parameters_correctly
```hb
A := struct {
f: uint,
s: B,
}
B := struct {
a: uint,
b: uint,
}
main := fn(): uint {
a := A.(1, .(0, 0))
return pass(a.s)
}
pass := fn(s: B): uint return s.a + s.b
```
#### null_check_test
```hb
get_ptr := fn(): ?^uint return null
main := fn(): uint {
ptr := get_ptr()
if ptr == null {
return 0
}
loop if *ptr != 10 {
*ptr += 1
} else break
return *ptr
}
```
2024-10-18 01:43:50 -05:00
#### const_folding_with_arg
```hb
2024-10-25 07:51:33 -05:00
main := fn(arg: uint): uint {
2024-10-18 01:43:50 -05:00
// reduces to 0
return arg + 0 - arg * 1 + arg + 1 + arg + 2 + arg + 3 - arg * 3 - 6
}
```
#### branch_assignments
```hb
2024-10-25 07:51:33 -05:00
main := fn(arg: uint): uint {
2024-10-18 01:43:50 -05:00
if arg == 1 {
arg = 1
} else if arg == 0 {
arg = 2
} else {
arg = 3
}
return arg
}
```
#### exhaustive_loop_testing
```hb
2024-10-25 07:51:33 -05:00
main := fn(): uint {
2024-10-22 15:57:40 -05:00
loop break
x := 0
loop {
x += 1
break
}
2024-10-18 01:43:50 -05:00
if multiple_breaks(0) != 3 {
return true
2024-10-18 01:43:50 -05:00
}
if multiple_breaks(4) != 10 {
return 2
}
if state_change_in_break(0) != 0 {
return 3
}
if state_change_in_break(4) != 10 {
return 4
}
if continue_and_state_change(10) != 10 {
return 5
}
if continue_and_state_change(3) != 0 {
return 6
}
2024-10-27 05:32:34 -05:00
infinite_loop()
return 0
}
infinite_loop := fn(): void {
2024-10-23 05:26:07 -05:00
f := 0
2024-10-22 15:57:40 -05:00
loop {
2024-10-23 05:26:07 -05:00
if f == 1 {
f = 0
} else {
f = 1
}
f = continue_and_state_change(0)
2024-10-22 15:57:40 -05:00
}
2024-10-18 01:43:50 -05:00
}
2024-10-25 07:51:33 -05:00
multiple_breaks := fn(arg: uint): uint {
2024-10-18 01:43:50 -05:00
loop if arg < 10 {
arg += 1
if arg == 3 break
} else break
return arg
}
2024-10-25 07:51:33 -05:00
state_change_in_break := fn(arg: uint): uint {
2024-10-18 01:43:50 -05:00
loop if arg < 10 {
if arg == 3 {
arg = 0
break
}
arg += 1
} else break
return arg
}
2024-10-25 07:51:33 -05:00
continue_and_state_change := fn(arg: uint): uint {
2024-10-18 01:43:50 -05:00
loop if arg < 10 {
if arg == 2 {
arg = 4
continue
}
if arg == 3 {
arg = 0
break
}
arg += 1
} else break
return arg
}
```
2024-09-28 08:13:32 -05:00
#### pointer_opts
```hb
2024-10-25 07:51:33 -05:00
main := fn(): uint {
2024-09-28 08:13:32 -05:00
mem := &0;
*mem = 1;
*mem = 2
b := *mem + *mem
clobber(mem)
b -= *mem
return b
}
2024-10-25 07:51:33 -05:00
clobber := fn(cb: ^uint): void {
2024-09-28 08:13:32 -05:00
*cb = 4
return
}
```
2024-10-18 06:11:11 -05:00
#### conditional_stores
```hb
2024-10-25 07:51:33 -05:00
main := fn(): uint {
cnd := cond()
2024-10-18 06:11:11 -05:00
mem := &1
if cnd == 0 {
2024-10-18 06:11:11 -05:00
*mem = 0
} else {
*mem = 2
}
return *mem
}
2024-10-25 07:51:33 -05:00
cond := fn(): uint return 0
2024-10-18 06:11:11 -05:00
```
#### loop_stores
```hb
2024-10-25 07:51:33 -05:00
main := fn(): uint {
mem := &10
loop if *mem == 0 break else {
*mem -= 1
}
return *mem
}
```
2024-10-26 13:29:31 -05:00
#### dead_code_in_loop
```hb
main := fn(): uint {
n := 0
loop if n < 10 {
if n < 10 break
n += 1
} else break
loop if n == 0 return n
return 1
}
```
2024-10-27 05:32:34 -05:00
#### infinite_loop_after_peephole
```hb
main := fn(): uint {
n := 0
f := 0
loop if n != 0 break else {
f += 1
}
return f
}
```
2024-10-28 12:39:42 -05:00
#### aliasing_overoptimization
```hb
Foo := struct {ptr: ^uint, rnd: uint}
main := fn(): uint {
mem := &2
stru := Foo.(mem, 0);
*stru.ptr = 0
return *mem
}
```
2024-10-29 09:04:07 -05:00
#### global_aliasing_overptimization
```hb
var := 0
main := fn(): uint {
var = 2
clobber()
return var
}
clobber := fn(): void {
var = 0
}
```
#### overwrite_aliasing_overoptimization
```hb
Foo := struct {a: int, b: int}
Bar := struct {f: Foo, b: int}
main := fn(): int {
value := Bar.{b: 1, f: .(4, 1)}
value.f = opaque()
return value.f.a - value.f.b - value.b
}
opaque := fn(): Foo {
return .(3, 2)
}
2024-10-30 14:20:03 -05:00
```
2024-11-04 12:18:37 -06:00
#### more_if_opts
```hb
main := fn(): uint {
opq1 := opaque()
opq2 := opaque()
a := 0
if opq1 == null {
} else a = *opq1
if opq1 != null a = *opq1
//if opq1 == null | opq2 == null {
//} else a = *opq1
//if opq1 != null & opq2 != null a = *opq1
return a
}
opaque := fn(): ?^uint return null
```