Mercurial > repo
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 } |