4223
|
1 #include "config.h"
|
|
2 #include "Str.h"
|
|
3 #include "compile.h"
|
|
4 #include "expr.h"
|
|
5 #include "main_var.h"
|
|
6 #include "op.h"
|
|
7 #include "text.h"
|
|
8 #include "zz.h"
|
|
9
|
|
10 #include <assert.h>
|
|
11
|
|
12 static struct op *end_if(struct text *code, size_t *n) {
|
|
13 for (; *n < code->length; ++*n) {
|
|
14 struct op *const p = code->start[*n];
|
|
15 switch (p->type) {
|
|
16 case OP_IF:
|
|
17 ++*n;
|
|
18 p->arh.op = code->start[*n];
|
|
19 p->next = end_if(code, n);
|
|
20 break;
|
|
21
|
|
22 case OP_ELSE: {
|
|
23 size_t tmp;
|
|
24 tmp = ++*n;
|
|
25 p->next = end_if(code, n);
|
|
26 p->type = OP_NOP;
|
|
27 if (tmp < code->length) {
|
|
28 return code->start[tmp];
|
|
29 }
|
|
30 return p;
|
|
31 }
|
|
32
|
|
33 case OP_FI:
|
|
34 p->type = OP_NOP;
|
|
35 return p;
|
|
36
|
|
37 default:
|
|
38 break;
|
|
39 }
|
|
40 }
|
|
41
|
|
42 return code->start[0];
|
|
43 }
|
|
44
|
|
45 static void resolve(struct expr *e) {
|
|
46 if (!e) {
|
|
47 return;
|
|
48 }
|
|
49
|
|
50 switch (e->type) {
|
|
51 case literE:
|
|
52 break;
|
|
53
|
|
54 case varE:
|
|
55 e->v.val = vr_data(Var_plain, e->v.tent);
|
|
56 assert(e->v.val != NULL);
|
|
57 break;
|
|
58
|
|
59 case varhashE:
|
|
60 e->v.hash = vr_data(Var_hash, e->v.tent);
|
|
61 resolve(e->right);
|
|
62 break;
|
|
63
|
|
64 case symbolE:
|
|
65 if (e->op == S_ARGV) {
|
|
66 resolve(e->right);
|
|
67 }
|
|
68 break;
|
|
69
|
|
70 case unopE:
|
|
71 resolve(e->right);
|
|
72 break;
|
|
73
|
|
74 case binopE:
|
|
75 resolve(e->left.expr);
|
|
76 resolve(e->right);
|
|
77 break;
|
|
78
|
|
79 case listE:
|
|
80 resolve(e->right);
|
|
81 resolve(e->left.expr);
|
|
82 break;
|
|
83 }
|
|
84 }
|
|
85
|
|
86 static void op_resolve(struct op *o) {
|
|
87 switch (o->type) {
|
|
88 case OP_NOP:
|
|
89 case OP_GOBACK:
|
|
90 case OP_GOTO:
|
|
91 case OP_HANG:
|
|
92 break;
|
|
93
|
|
94 case OP_ASSIGN:
|
|
95 case OP_CALL_BACK:
|
|
96 case OP_MODIFY:
|
|
97 case OP_PRINT:
|
|
98 case OP_PUTC:
|
|
99 case OP_TEMP:
|
|
100 resolve(o->arh.expr);
|
|
101 resolve(o->arg);
|
|
102 break;
|
|
103
|
|
104 case OP_CALL:
|
|
105 case OP_CALL_DYN:
|
|
106 case OP_CLOSE:
|
|
107 case OP_EXIT:
|
|
108 case OP_IF:
|
|
109 case OP_RETURN:
|
|
110 case OP_SYSTEM:
|
|
111 case OP_THROW:
|
|
112 resolve(o->arg);
|
|
113 break;
|
|
114
|
|
115 default:
|
|
116 NOTREACHED;
|
|
117 break;
|
|
118 }
|
|
119 }
|
|
120
|
|
121 void compile(struct text *code) {
|
|
122 size_t i;
|
|
123
|
|
124 for (i = 0; i < code->length; ++i) {
|
|
125 struct op *const p = code->start[i];
|
|
126
|
|
127 op_getop(p);
|
|
128
|
|
129 if (!p->next && p->type != OP_EXIT && i + 1 < code->length) {
|
|
130 p->next = code->start[i + 1];
|
|
131 }
|
|
132 }
|
|
133
|
|
134 if (!i) {
|
|
135 struct op tmp;
|
|
136 op_init(&tmp);
|
|
137 text_push(code, &tmp);
|
|
138 }
|
|
139
|
|
140 vr_freeze(Var_plain);
|
|
141 vr_freeze(Var_hash);
|
|
142
|
|
143 for (i = 0; i < code->length; ++i) {
|
|
144 struct op *const p = code->start[i];
|
|
145
|
|
146 switch (p->type) {
|
|
147 case OP_IF:
|
|
148 ++i;
|
|
149 p->arh.op = code->start[i];
|
|
150 p->next = end_if(code, &i);
|
|
151 break;
|
|
152
|
|
153 case OP_ELSE:
|
|
154 ++i;
|
|
155 p->next = end_if(code, &i);
|
|
156 p->type = OP_NOP;
|
|
157 break;
|
|
158
|
|
159 case OP_FI:
|
|
160 p->type = OP_NOP;
|
|
161 break;
|
|
162
|
|
163 default:
|
|
164 break;
|
|
165 }
|
|
166 }
|
|
167
|
|
168 for (i = 0; i < code->length; ++i) {
|
|
169 op_resolve(code->start[i]);
|
|
170 }
|
|
171 }
|