Mercurial > repo
comparison src/ploki/compile.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 "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 } |