source: mainline/uspace/app/sbi/src/run_expr.c@ 09ababb7

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 09ababb7 was 09ababb7, checked in by Jiri Svoboda <jiri@…>, 15 years ago

Add Sysel Bootstrap Interpreter (SBI) from Sysel repository rev. 53.

  • Property mode set to 100644
File size: 13.2 KB
Line 
1/*
2 * Copyright (c) 2010 Jiri Svoboda
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * - Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * - Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * - The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29/** @file Runner (executes the code). */
30
31#include <stdio.h>
32#include <stdlib.h>
33#include <assert.h>
34#include "debug.h"
35#include "list.h"
36#include "mytypes.h"
37#include "rdata.h"
38#include "run.h"
39#include "symbol.h"
40#include "strtab.h"
41
42#include "run_expr.h"
43
44static void run_nameref(run_t *run, stree_nameref_t *nameref,
45 rdata_item_t **res);
46static void run_literal(run_t *run, stree_literal_t *literal,
47 rdata_item_t **res);
48static void run_lit_int(run_t *run, stree_lit_int_t *lit_int,
49 rdata_item_t **res);
50static void run_lit_string(run_t *run, stree_lit_string_t *lit_string,
51 rdata_item_t **res);
52static void run_binop(run_t *run, stree_binop_t *binop, rdata_item_t **res);
53static void run_unop(run_t *run, stree_unop_t *unop, rdata_item_t **res);
54static void run_access(run_t *run, stree_access_t *access, rdata_item_t **res);
55static void run_call(run_t *run, stree_call_t *call, rdata_item_t **res);
56static void run_assign(run_t *run, stree_assign_t *assign, rdata_item_t **res);
57
58static void run_address_read(run_t *run, rdata_address_t *address,
59 rdata_item_t **ritem);
60static void run_address_write(run_t *run, rdata_address_t *address,
61 rdata_value_t *value);
62
63/** Evaluate expression. */
64void run_expr(run_t *run, stree_expr_t *expr, rdata_item_t **res)
65{
66#ifdef DEBUG_RUN_TRACE
67 printf("Executing expression.\n");
68#endif
69
70 switch (expr->ec) {
71 case ec_nameref:
72 run_nameref(run, expr->u.nameref, res);
73 break;
74 case ec_literal:
75 run_literal(run, expr->u.literal, res);
76 break;
77 case ec_binop:
78 run_binop(run, expr->u.binop, res);
79 break;
80 case ec_unop:
81 run_unop(run, expr->u.unop, res);
82 break;
83 case ec_access:
84 run_access(run, expr->u.access, res);
85 break;
86 case ec_call:
87 run_call(run, expr->u.call, res);
88 break;
89 case ec_assign:
90 run_assign(run, expr->u.assign, res);
91 break;
92 }
93
94#ifdef DEBUG_RUN_TRACE
95 printf("Expression result: ");
96 rdata_item_print(*res);
97 printf(".\n");
98#endif
99}
100
101/** Evaluate name reference expression. */
102static void run_nameref(run_t *run, stree_nameref_t *nameref,
103 rdata_item_t **res)
104{
105 stree_symbol_t *sym;
106 rdata_item_t *item;
107 rdata_address_t *address;
108 rdata_value_t *val;
109 rdata_var_t *var;
110 rdata_deleg_t *deleg_v;
111
112#ifdef DEBUG_RUN_TRACE
113 printf("Run nameref.\n");
114#endif
115
116 /*
117 * Look for a local variable.
118 */
119 var = run_local_vars_lookup(run, nameref->name->sid);
120 if (var != NULL) {
121 /* Found a local variable. */
122 item = rdata_item_new(ic_address);
123 address = rdata_address_new();
124
125 item->u.address = address;
126 address->vref = var;
127
128 *res = item;
129#ifdef DEBUG_RUN_TRACE
130 printf("Found local variable.\n");
131#endif
132 return;
133 }
134
135 /*
136 * Look for a class-wide or global symbol.
137 */
138
139 /* XXX Start lookup in currently active CSI. */
140 sym = symbol_lookup_in_csi(run->program, NULL, nameref->name);
141
142 switch (sym->sc) {
143 case sc_csi:
144#ifdef DEBUG_RUN_TRACE
145 printf("Referencing class.\n");
146#endif
147 item = rdata_item_new(ic_value);
148 val = rdata_value_new();
149 var = rdata_var_new(vc_deleg);
150 deleg_v = rdata_deleg_new();
151
152 item->u.value = val;
153 val->var = var;
154 var->u.deleg_v = deleg_v;
155
156 deleg_v->obj = NULL;
157 deleg_v->sym = sym;
158 *res = item;
159 break;
160 default:
161 printf("Referencing symbol class %d unimplemented.\n", sym->sc);
162 *res = NULL;
163 break;
164 }
165}
166
167/** Evaluate literal. */
168static void run_literal(run_t *run, stree_literal_t *literal,
169 rdata_item_t **res)
170{
171#ifdef DEBUG_RUN_TRACE
172 printf("Run literal.\n");
173#endif
174
175 switch (literal->ltc) {
176 case ltc_int:
177 run_lit_int(run, &literal->u.lit_int, res);
178 break;
179 case ltc_string:
180 run_lit_string(run, &literal->u.lit_string, res);
181 break;
182 default:
183 assert(b_false);
184 }
185}
186
187/** Evaluate integer literal. */
188static void run_lit_int(run_t *run, stree_lit_int_t *lit_int,
189 rdata_item_t **res)
190{
191 rdata_item_t *item;
192 rdata_value_t *value;
193 rdata_var_t *var;
194 rdata_int_t *int_v;
195
196#ifdef DEBUG_RUN_TRACE
197 printf("Run integer literal.\n");
198#endif
199
200 item = rdata_item_new(ic_value);
201 value = rdata_value_new();
202 var = rdata_var_new(vc_int);
203 int_v = rdata_int_new();
204
205 item->u.value = value;
206 value->var = var;
207 var->u.int_v = int_v;
208 int_v->value = lit_int->value;
209
210 *res = item;
211}
212
213/** Evaluate string literal. */
214static void run_lit_string(run_t *run, stree_lit_string_t *lit_string,
215 rdata_item_t **res)
216{
217 rdata_item_t *item;
218 rdata_value_t *value;
219 rdata_var_t *var;
220 rdata_string_t *string_v;
221
222#ifdef DEBUG_RUN_TRACE
223 printf("Run integer literal.\n");
224#endif
225 item = rdata_item_new(ic_value);
226 value = rdata_value_new();
227 var = rdata_var_new(vc_string);
228 string_v = rdata_string_new();
229
230 item->u.value = value;
231 value->var = var;
232 var->u.string_v = string_v;
233 string_v->value = lit_string->value;
234
235 *res = item;
236}
237
238
239/** Evaluate binary operation. */
240static void run_binop(run_t *run, stree_binop_t *binop, rdata_item_t **res)
241{
242 rdata_item_t *rarg1_i, *rarg2_i;
243 rdata_item_t *rarg1_vi, *rarg2_vi;
244 rdata_value_t *v1, *v2;
245 int i1, i2;
246
247 rdata_item_t *item;
248 rdata_value_t *value;
249 rdata_var_t *var;
250 rdata_int_t *int_v;
251
252#ifdef DEBUG_RUN_TRACE
253 printf("Run binary operation.\n");
254#endif
255 run_expr(run, binop->arg1, &rarg1_i);
256 run_expr(run, binop->arg2, &rarg2_i);
257
258 switch (binop->bc) {
259 case bo_plus:
260 case bo_equal:
261 case bo_notequal:
262 case bo_lt:
263 case bo_gt:
264 case bo_lt_equal:
265 case bo_gt_equal:
266 /* These are implemented so far. */
267 break;
268 default:
269 printf("Unimplemented: Binary operation type %d.\n",
270 binop->bc);
271 exit(1);
272 }
273
274#ifdef DEBUG_RUN_TRACE
275 printf("Check binop argument results.\n");
276#endif
277
278 run_cvt_value_item(run, rarg1_i, &rarg1_vi);
279 run_cvt_value_item(run, rarg2_i, &rarg2_vi);
280
281 v1 = rarg1_vi->u.value;
282 v2 = rarg2_vi->u.value;
283
284 if (v1->var->vc != vc_int || v2->var->vc != vc_int) {
285 printf("Unimplemented: Binary operation arguments are not "
286 "integer values.\n");
287 exit(1);
288 }
289
290 item = rdata_item_new(ic_value);
291 value = rdata_value_new();
292 var = rdata_var_new(vc_int);
293 int_v = rdata_int_new();
294
295 item->u.value = value;
296 value->var = var;
297 var->u.int_v = int_v;
298
299 i1 = v1->var->u.int_v->value;
300 i2 = v2->var->u.int_v->value;
301
302 switch (binop->bc) {
303 case bo_plus:
304 int_v->value = i1 + i2;
305 break;
306
307 /* XXX We should have a real boolean type. */
308 case bo_equal:
309 int_v->value = (i1 == i2) ? 1 : 0;
310 break;
311 case bo_notequal:
312 int_v->value = (i1 != i2) ? 1 : 0;
313 break;
314 case bo_lt:
315 int_v->value = (i1 < i2) ? 1 : 0;
316 break;
317 case bo_gt:
318 int_v->value = (i1 > i2) ? 1 : 0;
319 break;
320 case bo_lt_equal:
321 int_v->value = (i1 <= i2) ? 1 : 0;
322 break;
323 case bo_gt_equal:
324 int_v->value = (i1 >= i2) ? 1 : 0;
325 break;
326 default:
327 assert(b_false);
328 }
329
330 *res = item;
331}
332
333/** Evaluate unary operation. */
334static void run_unop(run_t *run, stree_unop_t *unop, rdata_item_t **res)
335{
336 rdata_item_t *rarg;
337
338#ifdef DEBUG_RUN_TRACE
339 printf("Run unary operation.\n");
340#endif
341 run_expr(run, unop->arg, &rarg);
342 *res = NULL;
343}
344
345/** Evaluate member acccess. */
346static void run_access(run_t *run, stree_access_t *access, rdata_item_t **res)
347{
348 rdata_item_t *rarg;
349 rdata_deleg_t *deleg_v;
350 stree_symbol_t *member;
351
352#ifdef DEBUG_RUN_TRACE
353 printf("Run access operation.\n");
354#endif
355 run_expr(run, access->arg, &rarg);
356
357 if (rarg->ic == ic_value && rarg->u.value->var->vc == vc_deleg) {
358#ifdef DEBUG_RUN_TRACE
359 printf("Accessing delegate.\n");
360#endif
361 deleg_v = rarg->u.value->var->u.deleg_v;
362 if (deleg_v->obj != NULL || deleg_v->sym->sc != sc_csi) {
363 printf("Error: Using '.' with symbol of wrong "
364 "type (%d).\n", deleg_v->sym->sc);
365 exit(1);
366 }
367
368 member = symbol_search_csi(run->program, deleg_v->sym->u.csi,
369 access->member_name);
370
371 if (member == NULL) {
372 printf("Error: No such member.\n");
373 exit(1);
374 }
375
376#ifdef DEBUG_RUN_TRACE
377 printf("Found member '%s'.\n",
378 strtab_get_str(access->member_name->sid));
379#endif
380
381 /* Reuse existing item, value, var, deleg. */
382 deleg_v->sym = member;
383
384 *res = rarg;
385 return;
386 }
387
388 *res = NULL;
389}
390
391/** Call a function. */
392static void run_call(run_t *run, stree_call_t *call, rdata_item_t **res)
393{
394 rdata_item_t *rfun;
395 rdata_deleg_t *deleg_v;
396 list_t arg_vals;
397 list_node_t *node;
398 stree_expr_t *arg;
399 rdata_item_t *rarg_i, *rarg_vi;
400
401#ifdef DEBUG_RUN_TRACE
402 printf("Run call operation.\n");
403#endif
404 run_expr(run, call->fun, &rfun);
405
406 if (rfun->ic != ic_value || rfun->u.value->var->vc != vc_deleg) {
407 printf("Unimplemented: Call expression of this type.\n");
408 *res = NULL;
409 return;
410 }
411
412 deleg_v = rfun->u.value->var->u.deleg_v;
413
414 if (deleg_v->sym->sc != sc_fun) {
415 printf("Error: Called symbol is not a function.\n");
416 exit(1);
417 }
418
419#ifdef DEBUG_RUN_TRACE
420 printf("Call function '");
421 symbol_print_fqn(run->program, deleg_v->sym);
422 printf("'\n");
423#endif
424
425 /* Evaluate function arguments. */
426 list_init(&arg_vals);
427 node = list_first(&call->args);
428
429 while (node != NULL) {
430 arg = list_node_data(node, stree_expr_t *);
431 run_expr(run, arg, &rarg_i);
432 run_cvt_value_item(run, rarg_i, &rarg_vi);
433
434 list_append(&arg_vals, rarg_vi);
435 node = list_next(&call->args, node);
436 }
437
438 run_fun(run, deleg_v->sym->u.fun, &arg_vals);
439
440#ifdef DEBUG_RUN_TRACE
441 printf("Returned from function call.\n");
442#endif
443 *res = NULL;
444}
445
446/** Execute assignment. */
447static void run_assign(run_t *run, stree_assign_t *assign, rdata_item_t **res)
448{
449 rdata_item_t *rdest_i, *rsrc_i;
450 rdata_item_t *rsrc_vi;
451 rdata_value_t *src_val;
452
453#ifdef DEBUG_RUN_TRACE
454 printf("Run assign operation.\n");
455#endif
456 run_expr(run, assign->dest, &rdest_i);
457 run_expr(run, assign->src, &rsrc_i);
458
459 run_cvt_value_item(run, rsrc_i, &rsrc_vi);
460 src_val = rsrc_vi->u.value;
461
462 if (rdest_i->ic != ic_address) {
463 printf("Error: Address expression required on left side of "
464 "assignment operator.\n");
465 exit(1);
466 }
467
468 run_address_write(run, rdest_i->u.address, rsrc_vi->u.value);
469
470 *res = NULL;
471}
472
473/** Return boolean value of an item.
474 *
475 * Tries to interpret @a item as a boolean value. If it is not a boolean
476 * value, this generates an error.
477 *
478 * XXX Currently int supplants the role of a true boolean type.
479 */
480bool_t run_item_boolean_value(run_t *run, rdata_item_t *item)
481{
482 rdata_item_t *vitem;
483 rdata_var_t *var;
484
485 run_cvt_value_item(run, item, &vitem);
486
487 assert(vitem->ic == ic_value);
488 var = vitem->u.value->var;
489
490 if (var->vc != vc_int) {
491 printf("Error: Boolean (int) expression expected.\n");
492 exit(1);
493 }
494
495 return (var->u.int_v->value != 0);
496}
497
498/** Convert item to value item.
499 *
500 * If @a item is a value, we just return a copy. If @a item is an address,
501 * we read from the address.
502 */
503void run_cvt_value_item(run_t *run, rdata_item_t *item,
504 rdata_item_t **ritem)
505{
506 rdata_value_t *value;
507
508 /* Address item. Perform read operation. */
509 if (item->ic == ic_address) {
510 run_address_read(run, item->u.address, ritem);
511 return;
512 }
513
514 /* It already is a value, we can share the @c var. */
515 value = rdata_value_new();
516 value->var = item->u.value->var;
517 *ritem = rdata_item_new(ic_value);
518 (*ritem)->u.value = value;
519}
520
521/** Read data from an address.
522 *
523 * Return value stored in a variable at the specified address.
524 */
525static void run_address_read(run_t *run, rdata_address_t *address,
526 rdata_item_t **ritem)
527{
528 rdata_value_t *value;
529 rdata_var_t *rvar;
530 (void) run;
531
532 /* Perform a shallow copy of @c var. */
533 rdata_var_copy(address->vref, &rvar);
534
535 value = rdata_value_new();
536 value->var = rvar;
537 *ritem = rdata_item_new(ic_value);
538 (*ritem)->u.value = value;
539}
540
541/** Write data to an address.
542 *
543 * Store @a value to the variable at @a address.
544 */
545static void run_address_write(run_t *run, rdata_address_t *address,
546 rdata_value_t *value)
547{
548 rdata_var_t *nvar;
549 rdata_var_t *orig_var;
550
551 /* Perform a shallow copy of @c value->var. */
552 rdata_var_copy(value->var, &nvar);
553 orig_var = address->vref;
554
555 /* XXX do this in a prettier way. */
556
557 orig_var->vc = nvar->vc;
558 switch (nvar->vc) {
559 case vc_int: orig_var->u.int_v = nvar->u.int_v; break;
560 case vc_ref: orig_var->u.ref_v = nvar->u.ref_v; break;
561 case vc_deleg: orig_var->u.deleg_v = nvar->u.deleg_v; break;
562 case vc_object: orig_var->u.object_v = nvar->u.object_v; break;
563 default: assert(b_false);
564 }
565
566 /* XXX We should free some stuff around here. */
567}
Note: See TracBrowser for help on using the repository browser.