summaryrefslogtreecommitdiff
path: root/doc/test.txt
blob: da8f50101e2592719e086336465639b51f152dd1 (plain)
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
	}
}