Mercurial > repo
comparison src/ploki/run.c @ 4223:ac0403686959
<oerjan> rm -rf src/ploki; mv ploki src
author | HackBot |
---|---|
date | Fri, 20 Dec 2013 22:18:50 +0000 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
4222:b0f3e267bb1e | 4223:ac0403686959 |
---|---|
1 #include "config.h" | |
2 #include "IO.h" | |
3 #include "Str.h" | |
4 #include "atechit.h" | |
5 #include "expr.h" | |
6 #include "hang.h" | |
7 #include "main.h" | |
8 #include "main_io.h" | |
9 #include "main_label.h" | |
10 #include "main_opt.h" | |
11 #include "run.h" | |
12 #include "stack.h" | |
13 #include "strhash.h" | |
14 #include "text.h" | |
15 #include "val.h" | |
16 #include "venus.h" | |
17 #include "xmalloc.h" | |
18 #include "zz.h" | |
19 | |
20 #include <ctype.h> | |
21 #include <errno.h> | |
22 #include <math.h> | |
23 #include <stdlib.h> | |
24 #include <string.h> | |
25 #include <assert.h> | |
26 #include <setjmp.h> | |
27 | |
28 struct Interp Interp; | |
29 | |
30 static void my_x_end(void) { | |
31 v_end(&Interp.arg); | |
32 v_end(&Interp.result); | |
33 | |
34 while (Interp.a.argc) { | |
35 --Interp.a.argc; | |
36 v_end(&Interp.a.argv[Interp.a.argc]); | |
37 } | |
38 xfree(Interp.a.argv); | |
39 | |
40 while (Interp.match.length) { | |
41 --Interp.match.length; | |
42 v_end(&Interp.match.matches[Interp.match.length]); | |
43 } | |
44 xfree(Interp.match.matches); | |
45 | |
46 xfree(Interp.m_start.index); | |
47 xfree(Interp.m_end.index); | |
48 } | |
49 | |
50 static void sp_nop(save_pair *sp) { | |
51 (void)sp; | |
52 } | |
53 | |
54 static void sp_writeback(save_pair *sp) { | |
55 v_set(sp->target, &sp->content); | |
56 v_end(&sp->content); | |
57 } | |
58 | |
59 ATTR_NORETURN | |
60 static void sp_error(const save_pair *x, const save_pair *y) { | |
61 (void)x; | |
62 (void)y; | |
63 NOTREACHED; | |
64 } | |
65 | |
66 stack_define(save_pair, extern, sp_nop, sp_writeback, sp_error) | |
67 | |
68 stack(save_pair) Saved; | |
69 | |
70 void stack_store(struct val *target, const struct val *value) { | |
71 save_pair *tos; | |
72 | |
73 stack_func(save_pair, pushnull)(&Saved); | |
74 tos = stack_func(save_pair, at)(&Saved, 0); | |
75 | |
76 tos->target = target; | |
77 v_iniset(&tos->content, target); | |
78 v_set(target, value); | |
79 } | |
80 | |
81 static void stack_store_del(struct val *target, struct val *value) { | |
82 stack_store(target, value); | |
83 v_delete(value); | |
84 } | |
85 | |
86 size_t depth_get(void) { | |
87 return stack_func(save_pair, size)(&Saved); | |
88 } | |
89 | |
90 void depth_restore(size_t n) { | |
91 assert(depth_get() >= n); | |
92 stack_func(save_pair, clear)(&Saved, depth_get() - n); | |
93 } | |
94 | |
95 struct val *execute(const struct op *op, struct val *arg) { | |
96 struct val *v; | |
97 const size_t curdepth = depth_get(); | |
98 | |
99 stack_store_del(&Interp.arg, arg); | |
100 | |
101 while (op) { | |
102 if (Opt.debug & DBG_OPS) { | |
103 fprintf(io_fp(Err), "op %d\n", op->type); | |
104 } | |
105 switch (op->type) { | |
106 case OP_NOP: | |
107 break; | |
108 | |
109 case OP_ASSIGN: | |
110 if (!op->arh.expr) { | |
111 eval_into(op->arg, &Interp.result); | |
112 } else { | |
113 switch (op->arh.expr->type) { | |
114 case varE: | |
115 eval_into(op->arg, op->arh.expr->v.val); | |
116 break; | |
117 | |
118 case varhashE: { | |
119 struct val *tmp; | |
120 eval_push(op->arg); | |
121 eval_push(op->arh.expr->right); | |
122 tmp = eval_pop(); | |
123 v = eval_pop(); | |
124 V_STR(tmp); | |
125 sh_put(op->arh.expr->v.hash, ko_ptr(tmp->ko), ko_length(tmp->ko), v); | |
126 v_delete(tmp); | |
127 break; | |
128 } | |
129 | |
130 default: | |
131 NOTREACHED; | |
132 break; | |
133 } | |
134 } | |
135 break; | |
136 | |
137 case OP_CALL: | |
138 v = eval_expr(op->arg); | |
139 v = execute(op->arh.op, v); | |
140 v_set(&Interp.result, v); | |
141 v_delete(v); | |
142 break; | |
143 | |
144 case OP_CALL_BACK: { | |
145 struct op *tmp; | |
146 | |
147 v = eval_expr(op->arh.expr); | |
148 TOLABEL(v); | |
149 if (!(tmp = ve_findprev(&Venus, ko_str(v->ko), op->line))) { | |
150 v_delete(v); | |
151 hang(); | |
152 } | |
153 v_delete(v); | |
154 v = eval_expr(op->arg); | |
155 v = execute(tmp, v); | |
156 v_set(&Interp.result, v); | |
157 v_delete(v); | |
158 break; | |
159 } | |
160 | |
161 case OP_CALL_DYN: { | |
162 struct op *tmp; | |
163 | |
164 v = eval_expr(op->arg); | |
165 TOLABEL(v); | |
166 if (!(tmp = ve_findnext(&Venus, ko_str(v->ko), op->line))) { | |
167 v_delete(v); | |
168 hang(); | |
169 } | |
170 v_set_undef(v); | |
171 v = execute(tmp, v); | |
172 v_set(&Interp.result, v); | |
173 v_delete(v); | |
174 break; | |
175 } | |
176 | |
177 case OP_CLOSE: | |
178 v = eval_expr(op->arg); | |
179 if (V_EXT_P(v)) { | |
180 v_set_n(&Interp.result, io_close(v->magic.ext)); | |
181 } else { | |
182 v_set_n(&Interp.result, -1); | |
183 #ifdef EBADF | |
184 errno = EBADF; | |
185 #endif | |
186 } | |
187 v_delete(v); | |
188 break; | |
189 | |
190 case OP_EXIT: { | |
191 int tmp; | |
192 | |
193 v = eval_expr(op->arg); | |
194 V_NUM(v); | |
195 tmp = v->num >= 0.0 ? v->num + .5 : EXIT_FAILURE; | |
196 v_delete(v); | |
197 exit(tmp); | |
198 } | |
199 | |
200 case OP_FLUSH: | |
201 v = eval_expr(op->arg); | |
202 if (!V_EXT_P(v)) { | |
203 v_delete(v); | |
204 v_set_n(&Interp.result, EOF); | |
205 #ifdef EBADF | |
206 errno = EBADF; | |
207 #endif | |
208 break; | |
209 } | |
210 v_set_n(&Interp.result, io_flush(v->magic.ext)); | |
211 v_delete(v); | |
212 break; | |
213 | |
214 case OP_GOBACK: | |
215 v = eval_expr(op->arg); | |
216 TOLABEL(v); | |
217 if ((op = ve_findprev(&Venus, ko_str(v->ko), op->line))) { | |
218 v_delete(v); | |
219 continue; | |
220 } | |
221 v_delete(v); | |
222 hang(); | |
223 break; | |
224 | |
225 case OP_GOTO: | |
226 v = eval_expr(op->arg); | |
227 TOLABEL(v); | |
228 if ((op = ve_findnext(&Venus, ko_str(v->ko), op->line))) { | |
229 v_delete(v); | |
230 continue; | |
231 } | |
232 v_delete(v); | |
233 hang(); | |
234 break; | |
235 | |
236 case OP_ELSE: | |
237 case OP_HANG: | |
238 case OP_FI: | |
239 hang(); | |
240 break; | |
241 | |
242 case OP_IF: | |
243 v = eval_expr(op->arg); | |
244 if (v_true(v)) { | |
245 v_delete(v); | |
246 op = op->arh.op; | |
247 continue; | |
248 } | |
249 v_delete(v); | |
250 break; | |
251 | |
252 case OP_MODIFY: { | |
253 struct val *tmp = eval_expr(op->arg); | |
254 expr_pp(op->arh.expr->op, op->arh.expr->v.val, tmp); | |
255 v_delete(tmp); | |
256 break; | |
257 } | |
258 | |
259 case OP_PRINT: { | |
260 IO *fh; | |
261 | |
262 eval_push(op->arg); | |
263 if (!op->arh.expr) { | |
264 fh = io_incr(Out); | |
265 } else { | |
266 struct val *const tmp = eval_expr(op->arh.expr); | |
267 | |
268 if (V_EXT_P(tmp)) { | |
269 fh = io_incr(tmp->magic.ext); | |
270 } else { | |
271 v_delete(tmp); | |
272 v_delete(eval_pop()); | |
273 v_set_n(&Interp.result, -1); | |
274 #ifdef EBADF | |
275 errno = EBADF; | |
276 #endif | |
277 break; | |
278 } | |
279 v_delete(tmp); | |
280 } | |
281 v = eval_pop(); | |
282 V_STR(v); | |
283 v_set_n(&Interp.result, io_write_m(fh, ko_ptr(v->ko), ko_length(v->ko)) + 1u - 1.); | |
284 io_decr(fh); | |
285 v_delete(v); | |
286 break; | |
287 } | |
288 | |
289 case OP_PUTC: { | |
290 IO *fh; | |
291 | |
292 eval_push(op->arg); | |
293 if (!op->arh.expr) { | |
294 fh = io_incr(Out); | |
295 } else { | |
296 struct val *const tmp = eval_expr(op->arh.expr); | |
297 | |
298 if (V_EXT_P(tmp)) { | |
299 fh = io_incr(tmp->magic.ext); | |
300 } else { | |
301 v_delete(tmp); | |
302 v_delete(eval_pop()); | |
303 v_set_n(&Interp.result, -1); | |
304 #ifdef EBADF | |
305 errno = EBADF; | |
306 #endif | |
307 break; | |
308 } | |
309 v_delete(tmp); | |
310 } | |
311 v = eval_pop(); | |
312 V_NUM(v); | |
313 | |
314 v_set_n(&Interp.result, io_putc(fh, RINT(v->num))); | |
315 io_decr(fh); | |
316 v_delete(v); | |
317 break; | |
318 } | |
319 | |
320 case OP_RESET: | |
321 v = eval_expr(op->arg); | |
322 if (!V_EXT_P(v)) { | |
323 v_delete(v); | |
324 v_set_n(&Interp.result, EOF); | |
325 #ifdef EBADF | |
326 errno = EBADF; | |
327 #endif | |
328 break; | |
329 } | |
330 io_clearerr(v->magic.ext); | |
331 v_delete(v); | |
332 break; | |
333 | |
334 case OP_RETURN: | |
335 if (op->arg->type == unopE && op->arg->op == F_CALL) { | |
336 eval_into(op->arg->right, &Interp.arg); | |
337 op = op->arg->left.op; | |
338 continue; | |
339 } | |
340 v = eval_expr(op->arg); | |
341 depth_restore(curdepth); | |
342 return v; | |
343 | |
344 case OP_SET_VAL: | |
345 switch (op->arh.expr->type) { | |
346 case varE: | |
347 v_set(op->arh.expr->v.val, op->arg->v.val); | |
348 break; | |
349 | |
350 case varhashE: { | |
351 struct val *const tmp = eval_expr(op->arh.expr->right); | |
352 struct val *const val = v_undef(); | |
353 V_STR(tmp); | |
354 v_set(val, op->arg->v.val); | |
355 sh_put(op->arh.expr->v.hash, ko_ptr(tmp->ko), ko_length(tmp->ko), val); | |
356 v_delete(tmp); | |
357 break; | |
358 } | |
359 | |
360 default: | |
361 NOTREACHED; | |
362 break; | |
363 } | |
364 break; | |
365 | |
366 case OP_SYSTEM: | |
367 v = eval_expr(op->arg); | |
368 V_STR(v); | |
369 v_set_n(&Interp.result, system(ko_szp(v->ko))); | |
370 v_delete(v); | |
371 break; | |
372 | |
373 case OP_TEMP: | |
374 eval_push(op->arg); | |
375 if (!op->arh.expr) { | |
376 v_delete(eval_pop()); | |
377 } else switch (op->arh.expr->type) { | |
378 case varE: | |
379 stack_store_del(op->arh.expr->v.val, eval_pop()); | |
380 break; | |
381 | |
382 case varhashE: { | |
383 struct val *addr; | |
384 struct val *const tmp = eval_expr(op->arh.expr->right); | |
385 v = eval_pop(); | |
386 V_STR(tmp); | |
387 if (!(addr = sh_get(op->arh.expr->v.hash, ko_ptr(tmp->ko), ko_length(tmp->ko)))) { | |
388 sh_put(op->arh.expr->v.hash, ko_ptr(tmp->ko), ko_length(tmp->ko), addr = v_undef()); | |
389 } | |
390 v_delete(tmp); | |
391 stack_store_del(addr, v); | |
392 break; | |
393 } | |
394 | |
395 default: | |
396 NOTREACHED; | |
397 } | |
398 break; | |
399 | |
400 case OP_THROW: | |
401 v = eval_expr(op->arg); | |
402 if (!depth_get()) { | |
403 V_STR(v); | |
404 if (ko_at(v->ko, ko_length(v->ko) - 1u) == '\n') { | |
405 io_write_m(Err, ko_ptr(v->ko), ko_length(v->ko)); | |
406 } else { | |
407 fprintf(io_fp(Err), "%s: uncaught exception: ", Prog); | |
408 io_write_m(Err, ko_ptr(v->ko), ko_length(v->ko)); | |
409 putc('\n', io_fp(Err)); | |
410 } | |
411 v_delete(v); | |
412 exit(EXIT_FAILURE); | |
413 } | |
414 v_set(&Interp.result, v); | |
415 v_delete(v); | |
416 longjmp(stack_func(t_context, at)(&Context, 0)->buf, 1); | |
417 break; | |
418 } | |
419 op = op->next; | |
420 } | |
421 | |
422 exit(0); | |
423 } | |
424 | |
425 static void cleanup(void) { | |
426 stack_func(save_pair, end)(&Saved); | |
427 } | |
428 | |
429 void run(const struct text *t, size_t argc, char **argv) { | |
430 int status; | |
431 struct val *result; | |
432 | |
433 v_init(&Interp.arg); | |
434 v_init(&Interp.result); | |
435 | |
436 Interp.a.argv = xmalloc(argc, sizeof *Interp.a.argv); | |
437 for (Interp.a.argc = 0; Interp.a.argc < argc; ++Interp.a.argc) { | |
438 struct val *const tmp = &Interp.a.argv[Interp.a.argc]; | |
439 v_init(tmp); | |
440 v_set_m(tmp, argv[Interp.a.argc], strlen(argv[Interp.a.argc])); | |
441 } | |
442 | |
443 Interp.match.matches = xmalloc(Interp.match.size = 2, sizeof *Interp.match.matches); | |
444 Interp.match.length = 0; | |
445 | |
446 Interp.m_start.index = xmalloc(Interp.m_start.size = 0, sizeof *Interp.m_start.index); | |
447 Interp.m_end.index = xmalloc(Interp.m_end.size = 0, sizeof *Interp.m_end.index); | |
448 | |
449 stack_func(save_pair, init)(&Saved); | |
450 atechit(cleanup); | |
451 atechit(my_x_end); | |
452 | |
453 result = execute(t->start[0], v_undef()); | |
454 V_NUM(result); | |
455 status = result->num >= 0.0 ? result->num + .5 : EXIT_FAILURE; | |
456 v_delete(result); | |
457 exit(status); | |
458 } |