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

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

Update SBI to rev. 75.

  • Property mode set to 100644
File size: 21.6 KB
RevLine 
[09ababb7]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"
[fa36f29]35#include "intmap.h"
[09ababb7]36#include "list.h"
37#include "mytypes.h"
38#include "rdata.h"
39#include "run.h"
40#include "symbol.h"
41#include "strtab.h"
42
43#include "run_expr.h"
44
45static void run_nameref(run_t *run, stree_nameref_t *nameref,
46 rdata_item_t **res);
[fa36f29]47
[09ababb7]48static void run_literal(run_t *run, stree_literal_t *literal,
49 rdata_item_t **res);
50static void run_lit_int(run_t *run, stree_lit_int_t *lit_int,
51 rdata_item_t **res);
[fa36f29]52static void run_lit_ref(run_t *run, stree_lit_ref_t *lit_ref,
53 rdata_item_t **res);
[09ababb7]54static void run_lit_string(run_t *run, stree_lit_string_t *lit_string,
55 rdata_item_t **res);
[fa36f29]56
57static void run_self_ref(run_t *run, stree_self_ref_t *self_ref,
58 rdata_item_t **res);
59
[09ababb7]60static void run_binop(run_t *run, stree_binop_t *binop, rdata_item_t **res);
[fa36f29]61static void run_binop_int(run_t *run, stree_binop_t *binop, rdata_value_t *v1,
62 rdata_value_t *v2, rdata_item_t **res);
63static void run_binop_ref(run_t *run, stree_binop_t *binop, rdata_value_t *v1,
64 rdata_value_t *v2, rdata_item_t **res);
65
[09ababb7]66static void run_unop(run_t *run, stree_unop_t *unop, rdata_item_t **res);
[fa36f29]67static void run_new(run_t *run, stree_new_t *new_op, rdata_item_t **res);
68
[09ababb7]69static void run_access(run_t *run, stree_access_t *access, rdata_item_t **res);
[fa36f29]70static void run_access_item(run_t *run, stree_access_t *access,
71 rdata_item_t *arg, rdata_item_t **res);
72static void run_access_ref(run_t *run, stree_access_t *access,
73 rdata_item_t *arg, rdata_item_t **res);
74static void run_access_deleg(run_t *run, stree_access_t *access,
75 rdata_item_t *arg, rdata_item_t **res);
76static void run_access_object(run_t *run, stree_access_t *access,
77 rdata_item_t *arg, rdata_item_t **res);
78
[09ababb7]79static void run_call(run_t *run, stree_call_t *call, rdata_item_t **res);
80static void run_assign(run_t *run, stree_assign_t *assign, rdata_item_t **res);
81
82/** Evaluate expression. */
83void run_expr(run_t *run, stree_expr_t *expr, rdata_item_t **res)
84{
85#ifdef DEBUG_RUN_TRACE
86 printf("Executing expression.\n");
87#endif
88
89 switch (expr->ec) {
90 case ec_nameref:
91 run_nameref(run, expr->u.nameref, res);
92 break;
93 case ec_literal:
94 run_literal(run, expr->u.literal, res);
95 break;
[fa36f29]96 case ec_self_ref:
97 run_self_ref(run, expr->u.self_ref, res);
98 break;
[09ababb7]99 case ec_binop:
100 run_binop(run, expr->u.binop, res);
101 break;
102 case ec_unop:
103 run_unop(run, expr->u.unop, res);
104 break;
[fa36f29]105 case ec_new:
106 run_new(run, expr->u.new_op, res);
107 break;
[09ababb7]108 case ec_access:
109 run_access(run, expr->u.access, res);
110 break;
111 case ec_call:
112 run_call(run, expr->u.call, res);
113 break;
114 case ec_assign:
115 run_assign(run, expr->u.assign, res);
116 break;
117 }
118
119#ifdef DEBUG_RUN_TRACE
120 printf("Expression result: ");
121 rdata_item_print(*res);
122 printf(".\n");
123#endif
124}
125
126/** Evaluate name reference expression. */
127static void run_nameref(run_t *run, stree_nameref_t *nameref,
128 rdata_item_t **res)
129{
130 stree_symbol_t *sym;
131 rdata_item_t *item;
132 rdata_address_t *address;
[fa36f29]133 rdata_value_t *value;
[09ababb7]134 rdata_var_t *var;
135 rdata_deleg_t *deleg_v;
136
[fa36f29]137 run_fun_ar_t *fun_ar;
138 stree_symbol_t *csi_sym;
139 stree_csi_t *csi;
140 rdata_object_t *obj;
141 rdata_var_t *member_var;
142
[09ababb7]143#ifdef DEBUG_RUN_TRACE
144 printf("Run nameref.\n");
145#endif
146
147 /*
148 * Look for a local variable.
149 */
150 var = run_local_vars_lookup(run, nameref->name->sid);
151 if (var != NULL) {
152 /* Found a local variable. */
153 item = rdata_item_new(ic_address);
154 address = rdata_address_new();
155
156 item->u.address = address;
157 address->vref = var;
158
159 *res = item;
160#ifdef DEBUG_RUN_TRACE
161 printf("Found local variable.\n");
162#endif
163 return;
164 }
165
166 /*
167 * Look for a class-wide or global symbol.
168 */
169
[fa36f29]170 /* Determine currently active object or CSI. */
171 fun_ar = run_get_current_fun_ar(run);
172 if (fun_ar->obj != NULL) {
173 assert(fun_ar->obj->vc == vc_object);
174 obj = fun_ar->obj->u.object_v;
175 csi_sym = obj->class_sym;
176 csi = symbol_to_csi(csi_sym);
177 assert(csi != NULL);
178 } else {
179 csi = fun_ar->fun_sym->outer_csi;
180 obj = NULL;
181 }
182
183 sym = symbol_lookup_in_csi(run->program, csi, nameref->name);
[09ababb7]184
185 switch (sym->sc) {
186 case sc_csi:
187#ifdef DEBUG_RUN_TRACE
188 printf("Referencing class.\n");
189#endif
190 item = rdata_item_new(ic_value);
[fa36f29]191 value = rdata_value_new();
[09ababb7]192 var = rdata_var_new(vc_deleg);
193 deleg_v = rdata_deleg_new();
194
[fa36f29]195 item->u.value = value;
196 value->var = var;
[09ababb7]197 var->u.deleg_v = deleg_v;
198
199 deleg_v->obj = NULL;
200 deleg_v->sym = sym;
[fa36f29]201 *res = item;
202 break;
203 case sc_fun:
204 /* There should be no global functions. */
205 assert(csi != NULL);
206
207 if (sym->outer_csi != csi) {
208 /* Function is not in the current object. */
209 printf("Error: Cannot access non-static member "
210 "function '");
211 symbol_print_fqn(run->program, sym);
212 printf("' from nested CSI '");
213 symbol_print_fqn(run->program, csi_sym);
214 printf("'.\n");
215 exit(1);
216 }
217
218 /* Construct delegate. */
219 item = rdata_item_new(ic_value);
220 value = rdata_value_new();
221 item->u.value = value;
222
223 var = rdata_var_new(vc_deleg);
224 deleg_v = rdata_deleg_new();
225 value->var = var;
226 var->u.deleg_v = deleg_v;
227
228 deleg_v->obj = fun_ar->obj;
229 deleg_v->sym = sym;
230
231 *res = item;
232 break;
233 case sc_var:
234#ifdef DEBUG_RUN_TRACE
235 printf("Referencing member variable.\n");
236#endif
237 /* There should be no global variables. */
238 assert(csi != NULL);
239
240 /* XXX Assume variable is not static for now. */
241 assert(obj != NULL);
242
243 if (sym->outer_csi != csi) {
244 /* Variable is not in the current object. */
245 printf("Error: Cannot access non-static member "
246 "variable '");
247 symbol_print_fqn(run->program, sym);
248 printf("' from nested CSI '");
249 symbol_print_fqn(run->program, csi_sym);
250 printf("'.\n");
251 exit(1);
252 }
253
254 /* Find member variable in object. */
255 member_var = intmap_get(&obj->fields, nameref->name->sid);
256 assert(member_var != NULL);
257
258 /* Return address of the variable. */
259 item = rdata_item_new(ic_address);
260 address = rdata_address_new();
261
262 item->u.address = address;
263 address->vref = member_var;
264
[09ababb7]265 *res = item;
266 break;
267 default:
268 printf("Referencing symbol class %d unimplemented.\n", sym->sc);
269 *res = NULL;
270 break;
271 }
272}
273
274/** Evaluate literal. */
275static void run_literal(run_t *run, stree_literal_t *literal,
276 rdata_item_t **res)
277{
278#ifdef DEBUG_RUN_TRACE
279 printf("Run literal.\n");
280#endif
281
282 switch (literal->ltc) {
283 case ltc_int:
284 run_lit_int(run, &literal->u.lit_int, res);
285 break;
[fa36f29]286 case ltc_ref:
287 run_lit_ref(run, &literal->u.lit_ref, res);
288 break;
[09ababb7]289 case ltc_string:
290 run_lit_string(run, &literal->u.lit_string, res);
291 break;
292 default:
293 assert(b_false);
294 }
295}
296
297/** Evaluate integer literal. */
298static void run_lit_int(run_t *run, stree_lit_int_t *lit_int,
299 rdata_item_t **res)
300{
301 rdata_item_t *item;
302 rdata_value_t *value;
303 rdata_var_t *var;
304 rdata_int_t *int_v;
305
306#ifdef DEBUG_RUN_TRACE
307 printf("Run integer literal.\n");
308#endif
[fa36f29]309 (void) run;
[09ababb7]310
311 item = rdata_item_new(ic_value);
312 value = rdata_value_new();
313 var = rdata_var_new(vc_int);
314 int_v = rdata_int_new();
315
316 item->u.value = value;
317 value->var = var;
318 var->u.int_v = int_v;
319 int_v->value = lit_int->value;
320
321 *res = item;
322}
323
[fa36f29]324/** Evaluate reference literal (@c nil). */
325static void run_lit_ref(run_t *run, stree_lit_ref_t *lit_ref,
326 rdata_item_t **res)
327{
328 rdata_item_t *item;
329 rdata_value_t *value;
330 rdata_var_t *var;
331 rdata_ref_t *ref_v;
332
333#ifdef DEBUG_RUN_TRACE
334 printf("Run reference literal (nil).\n");
335#endif
336 (void) run;
337 (void) lit_ref;
338
339 item = rdata_item_new(ic_value);
340 value = rdata_value_new();
341 var = rdata_var_new(vc_ref);
342 ref_v = rdata_ref_new();
343
344 item->u.value = value;
345 value->var = var;
346 var->u.ref_v = ref_v;
347 ref_v->vref = NULL;
348
349 *res = item;
350}
351
[09ababb7]352/** Evaluate string literal. */
353static void run_lit_string(run_t *run, stree_lit_string_t *lit_string,
354 rdata_item_t **res)
355{
356 rdata_item_t *item;
357 rdata_value_t *value;
358 rdata_var_t *var;
359 rdata_string_t *string_v;
360
361#ifdef DEBUG_RUN_TRACE
362 printf("Run integer literal.\n");
363#endif
[fa36f29]364 (void) run;
365
[09ababb7]366 item = rdata_item_new(ic_value);
367 value = rdata_value_new();
368 var = rdata_var_new(vc_string);
369 string_v = rdata_string_new();
370
371 item->u.value = value;
372 value->var = var;
373 var->u.string_v = string_v;
374 string_v->value = lit_string->value;
375
376 *res = item;
377}
378
[fa36f29]379/** Evaluate @c self reference. */
380static void run_self_ref(run_t *run, stree_self_ref_t *self_ref,
381 rdata_item_t **res)
382{
383 run_fun_ar_t *fun_ar;
384
385#ifdef DEBUG_RUN_TRACE
386 printf("Run self reference.\n");
387#endif
388 (void) self_ref;
389 fun_ar = run_get_current_fun_ar(run);
390
391 /* Return reference to the currently active object. */
392 rdata_reference(fun_ar->obj, res);
393}
[09ababb7]394
395/** Evaluate binary operation. */
396static void run_binop(run_t *run, stree_binop_t *binop, rdata_item_t **res)
397{
398 rdata_item_t *rarg1_i, *rarg2_i;
399 rdata_item_t *rarg1_vi, *rarg2_vi;
400 rdata_value_t *v1, *v2;
401
402#ifdef DEBUG_RUN_TRACE
403 printf("Run binary operation.\n");
404#endif
405 run_expr(run, binop->arg1, &rarg1_i);
406 run_expr(run, binop->arg2, &rarg2_i);
407
408 switch (binop->bc) {
409 case bo_plus:
410 case bo_equal:
411 case bo_notequal:
412 case bo_lt:
413 case bo_gt:
414 case bo_lt_equal:
415 case bo_gt_equal:
416 /* These are implemented so far. */
417 break;
418 default:
419 printf("Unimplemented: Binary operation type %d.\n",
420 binop->bc);
421 exit(1);
422 }
423
424#ifdef DEBUG_RUN_TRACE
425 printf("Check binop argument results.\n");
426#endif
427
[fa36f29]428 rdata_cvt_value_item(rarg1_i, &rarg1_vi);
429 rdata_cvt_value_item(rarg2_i, &rarg2_vi);
[09ababb7]430
431 v1 = rarg1_vi->u.value;
432 v2 = rarg2_vi->u.value;
433
[fa36f29]434 if (v1->var->vc != v2->var->vc) {
435 printf("Unimplemented: Binary operation arguments have "
436 "different type.\n");
[09ababb7]437 exit(1);
438 }
439
[fa36f29]440 switch (v1->var->vc) {
441 case vc_int:
442 run_binop_int(run, binop, v1, v2, res);
443 break;
444 case vc_ref:
445 run_binop_ref(run, binop, v1, v2, res);
446 break;
447 default:
448 printf("Unimplemented: Binary operation arguments of "
449 "type %d.\n", v1->var->vc);
450 exit(1);
451 }
452}
453
454/** Evaluate binary operation on int arguments. */
455static void run_binop_int(run_t *run, stree_binop_t *binop, rdata_value_t *v1,
456 rdata_value_t *v2, rdata_item_t **res)
457{
458 rdata_item_t *item;
459 rdata_value_t *value;
460 rdata_var_t *var;
461 rdata_int_t *int_v;
462
463 int i1, i2;
464
465 (void) run;
466
[09ababb7]467 item = rdata_item_new(ic_value);
468 value = rdata_value_new();
469 var = rdata_var_new(vc_int);
470 int_v = rdata_int_new();
471
472 item->u.value = value;
473 value->var = var;
474 var->u.int_v = int_v;
475
476 i1 = v1->var->u.int_v->value;
477 i2 = v2->var->u.int_v->value;
478
479 switch (binop->bc) {
480 case bo_plus:
481 int_v->value = i1 + i2;
482 break;
483
484 /* XXX We should have a real boolean type. */
485 case bo_equal:
486 int_v->value = (i1 == i2) ? 1 : 0;
487 break;
488 case bo_notequal:
489 int_v->value = (i1 != i2) ? 1 : 0;
490 break;
491 case bo_lt:
492 int_v->value = (i1 < i2) ? 1 : 0;
493 break;
494 case bo_gt:
495 int_v->value = (i1 > i2) ? 1 : 0;
496 break;
497 case bo_lt_equal:
498 int_v->value = (i1 <= i2) ? 1 : 0;
499 break;
500 case bo_gt_equal:
501 int_v->value = (i1 >= i2) ? 1 : 0;
502 break;
503 default:
504 assert(b_false);
505 }
506
507 *res = item;
508}
509
[fa36f29]510/** Evaluate binary operation on ref arguments. */
511static void run_binop_ref(run_t *run, stree_binop_t *binop, rdata_value_t *v1,
512 rdata_value_t *v2, rdata_item_t **res)
513{
514 rdata_item_t *item;
515 rdata_value_t *value;
516 rdata_var_t *var;
517 rdata_int_t *int_v;
518
519 rdata_var_t *ref1, *ref2;
520
521 (void) run;
522
523 item = rdata_item_new(ic_value);
524 value = rdata_value_new();
525 var = rdata_var_new(vc_int);
526 int_v = rdata_int_new();
527
528 item->u.value = value;
529 value->var = var;
530 var->u.int_v = int_v;
531
532 ref1 = v1->var->u.ref_v->vref;
533 ref2 = v2->var->u.ref_v->vref;
534
535 switch (binop->bc) {
536 /* XXX We should have a real boolean type. */
537 case bo_equal:
538 int_v->value = (ref1 == ref2) ? 1 : 0;
539 break;
540 case bo_notequal:
541 int_v->value = (ref1 != ref2) ? 1 : 0;
542 break;
543 default:
544 printf("Error: Invalid binary operation on reference "
545 "arguments (%d).\n", binop->bc);
546 assert(b_false);
547 }
548
549 *res = item;
550}
551
552
[09ababb7]553/** Evaluate unary operation. */
554static void run_unop(run_t *run, stree_unop_t *unop, rdata_item_t **res)
555{
556 rdata_item_t *rarg;
557
558#ifdef DEBUG_RUN_TRACE
559 printf("Run unary operation.\n");
560#endif
561 run_expr(run, unop->arg, &rarg);
562 *res = NULL;
563}
564
[fa36f29]565/** Evaluate @c new operation. */
566static void run_new(run_t *run, stree_new_t *new_op, rdata_item_t **res)
567{
568 rdata_object_t *obj;
569 rdata_var_t *obj_var;
570
571 stree_symbol_t *csi_sym;
572 stree_csi_t *csi;
573 stree_csimbr_t *csimbr;
574
575 rdata_var_t *mbr_var;
576
577 list_node_t *node;
578
579#ifdef DEBUG_RUN_TRACE
580 printf("Run 'new' operation.\n");
581#endif
582 /* Lookup object CSI. */
583 /* XXX Should start in the current CSI. */
584 csi_sym = symbol_xlookup_in_csi(run->program, NULL, new_op->texpr);
585 csi = symbol_to_csi(csi_sym);
586 if (csi == NULL) {
587 printf("Error: Symbol '");
588 symbol_print_fqn(run->program, csi_sym);
589 printf("' is not a CSI. CSI required for 'new' operator.\n");
590 exit(1);
591 }
592
593 /* Create the object. */
594 obj = rdata_object_new();
595 obj->class_sym = csi_sym;
596 intmap_init(&obj->fields);
597
598 obj_var = rdata_var_new(vc_object);
599 obj_var->u.object_v = obj;
600
601 /* Create object fields. */
602 node = list_first(&csi->members);
603 while (node != NULL) {
604 csimbr = list_node_data(node, stree_csimbr_t *);
605 if (csimbr->cc == csimbr_var) {
606 /* XXX Depends on member variable type. */
607 mbr_var = rdata_var_new(vc_int);
608 mbr_var->u.int_v = rdata_int_new();
609 mbr_var->u.int_v->value = 0;
610
611 intmap_set(&obj->fields, csimbr->u.var->name->sid,
612 mbr_var);
613 }
614
615 node = list_next(&csi->members, node);
616 }
617
618 /* Create reference to the new object. */
619 rdata_reference(obj_var, res);
620}
621
[09ababb7]622/** Evaluate member acccess. */
623static void run_access(run_t *run, stree_access_t *access, rdata_item_t **res)
624{
625 rdata_item_t *rarg;
626
627#ifdef DEBUG_RUN_TRACE
628 printf("Run access operation.\n");
629#endif
630 run_expr(run, access->arg, &rarg);
[fa36f29]631 if (rarg == NULL) {
632 printf("Error: Sub-expression has no value.\n");
633 exit(1);
634 }
635
636 run_access_item(run, access, rarg, res);
637}
638
639/** Evaluate member acccess (with base already evaluated). */
640static void run_access_item(run_t *run, stree_access_t *access,
641 rdata_item_t *arg, rdata_item_t **res)
642{
643 var_class_t vc;
[09ababb7]644
645#ifdef DEBUG_RUN_TRACE
[fa36f29]646 printf("Run access operation on pre-evaluated base.\n");
[09ababb7]647#endif
[fa36f29]648 switch (arg->ic) {
649 case ic_value:
650 vc = arg->u.value->var->vc;
651 break;
652 case ic_address:
653 vc = arg->u.address->vref->vc;
654 break;
655 default:
656 /* Silence warning. */
657 abort();
658 }
[09ababb7]659
[fa36f29]660 switch (vc) {
661 case vc_ref:
662 run_access_ref(run, access, arg, res);
663 break;
664 case vc_deleg:
665 run_access_deleg(run, access, arg, res);
666 break;
667 case vc_object:
668 run_access_object(run, access, arg, res);
669 break;
670 default:
671 printf("Unimplemented: Using access operator ('.') "
672 "with unsupported data type (value/%d).\n", vc);
673 exit(1);
674 }
675}
[09ababb7]676
[fa36f29]677/** Evaluate reference acccess. */
678static void run_access_ref(run_t *run, stree_access_t *access,
679 rdata_item_t *arg, rdata_item_t **res)
680{
681 rdata_item_t *darg;
682
683 /* Implicitly dereference. */
684 rdata_dereference(arg, &darg);
685
686 /* Try again. */
687 run_access_item(run, access, darg, res);
688}
689
690/** Evaluate delegate-member acccess. */
691static void run_access_deleg(run_t *run, stree_access_t *access,
692 rdata_item_t *arg, rdata_item_t **res)
693{
694 rdata_item_t *arg_vi;
695 rdata_value_t *arg_val;
696 rdata_deleg_t *deleg_v;
697 stree_symbol_t *member;
[09ababb7]698
699#ifdef DEBUG_RUN_TRACE
[fa36f29]700 printf("Run delegate access operation.\n");
701#endif
702 rdata_cvt_value_item(arg, &arg_vi);
703 arg_val = arg_vi->u.value;
704 assert(arg_val->var->vc == vc_deleg);
705
706 deleg_v = arg_val->var->u.deleg_v;
707 if (deleg_v->obj != NULL || deleg_v->sym->sc != sc_csi) {
708 printf("Error: Using '.' with delegate to different object "
709 "than a CSI (%d).\n", deleg_v->sym->sc);
710 exit(1);
711 }
712
713 member = symbol_search_csi(run->program, deleg_v->sym->u.csi,
714 access->member_name);
715
716 if (member == NULL) {
717 printf("Error: CSI '");
718 symbol_print_fqn(run->program, deleg_v->sym);
719 printf("' has no member named '%s'.\n",
[09ababb7]720 strtab_get_str(access->member_name->sid));
[fa36f29]721 exit(1);
722 }
723
724#ifdef DEBUG_RUN_TRACE
725 printf("Found member '%s'.\n",
726 strtab_get_str(access->member_name->sid));
[09ababb7]727#endif
728
[fa36f29]729 /*
730 * Reuse existing item, value, var, deleg.
731 * XXX This is maybe not a good idea because it complicates memory
732 * management as there is not a single owner
733 */
734 deleg_v->sym = member;
735 *res = arg;
736}
737
738/** Evaluate object member acccess. */
739static void run_access_object(run_t *run, stree_access_t *access,
740 rdata_item_t *arg, rdata_item_t **res)
741{
742 stree_symbol_t *member;
743 rdata_object_t *object;
744 rdata_item_t *ritem;
745 rdata_address_t *address;
746
747 rdata_value_t *value;
748 rdata_deleg_t *deleg_v;
749 rdata_var_t *var;
750
751#ifdef DEBUG_RUN_TRACE
752 printf("Run object access operation.\n");
753#endif
754 assert(arg->ic == ic_address);
755 assert(arg->u.value->var->vc == vc_object);
756
757 object = arg->u.value->var->u.object_v;
758
759 member = symbol_search_csi(run->program, object->class_sym->u.csi,
760 access->member_name);
761
762 if (member == NULL) {
763 printf("Error: Object of class '");
764 symbol_print_fqn(run->program, object->class_sym);
765 printf("' has no member named '%s'.\n",
766 strtab_get_str(access->member_name->sid));
767 exit(1);
768 }
769
770#ifdef DEBUG_RUN_TRACE
771 printf("Found member '%s'.\n",
772 strtab_get_str(access->member_name->sid));
773#endif
774
775 switch (member->sc) {
776 case sc_csi:
777 printf("Error: Accessing object member which is nested CSI.\n");
778 exit(1);
779 case sc_fun:
780 /* Construct delegate. */
781 ritem = rdata_item_new(ic_value);
782 value = rdata_value_new();
783 ritem->u.value = value;
784
785 var = rdata_var_new(vc_deleg);
786 value->var = var;
787 deleg_v = rdata_deleg_new();
788 var->u.deleg_v = deleg_v;
789
790 deleg_v->obj = arg->u.value->var;
[09ababb7]791 deleg_v->sym = member;
[fa36f29]792 break;
793 case sc_var:
794 /* Construct variable address item. */
795 ritem = rdata_item_new(ic_address);
796 address = rdata_address_new();
797 ritem->u.address = address;
[09ababb7]798
[fa36f29]799 address->vref = intmap_get(&object->fields,
800 access->member_name->sid);
801 assert(address->vref != NULL);
802 break;
803 case sc_prop:
804 printf("Unimplemented: Accessing object property.\n");
805 exit(1);
[09ababb7]806 }
807
[fa36f29]808 *res = ritem;
[09ababb7]809}
810
811/** Call a function. */
812static void run_call(run_t *run, stree_call_t *call, rdata_item_t **res)
813{
814 rdata_item_t *rfun;
815 rdata_deleg_t *deleg_v;
816 list_t arg_vals;
817 list_node_t *node;
818 stree_expr_t *arg;
819 rdata_item_t *rarg_i, *rarg_vi;
820
[fa36f29]821 stree_fun_t *fun;
822 run_fun_ar_t *fun_ar;
823
[09ababb7]824#ifdef DEBUG_RUN_TRACE
825 printf("Run call operation.\n");
826#endif
827 run_expr(run, call->fun, &rfun);
828
829 if (rfun->ic != ic_value || rfun->u.value->var->vc != vc_deleg) {
830 printf("Unimplemented: Call expression of this type.\n");
831 *res = NULL;
832 return;
833 }
834
835 deleg_v = rfun->u.value->var->u.deleg_v;
836
837 if (deleg_v->sym->sc != sc_fun) {
838 printf("Error: Called symbol is not a function.\n");
839 exit(1);
840 }
841
842#ifdef DEBUG_RUN_TRACE
843 printf("Call function '");
844 symbol_print_fqn(run->program, deleg_v->sym);
845 printf("'\n");
846#endif
847 /* Evaluate function arguments. */
848 list_init(&arg_vals);
849 node = list_first(&call->args);
850
851 while (node != NULL) {
852 arg = list_node_data(node, stree_expr_t *);
853 run_expr(run, arg, &rarg_i);
[fa36f29]854 rdata_cvt_value_item(rarg_i, &rarg_vi);
[09ababb7]855
856 list_append(&arg_vals, rarg_vi);
857 node = list_next(&call->args, node);
858 }
859
[fa36f29]860 fun = symbol_to_fun(deleg_v->sym);
861 assert(fun != NULL);
862
863 /* Create function activation record. */
864 run_fun_ar_create(run, deleg_v->obj, fun, &fun_ar);
865
866 /* Fill in argument values. */
867 run_fun_ar_set_args(run, fun_ar, &arg_vals);
868
869 /* Run the function. */
870 run_fun(run, fun_ar, res);
[09ababb7]871
872#ifdef DEBUG_RUN_TRACE
873 printf("Returned from function call.\n");
874#endif
875}
876
877/** Execute assignment. */
878static void run_assign(run_t *run, stree_assign_t *assign, rdata_item_t **res)
879{
880 rdata_item_t *rdest_i, *rsrc_i;
881 rdata_item_t *rsrc_vi;
882 rdata_value_t *src_val;
883
884#ifdef DEBUG_RUN_TRACE
885 printf("Run assign operation.\n");
886#endif
887 run_expr(run, assign->dest, &rdest_i);
888 run_expr(run, assign->src, &rsrc_i);
889
[fa36f29]890 rdata_cvt_value_item(rsrc_i, &rsrc_vi);
[09ababb7]891 src_val = rsrc_vi->u.value;
892
893 if (rdest_i->ic != ic_address) {
894 printf("Error: Address expression required on left side of "
895 "assignment operator.\n");
896 exit(1);
897 }
898
[fa36f29]899 rdata_address_write(rdest_i->u.address, rsrc_vi->u.value);
[09ababb7]900
901 *res = NULL;
902}
903
904/** Return boolean value of an item.
905 *
906 * Tries to interpret @a item as a boolean value. If it is not a boolean
907 * value, this generates an error.
908 *
909 * XXX Currently int supplants the role of a true boolean type.
910 */
911bool_t run_item_boolean_value(run_t *run, rdata_item_t *item)
912{
913 rdata_item_t *vitem;
914 rdata_var_t *var;
915
[fa36f29]916 (void) run;
917 rdata_cvt_value_item(item, &vitem);
[09ababb7]918
919 assert(vitem->ic == ic_value);
920 var = vitem->u.value->var;
921
922 if (var->vc != vc_int) {
923 printf("Error: Boolean (int) expression expected.\n");
924 exit(1);
925 }
926
927 return (var->u.int_v->value != 0);
928}
Note: See TracBrowser for help on using the repository browser.