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