comparison src/ploki/deparse.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 "deparse.h"
4 #include "expr.h"
5 #include "main_io.h"
6 #include "main_label.h"
7 #include "text.h"
8 #include "val.h"
9 #include "venus.h"
10 #include "xmalloc.h"
11 #include "zz.h"
12
13 #include <ctype.h>
14 #include <stdio.h>
15 #include <assert.h>
16
17 #if HAVE_VSNPRINTF_P
18 #define MAKE_LABEL(s, c) \
19 do { \
20 static unsigned long seq__; \
21 St_init(s); \
22 St_xprintf(s, "%c%lu", c, seq__++); \
23 } while (0)
24 #else
25 #define MAKE_LABEL(s, c) \
26 do { \
27 static unsigned long seq__; \
28 St_init(s); \
29 St_num(s, seq__++); \
30 St_tac_c(s, c); \
31 } while (0)
32 #endif
33
34 ATTR_CONST
35 static int display(enum t_binop b) {
36 switch (b) {
37 case B_SPARK_SPOT: return '!';
38 case B_DOUBLE_OH_SEVEN: return '%';
39 case B_AMPERSAND: return '&';
40 case B_SPARK: return '\'';
41 case B_SPLAT: return '*';
42 case B_INTERSECTION: return '+';
43 case B_TAIL: return ',';
44 case B_WORM: return '-';
45 case B_SPOT: return '.';
46 case B_SLAT: return '/';
47 case B_TWO_SPOT: return ':';
48 case B_HYBRID: return ';';
49 case B_ANGLE: return '<';
50 case B_HALF_MESH: return '=';
51 case B_RIGHT_ANGLE: return '>';
52 case B_U_TURN: return '[';
53 case B_U_TURN_BACK: return ']';
54 case B_SHARK_FIN: return '^';
55 case B_FLATWORM: return '_';
56 case B_BACKSPARK: return '`';
57 case B_EMBRACE: return '{';
58 case B_SPIKE: return '|';
59 case B_BRACELET: return '}';
60 case B_SQIGGLE: return '~';
61 default: break;
62 }
63 NOTREACHED;
64 }
65
66 static void dump_str(const String *s) {
67 size_t i;
68
69 io_write_m(Out, "\"", 1);
70 for (i = 0; i < St_len(s); ++i) {
71 const unsigned char c = ST_INDEX(s, i);
72 if (c != '\\' && c != '"' && isprint(c)) {
73 io_write_m(Out, &c, 1);
74 } else {
75 io_write_m(Out, "\\", 1);
76 switch (c) {
77 case '"':
78 case '\\': io_write_m(Out, &c , 1); break;
79 case '\a': io_write_m(Out, "a", 1); break;
80 case '\b': io_write_m(Out, "b", 1); break;
81 case '\f': io_write_m(Out, "f", 1); break;
82 case '\n': io_write_m(Out, "n", 1); break;
83 case '\r': io_write_m(Out, "r", 1); break;
84 case '\t': io_write_m(Out, "t", 1); break;
85 case '\v': io_write_m(Out, "v", 1); break;
86 default: fprintf(io_fp(Out), "%03o", c); break;
87 }
88 }
89 }
90 io_write_m(Out, "\"", 1);
91 }
92
93 static void dump_ko(const struct kork *k) {
94 String tmp;
95 St_fake(&tmp, (char *)ko_ptr(k), ko_length(k));
96 dump_str(&tmp);
97 }
98
99 static void to_id(struct kork *k, size_t n) {
100 static char id[] =
101 "abcdefghijklmnopqrstuvwxyz"
102 "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
103 "$"
104 ;
105 const size_t base = sizeof id - 1;
106 do {
107 ko_cat_c(k, id[n % base]);
108 n /= base;
109 } while (n);
110 }
111
112 static void make_var(struct val *v) {
113 static size_t seq;
114
115 ko_decouple(v->ko);
116 to_id(v->ko, seq++);
117 v->type = V_STR_K;
118 }
119
120 static void dump_expr(const struct expr *e, int inlist) {
121 assert(e != NULL);
122
123 switch (e->type) {
124 case literE:
125 if (V_EXT_P(e->v.val)) {
126 fprintf(io_fp(Out), "?%s?", io_name(e->v.val->magic.ext, NULL));
127 } else if (V_SUB_P(e->v.val)) {
128 fprintf(io_fp(Out), "?CODE(%p)?", (void *)e->v.val->magic.sub);
129 } else if (V_STR_P(e->v.val)) {
130 dump_ko(e->v.val->ko);
131 } else if (V_NUM_P(e->v.val)) {
132 if (e->v.val->num < 0.0) {
133 fprintf(io_fp(Out), "@NEG %g", -e->v.val->num);
134 } else {
135 fprintf(io_fp(Out), "%g", e->v.val->num);
136 }
137 } else {
138 #if 0
139 io_write_m(Out, "()", 2);
140 #endif
141 }
142 break;
143
144 case varE:
145 if (!V_STR_P(e->v.val)) {
146 assert(e->v.val->type == V_UNDEF);
147 make_var(e->v.val);
148 }
149 io_write_m(Out, ko_ptr(e->v.val->ko), ko_length(e->v.val->ko));
150 break;
151
152 case varhashE: {
153 struct val *tmp;
154 if (!(tmp = sh_get(e->v.hash, "name", 4))) {
155 tmp = v_undef();
156 make_var(tmp);
157 sh_put(e->v.hash, "name", 4, tmp);
158 }
159 io_write_m(Out, ko_ptr(tmp->ko), ko_length(tmp->ko));
160 io_write_m(Out, "(", 1);
161 dump_expr(e->right, 0);
162 io_write_m(Out, ")", 1);
163 break;
164 }
165
166 case symbolE:
167 io_write_m(Out, "\\", 1);
168 switch (e->op) {
169 case S_NUL: break;
170 case S_ARG: io_write_m(Out, "@", 1); break;
171 case S_ARGC: io_write_m(Out, "ARG", 3); break;
172
173 case S_ARGV:
174 io_write_m(Out, "ARG:", 4);
175 if (e->right->type == binopE) {
176 io_write_m(Out, "(", 1);
177 dump_expr(e->right, 0);
178 io_write_m(Out, ")", 1);
179 } else {
180 dump_expr(e->right, 0);
181 }
182 break;
183
184 case S_ERR: io_write_m(Out, "!", 1); break;
185 case S_EULER: io_write_m(Out, "E", 1); break;
186 case S_LUDOLF: io_write_m(Out, "PI", 2); break;
187 case S_MATCH:
188 fprintf(io_fp(Out), "%lu", (unsigned long)e->left.bonus);
189 break;
190 case S_RAND: io_write_m(Out, "?", 1); break;
191 case S_RESULT: io_write_m(Out, "_", 1); break;
192 case S_STDIN: io_write_m(Out, "EING", 4); break;
193 case S_STDOUT: io_write_m(Out, "AUSG", 4); break;
194 case S_STDERR: io_write_m(Out, "FEHL", 4); break;
195
196 default: NOTREACHED; break;
197 }
198 break;
199
200 case unopE:
201 switch (e->op) {
202 case F_EXP: io_write_m(Out, "\\E^", 3); break;
203 case F_LOWER: io_write_m(Out, "\\L" , 2); break;
204 case F_QUOTE: io_write_m(Out, "\\Q" , 2); break;
205 case F_RE_ESC: io_write_m(Out, "\\R" , 2); break;
206 case F_UPPER: io_write_m(Out, "\\U" , 2); break;
207 case F_MATCH: {
208 String tmp;
209 io_write_m(Out, "(", 1);
210 dump_expr(e->right, 0);
211 io_write_m(Out, " ~ ", 3);
212 St_init(&tmp);
213 re_decompile(e->left.rx, &tmp);
214 dump_str(&tmp);
215 St_clear(&tmp);
216 io_write_m(Out, ")", 1);
217 return;
218 }
219
220 default:
221 io_write_m(Out, "@", 1);
222 switch (e->op) {
223 case F_CALL: io_write(Out, &e->left.op->txt);
224 case F_NUL: break;
225 case F_ABS: io_write_m(Out, "ABS", 3); break;
226 case F_ACOS: io_write_m(Out, "ACOS", 4); break;
227 case F_ASIN: io_write_m(Out, "ASIN", 4); break;
228 case F_ATAN: io_write_m(Out, "ATAN", 4); break;
229 case F_ATAN2: io_write_m(Out, "ATAN2", 5); break;
230 case F_CATCH: io_write_m(Out, "EVAL", 4); break;
231 case F_CHR: io_write_m(Out, "CHR", 3); break;
232 case F_COS: io_write_m(Out, "COS", 3); break;
233 case F_DEFINED: io_write_m(Out, "DEF-P", 5); break;
234 case F_EOF: io_write_m(Out, "EDD-P", 5); break;
235 case F_ERROR: io_write_m(Out, "ERR-P", 5); break;
236 case F_FREEZE: io_write_m(Out, "OMFG", 4); break;
237 case F_GETC: io_write_m(Out, "GET", 3); break;
238 case F_GETENV: io_write_m(Out, "ENV", 3); break;
239 case F_GETS: io_write_m(Out, "LEGS", 4); break;
240 case F_HANG: {
241 size_t i;
242 String tmp;
243
244 St_init(&tmp);
245 for (St_num(&tmp, i = 1);
246 ve_findnext(&Venus, &tmp, 0);
247 St_num(&tmp, ++i))
248 ;
249 fprintf(io_fp(Out), "(%s)", St_ptr(&tmp));
250 St_clear(&tmp);
251 break;
252 }
253 case F_INT: io_write_m(Out, "INT", 3); break;
254 case F_IO: io_write_m(Out, "IO-P", 4); break;
255 case F_LENGTH: io_write_m(Out, "LENGTH", 6); break;
256 case F_LOG10: io_write_m(Out, "LG", 2); break;
257 case F_LOG: io_write_m(Out, "LN", 2); break;
258 case F_MOEND: io_write_m(Out, "+", 1); break;
259 case F_MOSTART: io_write_m(Out, "-", 1); break;
260 case F_NEG: io_write_m(Out, "NEG", 3); break;
261 case F_NOT: io_write_m(Out, "NOT", 3); break;
262 case F_NUM: io_write_m(Out, "NUM", 3); break;
263 case F_OPEN: io_write_m(Out, "APERS", 5); break;
264 case F_OPENR: io_write_m(Out, "LAPERS", 6); break;
265 case F_OPENW: io_write_m(Out, "SAPERS", 6); break;
266 case F_ORD: io_write_m(Out, "ORD", 3); break;
267 case F_REMOVE: io_write_m(Out, "REMOVE", 6); break;
268 case F_RENAME: io_write_m(Out, "RENAEM", 6); break;
269 case F_REVERSE: io_write_m(Out, "REVERSE", 7); break;
270 case F_SEEK: io_write_m(Out, "SUCH", 4); break;
271 case F_SIN: io_write_m(Out, "SIN", 3); break;
272 case F_SQRT: io_write_m(Out, "SPQR", 4); break;
273 case F_STR: io_write_m(Out, "STR", 3); break;
274 case F_TAN: io_write_m(Out, "TAN", 3); break;
275 case F_TELL: io_write_m(Out, "SAG", 3); break;
276 case F_TYPEOF: io_write_m(Out, "TYPE OF", 7); break;
277 default:
278 NOTREACHED;
279 break;
280 }
281 break;
282 }
283 if (e->right->type != unopE || e->op == F_NUL) {
284 io_write_m(Out, "(", 1);
285 dump_expr(e->right, 0);
286 io_write_m(Out, ")", 1);
287 } else {
288 io_write_m(Out, " ", 1);
289 dump_expr(e->right, 0);
290 }
291 break;
292
293 case binopE:
294 dump_expr(e->left.expr, 0);
295
296 if (e->op == B_XMATCH) {
297 io_write_m(Out, " ?o~ ", 5);
298 } else {
299 fprintf(io_fp(Out), "%s%c ", &" "[e->op == B_TAIL], display(e->op));
300 }
301
302 if (e->right->type == binopE) {
303 io_write_m(Out, "(", 1);
304 dump_expr(e->right, 0);
305 io_write_m(Out, ")", 1);
306 } else {
307 dump_expr(e->right, 0);
308 }
309 break;
310
311 case listE:
312 if (!inlist) {
313 io_write_m(Out, "#<", 2);
314 }
315 if (e->right) {
316 io_write_m(Out, "(", 1);
317 dump_expr(e->right, 0);
318 io_write_m(Out, ")", 1);
319 if (e->left.expr) {
320 io_write_m(Out, " ", 1);
321 dump_expr(e->left.expr, 1);
322 }
323 }
324 if (!inlist) {
325 io_write_m(Out, "#>", 2);
326 }
327 break;
328
329 }
330 }
331
332 static void dump_op(struct op *op) {
333 switch (op->type) {
334 case OP_NOP:
335 io_write_m(Out, "REM", 3);
336 break;
337
338 case OP_SET_VAL:
339 case OP_ASSIGN:
340 io_write_m(Out, "LET ", 4);
341 if (op->arh.expr) {
342 dump_expr(op->arh.expr, 0);
343 io_write_m(Out, " ", 1);
344 dump_expr(op->arg, 0);
345 } else {
346 io_write_m(Out, "(", 1);
347 dump_expr(op->arg, 0);
348 io_write_m(Out, ")", 1);
349 }
350 break;
351
352 case OP_CALL:
353 if (op->arh.op) {
354 fprintf(io_fp(Out), "%s ", St_ptr(&op->arh.op->txt));
355 dump_expr(op->arg, 0);
356 } else {
357 io_write_m(Out, "LET () ", 7);
358 dump_expr(op->arg, 0);
359 if (op->next) {
360 io_write_m(Out, "\nEND", 4);
361 }
362 }
363 break;
364
365 case OP_CALL_BACK:
366 io_write_m(Out, "ABRUF (", 7);
367 dump_expr(op->arh.expr, 0);
368 io_write_m(Out, ") ", 2);
369 dump_expr(op->arg, 0);
370 break;
371
372 case OP_CALL_DYN:
373 io_write_m(Out, "ANRUF ", 6);
374 dump_expr(op->arg, 0);
375 break;
376
377 case OP_CLOSE:
378 io_write_m(Out, "CLAUDS ", 7);
379 dump_expr(op->arg, 0);
380 break;
381
382 case OP_ELSE:
383 NOTREACHED;
384 break;
385
386 case OP_EXIT:
387 if (op->arg->type == literE && !op->arg->v.val->type) {
388 io_write_m(Out, "END", 3);
389 } else {
390 io_write_m(Out, "END ", 4);
391 dump_expr(op->arg, 0);
392 }
393 break;
394
395 case OP_FI:
396 NOTREACHED;
397 break;
398
399 case OP_FLUSH:
400 io_write_m(Out, "FLUSH ", 6);
401 dump_expr(op->arg, 0);
402 break;
403
404 case OP_GOBACK:
405 io_write_m(Out, "GOFOR ", 6);
406 dump_expr(op->arg, 0);
407 break;
408
409 case OP_GOTO:
410 io_write_m(Out, "GOTO ", 5);
411 dump_expr(op->arg, 0);
412 break;
413
414 case OP_HANG:
415 if (St_ptr(&op->txt)) {
416 fprintf(io_fp(Out), "NEXT %s", St_ptr(&op->txt));
417 } else {
418 String tmp;
419 MAKE_LABEL(&tmp, '*');
420 fprintf(io_fp(Out), "FOR %s NEXT %s", St_ptr(&tmp), St_ptr(&tmp));
421 St_clear(&tmp);
422 }
423 break;
424
425 case OP_IF:
426 if (op->arg->type == unopE && op->arg->op == F_NOT) {
427 io_write_m(Out, "IF ", 3);
428 dump_expr(op->arg->right, 0);
429 } else {
430 io_write_m(Out, "IF @NOT ", 8);
431 if (op->arg->type == binopE) {
432 io_write_m(Out, "(", 1);
433 dump_expr(op->arg, 0);
434 io_write_m(Out, ")", 1);
435 } else {
436 dump_expr(op->arg, 0);
437 }
438 }
439
440 if (op->next) {
441 fprintf(io_fp(Out), "\n NEXT %s\nFI", St_ptr(&op->next->txt));
442 } else {
443 io_write_m(Out, "\n END\nFI", 9);
444 }
445 break;
446
447 case OP_MODIFY:
448 io_write_m(Out, "LET ", 4);
449 dump_expr(op->arh.expr, 0);
450 if (op->arh.expr->op == B_XMATCH) {
451 io_write_m(Out, " ?o~= ", 6);
452 } else {
453 fprintf(io_fp(Out), " %c= ", display(op->arh.expr->op));
454 }
455 dump_expr(op->arg, 0);
456 break;
457
458 case OP_PRINT:
459 io_write_m(Out, "WUNT ", 5);
460 if (op->arh.expr) {
461 dump_expr(op->arh.expr, 0);
462 io_write_m(Out, " ", 1);
463 dump_expr(op->arg, 0);
464 } else if (op->arg->type != binopE) {
465 dump_expr(op->arg, 0);
466 } else {
467 io_write_m(Out, "(", 1);
468 dump_expr(op->arg, 0);
469 io_write_m(Out, ")", 1);
470 }
471 break;
472
473 case OP_PUTC:
474 io_write_m(Out, "SET ", 4);
475 dump_expr(op->arg, 0);
476 break;
477
478 case OP_RESET:
479 io_write_m(Out, "RESET ", 6);
480 dump_expr(op->arg, 0);
481 break;
482
483 case OP_RETURN:
484 io_write_m(Out, "KTHX ", 5);
485 dump_expr(op->arg, 0);
486 break;
487
488 case OP_SYSTEM:
489 io_write_m(Out, "# ", 2);
490 dump_expr(op->arg, 0);
491 break;
492
493 case OP_TEMP:
494 io_write_m(Out, "LEET ", 5);
495 dump_expr(op->arh.expr, 0);
496 io_write_m(Out, " ", 1);
497 dump_expr(op->arg, 0);
498 break;
499
500 case OP_THROW:
501 io_write_m(Out, "IACS ", 5);
502 dump_expr(op->arg, 0);
503 break;
504
505 default:
506 NOTREACHED;
507 break;
508 }
509 }
510
511 static struct {
512 size_t length;
513 size_t size;
514 struct op **ops;
515 } seen;
516
517 #define PUSH_SEEN(p) do { \
518 if (seen.length >= seen.size) { \
519 seen.ops = xrealloc(seen.ops, seen.size *= 2); \
520 } \
521 seen.ops[seen.length++] = (p); \
522 } while (0)
523
524 static int walk(const struct expr *e) {
525 for (;;) {
526 switch (e->type) {
527 case literE:
528 case symbolE:
529 return 0;
530
531 case varE:
532 return 0;
533
534 case varhashE:
535 e = e->right;
536 continue;
537
538 case unopE:
539 if (e->op == F_NUL) {
540 return 1;
541 } else if (e->op == F_CALL && !St_ptr(&e->left.op->txt)) {
542 MAKE_LABEL(&e->left.op->txt, 'f');
543 PUSH_SEEN(e->left.op);
544 }
545 e = e->right;
546 continue;
547
548 case binopE:
549 return walk(e->left.expr) | walk(e->right);
550
551 case listE:
552 return e->right && (walk(e->right) | (e->left.expr && walk(e->left.expr)));
553 }
554 }
555 }
556
557 static void do_stuff(struct op *op) {
558 for (; op && !op->line; op = op->next) {
559 op->line = 1;
560
561 if (St_ptr(&op->txt)) {
562 fprintf(io_fp(Out), "FOR %s ", St_ptr(&op->txt));
563 if (op->type != OP_NOP) {
564 dump_op(op);
565 } else {
566 io_write_m(Out, "REM", 4);
567 }
568 io_write_m(Out, "\n", 1);
569 } else {
570 dump_op(op);
571 #if 0
572 if (op->type != OP_NOP)
573 #endif
574 io_write_m(Out, "\n", 1);
575 }
576
577 if (op->type == OP_IF) {
578 if (op->arh.op) {
579 if (op->arh.op->line) {
580 fprintf(io_fp(Out), "NEXT %s\n", St_ptr(&op->arh.op->txt));
581 } else {
582 do_stuff(op->arh.op);
583 }
584 }
585 } else if (op->type == OP_CALL) {
586 if (op->arh.op && !op->arh.op->line) {
587 PUSH_SEEN(op->arh.op);
588 }
589 } else if (op->type == OP_HANG) {
590 return;
591 }
592
593 if (op->next) {
594 if (op->next->line && op->type != OP_IF && op->type != OP_RETURN) {
595 fprintf(io_fp(Out), "NEXT %s\n", St_ptr(&op->next->txt));
596 }
597 } else if (
598 op->type != OP_EXIT &&
599 op->type != OP_CALL &&
600 op->type != OP_CALL_BACK &&
601 op->type != OP_CALL_DYN &&
602 op->type != OP_HANG &&
603 op->type != OP_RETURN
604 ) {
605 io_write_m(Out, "END\n", 4);
606 }
607 }
608 }
609
610 enum {MAGIC = 23};
611 void deparse(const struct text *t) {
612 size_t i;
613 int computed_jumps;
614
615 computed_jumps = 0;
616 seen.ops = xmalloc(seen.size = MAGIC, sizeof *seen.ops);
617 seen.length = 0;
618
619 for (i = 0; i < t->length; ++i) {
620 struct op *op = t->start[i];
621
622 op->line = 0;
623
624 if (
625 op->type == OP_GOBACK ||
626 op->type == OP_GOTO ||
627 op->type == OP_CALL_DYN
628 ) {
629 walk(op->arg);
630 computed_jumps |= 1;
631 } else if (op->type == OP_CALL_BACK) {
632 walk(op->arh.expr);
633 walk(op->arg);
634 computed_jumps |= 1;
635 } else if (OP_1ARG_P(op->type)) {
636 computed_jumps |= walk(op->arg);
637 if (op->type == OP_CALL && op->arh.op) {
638 if (!St_ptr(&op->arh.op->txt)) {
639 MAKE_LABEL(&op->arh.op->txt, 'c');
640 }
641 }
642 } else if (OP_2ARG_P(op->type)) {
643 if (op->arh.expr) {
644 computed_jumps |= walk(op->arh.expr);
645 }
646 computed_jumps |= walk(op->arg);
647 }
648
649 if (
650 op->next &&
651 (op->next != t->start[i + 1] || op->type == OP_CALL) &&
652 !St_ptr(&op->next->txt)
653 ) {
654 MAKE_LABEL(&op->next->txt, 'x');
655 }
656 }
657
658 if (!computed_jumps) {
659 do_stuff(t->start[0]);
660 for (i = 0; i < seen.length; ++i) {
661 do_stuff(seen.ops[i]);
662 }
663 } else {
664 for (i = 0; i < t->length; ++i) {
665 struct op *op = t->start[i];
666 const String *tmp;
667
668 if ((tmp = ve_label(&Venus, op))) {
669 if (St_ptr(&op->txt)) {
670 fprintf(io_fp(Out), " FOR %s\n", St_ptr(&op->txt));
671 }
672 fprintf(io_fp(Out), "%s%s", St_ptr(tmp), &" "[!St_len(tmp)]);
673 } else {
674 if (St_ptr(&op->txt)) {
675 fprintf(io_fp(Out), "FOR %s ", St_ptr(&op->txt));
676 }
677 }
678
679 dump_op(op);
680 io_write_m(Out, "\n", 1);
681
682 if (op->next && op->next != t->start[i + 1] && op->type != OP_IF) {
683 fprintf(io_fp(Out), "NEXT %s\n", St_ptr(&op->next->txt));
684 }
685 }
686 }
687 xfree(seen.ops);
688 }