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
|
namespace;
include rt;
// packed byte strings in the zc0 subset: the same program runs on the resident
// compiler and, built into a run-only image, on stage 0 (src/tools/zc0.c). it
// covers every b"..." escape, the packed layout, bstr locals, globals,
// parameters and returns, + and the six comparisons, indexing, slicing, len
// and embed. run from the repository root: the embeds read tests/data/embed.
bstr greeting = b"hello";
bstr shout;
bstr plain = b"plain";
embed "tests/data/embed/text.txt" as bstr text;
embed "tests/data/embed/nul.bin" as bstr nul;
embed "tests/data/embed/text.txt" as untyped;
bstr tag(bstr s) { return b"<" + s + b">"; }
bstr twice(bstr s);
bstr twice(bstr s) { return s + s; }
bstr pick(int n) {
bstr r;
if (n) r = b"yes"; else r = b"no";
return r;
}
int rank(bstr a, bstr b) { return (a < b) * 8 + (a <= b) * 4 + (a == b) * 2 + (a > b); }
int count(bstr s, int c) {
int n = 0, i = 0;
while (i < len(s)) { if (s[i] == c) n++; i++; }
return n;
}
int num(int n) { rt.put_n(n); rt.put_c(32); return 0; }
int nl() { rt.put_c(10); return 0; }
int bytes(bstr s) {
int i = 0;
num(len(s));
while (i < len(s)) { num(s[i]); i++; }
nl();
return 0;
}
int words(bstr s) {
word* w = rt.bstr_storage(s);
int n = 1 + (w[0] >> 3) + 1, i = 0;
while (i < n) { num(w[i]); i++; }
nl();
return 0;
}
fn main() {
bstr a = b"abc", b, c;
bstr e = b"";
let u = b"x";
// every escape the lexer knows: n t r 0 e, and any other character stands for itself
bytes(b"\n\t\r\e\\\"\'\q\x41");
bytes(b"ab\0cd");
bytes(b"\0");
bytes(b"café");
bytes(b"caf\303\251");
bytes(b"quote \" inside, 'single', back\\slash");
// the layout: a length word, bytes packed 8 to a word, a 0 word after a full last word
words(e);
words(b"a");
words(b"abcdefg");
words(b"abcdefgh");
words(b"abcdefghi");
words(b"0123456789abcdef");
words(b"0123456789abcdefg");
words(text);
words(nul);
// declarations, assignment later, a return value, concatenation
b = tag(a);
c = twice(b) + e + u;
rt.put_s(a); rt.put_c(32); rt.put_s(b); rt.put_c(32); rt.put_s(c); nl();
shout = twice(greeting) + b"!";
rt.put_s(greeting); rt.put_c(32); rt.put_s(shout); rt.put_c(32); rt.put_s(plain); nl();
rt.put_s(tag(twice(tag(b"z")))); nl();
rt.put_s(pick(1) + b"/" + pick(0)); nl();
// comparisons: below, equal, above, a prefix, the empty string, a 9 byte string
num(rank(b"abc", b"abd")); num(rank(b"abc", b"abc")); num(rank(b"abd", b"abc"));
num(rank(b"ab", b"abc")); num(rank(b"", b"")); num(rank(b"", b"a"));
num(rank(b"abcdefghi", b"abcdefghi")); num(rank(b"abcdefgh", b"abcdefghi")); nl();
num(a == b"abc"); num(a != b"abc"); num(a == b); num(a != b);
num(tag(a) == b"<abc>"); num(shout > greeting); num(greeting >= shout); num(plain <= plain); nl();
// indexing, slicing, len
num(a[0]); num(a[2]); num(a[3]); num(len(a)); num(len(e)); num(len(c)); num(len(b"123456789")); nl();
rt.put_s(c[1:4]); rt.put_c(32); rt.put_s(a[1:2]); rt.put_c(32); rt.put_s(a[0:0]); rt.put_c('|');
rt.put_s(a[2:99]); rt.put_c('|'); rt.put_s(a[3:1]); rt.put_c('|'); rt.put_s((a + a)[2:4]); nl();
num(count(c, '<')); num(count(shout, 'l')); num(count(b"mississippi", 's')); num(count(e, 'x')); nl();
num(b"xyz"[1]); num(len(b"xyz")); num(len(a + a + a)); num(len(tag(e))); nl();
// embed: a global of the file's bytes, with or without the type, and a local
rt.put_s(text); num(len(text)); num(text[0]); num(text == untyped); num(len(nul)); num(nul[2]); nl();
embed "tests/data/embed/text.txt" as bstr here;
embed "tests/data/embed/answer.bin" as int answer;
embed "tests/data/embed/text.txt" as char* chars;
rt.put_s(here + b"|" + untyped); num(len(here)); num(here == text); num(answer); num(chars[6]); nl();
return 0;
}
|