primitive string formatter with struct & array support
This commit is contained in:
parent
3506c83535
commit
d907df14dd
6
Cargo.lock
generated
6
Cargo.lock
generated
|
@ -213,12 +213,12 @@ dependencies = [
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "hbbytecode"
|
name = "hbbytecode"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+https://git.ablecorp.us/AbleOS/holey-bytes.git#c0d957e70c7146f2c788a7b410632a940a18768f"
|
source = "git+https://git.ablecorp.us/AbleOS/holey-bytes.git#945e5c70f6cb20a77fbb654a0ab6bef7d2b25aac"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "hblang"
|
name = "hblang"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+https://git.ablecorp.us/AbleOS/holey-bytes.git#c0d957e70c7146f2c788a7b410632a940a18768f"
|
source = "git+https://git.ablecorp.us/AbleOS/holey-bytes.git#945e5c70f6cb20a77fbb654a0ab6bef7d2b25aac"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"hashbrown",
|
"hashbrown",
|
||||||
"hbbytecode",
|
"hbbytecode",
|
||||||
|
@ -229,7 +229,7 @@ dependencies = [
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "hbvm"
|
name = "hbvm"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+https://git.ablecorp.us/AbleOS/holey-bytes.git#c0d957e70c7146f2c788a7b410632a940a18768f"
|
source = "git+https://git.ablecorp.us/AbleOS/holey-bytes.git#945e5c70f6cb20a77fbb654a0ab6bef7d2b25aac"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"hbbytecode",
|
"hbbytecode",
|
||||||
]
|
]
|
||||||
|
|
146
sysdata/libraries/stn/src/formatters.hb
Normal file
146
sysdata/libraries/stn/src/formatters.hb
Normal file
|
@ -0,0 +1,146 @@
|
||||||
|
.{string, primitive, unsigned_int, signed_int, float, integer, memory, panic} := @use("stn")
|
||||||
|
|
||||||
|
format_int := fn($T: type, v: T, str: ^u8): uint {
|
||||||
|
if integer(T) {
|
||||||
|
is_negative := signed_int(T) & v < 0
|
||||||
|
i := 0
|
||||||
|
if is_negative v = -v
|
||||||
|
|
||||||
|
if v == 0 {
|
||||||
|
*str = '0'
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
loop if v == 0 break else {
|
||||||
|
remainder := v % 10
|
||||||
|
v /= 10;
|
||||||
|
*(str + i) = @intcast(remainder + '0')
|
||||||
|
i += 1
|
||||||
|
}
|
||||||
|
|
||||||
|
if is_negative {
|
||||||
|
*(str + i) = '-'
|
||||||
|
i += 1
|
||||||
|
}
|
||||||
|
|
||||||
|
@inline(string.reverse, str)
|
||||||
|
return i
|
||||||
|
} else {
|
||||||
|
panic("Type is not an integer\0")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
format_bool := fn(v: bool, str: ^u8): uint {
|
||||||
|
if v {
|
||||||
|
memory.copy(u8, "true\0", str, 4)
|
||||||
|
return 4
|
||||||
|
} else {
|
||||||
|
memory.copy(u8, "false\0", str, 5)
|
||||||
|
return 5
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
format_float := fn($T: type, v: T, str: ^u8, precision: uint): uint {
|
||||||
|
if float(T) {
|
||||||
|
is_negative := v < 0
|
||||||
|
i := 0
|
||||||
|
|
||||||
|
if is_negative v = -v
|
||||||
|
|
||||||
|
integer_part := @fti(v)
|
||||||
|
fractional_part := v - @itf(integer_part)
|
||||||
|
|
||||||
|
loop if integer_part == 0 & i > 0 break else {
|
||||||
|
remainder := integer_part % 10
|
||||||
|
integer_part /= 10;
|
||||||
|
*(str + i) = @intcast(remainder + '0')
|
||||||
|
i += 1
|
||||||
|
}
|
||||||
|
|
||||||
|
if is_negative {
|
||||||
|
*(str + i) = '-'
|
||||||
|
i += 1
|
||||||
|
}
|
||||||
|
|
||||||
|
@inline(string.reverse, str);
|
||||||
|
*(str + i) = '.'
|
||||||
|
i += 1
|
||||||
|
|
||||||
|
tolerance := @as(T, 0.000000001)
|
||||||
|
p := precision
|
||||||
|
loop if p <= 0 | fractional_part < tolerance break else {
|
||||||
|
fractional_part *= 10.0
|
||||||
|
digit := @fti(fractional_part);
|
||||||
|
*(str + i) = @intcast(digit + '0')
|
||||||
|
i += 1
|
||||||
|
fractional_part -= @itf(digit)
|
||||||
|
p -= 1
|
||||||
|
}
|
||||||
|
|
||||||
|
return i
|
||||||
|
} else {
|
||||||
|
panic("Type is not a floating point\0")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
format_inner := fn($T: type, v: T, str: ^u8, opts: FormatOptions): uint {
|
||||||
|
if integer(T) {
|
||||||
|
return @inline(format_int, T, v, str)
|
||||||
|
} else if T == bool {
|
||||||
|
return @inline(format_bool, v, str)
|
||||||
|
} else if float(T) {
|
||||||
|
return @inline(format_float, T, v, str, opts.decimal_digits)
|
||||||
|
} else {
|
||||||
|
i := 0
|
||||||
|
// name := @nameof(T)
|
||||||
|
// len := string.length(name)
|
||||||
|
// memory.copy(u8, name, str, len)
|
||||||
|
len := 0
|
||||||
|
memory.copy(u8, ".(\0", str + len, 2)
|
||||||
|
len += 2
|
||||||
|
$loop if i == @len(T) break else {
|
||||||
|
v_sub := v[i]
|
||||||
|
TSub := @TypeOf(v_sub)
|
||||||
|
len += @inline(format_inner, TSub, v_sub, str + len, opts)
|
||||||
|
if i != @len(T) - 1 {
|
||||||
|
memory.copy(u8, ", \0", str + len, 2)
|
||||||
|
len += 2
|
||||||
|
} else {
|
||||||
|
memory.copy(u8, ")\0", str + len, 1)
|
||||||
|
len += 1
|
||||||
|
}
|
||||||
|
i += 1
|
||||||
|
}
|
||||||
|
return len
|
||||||
|
}
|
||||||
|
panic("Unsupported formatter type\0")
|
||||||
|
}
|
||||||
|
|
||||||
|
/* TODO:
|
||||||
|
* Custom formatters using struct methods (T._fmt(self, str): uint),
|
||||||
|
* Format struct names "Name.(x, y, z)"
|
||||||
|
* Format struct fields "Name.{a: x, b: y, c: z}"
|
||||||
|
* Optimise (so many instructions...)
|
||||||
|
* -> Consider switching `memory.copy` to loop for comptime stuff
|
||||||
|
* Optionally tabulate
|
||||||
|
* Add more FormatOption fields
|
||||||
|
* Support radices for integers
|
||||||
|
* Support scientific notation for floating point
|
||||||
|
* Support format string (impossible right now)
|
||||||
|
* Support nullables (impossible right now)
|
||||||
|
* Support pointers
|
||||||
|
*/
|
||||||
|
|
||||||
|
FormatOptions := struct {
|
||||||
|
decimal_digits: uint,
|
||||||
|
}
|
||||||
|
|
||||||
|
$DEFAULT_OPTS := FormatOptions.(2)
|
||||||
|
|
||||||
|
format := fn($T: type, v: T, str: ^u8): ^u8 return @inline(format_args, T, v, str, DEFAULT_OPTS)
|
||||||
|
|
||||||
|
format_args := fn($T: type, v: T, str: ^u8, opts: FormatOptions): ^u8 {
|
||||||
|
@inline(string.clear, str)
|
||||||
|
_ = @inline(format_inner, T, v, str, opts)
|
||||||
|
return str
|
||||||
|
}
|
|
@ -1,5 +1,6 @@
|
||||||
acs := @use("acs.hb")
|
acs := @use("acs.hb")
|
||||||
allocators := @use("alloc/lib.hb")
|
allocators := @use("alloc/lib.hb")
|
||||||
|
formatters := @use("formatters.hb")
|
||||||
hashers := @use("hash/lib.hb")
|
hashers := @use("hash/lib.hb")
|
||||||
string := @use("string.hb")
|
string := @use("string.hb")
|
||||||
log := @use("log.hb")
|
log := @use("log.hb")
|
||||||
|
|
|
@ -77,7 +77,7 @@ TAN_TABLE := [f32].(0.0, 0.01227246237956628, 0.02454862210892544, 0.03683218099
|
||||||
$TABLE_SIZE := @sizeof(@TypeOf(SIN_TABLE)) / @sizeof(f32)
|
$TABLE_SIZE := @sizeof(@TypeOf(SIN_TABLE)) / @sizeof(f32)
|
||||||
|
|
||||||
sin := fn(theta: f32): f32 {
|
sin := fn(theta: f32): f32 {
|
||||||
si := @fti(theta * 0.5 * @itf(TABLE_SIZE) / PI)
|
si := @fti(theta * 0.5 * TABLE_SIZE / PI)
|
||||||
d := theta - @itf(si) * 2.0 * PI / TABLE_SIZE
|
d := theta - @itf(si) * 2.0 * PI / TABLE_SIZE
|
||||||
ci := si + TABLE_SIZE / 4 & TABLE_SIZE - 1
|
ci := si + TABLE_SIZE / 4 & TABLE_SIZE - 1
|
||||||
si &= TABLE_SIZE - 1
|
si &= TABLE_SIZE - 1
|
||||||
|
@ -85,7 +85,7 @@ sin := fn(theta: f32): f32 {
|
||||||
}
|
}
|
||||||
|
|
||||||
cos := fn(theta: f32): f32 {
|
cos := fn(theta: f32): f32 {
|
||||||
ci := @fti(theta * 0.5 * @itf(TABLE_SIZE) / PI)
|
ci := @fti(theta * 0.5 * TABLE_SIZE / PI)
|
||||||
d := theta - @itf(ci) * 2.0 * PI / TABLE_SIZE
|
d := theta - @itf(ci) * 2.0 * PI / TABLE_SIZE
|
||||||
si := ci + TABLE_SIZE / 4 & TABLE_SIZE - 1
|
si := ci + TABLE_SIZE / 4 & TABLE_SIZE - 1
|
||||||
ci &= TABLE_SIZE - 1
|
ci &= TABLE_SIZE - 1
|
||||||
|
|
|
@ -14,6 +14,12 @@ $X_MAX := -0.93
|
||||||
$Y_MIN := 0.31
|
$Y_MIN := 0.31
|
||||||
$Y_MAX := 0.306
|
$Y_MAX := 0.306
|
||||||
|
|
||||||
|
// zoom into that weird curve part of the main cardioid
|
||||||
|
// $X_MIN := 0.25
|
||||||
|
// $X_MAX := 0.34
|
||||||
|
// $Y_MIN := -0.075
|
||||||
|
// $Y_MAX := 0.075
|
||||||
|
|
||||||
$MAX_ITERATION := 300
|
$MAX_ITERATION := 300
|
||||||
|
|
||||||
$USE_SUNSET := true
|
$USE_SUNSET := true
|
||||||
|
|
|
@ -3,5 +3,5 @@ serial_driver := @use("./tests/serial_driver.hb")
|
||||||
|
|
||||||
main := fn(): uint {
|
main := fn(): uint {
|
||||||
// return serial_driver.test()
|
// return serial_driver.test()
|
||||||
return stn.sleep.test()
|
return stn.formatters.test()
|
||||||
}
|
}
|
25
sysdata/programs/test/src/tests/stn/formatters.hb
Normal file
25
sysdata/programs/test/src/tests/stn/formatters.hb
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
.{formatters: .{format, format_args}, log, memory, math} := @use("stn");
|
||||||
|
.{Color} := @use("lib:render")
|
||||||
|
|
||||||
|
Thingy := struct {
|
||||||
|
a: uint,
|
||||||
|
b: int,
|
||||||
|
c: SubThingy,
|
||||||
|
}
|
||||||
|
|
||||||
|
SubThingy := struct {
|
||||||
|
a: f32,
|
||||||
|
b: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
test := fn(): uint {
|
||||||
|
buffer := memory.request_page(1)
|
||||||
|
log.info(format(Thingy, .(-100, -100, .(-math.PI, true)), buffer))
|
||||||
|
log.info(format(SubThingy, .(-math.E, false), buffer))
|
||||||
|
log.info(format(Color, .{r: 1, g: 2, b: 3, a: 4}, buffer))
|
||||||
|
// default value: .{decimal_digits: 2}
|
||||||
|
log.info(format_args(f64, math.LN_2, buffer, .{decimal_digits: 1 << 32}))
|
||||||
|
log.info(format([u8; 3], .(1, 2, 3), buffer))
|
||||||
|
|
||||||
|
return 0
|
||||||
|
}
|
|
@ -3,3 +3,4 @@ allocators := @use("./allocators.hb")
|
||||||
sleep := @use("./sleep.hb")
|
sleep := @use("./sleep.hb")
|
||||||
dt := @use("./dt.hb")
|
dt := @use("./dt.hb")
|
||||||
process := @use("./process.hb")
|
process := @use("./process.hb")
|
||||||
|
formatters := @use("./formatters.hb")
|
|
@ -23,13 +23,14 @@ resolution = "1024x768x24"
|
||||||
|
|
||||||
[boot.limine.ableos.modules]
|
[boot.limine.ableos.modules]
|
||||||
|
|
||||||
[boot.limine.ableos.modules.render_example]
|
# [boot.limine.ableos.modules.render_example]
|
||||||
path = "boot:///render_example.hbf"
|
# path = "boot:///render_example.hbf"
|
||||||
[boot.limine.ableos.modules.sunset_server]
|
|
||||||
path = "boot:///sunset_server.hbf"
|
|
||||||
|
|
||||||
[boot.limine.ableos.modules.ps2_mouse_driver]
|
# [boot.limine.ableos.modules.sunset_server]
|
||||||
path = "boot:///ps2_mouse_driver.hbf"
|
# path = "boot:///sunset_server.hbf"
|
||||||
|
|
||||||
|
# [boot.limine.ableos.modules.ps2_mouse_driver]
|
||||||
|
# path = "boot:///ps2_mouse_driver.hbf"
|
||||||
|
|
||||||
# [boot.limine.ableos.modules.ps2_keyboard_driver]
|
# [boot.limine.ableos.modules.ps2_keyboard_driver]
|
||||||
# path = "boot:///ps2_keyboard_driver.hbf"
|
# path = "boot:///ps2_keyboard_driver.hbf"
|
||||||
|
@ -40,12 +41,14 @@ path = "boot:///ps2_mouse_driver.hbf"
|
||||||
# [boot.limine.ableos.modules.sunset_client_2]
|
# [boot.limine.ableos.modules.sunset_client_2]
|
||||||
# path = "boot:///sunset_client_2.hbf"
|
# path = "boot:///sunset_client_2.hbf"
|
||||||
|
|
||||||
[boot.limine.ableos.modules.ablefetch]
|
# [boot.limine.ableos.modules.ablefetch]
|
||||||
path = "boot:///ablefetch.hbf"
|
# path = "boot:///ablefetch.hbf"
|
||||||
|
|
||||||
# [boot.limine.ableos.modules.diskio_driver]
|
# [boot.limine.ableos.modules.diskio_driver]
|
||||||
# path = "boot:///diskio_driver.hbf"
|
# path = "boot:///diskio_driver.hbf"
|
||||||
|
|
||||||
|
# [boot.limine.ableos.modules.angels_halo]
|
||||||
|
# path = "boot:///angels_halo.hbf"
|
||||||
|
|
||||||
#[boot.limine.ableos.modules.angels_halo]
|
[boot.limine.ableos.modules.test]
|
||||||
#path = "boot:///angels_halo.hbf"
|
path = "boot:///test.hbf"
|
||||||
|
|
Loading…
Reference in a new issue