diff --git a/bend2/comp.ts b/bend2/comp.ts index 64dbc33669..fa709b7510 100644 --- a/bend2/comp.ts +++ b/bend2/comp.ts @@ -2712,6 +2712,8 @@ function effect_src(k: Name, tld: Bend.Def & { i: string[] }): void { // WL_LOAD is a ladder: clang is O(n^2) on a fallthrough switch. function c_units(): Unit[] { + const lists = tld_of("Array.to_list.go")?.b + && new Set(FL.book.tmps["Array.to_list.go"]?.values()); for (const [k, tld] of [...done_defs().reverse(), ...done_defs(def_foreign)]) { unit_new(k, () => { @@ -2719,6 +2721,27 @@ function c_units(): Unit[] { FL.unit!.segs.push(dl.seg); if (def_foreign(tld)) { emit_put(dl, null, val_new([ctr_build(dl, k, dl.seg.params)], BOX)); + } else if (lists && lists.has(k)) { + const [a, acc] = vals.flatMap((v) => val_own(v)); + const T = adt_of(fun_of(k).live[0][2]).x[0]; + const el = lay_el(T); + const stride = 2 ** lay_arr(el).lgs; + const [loc] = emit_hold(dl, [arr_loc(dl, a)], "at"); + const i = name_local(dl, "i"); + const poll = name_local(dl, "poll"); + file_push(dl, `u32 ${poll} = 0;`); + fact_when("ctr", "Con", () => facts_ctr(k, FL.book.ctrs.Con, + adt_of(tele_unbind(tld.T).ret).x)); + block(dl, `for (u32 ${i} = 1u << blk_cls(${a}); ${i} >= ${stride}u;) {`, () => { + file_push(dl, `if (err_spun(e.mem, &${poll})) { return 0; }`, + `${i} -= ${stride}u;`); + const v = arr_cells(dl, loc, i, el, + `blk_shr(${a}) ? blk_keep(e, $) : e.mem[$]`); + const con = ctr_build(dl, "Con", [val_box(dl, v), acc]); + file_push(dl, `${acc} = ${con};`); + }); + file_push(dl, `blk_free(e, ${a});`); + emit_put(dl, null, val_new([acc], BOX)); } else { emit_body(dl, fun_of(k).h!, tld.T, vals, null); } diff --git a/tests/compile/array_to_list_device.bend b/tests/compile/array_to_list_device.bend new file mode 100644 index 0000000000..f64a9c4e4e --- /dev/null +++ b/tests/compile/array_to_list_device.bend @@ -0,0 +1,28 @@ +import Base + +def vals(a: Array) -> U32: + List.foldl(~&1, ~U32, ~U32, ~(s => x => (s * 31 + x : U32)), Array.to_list(~U32, a), 0) + +def texts(xs: List) -> Nat: + match xs: + case []: 0n + case h <> t: (String.length(h) + texts(t) : Nat) + +def boxed(p: Array & Array) -> U32: + (a, b) = p + xs = Array.to_list(~String, a) + ys = Array.to_list(~String, Array.set(String, b, 0, "changed")) + U32.from_nat((texts(xs) + texts(ys) : Nat)) + +def fan(+d: Nat, +x: U32) -> U32: + match d: + case 0n: + (vals(Array.set(U32, [x : U32*8n], 6, (x + 1 : U32))) + boxed(Array.fork(String, [U32.show(x) : String*4n])) : U32) + case 1n+p: + a b = fan(p, x) fan(p, (x + 1 : U32)) + (a + b : U32) + +def main() -> U32: + fan!(6n, 42) + +#|2578033920 diff --git a/tests/compile/array_to_list_flat.bend b/tests/compile/array_to_list_flat.bend new file mode 100644 index 0000000000..e4fb23ddb3 --- /dev/null +++ b/tests/compile/array_to_list_flat.bend @@ -0,0 +1,57 @@ +import Base + +type Shape is Data: + Z{} + W{x: U32, y: U32} + S{text: String} + +def shape(x: Shape) -> String: + match x: + case Z{}: "z" + case W{x, y}: U32.show(x) ++ ":" ++ U32.show(y) + case S{text}: text + +def shapes(xs: List) -> String: + match xs: + case []: + "" + case h <> t: + shape(h) ++ "/" ++ shapes(t) + +def nums(xs: List, +s: U32) -> U32: + match xs: + case []: s + case h <> t: nums(t, (s * 10 + h : U32)) + +def funcs(xs: List<(U32 -> U32)>, +s: U32) -> U32: + match xs: + case []: s + case h <> t: funcs(t, (s * 10 + h(3) : U32)) + +def box(n: U32) -> Array<(U32 -> U32)>: + ALeaf{x => (n + x : U32)} + +def shared(p: Array & Array) -> String: + (a, b) = p + xs = Array.to_list(~Shape, a) + ys = Array.to_list(~Shape, Array.set(Shape, b, 0, S{"changed"})) + shapes(xs) ++ "|" ++ shapes(ys) + +def run(+n: U32) -> IO(Unit): + a = Array.set(Shape, Array.set(Shape, [Z{} : Shape*4n], 1, W{n, 2}), 2, S{U32.show(n)}) + f = Array.to_list(~(U32 -> U32)) + do IO: + Unit <- IO.print(U32.show(nums(Array.to_list(~U32, Array.set(U32, [n : U32*4n], 2, 3)), 0))) + Unit <- IO.print(U32.show(funcs(f(ANode{box(n), box(2)}), 0))) + Unit <- IO.print(shared(Array.fork(Shape, a))) + Unit <- IO.print(shapes(Array.to_list.go(~Shape, ALeaf{S{U32.show(n)}}, [S{"tail"}]))) + IO.print(Nat.show(List.length(&1, Unit, Array.to_list(~Unit, [Unit{} : Unit*4n])))) + +def main() -> IO(Unit): + run(4) + +#|4434 +#|75 +#|z/4:2/4/z/|changed/4:2/4/z/ +#|4/tail/ +#|4