]> mj.ucw.cz Git - umpf.git/blob - code.c
fix ass_right bugs, finish print_code
[umpf.git] / code.c
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <string.h>
4 #include <ctype.h>
5
6 #include "umpf.h"
7
8 #define HASHSIZE 103
9 #define MAGIC 19
10
11 struct list* 
12 new_var_hash(void)
13 {
14         struct list* res;
15         int i;
16
17         res = xmalloc (HASHSIZE * sizeof(struct list));
18         for (i = 0; i < HASHSIZE; i++)
19                 list_init(res + i);
20         
21         return res;
22 }
23
24 static int
25 get_bucket_number(char* name)
26 {
27         unsigned int n = 0;
28         unsigned char* p = name;
29
30         while (*p != '\0'){
31                 n = n * MAGIC + toupper(*p++);
32         }
33         n %= HASHSIZE;
34
35         return n;
36 }
37
38 /* if not found, variable with value "" is created  */ 
39 int
40 find_var(char* name, struct list* hash)
41 {
42         int n;
43         struct variable *p;
44
45         n = get_bucket_number(name);
46         int nocase = isupper(*name);
47         LIST_FOREACH(p, hash + n)
48                 if (!(nocase ? strcasecmp : strcmp)(p->name,name))
49                         return p->varcode;
50
51         p = xmalloc(sizeof(struct variable));
52         p->name = xstrdup(name);
53         p->varcode = current_varcode++;
54         list_add_last(hash+n, &p->car);
55
56         return p->varcode;
57 }
58
59 int
60 store_const(char* c)
61 {
62         if (cur_const_n >= cur_const_s) {
63                 cur_const_s *= 2;
64                 const_tab = xrealloc(const_tab, cur_const_s);
65         }
66
67         const_tab[cur_const_n] = c;
68
69         return -cur_const_n++;  
70 }
71
72 static void
73 new_instr(struct code c, struct list* where)
74 {
75         struct code* p = xmalloc(sizeof(struct code));
76         *p = c;
77         if (where)
78                 list_add_last(where, &p->car);
79         else
80                 list_add_last(&input_code, &p->car);
81 }
82
83 static int
84 new_3par_instr(int opcode, int left, int right, int pref_var, 
85                  struct list* where)
86 {
87         struct code ins;
88
89         ins.opcode = opcode;
90         ins.u.tpop.l = left;
91         ins.u.tpop.r = right;
92         if (pref_var >= 0)
93                 ins.u.tpop.res = pref_var;
94         else
95                 ins.u.tpop.res = current_varcode++;;
96         new_instr(ins, where);
97         return ins.u.tpop.res;
98 }
99
100 /* return number of variable where lies result 
101  * pref_var < 0 => no preference
102  */
103 static int
104 evaluate(struct tree* t, int pref_var, struct list* where)
105 {
106         if (t->st == ST_LEAF) { 
107                 return t->pt.leaf.n;
108         } else if (t->st == ST_OP) {
109                 int left, right;
110                 left = evaluate(t->pt.op.left, -1, where);
111                 right = evaluate(t->pt.op.right, -1, where);
112                 switch (t->pt.op.op) {
113                         case '.':
114                                 return new_3par_instr(OPC_CAT, left, 
115                                         right, pref_var, where);
116                                 break;
117                         case '+':
118                                 return new_3par_instr(OPC_PLUS, left, 
119                                         right, pref_var, where);
120                                 break;
121                         case '-':
122                                 return new_3par_instr(OPC_MINUS, left, 
123                                         right, pref_var, where);
124                                 break;
125                         case '*':
126                                 return new_3par_instr(OPC_MUL, left, 
127                                         right, pref_var, where);
128                                 break;
129                         case '/':
130                                 return new_3par_instr(OPC_DIV, left, 
131                                         right, pref_var, where);
132                                 break;
133                         default:
134                                 die("evaluate: got to default");
135                 }
136         } else
137                 die("evaluate: I can evaluate only expressions but I got %d",
138                         t->st);
139 }
140
141 static void
142 do_ass(struct tree* t, struct list* where)
143 {
144         int var_l, var_r;
145         struct code ins;
146         var_l = t->pt.ass.left->pt.leaf.n;
147         var_r = evaluate(t->pt.ass.right, -1, where);
148         
149         ins.opcode = OPC_SET;
150         ins.u.set.l = var_l;
151         ins.u.set.r = var_r;
152         new_instr(ins, where);
153
154 }
155
156 static int
157 eval_cond(struct tree *t, int pref_var, struct list* where)
158 {
159         int left, right;
160         if (t->pt.cond.type == JUST_BOOL) {
161                 if (t->pt.cond.left->st == ST_LEAF)
162                         return t->pt.cond.left->pt.leaf.n;
163                 if (t->pt.cond.left->st == ST_OP)
164                         return evaluate(t->pt.cond.left, -1, where);
165                 else
166                         die("eval_cond: %d cannot be JUST_BOOL\n", 
167                         t->pt.cond.left->st);
168         }
169         if (t->pt.cond.type == OP_REL) {
170                 left = evaluate(t->pt.cond.left, -1, where);
171                 right = evaluate(t->pt.cond.right, -1, where);
172
173                 switch (t->pt.cond.op) {                
174                         case '>':
175                                 return new_3par_instr (OPC_GT, left, 
176                                         right, pref_var, where);
177                                 break;
178                         case '<':
179                                 return new_3par_instr (OPC_LT, left, 
180                                         right, pref_var, where);
181                                 break;
182                         case CC('<','='):
183                                 return new_3par_instr (OPC_LE, left, 
184                                         right, pref_var, where);
185                                 break;
186                         case CC('>','='):
187                                 return new_3par_instr (OPC_GE, left, 
188                                         right, pref_var, where);
189                                 break;
190                         case CC('!','~'):
191                                 return new_3par_instr (OPC_NRE, left, 
192                                         right, pref_var, where);
193                                 break;
194                         case CC('~','~'):
195                                 return new_3par_instr (OPC_RE, left, 
196                                         right, pref_var, where);
197                                 break;
198                         case CC('=','='):
199                                 return new_3par_instr (OPC_EQ, left, 
200                                         right, pref_var, where);
201                                 break;
202                         case CC('!','='):
203                                 return new_3par_instr (OPC_NEQ, left, 
204                                         right, pref_var, where);
205                                 break;
206                         /* fixme: do more of them */
207                         default:
208                                 die("eval_cond: unknown relation op %c\n", 
209                                 t->pt.cond.op);
210
211                 }
212         }
213         if (t->pt.cond.type == OP_BOOL) {
214                 struct code ins;
215
216                 left = eval_cond(t->pt.cond.left, -1, where);
217                 if (t->pt.cond.op != '!') /* ! is unary */
218                         right = eval_cond(t->pt.cond.right, -1, where);
219                 switch (t->pt.cond.op) {
220                         case '&':
221                                 return new_3par_instr (OPC_AND, left, 
222                                         right, pref_var, where);
223                                 break;
224                         case '|':
225                                 return new_3par_instr (OPC_OR, left, 
226                                         right, pref_var, where);
227                                 break;
228                         case '^':
229                                 return new_3par_instr (OPC_XOR, left, 
230                                         right, pref_var, where);
231                                 break;
232                         case '!':
233                                 ins.opcode = OPC_NOT;
234                                 ins.u.dpop.par = left;
235                                 if (pref_var >= 0)
236                                         ins.u.dpop.res = pref_var;
237                                 else
238                                         ins.u.dpop.res = current_varcode++;;
239                                 new_instr(ins, where);
240                                 return ins.u.dpop.res;
241                                 break;
242                         default:
243                                 die("eval_cond: unknown boolean op %c\n", 
244                                 t->pt.cond.op);
245                 }
246         }
247         
248         die("eval_cond: unknown condition type");
249 }
250
251 static void
252 do_if(struct tree *t, struct list* where)
253 {
254         int c;
255         struct code ins, nop, jmp;
256         struct list* if_branch = xmalloc(sizeof(struct list));
257         struct list* else_branch = xmalloc(sizeof(struct list));
258
259         list_init(if_branch);
260         list_init(else_branch);
261         nop.opcode  = OPC_NOP;
262         jmp.opcode = OPC_JUMP;
263
264         c = eval_cond(t->pt.tif.c, -1, where);
265
266         compile(t->pt.tif.i, if_branch);        
267         compile(t->pt.tif.i, else_branch);      
268         new_instr(nop, if_branch);
269         new_instr(nop, else_branch);
270         jmp.u.jump.target = list_last(else_branch);
271         new_instr(jmp, if_branch);
272         
273         ins.opcode = OPC_JUMP_UNLESS;
274         ins.u.jump_unless.cond = c;
275         ins.u.jump_unless.target = list_last(if_branch);
276         new_instr(ins, where);
277         list_cat(where, if_branch);
278         list_cat(where, else_branch);
279
280         free(if_branch);
281         free(else_branch);
282 }
283
284 static void
285 do_arrow(struct tree* t, struct list* where)
286 {
287         int v;
288         struct code ins;
289
290
291         if (t->pt.arrow.left == K_COPY)
292                 ins.u.arrow.copy = 1;
293         else
294                 ins.u.arrow.copy = 0;
295         switch (t->pt.arrow.right) {
296                 case K_EMPTY:
297                         ins.opcode = OPC_STORE;
298                         break;
299                 case K_PIPE:
300                         ins.opcode = OPC_PIPE;
301                         break;
302                 case K_MAIL:
303                         ins.opcode = OPC_MAIL;
304                         break;
305                 case K_DISCARD:
306                         ins.opcode = OPC_DISCARD;
307                         break;
308                 default:
309                         die("do_arrow: This cannot happen ;-)");
310         }
311
312         if (t->pt.arrow.right != K_DISCARD) {
313                 v = evaluate(t->pt.arrow.s, -1, where);
314                 ins.u.arrow.what = v;
315         }
316
317         new_instr(ins, where);
318 }
319
320 static void
321 reset_temp_var_count(void)
322 {
323         current_varcode = temp_varcode_start;
324 }
325
326 void
327 compile(struct tree* t, struct list* where)
328 {
329         if (!t)
330                 return;
331         if (! where)
332                 where = &input_code;
333
334         switch(t->st) {
335                 case ST_BLOCK:
336                         reset_temp_var_count();
337                         compile(t->pt.block.head, where);
338                         compile(t->pt.block.tail, where);
339                         break;
340                 case ST_EMPTY:
341                         break;
342                 case ST_LEAF: //warn?
343                         break;
344                 case ST_ASS:
345                         do_ass(t, where);
346                         break;
347                 case ST_OP:
348                         evaluate(t, -1, where); //emit warning?
349                         break;
350                 case ST_IF:
351                         do_if(t, where);
352                         break;
353                 case ST_COND:
354                         eval_cond(t, -1, where); // warn?
355                 case ST_ARROW:
356                         do_arrow(t, where);
357                         break;
358                 default:
359                         die("compile: got to default, type: %d", t->st);
360         }
361 }
362
363 void
364 print_code(void)
365 {
366         struct code* p;
367
368         LIST_FOREACH(p, &input_code) {
369                 switch (p->opcode) {
370                         case OPC_SET:
371                                 printf("SET %d %d\n", p->u.set.l, p->u.set.r);
372                                 break; 
373                         case OPC_CAT:
374                                 printf("CAT %d %d %d\n", p->u.tpop.l,
375                                 p->u.tpop.r, p->u.tpop.res);
376                                 break;
377                         case OPC_JUMP:
378                                 printf("JUMP %d\n", (int) p->u.jump.target);
379                                 break;
380                         case OPC_JUMP_UNLESS:
381                                 printf("JUMP_UNLESS %d %d\n", p->u.jump_unless.cond,(int) p->u.jump_unless.target);
382                                 break;
383                         case OPC_GT:
384                                 printf("GT %d %d %d\n", p->u.tpop.l, p->u.tpop.r, p->u.tpop.res);
385                                 break;
386                         case OPC_LT:
387                                 printf("LT %d %d %d\n", p->u.tpop.l, p->u.tpop.r, p->u.tpop.res);
388                                 break;
389                         case OPC_LE:
390                                 printf("LE %d %d %d\n", p->u.tpop.l, p->u.tpop.r, p->u.tpop.res);
391                                 break;
392                         case OPC_GE:
393                                 printf("GE %d %d %d\n", p->u.tpop.l, p->u.tpop.r, p->u.tpop.res);
394                                 break;
395                         case OPC_RE:
396                                 printf("RE %d %d %d\n", p->u.tpop.l, p->u.tpop.r, p->u.tpop.res);
397                                 break;
398                         case OPC_NRE:
399                                 printf("NRE %d %d %d\n", p->u.tpop.l, p->u.tpop.r, p->u.tpop.res);
400                                 break;
401                         case OPC_NEQ:
402                                 printf("NEQ %d %d %d\n", p->u.tpop.l, p->u.tpop.r, p->u.tpop.res);
403                                 break;
404                         case OPC_EQ:
405                                 printf("EQ %d %d %d\n", p->u.tpop.l, p->u.tpop.r, p->u.tpop.res);
406                                 break;
407                         case OPC_AND:
408                                 printf("AND %d %d %d\n", p->u.tpop.l, p->u.tpop.r, p->u.tpop.res);
409                                 break;
410                         case OPC_OR:
411                                 printf("OR %d %d %d\n", p->u.tpop.l, p->u.tpop.r, p->u.tpop.res);
412                                 break;
413                         case OPC_XOR:
414                                 printf("XOR %d %d %d\n", p->u.tpop.l, p->u.tpop.r, p->u.tpop.res);
415                                 break;
416                         case OPC_PLUS:
417                                 printf("PLUS %d %d %d\n", p->u.tpop.l, p->u.tpop.r, p->u.tpop.res);
418                                 break;
419                         case OPC_MINUS:
420                                 printf("MINUS %d %d %d\n", p->u.tpop.l, p->u.tpop.r, p->u.tpop.res);
421                                 break;
422                         case OPC_MUL:
423                                 printf("MUL %d %d %d\n", p->u.tpop.l, p->u.tpop.r, p->u.tpop.res);
424                                 break;
425                         case OPC_DIV:
426                                 printf("DIV %d %d %d\n", p->u.tpop.l, p->u.tpop.r, p->u.tpop.res);
427                                 break;
428                         case OPC_NOT:
429                                 printf("NOT %d %d\n", p->u.dpop.par, p->u.dpop.res);
430                                 break;
431                         case OPC_NOP:
432                                 puts("NOP");    
433                                 break;
434                         case OPC_PIPE:
435                                 printf("PIPE %d %d\n", p->u.arrow.what, p->u.arrow.copy);
436                                 break;
437                         case OPC_STORE:
438                                 printf("STORE %d %d\n", p->u.arrow.what, p->u.arrow.copy);
439                                 break;
440                         case OPC_MAIL:
441                                 printf("MAIL %d %d\n", p->u.arrow.what, p->u.arrow.copy);
442                                 break;
443                         case OPC_DISCARD:
444                                 puts("DISCARD");
445                                 break;
446                         default:
447                                 printf("not implemented, opcode: %d\n",
448                                 p->opcode);
449                 }
450         }
451 }