begin work on iterators & memory functions
This commit is contained in:
parent
01ea41bc34
commit
c1d8688539
62
build
62
build
|
@ -8,56 +8,62 @@ readonly LILY_TEST_DIR="${LILY_TEST_DIR:-$LILY_SCRIPT_DIR/test}"
|
|||
readonly LILY_BUILD_DIR="${LILY_BUILD_DIR:-$LILY_SCRIPT_DIR/out}"
|
||||
|
||||
readonly HBLANG_GIT="https://git.ablecorp.us/mlokis/hblang"
|
||||
readonly HBLANG_COMMIT="fcbcaac67dd47887fef81bc62d4b66a6cf071f8c"
|
||||
readonly HBLANG_BRANCH="main"
|
||||
readonly HBLANG_COMMIT="025a4865beb9b372f6f1025fdcca13f55aa55517"
|
||||
readonly HBLANG_CFLAGS="--path-projection lily $LILY_SRC_DIR/lib.hb ${HBLANG_CFLAGS:-}"
|
||||
|
||||
die() { error "$2" && exit "$1"; }
|
||||
error() { printf "\033[31mERROR\033[0m: %s\n" "$1" 1>&2; }
|
||||
log() { printf "\033[32mINFO\033[0m: %s\n" "$1"; }
|
||||
warn() { printf "\033[33mWARN\033[0m: %s\n" "$1"; }
|
||||
log() { printf "\033[32mINFO\033[0m: %s\n" "$1" 1>&2; }
|
||||
warn() { printf "\033[33mWARN\033[0m: %s\n" "$1" 1>&2; }
|
||||
|
||||
fetch_step() {
|
||||
|
||||
command -v zig >/dev/null 2>&1 || die 101 "'zig' binary not found in PATH"
|
||||
command -v git >/dev/null 2>&1 || die 101 "'git' binary not found in PATH"
|
||||
|
||||
if [ -d "$LILY_BUILD_DIR/hblang" ]; then
|
||||
cd "$LILY_BUILD_DIR/hblang" || die 1 "cd to $LILY_BUILD_DIR/hblang failed"
|
||||
hblang_dir="$LILY_BUILD_DIR/hblang"
|
||||
mkdir -p "$hblang_dir" || die 1 "failed to create hblang directory"
|
||||
|
||||
CURR_BRANCH=$(git rev-parse --abbrev-ref HEAD >/dev/null 2>&1)
|
||||
[ "$CURR_BRANCH" = "$HBLANG_BRANCH" ] || git checkout "$HBLANG_BRANCH" >/dev/null 2>&1
|
||||
CURR_COMMIT=$(git rev-parse HEAD >/dev/null 2>&1)
|
||||
[ "$CURR_COMMIT" = "$HBLANG_COMMIT" ] || git checkout "$HBLANG_COMMIT" >/dev/null 2>&1
|
||||
if [ -d "$hblang_dir/.git" ]; then
|
||||
cd "$hblang_dir" || die 1 "failed to enter hblang directory"
|
||||
|
||||
current_commit=$(git rev-parse HEAD 2>/dev/null)
|
||||
if [ "$current_commit" != "$HBLANG_COMMIT" ]; then
|
||||
if ! git cat-file -e "$HBLANG_COMMIT^{commit}" 2>/dev/null; then
|
||||
log "fetching hblang repository updates"
|
||||
git fetch --all >/dev/null 2>&1 || die 1 "failed to fetch repository"
|
||||
fi
|
||||
git checkout -f "$HBLANG_COMMIT" >/dev/null 2>&1 || die 1 "failed to checkout commit"
|
||||
fi
|
||||
else
|
||||
mkdir -p "$LILY_BUILD_DIR/hblang"
|
||||
git clone "$HBLANG_GIT" "$LILY_BUILD_DIR/hblang" --branch "$HBLANG_BRANCH"
|
||||
cd "$LILY_BUILD_DIR/hblang" || die 1 "cd to $LILY_BUILD_DIR/hblang failed"
|
||||
git checkout "$HBLANG_COMMIT" >/dev/null 2>&1
|
||||
log "cloning hblang repository"
|
||||
git clone "$HBLANG_GIT" "$hblang_dir" >/dev/null 2>&1 || die 1 "failed to clone repository"
|
||||
cd "$hblang_dir" || die 1 "failed to enter cloned directory"
|
||||
|
||||
if ! git cat-file -e "$HBLANG_COMMIT^{commit}" 2>/dev/null; then
|
||||
git fetch origin "$HBLANG_COMMIT" >/dev/null 2>&1 || die 1 "failed to fetch commit"
|
||||
fi
|
||||
git checkout -f "$HBLANG_COMMIT" >/dev/null 2>&1 || die 1 "failed to checkout commit"
|
||||
fi
|
||||
|
||||
zig build install
|
||||
|
||||
PATH="$LILY_BUILD_DIR/hblang/zig-out/bin:$PATH"
|
||||
|
||||
cd "$LILY_SCRIPT_DIR" || die 1 "cd to $LILY_SCRIPT_DIR failed"
|
||||
zig build install >/dev/null 2>&1 || die 1 "failed to build hblang"
|
||||
|
||||
PATH="$hblang_dir/zig-out/bin:$PATH"
|
||||
cd "$LILY_SCRIPT_DIR" || die 1 "failed to return to script directory"
|
||||
}
|
||||
|
||||
main() {
|
||||
mkdir -p "$LILY_BUILD_DIR" || die 1 "can't create build dir"
|
||||
mkdir -p "$LILY_BUILD_DIR" || die 1 "failed to create build directory"
|
||||
fetch_step
|
||||
|
||||
inp="${1:-main.hb}"
|
||||
|
||||
[ -z "$inp" ] || [ ! -e "$inp" ] && die 1 "source file '$inp' does not exist"
|
||||
[ ! -e "$inp" ] && die 1 "source file '$inp' does not exist"
|
||||
|
||||
# shellcheck disable=SC2086
|
||||
{
|
||||
hblang $HBLANG_CFLAGS $inp
|
||||
# todo: dont do this second compile if first fails
|
||||
hblang $HBLANG_CFLAGS $inp --fmt >/dev/null 2>&1
|
||||
}
|
||||
if hblang $HBLANG_CFLAGS "$inp"; then
|
||||
hblang $HBLANG_CFLAGS "$inp" --fmt >/dev/null 2>&1
|
||||
else
|
||||
exit $?
|
||||
fi
|
||||
}
|
||||
|
||||
main "$@"
|
||||
|
|
30
main.hb
30
main.hb
|
@ -1,5 +1,31 @@
|
|||
lily := @use("lily")
|
||||
lily.{target, log, mem} := @use("lily")
|
||||
|
||||
FunkyTown := struct {
|
||||
.is_null: bool;
|
||||
.ptr: ^u8;
|
||||
}
|
||||
|
||||
main := fn(): void {
|
||||
a := lily.target.func()
|
||||
a := "Hello, World!"
|
||||
b := mem.bytes(a).map(fn(x: u8): u8 return x + 2)
|
||||
c := b.next().val
|
||||
if c != 0x48 + 2 die
|
||||
|
||||
// a := target.alloc(1000)[0..1000]
|
||||
// // todo: remove @as()
|
||||
// if @as(uint, @bit_cast(a.ptr)) == 0 {
|
||||
// log.error("alloced is null")
|
||||
// die
|
||||
// }
|
||||
|
||||
// mem.copy(a.ptr, "Hello, World!".ptr, 13)
|
||||
|
||||
// if !mem.equals(a[0..13], "Hello, World!") {
|
||||
// log.error("badness")
|
||||
// die
|
||||
// }
|
||||
|
||||
// log.info(a[0..13])
|
||||
|
||||
// target.dealloc(a.ptr, 1000)
|
||||
}
|
||||
|
|
30
src/iter.hb
Normal file
30
src/iter.hb
Normal file
|
@ -0,0 +1,30 @@
|
|||
Next := fn(T: type): type return struct {
|
||||
.finished: bool;
|
||||
.val: T
|
||||
|
||||
$yield := fn(val: T): @CurrentScope() return .(false, val)
|
||||
$done := fn(): @CurrentScope() return .(true, idk)
|
||||
}
|
||||
|
||||
Iterator := fn(T: type): type return struct {
|
||||
.inner: T
|
||||
IterNext := @TypeOf(T.next(idk))
|
||||
IterVal := @TypeOf(T.next(idk).val)
|
||||
|
||||
$next := fn(self: ^@CurrentScope()): IterNext {
|
||||
return self.inner.next()
|
||||
}
|
||||
$map := fn(self: ^@CurrentScope(), func: type): Iterator(Map(T, func)) {
|
||||
return .(.(self))
|
||||
}
|
||||
}
|
||||
|
||||
Map := fn(T: type, func: type): type return struct {
|
||||
.iter: Iterator(T)
|
||||
IterNext := @TypeOf(func(@as(@TypeOf(T.next(idk).val), idk)))
|
||||
|
||||
next := fn(self: ^@CurrentScope()): Next(IterNext) {
|
||||
x := self.iter.inner.next()
|
||||
return .(x.finished, func(x.val))
|
||||
}
|
||||
}
|
|
@ -1,2 +1,4 @@
|
|||
target := @use("target/lib.hb")
|
||||
iter := @use("iter.hb")
|
||||
mem := @use("mem.hb")
|
||||
log := @use("log.hb")
|
||||
|
|
36
src/mem.hb
Normal file
36
src/mem.hb
Normal file
|
@ -0,0 +1,36 @@
|
|||
.{target, iter: .{Iterator, Next}} := @use("lib.hb")
|
||||
|
||||
$copy := fn(dest: ^u8, src: ^u8, len: uint): void {
|
||||
target.memcopy(dest, src, len)
|
||||
}
|
||||
|
||||
$move := fn(dest: ^u8, src: ^u8, len: uint): void {
|
||||
target.memmove(dest, src, len)
|
||||
}
|
||||
|
||||
$set := fn(dest: ^u8, src: u8, len: uint): void {
|
||||
target.memset(dest, src, len)
|
||||
}
|
||||
|
||||
equals := fn(lhs: []u8, rhs: []u8): bool {
|
||||
if lhs.len != rhs.len return false
|
||||
if lhs.ptr == rhs.ptr return true
|
||||
i := 0
|
||||
loop if i == lhs.len break else {
|
||||
if lhs[i] != rhs[i] return false
|
||||
i += 1
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
$bytes := fn(slice: []u8): Iterator(struct {
|
||||
.slice: []u8
|
||||
|
||||
$next := fn(self: ^@CurrentScope()): Next(u8) {
|
||||
tmp := Next(u8).(self.slice.len == 0, self.slice.ptr.*)
|
||||
self.slice = self.slice[1..]
|
||||
return tmp
|
||||
}
|
||||
}) {
|
||||
return .(.(slice))
|
||||
}
|
|
@ -1,9 +1,5 @@
|
|||
.{LogLevel} := @use("../lib.hb").log
|
||||
|
||||
func := fn(): uint {
|
||||
return 0
|
||||
}
|
||||
|
||||
LogEcall := struct align(1){.level: LogLevel; .str_ptr: ^u8; .str_len: uint}
|
||||
|
||||
$page_len := fn(): uint {
|
||||
|
@ -15,16 +11,19 @@ $pages := fn(len: uint): uint {
|
|||
}
|
||||
|
||||
AllocEcall := struct align(1){.pad: u8; .pages_new: uint; .zeroed: bool}
|
||||
$alloc := fn(len: uint): ?^u8 {
|
||||
// todo: return ?^u8
|
||||
$alloc := fn(len: uint): ^u8 {
|
||||
return @ecall(3, 2, AllocEcall.(0, pages(len), false), @size_of(AllocEcall))
|
||||
}
|
||||
|
||||
$alloc_zeroed := fn(len: uint): ?^u8 {
|
||||
// todo: return ?^u8
|
||||
$alloc_zeroed := fn(len: uint): ^u8 {
|
||||
return @ecall(3, 2, AllocEcall.(0, pages(len), true), @size_of(AllocEcall))
|
||||
}
|
||||
|
||||
ReallocEcall := struct align(1){.pad: u8; .pages_old: uint; .pages_new: uint; .ptr_old: ^u8}
|
||||
$realloc := fn(ptr_old: ^u8, len_old: uint, len_new: uint): ?^u8 {
|
||||
// todo: return ?^u8.
|
||||
$realloc := fn(ptr_old: ^u8, len_old: uint, len_new: uint): ^u8 {
|
||||
return @ecall(3, 2, ReallocEcall.(7, pages(len_old), pages(len_new), ptr_old), @size_of(ReallocEcall))
|
||||
}
|
||||
|
||||
|
@ -42,11 +41,11 @@ $memmove := fn(dest: ^u8, src: ^u8, len: uint): void {
|
|||
}
|
||||
|
||||
SetEcall := struct align(1){.pad: u8; .count: uint; .len: uint; .src: ^u8; .dest: ^u8}
|
||||
$memcopy := fn(dest: ^u8, src: u8, len: uint): void {
|
||||
@ecall(3, 2, SetEcall.(4, len, 1, &src, dest), @size_of(SetEcall))
|
||||
$memset := fn(dest: ^u8, src: u8, len: uint): void {
|
||||
@ecall(3, 2, SetEcall.(5, len, 1, &src, dest), @size_of(SetEcall))
|
||||
}
|
||||
|
||||
$exit := fn(code: u8): void {
|
||||
}
|
||||
$fill_rand := fn(dest: ^u8, len: uint): void @ecall(3, 4, dest, len)
|
||||
$fill_rand := fn(dest: ^u8, len: uint): void return @ecall(3, 4, dest, len)
|
||||
$fork := fn(): uint return @ecall(3, 7)
|
||||
|
|
|
@ -1,10 +1,24 @@
|
|||
.{func} := Lib(current())
|
||||
.{
|
||||
LogEcall,
|
||||
pages,
|
||||
page_len,
|
||||
alloc,
|
||||
alloc_zeroed,
|
||||
realloc,
|
||||
dealloc,
|
||||
memcopy,
|
||||
memmove,
|
||||
memset,
|
||||
exit,
|
||||
fill_rand,
|
||||
fork,
|
||||
} := Lib(current())
|
||||
|
||||
Target := enum {
|
||||
.AbleOS;
|
||||
}
|
||||
|
||||
$current := fn(): Target {
|
||||
current := fn(): Target {
|
||||
$if @target("ableos") {
|
||||
return .AbleOS
|
||||
} else {
|
||||
|
@ -12,7 +26,7 @@ $current := fn(): Target {
|
|||
}
|
||||
}
|
||||
|
||||
$Lib := fn(target: Target): type {
|
||||
Lib := fn(target: Target): type {
|
||||
$match target {
|
||||
.AbleOS => return @use("ableos.hb"),
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue