-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathNEST.c
150 lines (136 loc) · 3.76 KB
/
NEST.c
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
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
#include "NEST.h"
#include "PRO.h"
typedef struct {
u64 var;
u32 pos;
u32 ins;
} mark128;
#define NESTlog(ct) ((mark128**)ct + 2)
fun mark128* NESTmark(Bu8 ct, u32 ndx) {
mark128** log = NESTlog(ct);
assert(ndx > 0 && ndx <= $len(log));
return log[1] - ndx;
}
fun u32 NESTloglen(Bu8 ct) { return $len(NESTlog(ct)); }
fun ok64 NESTaddmark(Bu8 ct, mark128 const* rec) {
mark128** log = NESTlog(ct);
u8$ idle = NESTidle(ct);
if ($size(idle) < sizeof(u128)) return NESTnoroom;
--log[0];
**log = *rec;
return OK;
}
fun ok64 NESTaddvar(Bu8 ct, u64 var) {
mark128 mark = {.var = var, .pos = $len(NESTdata(ct))};
return NESTaddmark(ct, &mark);
}
fun u32 NESTfind(Bu8 ct, u64 var) {
for (u32 i = $len(NESTlog(ct)); i > 0; --i)
if (NESTmark(ct, i)->var == var) return i;
return 0;
}
ok64 NESTsplice(Bu8 ct, u64 var) {
sane(Bok(ct));
u32 at = NESTfind(ct, var);
if (at == 0) return NESTnone;
mark128 mark = {.pos = $len(NESTdata(ct))};
call(NESTaddmark, ct, &mark);
while (NESTmark(ct, at)->ins != 0) at = NESTmark(ct, at)->ins;
NESTmark(ct, at)->ins = $len(NESTlog(ct));
done;
}
ok64 NESTsplicemany(Bu8 ct, u64 var, b8 some) {
sane(Bok(ct));
mark128 mark = {.pos = $len(NESTdata(ct))};
call(NESTaddmark, ct, &mark);
int found = 0;
for (u32 i = $len(NESTlog(ct)); i > 0; --i) {
mark128* m = NESTmark(ct, i);
if (m->var == var && m->ins == 0) {
m->ins = $len(NESTlog(ct));
++found;
}
}
if (!found) fail(NESTnone);
done;
}
// $1 $var ${var}
ok64 NESTscanvar(ok64* var, $u8c input) {
sane(**input == '$' && $len(input) > 1 && var != nil);
u8c* p = input[0];
++p;
if (*p == '$') {
++input[0];
return NESTnone;
}
b8 bracket = (*p == '{');
if (bracket) ++p;
$u8c name = {p};
while (p < input[1] && BASEron64rev[*p] != 0xff) ++p;
if (bracket) {
test(p < input[1] && *p == '}', NESTbad);
name[1] = p;
++p;
} else {
name[1] = p;
}
test($len(name) > 0 && $len(name) <= 10, NESTbad);
OKscan(var, name);
input[0] = p;
done;
}
ok64 NESTfeed(Bu8 ct, $u8c insert) {
sane(Bok(ct) && $ok(insert));
u8$ idle = NESTidle(ct);
u8c$ data = NESTdata(ct);
if ($len(idle) < $len(insert)) return NESTnoroom;
a$dup(u8c, ins, insert);
while (!$empty(ins)) {
if (**ins != '$' || $len(ins) <= 1) {
**idle = **ins, ++*idle, ++*ins;
continue;
}
ok64 var = 0;
ok64 o = NESTscanvar(&var, ins);
if (o != OK) {
**idle = **ins, ++*idle, ++*ins;
} else {
call(NESTaddvar, ct, var);
}
}
done;
}
ok64 NESTrendertree($u8 into, Bu8 ct, u32 ndx) {
sane(Bok(ct) && $ok(into));
u8c$ data = NESTdata(ct);
mark128 zero = {};
do {
mark128* mark = ndx ? NESTmark(ct, ndx) : &zero;
u32 from = mark->pos;
u32 n = ndx + 1;
mark128* next = NESTmark(ct, n);
while (next->var != 0) {
u32 till = next->pos;
a$part(u8c, part, data, from, till - from); // TODO
call($u8feedall, into, part);
from = till;
if (next->ins != 0) {
call(NESTrendertree, into, ct, next->ins);
}
next = NESTmark(ct, ++n);
}
u32 till = next->pos;
a$part(u8c, part, data, from, till - from); // TODO
call($u8feedall, into, part);
ndx = mark->ins;
} while (ndx != 0);
done;
}
ok64 NESTrender($u8 into, Bu8 ct) {
sane($ok(into) && Bok(ct));
u32 from = 0;
mark128 mark = {.pos = $len(NESTdata(ct))};
try(NESTaddmark, ct, &mark);
then try(NESTrendertree, into, ct, 0);
done;
}