From 90b0d817fedfa5715b195e16da67fa6bdd67638e Mon Sep 17 00:00:00 2001 From: Kimplul Date: Mon, 29 Dec 2025 00:07:16 +0200 Subject: work towards a simple integer vector implementation + Hopefully shows that useful programs can be implemented with the rules present + Still missing at least external functions with non-void returns --- examples/vec.fwd | 150 +++++++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 112 insertions(+), 38 deletions(-) (limited to 'examples/vec.fwd') diff --git a/examples/vec.fwd b/examples/vec.fwd index 1cc10b3..6c854d5 100644 --- a/examples/vec.fwd +++ b/examples/vec.fwd @@ -1,51 +1,125 @@ +import "../mod/libfwdio.so" import "../mod/libfwdmem.so" import "../mod/libfwdutil.so" -/* trait */ -any = {} +vec { + u64 n; + u64 s; + *i64 buf; +} + +init_vec(u64 n, (vec) ok) +{ + ok([n => n, 0 as u64 => s, * => buf] vec); +} + +next_s_vec(u64 s, (u64) ok) +{ + if s == 0 as u64 { + ok(1 as u64); + } else { + ok(2 as u64 * s); + } +} -/* template */ -vec[any type]() { - <> { - i64 s; - i64 n; - *[]type buf; +reserve_vec(vec v, u64 c, (vec) ok) +{ + v => [n => n, s => s, buf => buf]; + n + c => nn; + + /* expand if we run out of space */ + if nn > s { + next_s_vec(s) => s; + + /* note that fwdrealloc creates a new closure, meaning that it + * takes ownership of v.buf, so we can't back out and do a + * single ok(v) at the end of the function */ + fwdrealloc(buf, s * sizeof(i64)) => nbuf; + ok([nn => n, s => s, nbuf => buf] vec); + } else { + ok([nn => n, s => s, buf => buf] vec); } +} + +set_vec(vec v, i64 i, i64 e, (vec) ok) +{ + v => [n => n, s => s, buf => buf]; + buf + (n - 1 as u64) => nbuf; + nil nbuf {fwdpanic("should never happen");} => dst; + e => dst*; + ok([n => n, s => s, nbuf => buf] vec); +} + +n_vec(vec v, (vec, u64) ok) +{ + v => [n => n, s => s, buf => buf]; + ok([n => n, s => s, buf => buf] vec, n); +} + +append_vec(vec v, i64 e, (vec) ok) +{ + n_vec(v) => v, n; + reserve_vec(v, n + 1 as u64) => v; + set_vec(v, n as i64 - 1, e) => v; + ok(v); +} + +at_vec(vec v, u64 i, (vec, &i64) ok) +{ + v => [n => n, s => s, buf => buf]; + if i >= n {fwdpanic("bounds error");} + fwdptradd(buf, (i * sizeof(i64)) as i64) => *i64 buf; + nil buf {fwdpanic("should never happen");} => &i64 bufr; + ok([n => n, s => s, buf => buf] vec, bufr); +} + +destroy_vec(vec v) +{ + v => [n => n, s => s, buf => buf]; + fwdfree(buf); + nil n; + nil s; +} - <>create((<>) next) - { - next((0 => s, 0 => n, * => buf)<>); +populate_vec(i64 i, i64 n, vec v, (vec) ok) +{ + if i < n { + append_vec(v, i) => vec v; + populate_vec(i + 1, n, v, ok); + } else { + ok(v); } +} - <>append(<> v, type n, (<>) next) - { - v.n = v.n + 1; - if v.s == 0 { - v.s = 1; - } - - if v.n > v.s { - if v.s == 0 { - v.s = 1; - } - - v.s = v.s * 2; - fwdrealloc(v.buf, v.s as u64 * sizeof(type)) => ptr; - v.buf = ptr; - } - - /* in a real implementation this would be moved to after - * fwdrealloc I guess, but this is fine for now */ - nil v.buf {fwdpanic("no buf for vector");} => buf; - buf*[v.n - 1] = n; - next(v); +guard(bool c, () err | () ok) +{ + if c { + err(); + } else { + ok(); } +} - <>destroy(<> v) - { - fwdfree(v.buf); - nil v; +check_vec(i64 i, i64 n, vec v, (vec) ok) +{ + if i < n { + at_vec(v, i as u64) => v, elem; + + guard(elem* != i) => { + destroy_vec(v); + fwdpanic("vec built wrong"); + } => ; + + check_vec(i + 1, n, v, ok); + } else { + ok(v); } } -u8vec = vec[u8]() +main() +{ + init_vec(0 as u64) => vec v; + populate_vec(0, 1000000, v) => vec v; + check_vec(0, 1000000, v) => vec v; + destroy_vec(v); +} -- cgit v1.2.3