1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
|
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
}
}
|