more target stuff. ableos buffer ipc & device tree. update hblang, new tests. minor additions.
This commit is contained in:
parent
28afaac383
commit
5717bd9157
6
build
6
build
|
@ -8,7 +8,7 @@ readonly LILY_TEST_DIR="${LILY_TEST_DIR:-$LILY_SCRIPT_DIR/hbc-tests}"
|
|||
readonly LILY_BUILD_DIR="${LILY_BUILD_DIR:-$LILY_SCRIPT_DIR/out}"
|
||||
|
||||
readonly HBLANG_GIT="https://git.ablecorp.us/mlokis/hblang"
|
||||
readonly HBLANG_COMMIT="4bd1d3a4e1040b36f9185cf3ebedb99b1ad17ac6"
|
||||
readonly HBLANG_COMMIT="dd46d8a2d505ea8611f6c5b44c08131bb3abf220"
|
||||
readonly HBC_FLAGS="--path-projection lily $LILY_SRC_DIR/lib.hb ${HBC_FLAGS:-}"
|
||||
readonly HBC_BINARY="hbc"
|
||||
readonly HBC_TESTS="${HBC_TESTS:-0}"
|
||||
|
@ -83,8 +83,8 @@ main() {
|
|||
result_file=$(mktemp)
|
||||
find "$LILY_TEST_DIR" -type f >"$tmpfile"
|
||||
while IFS= read -r file; do
|
||||
# test_name=$(basename "$file" .hb)
|
||||
test_name=$(echo "$(basename -- "$(dirname -- "$file")")/$(basename -- "$file" .hb)" | tr '/' '.')
|
||||
test_name=$(realpath -s --relative-to="$LILY_TEST_DIR" "$file" | tr '/' '.')
|
||||
test_name="${test_name%.*}"
|
||||
do_test 2>/dev/null &
|
||||
done <"$tmpfile"
|
||||
rm -f "$tmpfile"
|
||||
|
|
|
@ -7,3 +7,4 @@ a collection of guidelines for programmers to use to create lily-compatible impl
|
|||
the following files define the spec:
|
||||
- [allocators](./spec/alloc.md)
|
||||
- [iterators](./spec/iter.md)
|
||||
- [tests](./spec/tests.md)
|
||||
|
|
22
docs/spec/tests.md
Normal file
22
docs/spec/tests.md
Normal file
|
@ -0,0 +1,22 @@
|
|||
# tests
|
||||
|
||||
1. tests should attempt to be meaningful in some way, patching targeting bugs, or behaviours.
|
||||
|
||||
2. tests should be written as hblang vendored tests. all tests can be run with `HBC_TESTS=1 ./build`. status of failed tests should be emitted to `out/subdir.test-name.test`
|
||||
|
||||
3. tests should be written as one of:
|
||||
- part of an exhaustive folder covering all aspects of a datastructure / module. e.g:
|
||||
```
|
||||
lily/
|
||||
some-module/
|
||||
func1.hb
|
||||
struct/
|
||||
method1.hb
|
||||
method2.hb
|
||||
other-module/
|
||||
...
|
||||
...
|
||||
lang/
|
||||
...
|
||||
```
|
||||
- one-and-done tests for locating bugs (which should be kept after the bug is patched, unless it is made obsolete by an exhaustive test)
|
17
hbc-tests/lang/inline-declaration-order.hb
Normal file
17
hbc-tests/lang/inline-declaration-order.hb
Normal file
|
@ -0,0 +1,17 @@
|
|||
expectations := .{
|
||||
return_value: 0,
|
||||
}
|
||||
|
||||
secondary := fn(): uint {
|
||||
return inlined()
|
||||
}
|
||||
|
||||
// ! if $ is removed this works.
|
||||
// ! if this function is moved above `secondary`, this works.
|
||||
$inlined := fn(): uint {
|
||||
return 0
|
||||
}
|
||||
|
||||
main := fn(): uint {
|
||||
return secondary()
|
||||
}
|
14
hbc-tests/lily/type-kindof.hb
Normal file
14
hbc-tests/lily/type-kindof.hb
Normal file
|
@ -0,0 +1,14 @@
|
|||
expectations := .{
|
||||
return_value: 0,
|
||||
}
|
||||
|
||||
lily.{Type} := @use("../../src/lib.hb")
|
||||
|
||||
main := fn(): uint {
|
||||
// ! (compiler) bug: "the functions types most likely depend on it being evaluated"
|
||||
$match Type(uint).kind() {
|
||||
.Builtin => {},
|
||||
_ => return 1,
|
||||
}
|
||||
return 0
|
||||
}
|
14
hbc-tests/lily/type-of.hb
Normal file
14
hbc-tests/lily/type-of.hb
Normal file
|
@ -0,0 +1,14 @@
|
|||
expectations := .{
|
||||
return_value: 0,
|
||||
}
|
||||
|
||||
lily.{TypeOf} := @use("../../src/lib.hb")
|
||||
|
||||
main := fn(): uint {
|
||||
// ! (compiler) bug: "the functions types most likely depend on it being evaluated"
|
||||
$match TypeOf(@as(uint, 1)).kind() {
|
||||
.Builtin => {},
|
||||
_ => return 1,
|
||||
}
|
||||
return 0
|
||||
}
|
86
src/ipc.hb
Normal file
86
src/ipc.hb
Normal file
|
@ -0,0 +1,86 @@
|
|||
lily.{target, mem, Type} := @use("lib.hb")
|
||||
|
||||
Buffer := struct {
|
||||
.id: uint
|
||||
|
||||
Self := @CurrentScope()
|
||||
|
||||
new := fn(name: ?[]u8): ?Self {
|
||||
id: uint = 0
|
||||
if name == null {
|
||||
id = target.buf_create()
|
||||
} else {
|
||||
id = target.buf_create_named(name.?)
|
||||
}
|
||||
if id == 0 return null
|
||||
return Self.from_raw(id)
|
||||
}
|
||||
search := fn(name: []u8): ?Self {
|
||||
id := target.buf_search(name)
|
||||
if id == 0 return null
|
||||
return Self.from_raw(id)
|
||||
}
|
||||
deinit := fn(self: ^Self): void {
|
||||
target.buf_destroy(self.id)
|
||||
self.* = idk
|
||||
}
|
||||
$from_raw := fn(id: uint): Self {
|
||||
return .(id)
|
||||
}
|
||||
$await := fn(self: ^Self): void {
|
||||
target.buf_await(self.id)
|
||||
}
|
||||
$write := fn(self: ^Self, val: @Any()): void {
|
||||
$match Type(@TypeOf(val)).kind() {
|
||||
.Pointer => target.buf_write(self.id, mem.as_bytes(val)),
|
||||
.Slice => target.buf_write(self.id, mem.as_bytes(val)),
|
||||
_ => target.buf_write(self.id, mem.as_bytes(&val)),
|
||||
}
|
||||
}
|
||||
$read_into := fn(self: ^Self, slice: []u8): void {
|
||||
target.buf_read(self.id, slice)
|
||||
}
|
||||
$read := fn(self: ^Self, $T: type): T {
|
||||
buf: T = idk
|
||||
target.buf_read(self.id, mem.as_bytes(&buf))
|
||||
return buf
|
||||
}
|
||||
}
|
||||
|
||||
Channel := struct {
|
||||
.local: Buffer;
|
||||
.remote: Buffer
|
||||
|
||||
Self := @CurrentScope()
|
||||
|
||||
new := fn(local_name: ?[]u8, remote_name: ?[]u8): ?Self {
|
||||
local := Buffer.new(local_name)
|
||||
if local == null return null
|
||||
remote := Buffer.new(remote_name)
|
||||
if remote == null return null
|
||||
return .(local.?, remote.?)
|
||||
}
|
||||
$deinit := fn(self: ^Self): void {
|
||||
self.local.deinit()
|
||||
self.remote.deinit()
|
||||
self.* = idk
|
||||
}
|
||||
$to_remote := fn(self: Self): Self {
|
||||
return .(self.remote, self.local)
|
||||
}
|
||||
$from_raw := fn(local_id: uint, remote_id: uint): Self {
|
||||
return .(Buffer.from_raw(local_id), Buffer.from_raw(remote_id))
|
||||
}
|
||||
$await := fn(self: ^Self): void {
|
||||
self.local.await()
|
||||
}
|
||||
$write := fn(self: ^Self, val: @Any()): void {
|
||||
self.remote.write(val)
|
||||
}
|
||||
$read_into := fn(self: ^Self, slice: []u8): void {
|
||||
self.local.read_into(slice)
|
||||
}
|
||||
$read := fn(self: ^Self, $T: type): T {
|
||||
return self.local.read(T)
|
||||
}
|
||||
}
|
|
@ -1,7 +1,9 @@
|
|||
.{Type, TypeOf} := @use("type.hb")
|
||||
process := @use("process.hb")
|
||||
target := @use("target/lib.hb")
|
||||
alloc := @use("alloc/lib.hb")
|
||||
iter := @use("iter.hb")
|
||||
ipc := @use("ipc.hb")
|
||||
mem := @use("mem.hb")
|
||||
log := @use("log.hb")
|
||||
fmt := @use("fmt.hb")
|
||||
|
|
11
src/mem.hb
11
src/mem.hb
|
@ -34,6 +34,17 @@ $as_bytes := fn(v: @Any()): []u8 {
|
|||
}
|
||||
}
|
||||
|
||||
$to_owned := fn($T: type, slice: []u8): T {
|
||||
$match Type(T).kind() {
|
||||
.Array => {
|
||||
ret: T = idk
|
||||
copy(ret[..], slice)
|
||||
return ret
|
||||
},
|
||||
_ => @error("todo: write this error"),
|
||||
}
|
||||
}
|
||||
|
||||
$overlaps := fn(lhs: []u8, rhs: []u8): bool {
|
||||
return lhs.ptr < rhs.ptr + rhs.len & rhs.ptr < lhs.ptr + lhs.len
|
||||
}
|
||||
|
|
24
src/process.hb
Normal file
24
src/process.hb
Normal file
|
@ -0,0 +1,24 @@
|
|||
lily.{target} := @use("lib.hb")
|
||||
|
||||
ProcessID := fn(): type {
|
||||
$match target.current() {
|
||||
.AbleOS => return struct {
|
||||
.host_id: uint;
|
||||
.id: uint;
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
$HOST_ID_PLACEHOLDER := 0
|
||||
|
||||
$spawn := fn(executable: []u8): ProcessID() {
|
||||
raw := target.proc_spawn(executable)
|
||||
// todo: this
|
||||
return .(HOST_ID_PLACEHOLDER, raw)
|
||||
}
|
||||
|
||||
$fork := fn(): ProcessID() {
|
||||
raw := target.proc_fork()
|
||||
// todo: this
|
||||
return .(HOST_ID_PLACEHOLDER, raw)
|
||||
}
|
|
@ -45,9 +45,37 @@ $memfill := fn(dest: ^u8, src: ^u8, count: uint, len: uint): void {
|
|||
|
||||
$exit := fn(code: u8): void {
|
||||
}
|
||||
$fill_rand := fn(dest: ^u8, len: uint): void return @ecall(3, 4, dest, len)
|
||||
$fork := fn(): uint return @ecall(3, 7)
|
||||
|
||||
$rand_fill := fn(dest: ^u8, len: uint): void return @ecall(3, 4, dest, len)
|
||||
|
||||
$proc_fork := fn(): uint return @ecall(3, 7)
|
||||
$proc_spawn := fn(executable: []u8): uint {
|
||||
return @ecall(3, 6, executable.ptr, executable.len)
|
||||
}
|
||||
|
||||
$dt_get := fn($T: type, query: []u8): T {
|
||||
return @ecall(3, 5, query.ptr, query.len)
|
||||
}
|
||||
|
||||
BufferEcall := struct align(1){.operation: u8; .str_ptr: ^u8; .str_len: uint}
|
||||
$buf_create_named := fn(name: []u8): uint {
|
||||
return @ecall(3, 0, BufferEcall.(0, name.ptr, name.len), @size_of(BufferEcall))
|
||||
}
|
||||
$buf_create := fn(): uint {
|
||||
return @ecall(1, 0)
|
||||
}
|
||||
$buf_destroy := fn(id: uint): void {
|
||||
return @ecall(2, id)
|
||||
}
|
||||
$buf_search := fn(name: []u8): uint {
|
||||
return @ecall(3, 0, BufferEcall.(3, name.ptr, name.len), @size_of(BufferEcall))
|
||||
}
|
||||
$buf_await := fn(id: uint): void {
|
||||
return @ecall(7, id)
|
||||
}
|
||||
$buf_read := fn(id: uint, mmap: []u8): void {
|
||||
return @ecall(4, id, mmap.ptr, mmap.len)
|
||||
}
|
||||
$buf_write := fn(id: uint, mmap: []u8): void {
|
||||
return @ecall(3, id, mmap.ptr, mmap.len)
|
||||
}
|
||||
|
|
|
@ -11,8 +11,16 @@ lib.{
|
|||
memset,
|
||||
memfill,
|
||||
exit,
|
||||
fill_rand,
|
||||
fork,
|
||||
rand_fill,
|
||||
proc_fork,
|
||||
proc_spawn,
|
||||
buf_create_named,
|
||||
buf_create,
|
||||
buf_destroy,
|
||||
buf_search,
|
||||
buf_await,
|
||||
buf_read,
|
||||
buf_write,
|
||||
} := Lib(current())
|
||||
|
||||
Target := enum {
|
||||
|
|
Loading…
Reference in a new issue