Atualizado docs. Implementado ops logicos.
[myPerl.git] / vm.c
blob90944162ed787f8521525d19dd01f4fc2bf00863
1 #include <stdio.h>
2 #include <assert.h>
3 #include "heap.h"
4 #include "code.h"
5 #include "symtab.h"
6 #include "vm.h"
8 #define STACK_SIZE 4096
10 /*
11 * Pilha de execucao.
13 * Essa pilha eh a usada por praticamente tds as
14 * rotinas da maquina virtual
16 static int top = -1;
17 static int stack[STACK_SIZE];
19 /*
20 * Pilha usada para armazenar informacoes especificas
21 * das chamadas de funcao
23 static int fun_top = -1;
24 static int fun_stack[STACK_SIZE];
26 /* Program counter */
27 static int pc = 0;
29 /* Operacoes binarias */
30 enum {
31 O_ADD, O_SUB, O_MUL, O_DIV, O_MOD,
32 O_EQL, O_NE, O_GEQL, O_LEQL, O_GT, O_LT,
33 O_OR, O_NOT, O_AND };
35 static void
36 bin_op(int op)
38 assert(top >= 1);
39 switch(op) {
40 case O_ADD:
41 stack[top-1] = stack[top-1] + stack[top];
42 break;
43 case O_SUB:
44 stack[top-1] = stack[top-1] - stack[top];
45 break;
46 case O_MUL:
47 stack[top-1] = stack[top-1] * stack[top];
48 break;
49 case O_DIV:
50 stack[top-1] = stack[top-1] / stack[top];
51 break;
52 case O_MOD:
53 stack[top-1] = stack[top-1] % stack[top];
54 break;
55 case O_EQL:
56 stack[top-1] = stack[top-1] == stack[top];
57 break;
58 case O_NE:
59 stack[top-1] = stack[top-1] != stack[top];
60 break;
61 case O_GEQL:
62 stack[top-1] = stack[top-1] >= stack[top];
63 break;
64 case O_LEQL:
65 stack[top-1] = stack[top-1] <= stack[top];
66 break;
67 case O_GT:
68 stack[top-1] = stack[top-1] > stack[top];
69 break;
70 case O_LT:
71 stack[top-1] = stack[top-1] < stack[top];
72 break;
73 case O_OR:
74 stack[top-1] = stack[top-1] || stack[top];
75 break;
76 case O_AND:
77 stack[top-1] = stack[top-1] && stack[top];
78 break;
79 case O_NOT:
80 stack[top-1] = !stack[top-1];
81 top++; /* we do not reduce the stack */
82 break;
83 default:
84 fprintf(stderr, "Operacao %d nao reconhecida\n", op);
85 break;
87 --top;
88 pc++;
91 void
92 vm_halt(int arg)
96 void
97 vm_add(int arg)
99 bin_op(O_ADD);
102 void
103 vm_sub(int arg)
105 bin_op(O_SUB);
108 void
109 vm_mul(int arg)
111 bin_op(O_MUL);
114 void
115 vm_div(int arg)
117 bin_op(O_DIV);
120 void
121 vm_mod(int arg)
123 bin_op(O_MOD);
126 void
127 vm_cmp_eql(int arg)
129 bin_op(O_EQL);
132 void
133 vm_cmp_ne(int arg)
135 bin_op(O_NE);
138 void
139 vm_cmp_geql(int arg)
141 bin_op(O_GEQL);
144 void
145 vm_cmp_leql(int arg)
147 bin_op(O_LEQL);
150 void
151 vm_cmp_gt(int arg)
153 bin_op(O_GT);
156 void
157 vm_cmp_lt(int arg)
159 bin_op(O_LT);
162 void
163 vm_cmp_or(int arg)
165 bin_op(O_OR);
168 void
169 vm_cmp_and(int arg)
171 bin_op(O_AND);
174 void
175 vm_cmp_not(int arg)
177 bin_op(O_NOT);
180 void
181 vm_load_var(int arg)
183 int off = stack[top--];
184 stack[++top] = data_get(arg, off);
185 pc++;
188 void
189 vm_load_int(int arg)
191 stack[++top] = arg;
192 pc++;
195 void
196 vm_load_off(int arg)
198 stack[++top] = arg;
199 pc++;
202 void
203 vm_store(int arg)
205 int off = stack[top--];
206 assert(top >= 0);
207 data_put(arg, off, stack[top]);
208 top--;
209 pc++;
212 void
213 vm_jmp_false(int arg)
215 if (stack[top] == 0)
216 pc = arg;
217 else
218 pc++;
219 top--;
222 void
223 vm_goto(int arg)
225 pc = arg;
228 void
229 vm_write_int(int arg)
231 printf("%d\n", stack[top]);
232 top--;
233 pc++;
236 void
237 vm_call(int arg)
239 int nargs = fun_stack[fun_top-1];
241 scope++;
242 /* store the base pointer */
243 fun_stack[++fun_top] = top-nargs+1;
244 pc = arg;
247 void
248 vm_push_int(int arg)
250 fun_stack[++fun_top] = arg;
251 pc++;
254 void
255 vm_push_var(int arg)
257 fun_stack[++fun_top] = data_get(arg, stack[top--]);
258 pc++;
261 void
262 vm_ret(int arg)
264 int nargs;
266 fun_top--; /* take off the base pointer */
267 pc = fun_stack[fun_top--];
268 nargs = fun_stack[fun_top--];
270 top -= nargs;
272 assert(fun_top >= -1 && top >= -1);
274 scoperem(scope--);
277 void
278 vm_shift(int arg)
280 int bp = fun_stack[fun_top];
281 stack[++top] = stack[bp];
282 fun_stack[fun_top]++;
283 pc++;
287 vm_loop(void)
289 while (code[pc].op != HALT) {
290 ops[code[pc].op].op(code[pc].arg);
293 return 0;