on c19bc7a help sign in
urbit.org/docs/tutorials/nock/implementations.udon
260 lines 5.8 kB history raw
1:- :~ navhome/'/docs/'
2 navuptwo/'true'
3 sort/'4'
4 title/'Implementation'
5 ==
6;>
8# C implementation
10The actual production Nock interpreter. Note gotos for tail-call elimination,
11and manual reference counting. More about the C environment can be found
12in the [runtime system documentation](../../../vere/runtime).
14```
15/* _n_nock_on(): produce .*(bus fol). Do not virtualize.
16*/
17static u3_noun
18_n_nock_on(u3_noun bus, u3_noun fol)
20 u3_noun hib, gal;
22 while ( 1 ) {
23 hib = u3h(fol);
24 gal = u3t(fol);
26#ifdef U3_CPU_DEBUG
27 u3R->pro.nox_d += 1;
28#endif
30 if ( c3y == u3r_du(hib) ) {
31 u3_noun poz, riv;
33 poz = _n_nock_on(u3k(bus), u3k(hib));
34 riv = _n_nock_on(bus, u3k(gal));
36 u3a_lose(fol);
37 return u3i_cell(poz, riv);
38 }
39 else switch ( hib ) {
40 default: return u3m_bail(c3__exit);
42 case 0: {
43 if ( c3n == u3r_ud(gal) ) {
44 return u3m_bail(c3__exit);
45 }
46 else {
47 u3_noun pro = u3k(u3at(gal, bus));
49 u3a_lose(bus); u3a_lose(fol);
50 return pro;
51 }
52 }
53 c3_assert(!"not reached");
55 case 1: {
56 u3_noun pro = u3k(gal);
58 u3a_lose(bus); u3a_lose(fol);
59 return pro;
60 }
61 c3_assert(!"not reached");
63 case 2: {
64 u3_noun nex = _n_nock_on(u3k(bus), u3k(u3t(gal)));
65 u3_noun seb = _n_nock_on(bus, u3k(u3h(gal)));
67 u3a_lose(fol);
68 bus = seb;
69 fol = nex;
70 continue;
71 }
72 c3_assert(!"not reached");
74 case 3: {
75 u3_noun gof, pro;
77 gof = _n_nock_on(bus, u3k(gal));
78 pro = u3r_du(gof);
80 u3a_lose(gof); u3a_lose(fol);
81 return pro;
82 }
83 c3_assert(!"not reached");
85 case 4: {
86 u3_noun gof, pro;
88 gof = _n_nock_on(bus, u3k(gal));
89 pro = u3i_vint(gof);
91 u3a_lose(fol);
92 return pro;
93 }
94 c3_assert(!"not reached");
96 case 5: {
97 u3_noun wim = _n_nock_on(bus, u3k(gal));
98 u3_noun pro = u3r_sing(u3h(wim), u3t(wim));
100 u3a_lose(wim); u3a_lose(fol);
101 return pro;
102 }
103 c3_assert(!"not reached");
105 case 6: {
106 u3_noun b_gal, c_gal, d_gal;
108 u3x_trel(gal, &b_gal, &c_gal, &d_gal);
109 {
110 u3_noun tys = _n_nock_on(u3k(bus), u3k(b_gal));
111 u3_noun nex;
113 if ( 0 == tys ) {
114 nex = u3k(c_gal);
115 } else if ( 1 == tys ) {
116 nex = u3k(d_gal);
117 } else return u3m_bail(c3__exit);
119 u3a_lose(fol);
120 fol = nex;
121 continue;
122 }
123 }
124 c3_assert(!"not reached");
126 case 7: {
127 u3_noun b_gal, c_gal;
129 u3x_cell(gal, &b_gal, &c_gal);
130 {
131 u3_noun bod = _n_nock_on(bus, u3k(b_gal));
132 u3_noun nex = u3k(c_gal);
134 u3a_lose(fol);
135 bus = bod;
136 fol = nex;
137 continue;
138 }
139 }
140 c3_assert(!"not reached");
142 case 8: {
143 u3_noun b_gal, c_gal;
145 u3x_cell(gal, &b_gal, &c_gal);
146 {
147 u3_noun heb = _n_nock_on(u3k(bus), u3k(b_gal));
148 u3_noun bod = u3nc(heb, bus);
149 u3_noun nex = u3k(c_gal);
151 u3a_lose(fol);
152 bus = bod;
153 fol = nex;
154 continue;
155 }
156 }
157 c3_assert(!"not reached");
159 case 9: {
160 u3_noun b_gal, c_gal;
162 u3x_cell(gal, &b_gal, &c_gal);
163 {
164 u3_noun seb = _n_nock_on(bus, u3k(c_gal));
165 u3_noun pro;
167 u3t_off(noc_o);
168 pro = u3j_kick(seb, b_gal);
169 u3t_on(noc_o);
171 if ( u3_none != pro ) {
172 u3a_lose(fol);
173 return pro;
174 }
175 else {
176 if ( c3n == u3r_ud(b_gal) ) {
177 return u3m_bail(c3__exit);
178 }
179 else {
180 u3_noun nex = u3k(u3at(b_gal, seb));
182 u3a_lose(fol);
183 bus = seb;
184 fol = nex;
185 continue;
186 }
187 }
188 }
189 }
190 c3_assert(!"not reached");
192 case 10: {
193 u3_noun p_gal, q_gal;
195 u3x_cell(gal, &p_gal, &q_gal);
196 {
197 u3_noun zep, hod, nex;
199 if ( c3y == u3r_du(p_gal) ) {
200 u3_noun b_gal = u3h(p_gal);
201 u3_noun c_gal = u3t(p_gal);
202 u3_noun d_gal = q_gal;
204 zep = u3k(b_gal);
205 hod = _n_nock_on(u3k(bus), u3k(c_gal));
206 nex = u3k(d_gal);
207 }
208 else {
209 u3_noun b_gal = p_gal;
210 u3_noun c_gal = q_gal;
212 zep = u3k(b_gal);
213 hod = u3_nul;
214 nex = u3k(c_gal);
215 }
217 u3a_lose(fol);
218 return _n_hint(zep, hod, bus, nex);
219 }
220 }
222 case 11: {
223 u3_noun ref = _n_nock_on(u3k(bus), u3k(u3h(gal)));
224 u3_noun gof = _n_nock_on(bus, u3k(u3t(gal)));
225 u3_noun val;
227 u3t_off(noc_o);
228 val = u3m_soft_esc(ref, u3k(gof));
229 u3t_on(noc_o);
231 if ( !_(u3du(val)) ) {
232 u3m_bail(u3nt(1, gof, 0));
233 }
234 if ( !_(u3du(u3t(val))) ) {
235 //
236 // replace with proper error stack push
237 //
238 u3t_push(u3nc(c3__hunk, _n_mush(gof)));
239 return u3m_bail(c3__exit);
240 }
241 else {
242 u3_noun pro;
244 u3z(gof);
245 u3z(fol);
246 pro = u3k(u3t(u3t(val)));
247 u3z(val);
249 return pro;
250 }
251 }
252 c3_assert(!"not reached");
253 }
254 }
256```
258Building a Nock interpreter in another language is a fun exercise. Check out our community Nock implementations. (Note: these were written for a slightly older version of Nock, Nock 5K. The current version is Nock 4K.):
260;list(src "../../nock/implementations");