]> mj.ucw.cz Git - umpf.git/blob - code.c
af2348973efb31f07f733130576f46366003e908
[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)
74 {
75         struct code* p = xmalloc(sizeof(struct code));
76         *p = c;
77         list_add_last(&input_code, &p->car);
78 }
79
80 /* return number of variable where lies result 
81  * pref_var < 0 => no preference
82  */
83 static int
84 evaluate(struct tree* t, int pref_var)
85 {
86         struct code ins;
87
88         if (t->st == ST_LEAF) { 
89                 return t->pt.leaf.n;
90         } else if (t->st == ST_OP) {
91                 int left, right;
92                 left = evaluate(t->pt.op.left, -1);
93                 right = evaluate(t->pt.op.right, -1);
94                 switch (t->pt.op.op) {
95                         case '.':
96                                 ins.opcode = CAT;
97                                 ins.u.cat.l = left;
98                                 ins.u.cat.r = right;
99                                 if (pref_var >= 0)
100                                         ins.u.cat.res = pref_var;
101                                 else
102                                         ins.u.cat.res = current_varcode++;;
103                                 new_instr(ins);
104                                 return ins.u.cat.res;
105                                 break;
106                         default:
107                                 die("evaluate: got to default");
108                 }
109         } else
110                 die("evaluate: I can evaluate only expressions but I got %d",
111                         t->st);
112 }
113
114 static void
115 do_ass(struct tree* t)
116 {
117         int var_l, var_r;
118         struct code ins;
119         var_l = t->pt.ass.left->pt.leaf.n;
120         var_r = evaluate(t->pt.ass.right, -1);
121         
122         ins.opcode = SET;
123         ins.u.set.l = var_l;
124         ins.u.set.r = var_r;
125         new_instr(ins);
126
127 }
128
129 static void
130 reset_temp_var_count(void)
131 {
132         current_varcode = temp_varcode_start;
133 }
134
135 void
136 compile(struct tree* t)
137 {
138         if (!t)
139                 return;
140         switch(t->st) {
141                 case ST_BLOCK:
142                         reset_temp_var_count();
143                         compile(t->pt.block.head);
144                         compile(t->pt.block.tail);
145                         break;
146                 case ST_EMPTY:
147                         break;
148                 case ST_ASS:
149                         do_ass(t);
150                         break;
151                 case ST_OP:
152                         break;
153                 default:
154                         die("compile: got to default");
155         }
156 }
157
158 void
159 print_code(void)
160 {
161         struct code* p;
162
163         LIST_FOREACH(p, &input_code) {
164                 switch (p->opcode) {
165                         case SET:
166                                 printf("SET %d %d\n", p->u.set.l, p->u.set.r);
167                                 break; 
168                         case CAT:
169                                 printf("CAT %d %d %d\n", p->u.cat.l,
170                                 p->u.cat.r, p->u.cat.res);
171                                 break;
172                         default:
173                                 printf("not implemented, opcode: %d\n",
174                                 p->opcode);
175                 }
176         }
177 }