comparison src/ploki/expr.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 "Str.h"
3 #include "expr.h"
4 #include "hang.h"
5 #include "list.h"
6 #include "main_io.h"
7 #include "main_label.h"
8 #include "main_var.h"
9 #include "mars.h"
10 #include "match.h"
11 #include "op.h"
12 #include "pp.h"
13 #include "random.h"
14 #include "re.h"
15 #include "run.h"
16 #include "stack.h"
17 #include "val.h"
18 #include "venus.h"
19 #include "xmalloc.h"
20 #include "zz.h"
21
22 #include <ctype.h>
23 #include <errno.h>
24 #include <math.h>
25 #include <stdlib.h>
26 #include <string.h>
27 #include <assert.h>
28 #include <setjmp.h>
29
30 #ifdef M_PI
31 #define MY_PI M_PI
32 #else
33 #define MY_PI 3.1415926535897932384626433832795028841971693993751058209749445923
34 #endif
35
36 #ifdef M_E
37 #define MY_E M_E
38 #else
39 #define MY_E 2.71828182845904523536028747135266249775724709369995957496696762772
40 #endif
41
42 typedef struct val *svalp;
43 stack_declare(svalp, static)
44
45 static void sv_init(svalp *x) {
46 *x = v_undef();
47 }
48
49 static void sv_end(svalp *x) {
50 v_delete(*x);
51 }
52
53 static void sv_copy(svalp *dst, const svalp *src) {
54 v_set(*dst, *src);
55 }
56
57 stack_define(svalp, static, sv_init, sv_end, sv_copy)
58 static stack(svalp) Stack;
59
60 static void con_nop(t_context *c) {
61 (void)c;
62 }
63
64 ATTR_NORETURN
65 static void con_error(const t_context *x, const t_context *y) {
66 (void)x;
67 (void)y;
68 NOTREACHED;
69 }
70
71 stack_define(t_context, extern, con_nop, con_nop, con_error)
72 stack(t_context) Context;
73
74 void expr_init(void) {
75 stack_func(svalp, init)(&Stack);
76 stack_func(t_context, init)(&Context);
77 }
78
79 void expr_end(void) {
80 stack_func(t_context, end)(&Context);
81 stack_func(svalp, end)(&Stack);
82 }
83
84 void expr_pp(enum t_binop op, struct val *x, struct val *y) {
85 switch (op) {
86 case B_AMPERSAND: pp_and(x, y); return;
87 case B_ANGLE: pp_lt_n(x, y); return;
88 case B_BACKSPARK: pp_tobase(x, y); return;
89 case B_BRACELET: pp_gt(x, y); return;
90 case B_DOUBLE_OH_SEVEN: pp_mod(x, y); return;
91 case B_EMBRACE: pp_lt(x, y); return;
92 case B_FLATWORM: pp_concat(x, y); return;
93 case B_HALF_MESH: pp_eq_n(x, y); return;
94 case B_HYBRID: pp_ne(x, y); return;
95 case B_INTERSECTION: pp_add(x, y); return;
96 case B_RIGHT_ANGLE: pp_gt_n(x, y); return;
97 case B_SHARK_FIN: pp_pow(x, y); return;
98 case B_SLAT: pp_div(x, y); return;
99 case B_SPARK: pp_frombase(x, y); return;
100 case B_SPARK_SPOT: pp_ne_n(x, y); return;
101 case B_SPIKE: pp_or(x, y); return;
102 case B_SPLAT: pp_mult(x, y); return;
103 case B_SPOT: pp_read(x, y); return;
104 case B_SQIGGLE: pp_match(x, y); return;
105 case B_TAIL: pp_comma(x, y); return;
106 case B_TWO_SPOT: pp_eq(x, y); return;
107 case B_U_TURN: pp_shift(x, y); return;
108 case B_U_TURN_BACK: pp_pop(x, y); return;
109 case B_WORM: pp_sub(x, y); return;
110 case B_XMATCH: NOTREACHED;
111 }
112 }
113
114 enum t_binop expr_binop(int c) {
115 switch (c) {
116 case '!': return B_SPARK_SPOT;
117 case '%': return B_DOUBLE_OH_SEVEN;
118 case '&': return B_AMPERSAND;
119 case '\'': return B_SPARK;
120 case '*': return B_SPLAT;
121 case '+': return B_INTERSECTION;
122 case ',': return B_TAIL;
123 case '-': return B_WORM;
124 case '.': return B_SPOT;
125 case '/': return B_SLAT;
126 case ':': return B_TWO_SPOT;
127 case ';': return B_HYBRID;
128 case '<': return B_ANGLE;
129 case '=': return B_HALF_MESH;
130 case '>': return B_RIGHT_ANGLE;
131 case '[': return B_U_TURN;
132 case ']': return B_U_TURN_BACK;
133 case '^': return B_SHARK_FIN;
134 case '_': return B_FLATWORM;
135 case '`': return B_BACKSPARK;
136 case '{': return B_EMBRACE;
137 case '|': return B_SPIKE;
138 case '}': return B_BRACELET;
139 case '~': return B_SQIGGLE;
140 }
141 NOTREACHED;
142 }
143
144 void free_expr(struct expr *x) {
145 if (!x) {
146 return;
147 }
148
149 switch (x->type) {
150 case literE:
151 v_end(x->v.val);
152 xfree(x->v.val);
153 break;
154
155 case varE:
156 break;
157
158 case varhashE:
159 free_expr(x->right);
160 break;
161
162 case symbolE:
163 switch (x->op) {
164 case S_ARGV:
165 free_expr(x->right);
166 break;
167 }
168 break;
169
170 case unopE:
171 free_expr(x->right);
172 if (x->op == F_MATCH) {
173 re_free(x->left.rx);
174 }
175 break;
176
177 case binopE:
178 free_expr(x->left.expr);
179 free_expr(x->right);
180 break;
181
182 case listE:
183 free_expr(x->right);
184 free_expr(x->left.expr);
185 break;
186 }
187 xfree(x);
188 }
189
190 static struct expr *undef(void) {
191 struct expr *e;
192 e = xmalloc(1, sizeof *e);
193 e->type = literE;
194 e->left.expr = e->right = NULL;
195 e->v.val = v_undef();
196 return e;
197 }
198
199 static void xv_delete(void *v) {
200 v_delete(v);
201 }
202
203 struct expr *get_lval(struct op *op) {
204 struct expr *x;
205 int c;
206 size_t n;
207
208 St_shiftws(&op->txt);
209 c = ST_FIRSTCHAR(&op->txt);
210 if (!(c == '$' || isalpha(c))) {
211 return NULL;
212 }
213 for (n = 1; (c = ST_INDEX(&op->txt, n)) == '$' || isalpha(c); ++n)
214 ;
215
216 x = xmalloc(1, sizeof *x);
217 x->left.expr = x->right = NULL;
218
219 if (ST_INDEX(&op->txt, n) != '(') {
220 x->type = varE;
221 if ((x->v.tent = vr_exists(Var_plain, St_ptr(&op->txt), n)) == VR_NO_COOKIE) {
222 x->v.tent = vr_register(Var_plain, St_ptr(&op->txt), n, v_undef());
223 }
224 St_del(&op->txt, 0, n);
225 } else {
226 x->type = varhashE;
227 if ((x->v.tent = vr_exists(Var_hash, St_ptr(&op->txt), n)) == VR_NO_COOKIE) {
228 x->v.tent = vr_register(Var_hash, St_ptr(&op->txt), n, sh_new(xv_delete));
229 }
230 St_del(&op->txt, 0, n + 1);
231 x->right = get_expr(op);
232 if (ST_FIRSTCHAR(&op->txt) == ')') {
233 St_shift(&op->txt);
234 }
235 }
236 return x;
237 }
238
239 ATTR_CONST
240 static int xval(int c) {
241 switch (c) {
242 case '0': return 0;
243 case '1': return 1;
244 case '2': return 2;
245 case '3': return 3;
246 case '4': return 4;
247 case '5': return 5;
248 case '6': return 6;
249 case '7': return 7;
250 case '8': return 8;
251 case '9': return 9;
252 case 'A':
253 case 'a': return 10;
254 case 'B':
255 case 'b': return 11;
256 case 'C':
257 case 'c': return 12;
258 case 'D':
259 case 'd': return 13;
260 case 'E':
261 case 'e': return 14;
262 case 'F':
263 case 'f': return 15;
264 }
265 NOTREACHED;
266 }
267
268 static struct expr *get_value(struct op *, int);
269
270 static struct expr *get_list(struct op *op, int null) {
271 struct expr *e;
272
273 e = xmalloc(1, sizeof *e);
274 e->type = listE;
275 if ((e->right = get_value(op, 1))) {
276 e->left.expr = get_list(op, 1);
277 } else if (null) {
278 xfree(e);
279 return NULL;
280 } else {
281 e->right = e->left.expr = NULL;
282 }
283 return e;
284 }
285
286 static struct expr *get_value(struct op *op, int null) {
287 struct expr *e;
288 int c;
289
290 St_shiftws(&op->txt);
291 if (!St_len(&op->txt)) {
292 return null ? NULL : undef();
293 }
294 c = ST_FIRSTCHAR(&op->txt);
295
296 if (c == '$' || isalpha(c)) {
297 return get_lval(op);
298 }
299
300 if (isdigit(c) || (c == '.' && isdigit(ST_INDEX(&op->txt, 1)))) {
301 char *tmp;
302
303 e = undef();
304 tmp = St_ptr(&op->txt);
305 v_set_n(e->v.val, strtod(tmp, &tmp));
306 tmp += tmp == St_ptr(&op->txt);
307 St_del(&op->txt, 0, tmp - St_ptr(&op->txt));
308
309 return e;
310 }
311
312 if (OPERATOR_P(c)) {
313 e = xmalloc(1, sizeof *e);
314 e->type = binopE;
315 e->op = expr_binop(c);
316 St_shift(&op->txt);
317 e->left.expr = undef();
318 e->right = get_value(op, 0);
319 return e;
320 }
321 if (c == '?' && ST_INDEX(&op->txt, 1) == 'o' && ST_INDEX(&op->txt, 2) == '~') {
322 e = xmalloc(1, sizeof *e);
323 e->type = binopE;
324 e->op = B_XMATCH;
325 St_del(&op->txt, 0, 3);
326 e->left.expr = undef();
327 e->right = get_value(op, 0);
328 return e;
329 }
330
331 switch (c) {
332 case '#':
333 if (ST_INDEX(&op->txt, 1) != '<') {
334 goto unrecog;
335 }
336 St_del(&op->txt, 0, 2);
337 e = get_list(op, 0);
338 St_shiftws(&op->txt);
339 if (ST_FIRSTCHAR(&op->txt) == '#' && ST_INDEX(&op->txt, 1) == '>') {
340 St_del(&op->txt, 0, 2);
341 }
342 break;
343
344 case '(':
345 St_shift(&op->txt);
346 e = get_expr(op);
347 St_shiftws(&op->txt);
348 if (ST_FIRSTCHAR(&op->txt) == ')') {
349 St_shift(&op->txt);
350 }
351 break;
352
353 case '"': {
354 struct val *v;
355 St_shift(&op->txt);
356 e = undef();
357 v = e->v.val;
358 V_STR(v);
359 for (; St_len(&op->txt) && (c = St_shift(&op->txt)) != '"'; ) {
360 switch (c) {
361 case '\\':
362 if (St_len(&op->txt) == 0) {
363 v_cat_c(v, c);
364 break;
365 }
366 c = St_shift(&op->txt);
367 if (c >= '0' && c <= '7') {
368 int oct;
369 oct = c - '0';
370 c = ST_FIRSTCHAR(&op->txt);
371 if (c >= '0' && c <= '7') {
372 oct *= 010;
373 oct += c - '0';
374 St_shift(&op->txt);
375 c = ST_FIRSTCHAR(&op->txt);
376 if (c >= '0' && c <= '7') {
377 oct *= 010;
378 oct += c - '0';
379 St_shift(&op->txt);
380 }
381 }
382 v_cat_c(v, oct);
383 break;
384 }
385 switch (c) {
386 case 'x':
387 c = ST_FIRSTCHAR(&op->txt);
388 if (isxdigit(c)) {
389 int hex;
390 hex = xval(c);
391 St_shift(&op->txt);
392 c = ST_FIRSTCHAR(&op->txt);
393 if (isxdigit(c)) {
394 hex *= 0x10;
395 hex += xval(c);
396 St_shift(&op->txt);
397 }
398 v_cat_c(v, hex);
399 } else {
400 v_cat_m(v, "\\x", 2);
401 }
402 break;
403
404 case 'a': v_cat_c(v, '\a'); break;
405 case 'b': v_cat_c(v, '\b'); break;
406 case 'f': v_cat_c(v, '\f'); break;
407 case 'n': v_cat_c(v, '\n'); break;
408 case 'r': v_cat_c(v, '\r'); break;
409 case 't': v_cat_c(v, '\t'); break;
410 case 'v': v_cat_c(v, '\v'); break;
411
412 case 'c':
413 if (St_len(&op->txt)) {
414 c = St_shift(&op->txt);
415 v_cat_c(v, (toupper(c) + 64) % 128);
416 } else {
417 v_cat_m(v, "\\c", 2);
418 }
419 break;
420
421 case 'V': {
422 struct expr *tmp;
423 tmp = e;
424 e = xmalloc(1, sizeof *e);
425 e->type = binopE;
426 e->op = B_FLATWORM;
427 e->left.expr = tmp;
428 e->right = get_value(op, 0);
429 tmp = e;
430 e = xmalloc(1, sizeof *e);
431 e->type = binopE;
432 e->op = B_FLATWORM;
433 e->left.expr = tmp;
434 e->right = undef();
435 v = e->right->v.val;
436 break;
437 }
438
439 default:
440 v_cat_c(v, c);
441 break;
442 }
443 break;
444
445 default:
446 v_cat_c(v, c);
447 break;
448 }
449 }
450 }
451 break;
452
453 case '\\':
454 St_shift(&op->txt);
455 e = xmalloc(1, sizeof *e);
456 e->type = symbolE;
457 e->right = NULL;
458 e->left.expr = NULL;
459
460 c = ST_FIRSTCHAR(&op->txt);
461 if (isdigit(c)) {
462 char *tmp = St_ptr(&op->txt);
463 e->left.bonus = strtoul(tmp, &tmp, 10);
464 St_del(&op->txt, 0, tmp - St_ptr(&op->txt));
465 e->op = S_MATCH;
466 } else switch (c) {
467 case '!': St_shift(&op->txt); e->op = S_ERR; break;
468 case '?': St_shift(&op->txt); e->op = S_RAND; break;
469 case '_': St_shift(&op->txt); e->op = S_RESULT; break;
470
471 case '@':
472 St_shift(&op->txt);
473 e->op = S_ARG;
474 break;
475
476 case 'A':
477 switch (ST_INDEX(&op->txt, 1)) {
478 case 'R':
479 if (ST_INDEX(&op->txt, 2) == 'G') {
480 St_del(&op->txt, 0, 3);
481 e->op = S_ARGC;
482 if (ST_FIRSTCHAR(&op->txt) == ':') {
483 St_shift(&op->txt);
484 e->op = S_ARGV;
485 e->right = get_value(op, 0);
486 }
487 break;
488 }
489 goto nullsym;
490
491 case 'U':
492 if (ST_INDEX(&op->txt, 2) == 'S' &&
493 ST_INDEX(&op->txt, 3) == 'G') {
494 St_del(&op->txt, 0, 4);
495 e->op = S_STDOUT;
496 break;
497 }
498 goto nullsym;
499
500 default:
501 goto nullsym;
502 }
503 break;
504
505 case 'E':
506 switch (ST_INDEX(&op->txt, 1)) {
507 case 'I':
508 if (
509 ST_INDEX(&op->txt, 2) == 'N' &&
510 ST_INDEX(&op->txt, 3) == 'G'
511 ) {
512 St_del(&op->txt, 0, 4);
513 e->op = S_STDIN;
514 break;
515 }
516 if (0)
517 case 'N': {
518 if (ST_INDEX(&op->txt, 2) == 'V') {
519 St_del(&op->txt, 0, 3);
520 e->type = unopE;
521 e->op = F_GETENV;
522 e->right = get_value(op, 0);
523 break;
524 }
525 }
526 /*DURCHFALL*/
527 default:
528 St_shift(&op->txt);
529 e->op = S_EULER;
530 break;
531 }
532 break;
533
534 case 'F':
535 if (
536 ST_INDEX(&op->txt, 1) == 'E' &&
537 ST_INDEX(&op->txt, 2) == 'H' &&
538 ST_INDEX(&op->txt, 3) == 'L'
539 ) {
540 St_del(&op->txt, 0, 4);
541 e->op = S_STDERR;
542 break;
543 }
544 goto nullsym;
545
546 case 'L': e->op = F_LOWER; goto simplefunc;
547 case 'Q': e->op = F_QUOTE; goto simplefunc;
548 case 'R': e->op = F_RE_ESC; goto simplefunc;
549 case 'U': e->op = F_UPPER; goto simplefunc;
550 simplefunc:
551 St_shift(&op->txt);
552 e->type = unopE;
553 e->right = get_value(op, 0);
554 break;
555
556 case 'P':
557 if (ST_INDEX(&op->txt, 1) == 'I') {
558 St_del(&op->txt, 0, 2);
559 e->op = S_LUDOLF;
560 break;
561 }
562 goto nullsym;
563
564 nullsym:
565 default:
566 e->op = S_NUL;
567 break;
568 }
569 break;
570
571 case '@':
572 #define CASE_DO_STUFF(n, o) \
573 if (1) { \
574 St_del(&op->txt, 0, (n)); \
575 e->op = (o); \
576 e->right = get_value(op, 0); \
577 break; \
578 } else ((void)0)
579
580 #define CASE(i, w, n, o) \
581 case i: if (1) { \
582 if (St_len(&op->txt) < (n) || St_ncmp_m(&op->txt, w, n)) { \
583 goto usrfunc; \
584 } \
585 CASE_DO_STUFF(n, o); \
586 } else ((void)0)
587
588 St_shift(&op->txt);
589 e = xmalloc(1, sizeof *e);
590 e->type = unopE;
591 e->left.expr = NULL;
592
593 switch (ST_FIRSTCHAR(&op->txt)) {
594 case '+': CASE_DO_STUFF(1, F_MOEND);
595 case '-': CASE_DO_STUFF(1, F_MOSTART);
596 case 'A':
597 switch (ST_INDEX(&op->txt, 1)) {
598 CASE('B', "ABS", 3, F_ABS);
599 CASE('C', "ACOS", 4, F_ACOS);
600 CASE('P', "APERS", 5, F_OPEN);
601 CASE('S', "ASIN", 4, F_ASIN);
602 case 'T':
603 if (St_len(&op->txt) >= 4) {
604 if (St_ncmp_m(&op->txt, "ATAN2", 5) == 0) {
605 CASE_DO_STUFF(5, F_ATAN2);
606 }
607 if (St_ncmp_m(&op->txt, "ATAN", 4) == 0) {
608 CASE_DO_STUFF(4, F_ATAN);
609 }
610 }
611 goto usrfunc;
612
613 default:
614 goto usrfunc;
615 }
616 break;
617
618 case 'C':
619 switch (ST_INDEX(&op->txt, 1)) {
620 CASE('H', "CHR", 3, F_CHR);
621 CASE('O', "COS", 3, F_COS);
622 default:
623 goto usrfunc;
624 }
625 break;
626
627 CASE('D', "DEF-P", 5, F_DEFINED);
628
629 case 'E':
630 switch (ST_INDEX(&op->txt, 1)) {
631 CASE('D', "EDD-P", 5, F_EOF);
632 CASE('N', "ENV", 3, F_GETENV);
633 CASE('R', "ERR-P", 5, F_ERROR);
634 CASE('V', "EVAL", 4, F_CATCH);
635 default: goto usrfunc;
636 }
637 break;
638
639 CASE('G', "GET", 3, F_GETC);
640
641 case 'I':
642 switch (ST_INDEX(&op->txt, 1)) {
643 CASE('N', "INT", 3, F_INT);
644 CASE('O', "IO-P", 4, F_IO);
645 default: goto usrfunc;
646 }
647 break;
648
649 case 'L':
650 switch (ST_INDEX(&op->txt, 1)) {
651 CASE('A', "LAPERS", 6, F_OPENR);
652 case 'E':
653 switch (ST_INDEX(&op->txt, 2)) {
654 CASE('G', "LEGS", 4, F_GETS);
655 CASE('N', "LENGTH", 6, F_LENGTH);
656 default: goto usrfunc;
657 }
658 break;
659 CASE('G', "LG", 2, F_LOG10);
660 CASE('N', "LN", 2, F_LOG);
661 default: goto usrfunc;
662 }
663 break;
664
665 case 'N':
666 switch (ST_INDEX(&op->txt, 1)) {
667 CASE('E', "NEG", 3, F_NEG);
668 CASE('O', "NOT", 3, F_NOT);
669 CASE('U', "NUM", 3, F_NUM);
670 default: goto usrfunc;
671 }
672 break;
673
674 case 'O':
675 switch (ST_INDEX(&op->txt, 1)) {
676 CASE('R', "ORD", 3, F_ORD);
677 CASE('M', "OMFG", 4, F_FREEZE);
678 default: goto usrfunc;
679 }
680 break;
681
682 case 'R':
683 if (ST_INDEX(&op->txt, 1) != 'E') {
684 goto usrfunc;
685 }
686 switch (ST_INDEX(&op->txt, 2)) {
687 CASE('M', "REMOVE", 6, F_REMOVE);
688 CASE('N', "RENAEM", 6, F_RENAME);
689 CASE('V', "REVERSE", 7, F_REVERSE);
690 default: goto usrfunc;
691 }
692 break;
693
694 case 'S':
695 switch (ST_INDEX(&op->txt, 1)) {
696 case 'A':
697 switch (ST_INDEX(&op->txt, 2)) {
698 CASE('G', "SAG", 3, F_TELL);
699 CASE('P', "SAPERS", 6, F_OPENW);
700 default: goto usrfunc;
701 }
702 break;
703 CASE('I', "SIN", 3, F_SIN);
704 CASE('Q', "SQRT", 4, F_SQRT);
705 CASE('T', "STR", 3, F_STR);
706 CASE('U', "SUCH", 4, F_SEEK);
707 default: goto usrfunc;
708 }
709 break;
710
711 case 'T':
712 switch (ST_INDEX(&op->txt, 1)) {
713 CASE('A', "TAN", 3, F_TAN);
714 CASE('Y', "TYPE OF", 7, F_TYPEOF);
715 default: goto usrfunc;
716 }
717 break;
718
719 usrfunc:
720 default:
721 if ((e->left.op = ma_find(&Mars, &op->txt))) {
722 e->op = F_CALL;
723 } else {
724 e->op = F_NUL;
725 e->left.bonus = op->line;
726 }
727 e->right = get_value(op, 0);
728 break;
729 }
730 #undef CASE_DO_STUFF
731 #undef CASE
732 break;
733
734 unrecog:
735 default:
736 if (null) {
737 e = NULL;
738 } else {
739 e = undef();
740 }
741 break;
742 }
743
744 return e;
745 }
746
747 struct expr *get_iobj(struct op *op) {
748 return get_value(op, 0);
749 }
750
751 struct expr *get_expr(struct op *op) {
752 struct expr *a, *b;
753
754 a = get_value(op, 0);
755
756 for (St_shiftws(&op->txt); St_len(&op->txt); St_shiftws(&op->txt)) {
757 struct expr *tmp;
758 enum t_binop k;
759
760 if (OPERATOR_P(ST_FIRSTCHAR(&op->txt))) {
761 k = expr_binop(St_shift(&op->txt));
762 b = get_value(op, 0);
763 } else if (St_ncmp_m(&op->txt, "?o~", 3) == 0) {
764 k = B_XMATCH;
765 St_del(&op->txt, 0, 3);
766 b = get_value(op, 0);
767 } else {
768 if (!(b = get_value(op, 1))) {
769 break;
770 }
771 k = B_SPOT;
772 }
773
774 tmp = a;
775 a = xmalloc(1, sizeof *a);
776 a->type = binopE;
777 a->op = k;
778 a->left.expr = tmp;
779 a->right = b;
780 }
781
782 return a;
783 }
784
785 #define TOS (*stack_func(svalp, at)(&Stack, 0))
786
787 void eval_push(struct expr *ex) {
788 const struct expr *const e = ex;
789
790 switch (e->type) {
791 case literE:
792 case varE:
793 stack_func(svalp, push)(&Stack, &e->v.val);
794 return;
795
796 case varhashE: {
797 struct val *tmp, *tos;
798 const char *ptr;
799 size_t len;
800
801 eval_push(e->right);
802 tos = TOS;
803 ptr = v_sptr(tos, &len);
804 if ((tmp = sh_get(e->v.hash, ptr, len))) {
805 v_set(tos, tmp);
806 } else {
807 v_set_undef(tos);
808 }
809 return;
810 }
811
812 case symbolE:
813 switch (e->op) {
814 case S_NUL:
815 stack_func(svalp, pushnull)(&Stack);
816 break;
817
818 case S_ARG: {
819 struct val *const tmp = &Interp.arg;
820 stack_func(svalp, push)(&Stack, &tmp);
821 break;
822 }
823
824 case S_ARGC:
825 stack_func(svalp, pushnull)(&Stack);
826 v_set_n(TOS, Interp.a.argc);
827 break;
828
829 case S_ARGV: {
830 struct val *tos;
831 size_t n;
832
833 eval_push(e->right);
834 tos = TOS;
835 V_NUM(tos);
836 n = RINT(tos->num);
837
838 if (n < Interp.a.argc) {
839 v_set(tos, &Interp.a.argv[n]);
840 } else {
841 v_set_undef(tos);
842 }
843 break;
844 }
845
846 case S_ERR: {
847 struct val *tos;
848 const char *const tmp = strerror(errno);
849 stack_func(svalp, pushnull)(&Stack);
850 tos = TOS;
851 v_set_m(tos, tmp, strlen(tmp));
852 tos->num = errno;
853 tos->type |= V_NUM_K;
854 break;
855 }
856
857 case S_EULER:
858 stack_func(svalp, pushnull)(&Stack);
859 v_set_n(TOS, MY_E);
860 break;
861
862 case S_LUDOLF:
863 stack_func(svalp, pushnull)(&Stack);
864 v_set_n(TOS, MY_PI);
865 break;
866
867 case S_MATCH:
868 stack_func(svalp, pushnull)(&Stack);
869 if (e->left.bonus < Interp.match.length) {
870 v_set(TOS, &Interp.match.matches[e->left.bonus]);
871 }
872 break;
873
874 case S_RAND:
875 stack_func(svalp, pushnull)(&Stack);
876 v_set_n(TOS, randval());
877 break;
878
879 case S_RESULT: {
880 struct val *const tmp = &Interp.result;
881 stack_func(svalp, push)(&Stack, &tmp);
882 break;
883 }
884
885 case S_STDIN:
886 stack_func(svalp, pushnull)(&Stack);
887 v_set_io(TOS, In);
888 break;
889
890 case S_STDOUT:
891 stack_func(svalp, pushnull)(&Stack);
892 v_set_io(TOS, Out);
893 break;
894
895 case S_STDERR:
896 stack_func(svalp, pushnull)(&Stack);
897 v_set_io(TOS, Err);
898 break;
899 }
900 return;
901
902 case unopE:
903 if (e->op == F_FREEZE) {
904 struct sub *const tmp = sub_new(e->right);
905 stack_func(svalp, pushnull)(&Stack);
906 v_set_sub(TOS, tmp);
907 sub_decr(tmp);
908 return;
909 }
910
911 if (e->op == F_CATCH) {
912 const size_t stackmark = stack_func(svalp, size)(&Stack);
913 t_context *tos;
914
915 stack_func(t_context, pushnull)(&Context);
916 tos = stack_func(t_context, at)(&Context, 0);
917 if (!setjmp(tos->buf)) {
918 tos->depth = stack_func(save_pair, size)(&Saved);
919 eval_push(e->right);
920 assert(stack_func(svalp, size)(&Stack) - stackmark == 1u);
921 stack_func(t_context, clear)(&Context, 1);
922 } else {
923 tos = stack_func(t_context, at)(&Context, 0);
924 depth_restore(tos->depth);
925 stack_func(t_context, clear)(&Context, 1);
926 assert(stackmark <= stack_func(svalp, size)(&Stack));
927 stack_func(svalp, clear)(&Stack, stack_func(svalp, size)(&Stack) - stackmark);
928 stack_func(svalp, pushnull)(&Stack);
929 }
930 return;
931 }
932
933 eval_push(e->right);
934 switch (e->op) {
935 case F_NUL: {
936 struct op *op;
937 struct val *const tos = TOS;
938
939 TOLABEL(tos);
940 if ((op = ve_findnext(&Venus, ko_str(tos->ko), e->left.bonus))) {
941 struct val *tmp = v_undef();
942 v_set(tmp, tos);
943 tmp = execute(op, tmp);
944 v_set(TOS, tmp);
945 v_delete(tmp);
946 } else {
947 hang();
948 }
949 break;
950 }
951
952 case F_CALL: {
953 struct val *tmp = v_undef();
954 v_set(tmp, TOS);
955 tmp = execute(e->left.op, tmp);
956 v_set(TOS, tmp);
957 v_delete(tmp);
958 break;
959 }
960
961 case F_MATCH:
962 do_match(TOS, e->left.rx);
963 break;
964
965 case F_ABS: pp_abs(TOS); break;
966 case F_ACOS: pp_acos(TOS); break;
967 case F_ASIN: pp_asin(TOS); break;
968 case F_ATAN: pp_atan(TOS); break;
969 case F_ATAN2: pp_atan2(TOS); break;
970 case F_CHR: pp_chr(TOS); break;
971 case F_COS: pp_cos(TOS); break;
972 case F_DEFINED: pp_defined(TOS); break;
973 case F_EOF: pp_eof(TOS); break;
974 case F_ERROR: pp_error(TOS); break;
975 case F_GETC: pp_getc(TOS); break;
976 case F_GETENV: pp_getenv(TOS); break;
977 case F_GETS: pp_gets(TOS); break;
978 case F_HANG: hang(); break;
979 case F_INT: pp_int(TOS); break;
980 case F_IO: pp_io(TOS); break;
981 case F_LENGTH: pp_length(TOS); break;
982 case F_LOG: pp_log(TOS); break;
983 case F_LOG10: pp_log10(TOS); break;
984 case F_LOWER: pp_lower(TOS); break;
985 case F_MOEND: pp_moend(TOS); break;
986 case F_MOSTART: pp_mostart(TOS); break;
987 case F_NEG: pp_neg(TOS); break;
988 case F_NOT: pp_not(TOS); break;
989 case F_NUM: pp_num(TOS); break;
990 case F_OPEN: pp_open(TOS); break;
991 case F_OPENR: pp_openr(TOS); break;
992 case F_OPENW: pp_openw(TOS); break;
993 case F_ORD: pp_ord(TOS); break;
994 case F_QUOTE: pp_quote(TOS); break;
995 case F_RE_ESC: pp_escape(TOS); break;
996 case F_REMOVE: pp_remove(TOS); break;
997 case F_RENAME: pp_rename(TOS); break;
998 case F_REVERSE: pp_reverse(TOS); break;
999 case F_SEEK: pp_seek(TOS); break;
1000 case F_SIN: pp_sin(TOS); break;
1001 case F_SQRT: pp_sqrt(TOS); break;
1002 case F_STR: pp_str(TOS); break;
1003 case F_TAN: pp_tan(TOS); break;
1004 case F_TELL: pp_tell(TOS); break;
1005 case F_TYPEOF: pp_typeof(TOS); break;
1006 case F_UPPER: pp_upper(TOS); break;
1007 }
1008 return;
1009
1010 case binopE:
1011 eval_push(e->left.expr);
1012 eval_push(e->right);
1013
1014 if (e->op != B_XMATCH) {
1015 expr_pp(e->op, *stack_func(svalp, at)(&Stack, 1), TOS);
1016 stack_func(svalp, clear)(&Stack, 1);
1017 } else {
1018 t_regex *rx;
1019 struct val *const tos = TOS;
1020 V_STR(tos);
1021 rx = re_compile(ko_str(tos->ko));
1022 stack_func(svalp, clear)(&Stack, 1);
1023 free_expr(ex->right);
1024 ex->right = ex->left.expr;
1025 ex->left.rx = rx;
1026 ex->op = F_MATCH;
1027 ex->type = unopE;
1028
1029 do_match(TOS, rx);
1030 }
1031 return;
1032
1033 case listE: {
1034 struct val *tos;
1035
1036 stack_func(svalp, pushnull)(&Stack);
1037 tos = TOS;
1038 tos->magic.list = li_new();
1039 tos->type = V_LIST_K;
1040
1041 if (e->right) {
1042 struct val *tmp;
1043
1044 eval_push(e->right);
1045 tmp = v_undef();
1046 stack_func(svalp, pop)(&Stack, &tmp);
1047 li_push(tos->magic.list, tmp);
1048
1049 if (e->left.expr) {
1050 eval_push(e->left.expr);
1051 assert(!!V_LIST_P(TOS));
1052 li_append((*stack_func(svalp, at)(&Stack, 1))->magic.list, TOS->magic.list);
1053 stack_func(svalp, clear)(&Stack, 1);
1054 }
1055 }
1056 return;
1057 }
1058 }
1059
1060 NOTREACHED;
1061 }
1062
1063 void eval_into(struct expr *e, struct val *v) {
1064 DEBUG(const size_t oldsize = stack_func(svalp, size)(&Stack);)
1065 eval_push(e);
1066 assert(stack_func(svalp, size)(&Stack) - oldsize == 1u);
1067 stack_func(svalp, pop)(&Stack, &v);
1068 }
1069
1070 struct val *eval_pop(void) {
1071 struct val *new = v_undef();
1072 assert(stack_func(svalp, size)(&Stack) != 0);
1073 stack_func(svalp, pop)(&Stack, &new);
1074 return new;
1075 }
1076
1077 struct val *eval_expr(struct expr *e) {
1078 eval_push(e);
1079 return eval_pop();
1080 }