type string = []char func split(src: string, by: char, a: ^Arena): [dyn]string do let r: [dyn]string = {} let s: string = "" for c in src do if c == by then r.push(s, a) s = "" else s.push(c, a) end end return r end proc main do let a = Arena() let lines = split(stdin.readAll(@a), '\n', @a) for i in 0..len(lines) do print(lines[i]) end end --- fn next_line(src, line: ^[]u8) -> bool { if len(src) < 1 { return false } let idx = find(src, '\n') if idx <> -1 { line^ := src^[0..idx] } else { line^ := src^ } src^ = src^[len(line)..] return true } fn main { let a = Arena() let buf = readall(stdin, &a) let line: []u8 while next_line(&buf, &line) { print(line) } } --- /* builtin slice type */ fn print(str []u8) { for i in str { putchar(str[i]) } putchar('\n') } /* iterators are just functions that return an initial state object and a * step function that acts on it to produce a value */ type LineIterFn = fn(it ^[]u8) ([]u8, bool) fn lines(src []u8) ([]u8, LineIterFn) { fn step(it ^[]u8) []u8, bool { if len(it^) < 1 { return {}, false } idx := find(it^, '\n') line := if idx == -1 { it^ } else { it^[0..idx] } it^ = it^[len(line)..] return line, true } return src, step } /* if multiple values used in if/while condition, only the last one is checked */ fn main { a := Arena {} buf := readall(stdin, &a) for line in lines(buf) { print(line) } } /* generics? */ fn reverse[T any](buf []T) ([]T, fn(it ^[]T) (T, bool)) { fn step(it ^[]T) (T, bool) { if len(^it) < 1 { return {}, false } n := len(it^) - 1 v := it^[n] it^ := it^[0..n] return v, true } return buf, step } fn foo { s := "Hello, world!" // print(reverse(s)) <- wouldn't actually work, because iterators can't be cast back to slices a := Arena {} print(collect(reverse(s), &a)) } struct MapIter[In any, Out any] { ctx: rawptr, iter: fn(it rawptr) In, map: fn(x ^In) Out } fn map[In any, Out any](p rawptr, f func(it rawptr) In, f func(x ^In) Out) (MapIter[In, Out], fn(it ^MapIter[In, Out]) (Out, bool)) { fn step(it ^MapIter[In, Out]) (Out, bool) { v, ok := it.iter(it.ctx) if !ok { return {}, false } return it.map(&v), true } }