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

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

Update SBI to rev. 157.

  • Property mode set to 100644
File size: 35.0 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 "intmap.h"
36#include "list.h"
37#include "mytypes.h"
38#include "os/os.h"
39#include "rdata.h"
40#include "run.h"
41#include "run_texpr.h"
42#include "symbol.h"
43#include "stree.h"
44#include "strtab.h"
45#include "tdata.h"
46
47#include "run_expr.h"
48
49static void run_nameref(run_t *run, stree_nameref_t *nameref,
50 rdata_item_t **res);
51
52static void run_literal(run_t *run, stree_literal_t *literal,
53 rdata_item_t **res);
54static void run_lit_int(run_t *run, stree_lit_int_t *lit_int,
55 rdata_item_t **res);
56static void run_lit_ref(run_t *run, stree_lit_ref_t *lit_ref,
57 rdata_item_t **res);
58static void run_lit_string(run_t *run, stree_lit_string_t *lit_string,
59 rdata_item_t **res);
60
61static void run_self_ref(run_t *run, stree_self_ref_t *self_ref,
62 rdata_item_t **res);
63
64static void run_binop(run_t *run, stree_binop_t *binop, rdata_item_t **res);
65static void run_binop_int(run_t *run, stree_binop_t *binop, rdata_value_t *v1,
66 rdata_value_t *v2, rdata_item_t **res);
67static void run_binop_string(run_t *run, stree_binop_t *binop, rdata_value_t *v1,
68 rdata_value_t *v2, rdata_item_t **res);
69static void run_binop_ref(run_t *run, stree_binop_t *binop, rdata_value_t *v1,
70 rdata_value_t *v2, rdata_item_t **res);
71
72static void run_unop(run_t *run, stree_unop_t *unop, rdata_item_t **res);
73static void run_new(run_t *run, stree_new_t *new_op, rdata_item_t **res);
74static void run_new_array(run_t *run, stree_new_t *new_op,
75 tdata_item_t *titem, rdata_item_t **res);
76static void run_new_object(run_t *run, stree_new_t *new_op,
77 tdata_item_t *titem, rdata_item_t **res);
78
79static void run_access(run_t *run, stree_access_t *access, rdata_item_t **res);
80static void run_access_item(run_t *run, stree_access_t *access,
81 rdata_item_t *arg, rdata_item_t **res);
82static void run_access_ref(run_t *run, stree_access_t *access,
83 rdata_item_t *arg, rdata_item_t **res);
84static void run_access_deleg(run_t *run, stree_access_t *access,
85 rdata_item_t *arg, rdata_item_t **res);
86static void run_access_object(run_t *run, stree_access_t *access,
87 rdata_item_t *arg, rdata_item_t **res);
88
89static void run_call(run_t *run, stree_call_t *call, rdata_item_t **res);
90static void run_index(run_t *run, stree_index_t *index, rdata_item_t **res);
91static void run_index_array(run_t *run, stree_index_t *index,
92 rdata_item_t *base, list_t *args, rdata_item_t **res);
93static void run_index_object(run_t *run, stree_index_t *index,
94 rdata_item_t *base, list_t *args, rdata_item_t **res);
95static void run_index_string(run_t *run, stree_index_t *index,
96 rdata_item_t *base, list_t *args, rdata_item_t **res);
97static void run_assign(run_t *run, stree_assign_t *assign, rdata_item_t **res);
98static void run_as(run_t *run, stree_as_t *as_op, rdata_item_t **res);
99
100/** Evaluate expression. */
101void run_expr(run_t *run, stree_expr_t *expr, rdata_item_t **res)
102{
103#ifdef DEBUG_RUN_TRACE
104 printf("Executing expression.\n");
105#endif
106
107 switch (expr->ec) {
108 case ec_nameref:
109 run_nameref(run, expr->u.nameref, res);
110 break;
111 case ec_literal:
112 run_literal(run, expr->u.literal, res);
113 break;
114 case ec_self_ref:
115 run_self_ref(run, expr->u.self_ref, res);
116 break;
117 case ec_binop:
118 run_binop(run, expr->u.binop, res);
119 break;
120 case ec_unop:
121 run_unop(run, expr->u.unop, res);
122 break;
123 case ec_new:
124 run_new(run, expr->u.new_op, res);
125 break;
126 case ec_access:
127 run_access(run, expr->u.access, res);
128 break;
129 case ec_call:
130 run_call(run, expr->u.call, res);
131 break;
132 case ec_index:
133 run_index(run, expr->u.index, res);
134 break;
135 case ec_assign:
136 run_assign(run, expr->u.assign, res);
137 break;
138 case ec_as:
139 run_as(run, expr->u.as_op, res);
140 break;
141 }
142
143#ifdef DEBUG_RUN_TRACE
144 printf("Expression result: ");
145 rdata_item_print(*res);
146 printf(".\n");
147#endif
148}
149
150/** Evaluate name reference expression. */
151static void run_nameref(run_t *run, stree_nameref_t *nameref,
152 rdata_item_t **res)
153{
154 stree_symbol_t *sym;
155 rdata_item_t *item;
156 rdata_address_t *address;
157 rdata_addr_var_t *addr_var;
158 rdata_value_t *value;
159 rdata_var_t *var;
160 rdata_deleg_t *deleg_v;
161
162 run_proc_ar_t *proc_ar;
163 stree_symbol_t *csi_sym;
164 stree_csi_t *csi;
165 rdata_object_t *obj;
166 rdata_var_t *member_var;
167
168#ifdef DEBUG_RUN_TRACE
169 printf("Run nameref.\n");
170#endif
171
172 /*
173 * Look for a local variable.
174 */
175 var = run_local_vars_lookup(run, nameref->name->sid);
176 if (var != NULL) {
177 /* Found a local variable. */
178 item = rdata_item_new(ic_address);
179 address = rdata_address_new(ac_var);
180 addr_var = rdata_addr_var_new();
181
182 item->u.address = address;
183 address->u.var_a = addr_var;
184 addr_var->vref = var;
185
186 *res = item;
187#ifdef DEBUG_RUN_TRACE
188 printf("Found local variable.\n");
189#endif
190 return;
191 }
192
193 /*
194 * Look for a class-wide or global symbol.
195 */
196
197 /* Determine currently active object or CSI. */
198 proc_ar = run_get_current_proc_ar(run);
199 if (proc_ar->obj != NULL) {
200 assert(proc_ar->obj->vc == vc_object);
201 obj = proc_ar->obj->u.object_v;
202 csi_sym = obj->class_sym;
203 csi = symbol_to_csi(csi_sym);
204 assert(csi != NULL);
205 } else {
206 csi = proc_ar->proc->outer_symbol->outer_csi;
207 obj = NULL;
208 }
209
210 sym = symbol_lookup_in_csi(run->program, csi, nameref->name);
211
212 /* Existence should have been verified in type checking phase. */
213 assert(sym != NULL);
214
215 switch (sym->sc) {
216 case sc_csi:
217#ifdef DEBUG_RUN_TRACE
218 printf("Referencing class.\n");
219#endif
220 item = rdata_item_new(ic_value);
221 value = rdata_value_new();
222 var = rdata_var_new(vc_deleg);
223 deleg_v = rdata_deleg_new();
224
225 item->u.value = value;
226 value->var = var;
227 var->u.deleg_v = deleg_v;
228
229 deleg_v->obj = NULL;
230 deleg_v->sym = sym;
231 *res = item;
232 break;
233 case sc_fun:
234 /* There should be no global functions. */
235 assert(csi != NULL);
236
237 if (sym->outer_csi != csi) {
238 /* Function is not in the current object. */
239 printf("Error: Cannot access non-static member "
240 "function '");
241 symbol_print_fqn(sym);
242 printf("' from nested CSI '");
243 symbol_print_fqn(csi_sym);
244 printf("'.\n");
245 exit(1);
246 }
247
248 /* Construct delegate. */
249 item = rdata_item_new(ic_value);
250 value = rdata_value_new();
251 item->u.value = value;
252
253 var = rdata_var_new(vc_deleg);
254 deleg_v = rdata_deleg_new();
255 value->var = var;
256 var->u.deleg_v = deleg_v;
257
258 deleg_v->obj = proc_ar->obj;
259 deleg_v->sym = sym;
260
261 *res = item;
262 break;
263 case sc_var:
264#ifdef DEBUG_RUN_TRACE
265 printf("Referencing member variable.\n");
266#endif
267 /* There should be no global variables. */
268 assert(csi != NULL);
269
270 /* XXX Assume variable is not static for now. */
271 assert(obj != NULL);
272
273 if (sym->outer_csi != csi) {
274 /* Variable is not in the current object. */
275 printf("Error: Cannot access non-static member "
276 "variable '");
277 symbol_print_fqn(sym);
278 printf("' from nested CSI '");
279 symbol_print_fqn(csi_sym);
280 printf("'.\n");
281 exit(1);
282 }
283
284 /* Find member variable in object. */
285 member_var = intmap_get(&obj->fields, nameref->name->sid);
286 assert(member_var != NULL);
287
288 /* Return address of the variable. */
289 item = rdata_item_new(ic_address);
290 address = rdata_address_new(ac_var);
291 addr_var = rdata_addr_var_new();
292
293 item->u.address = address;
294 address->u.var_a = addr_var;
295 addr_var->vref = member_var;
296
297 *res = item;
298 break;
299 default:
300 printf("Referencing symbol class %d unimplemented.\n", sym->sc);
301 *res = NULL;
302 break;
303 }
304}
305
306/** Evaluate literal. */
307static void run_literal(run_t *run, stree_literal_t *literal,
308 rdata_item_t **res)
309{
310#ifdef DEBUG_RUN_TRACE
311 printf("Run literal.\n");
312#endif
313
314 switch (literal->ltc) {
315 case ltc_int:
316 run_lit_int(run, &literal->u.lit_int, res);
317 break;
318 case ltc_ref:
319 run_lit_ref(run, &literal->u.lit_ref, res);
320 break;
321 case ltc_string:
322 run_lit_string(run, &literal->u.lit_string, res);
323 break;
324 default:
325 assert(b_false);
326 }
327}
328
329/** Evaluate integer literal. */
330static void run_lit_int(run_t *run, stree_lit_int_t *lit_int,
331 rdata_item_t **res)
332{
333 rdata_item_t *item;
334 rdata_value_t *value;
335 rdata_var_t *var;
336 rdata_int_t *int_v;
337
338#ifdef DEBUG_RUN_TRACE
339 printf("Run integer literal.\n");
340#endif
341 (void) run;
342
343 item = rdata_item_new(ic_value);
344 value = rdata_value_new();
345 var = rdata_var_new(vc_int);
346 int_v = rdata_int_new();
347
348 item->u.value = value;
349 value->var = var;
350 var->u.int_v = int_v;
351 int_v->value = lit_int->value;
352
353 *res = item;
354}
355
356/** Evaluate reference literal (@c nil). */
357static void run_lit_ref(run_t *run, stree_lit_ref_t *lit_ref,
358 rdata_item_t **res)
359{
360 rdata_item_t *item;
361 rdata_value_t *value;
362 rdata_var_t *var;
363 rdata_ref_t *ref_v;
364
365#ifdef DEBUG_RUN_TRACE
366 printf("Run reference literal (nil).\n");
367#endif
368 (void) run;
369 (void) lit_ref;
370
371 item = rdata_item_new(ic_value);
372 value = rdata_value_new();
373 var = rdata_var_new(vc_ref);
374 ref_v = rdata_ref_new();
375
376 item->u.value = value;
377 value->var = var;
378 var->u.ref_v = ref_v;
379 ref_v->vref = NULL;
380
381 *res = item;
382}
383
384/** Evaluate string literal. */
385static void run_lit_string(run_t *run, stree_lit_string_t *lit_string,
386 rdata_item_t **res)
387{
388 rdata_item_t *item;
389 rdata_value_t *value;
390 rdata_var_t *var;
391 rdata_string_t *string_v;
392
393#ifdef DEBUG_RUN_TRACE
394 printf("Run integer literal.\n");
395#endif
396 (void) run;
397
398 item = rdata_item_new(ic_value);
399 value = rdata_value_new();
400 var = rdata_var_new(vc_string);
401 string_v = rdata_string_new();
402
403 item->u.value = value;
404 value->var = var;
405 var->u.string_v = string_v;
406 string_v->value = lit_string->value;
407
408 *res = item;
409}
410
411/** Evaluate @c self reference. */
412static void run_self_ref(run_t *run, stree_self_ref_t *self_ref,
413 rdata_item_t **res)
414{
415 run_proc_ar_t *proc_ar;
416
417#ifdef DEBUG_RUN_TRACE
418 printf("Run self reference.\n");
419#endif
420 (void) self_ref;
421 proc_ar = run_get_current_proc_ar(run);
422
423 /* Return reference to the currently active object. */
424 run_reference(run, proc_ar->obj, res);
425}
426
427/** Evaluate binary operation. */
428static void run_binop(run_t *run, stree_binop_t *binop, rdata_item_t **res)
429{
430 rdata_item_t *rarg1_i, *rarg2_i;
431 rdata_item_t *rarg1_vi, *rarg2_vi;
432 rdata_value_t *v1, *v2;
433
434#ifdef DEBUG_RUN_TRACE
435 printf("Run binary operation.\n");
436#endif
437 run_expr(run, binop->arg1, &rarg1_i);
438 run_expr(run, binop->arg2, &rarg2_i);
439
440 switch (binop->bc) {
441 case bo_plus:
442 case bo_equal:
443 case bo_notequal:
444 case bo_lt:
445 case bo_gt:
446 case bo_lt_equal:
447 case bo_gt_equal:
448 /* These are implemented so far. */
449 break;
450 default:
451 printf("Unimplemented: Binary operation type %d.\n",
452 binop->bc);
453 exit(1);
454 }
455
456#ifdef DEBUG_RUN_TRACE
457 printf("Check binop argument results.\n");
458#endif
459
460 run_cvt_value_item(run, rarg1_i, &rarg1_vi);
461 run_cvt_value_item(run, rarg2_i, &rarg2_vi);
462
463 v1 = rarg1_vi->u.value;
464 v2 = rarg2_vi->u.value;
465
466 if (v1->var->vc != v2->var->vc) {
467 printf("Unimplemented: Binary operation arguments have "
468 "different type.\n");
469 exit(1);
470 }
471
472 switch (v1->var->vc) {
473 case vc_int:
474 run_binop_int(run, binop, v1, v2, res);
475 break;
476 case vc_string:
477 run_binop_string(run, binop, v1, v2, res);
478 break;
479 case vc_ref:
480 run_binop_ref(run, binop, v1, v2, res);
481 break;
482 default:
483 printf("Unimplemented: Binary operation arguments of "
484 "type %d.\n", v1->var->vc);
485 exit(1);
486 }
487}
488
489/** Evaluate binary operation on int arguments. */
490static void run_binop_int(run_t *run, stree_binop_t *binop, rdata_value_t *v1,
491 rdata_value_t *v2, rdata_item_t **res)
492{
493 rdata_item_t *item;
494 rdata_value_t *value;
495 rdata_var_t *var;
496 rdata_int_t *int_v;
497
498 int i1, i2;
499
500 (void) run;
501
502 item = rdata_item_new(ic_value);
503 value = rdata_value_new();
504 var = rdata_var_new(vc_int);
505 int_v = rdata_int_new();
506
507 item->u.value = value;
508 value->var = var;
509 var->u.int_v = int_v;
510
511 i1 = v1->var->u.int_v->value;
512 i2 = v2->var->u.int_v->value;
513
514 switch (binop->bc) {
515 case bo_plus:
516 int_v->value = i1 + i2;
517 break;
518
519 /* XXX We should have a real boolean type. */
520 case bo_equal:
521 int_v->value = (i1 == i2) ? 1 : 0;
522 break;
523 case bo_notequal:
524 int_v->value = (i1 != i2) ? 1 : 0;
525 break;
526 case bo_lt:
527 int_v->value = (i1 < i2) ? 1 : 0;
528 break;
529 case bo_gt:
530 int_v->value = (i1 > i2) ? 1 : 0;
531 break;
532 case bo_lt_equal:
533 int_v->value = (i1 <= i2) ? 1 : 0;
534 break;
535 case bo_gt_equal:
536 int_v->value = (i1 >= i2) ? 1 : 0;
537 break;
538 default:
539 assert(b_false);
540 }
541
542 *res = item;
543}
544
545/** Evaluate binary operation on string arguments. */
546static void run_binop_string(run_t *run, stree_binop_t *binop, rdata_value_t *v1,
547 rdata_value_t *v2, rdata_item_t **res)
548{
549 rdata_item_t *item;
550 rdata_value_t *value;
551 rdata_var_t *var;
552 rdata_string_t *string_v;
553
554 char *s1, *s2;
555
556 (void) run;
557
558 item = rdata_item_new(ic_value);
559 value = rdata_value_new();
560 var = rdata_var_new(vc_string);
561 string_v = rdata_string_new();
562
563 item->u.value = value;
564 value->var = var;
565 var->u.string_v = string_v;
566
567 s1 = v1->var->u.string_v->value;
568 s2 = v2->var->u.string_v->value;
569
570 switch (binop->bc) {
571 case bo_plus:
572 /* Concatenate strings. */
573 string_v->value = os_str_acat(s1, s2);
574 break;
575 default:
576 printf("Error: Invalid binary operation on string "
577 "arguments (%d).\n", binop->bc);
578 assert(b_false);
579 }
580
581 *res = item;
582}
583
584/** Evaluate binary operation on ref arguments. */
585static void run_binop_ref(run_t *run, stree_binop_t *binop, rdata_value_t *v1,
586 rdata_value_t *v2, rdata_item_t **res)
587{
588 rdata_item_t *item;
589 rdata_value_t *value;
590 rdata_var_t *var;
591 rdata_int_t *int_v;
592
593 rdata_var_t *ref1, *ref2;
594
595 (void) run;
596
597 item = rdata_item_new(ic_value);
598 value = rdata_value_new();
599 var = rdata_var_new(vc_int);
600 int_v = rdata_int_new();
601
602 item->u.value = value;
603 value->var = var;
604 var->u.int_v = int_v;
605
606 ref1 = v1->var->u.ref_v->vref;
607 ref2 = v2->var->u.ref_v->vref;
608
609 switch (binop->bc) {
610 /* XXX We should have a real boolean type. */
611 case bo_equal:
612 int_v->value = (ref1 == ref2) ? 1 : 0;
613 break;
614 case bo_notequal:
615 int_v->value = (ref1 != ref2) ? 1 : 0;
616 break;
617 default:
618 printf("Error: Invalid binary operation on reference "
619 "arguments (%d).\n", binop->bc);
620 assert(b_false);
621 }
622
623 *res = item;
624}
625
626
627/** Evaluate unary operation. */
628static void run_unop(run_t *run, stree_unop_t *unop, rdata_item_t **res)
629{
630 rdata_item_t *rarg;
631
632#ifdef DEBUG_RUN_TRACE
633 printf("Run unary operation.\n");
634#endif
635 run_expr(run, unop->arg, &rarg);
636 *res = NULL;
637}
638
639/** Evaluate @c new operation. */
640static void run_new(run_t *run, stree_new_t *new_op, rdata_item_t **res)
641{
642 tdata_item_t *titem;
643
644#ifdef DEBUG_RUN_TRACE
645 printf("Run 'new' operation.\n");
646#endif
647 /* Evaluate type expression */
648 run_texpr(run->program, run_get_current_csi(run), new_op->texpr,
649 &titem);
650
651 switch (titem->tic) {
652 case tic_tarray:
653 run_new_array(run, new_op, titem, res);
654 break;
655 case tic_tobject:
656 run_new_object(run, new_op, titem, res);
657 break;
658 default:
659 printf("Error: Invalid argument to operator 'new', "
660 "expected object.\n");
661 exit(1);
662 }
663}
664
665/** Create new array. */
666static void run_new_array(run_t *run, stree_new_t *new_op,
667 tdata_item_t *titem, rdata_item_t **res)
668{
669 tdata_array_t *tarray;
670 rdata_array_t *array;
671 rdata_var_t *array_var;
672 rdata_var_t *elem_var;
673
674 rdata_item_t *rexpr, *rexpr_vi;
675 rdata_var_t *rexpr_var;
676
677 stree_expr_t *expr;
678
679 list_node_t *node;
680 int length;
681 int i;
682
683#ifdef DEBUG_RUN_TRACE
684 printf("Create new array.\n");
685#endif
686 (void) run;
687 (void) new_op;
688
689 assert(titem->tic == tic_tarray);
690 tarray = titem->u.tarray;
691
692 /* Create the array. */
693 assert(titem->u.tarray->rank > 0);
694 array = rdata_array_new(titem->u.tarray->rank);
695
696 /* Compute extents. */
697 node = list_first(&tarray->extents);
698 if (node == NULL) {
699 printf("Error: Extents must be specified when constructing "
700 "an array with 'new'.\n");
701 exit(1);
702 }
703
704 i = 0; length = 1;
705 while (node != NULL) {
706 expr = list_node_data(node, stree_expr_t *);
707
708 /* Evaluate extent argument. */
709 run_expr(run, expr, &rexpr);
710 run_cvt_value_item(run, rexpr, &rexpr_vi);
711 assert(rexpr_vi->ic == ic_value);
712 rexpr_var = rexpr_vi->u.value->var;
713
714 if (rexpr_var->vc != vc_int) {
715 printf("Error: Array extent must be an integer.\n");
716 exit(1);
717 }
718
719#ifdef DEBUG_RUN_TRACE
720 printf("Array extent: %d.\n", rexpr_var->u.int_v->value);
721#endif
722 array->extent[i] = rexpr_var->u.int_v->value;
723 length = length * array->extent[i];
724
725 node = list_next(&tarray->extents, node);
726 i += 1;
727 }
728
729 array->element = calloc(length, sizeof(rdata_var_t *));
730 if (array->element == NULL) {
731 printf("Memory allocation failed.\n");
732 exit(1);
733 }
734
735 /* Create member variables */
736 for (i = 0; i < length; ++i) {
737 /* XXX Depends on member variable type. */
738 elem_var = rdata_var_new(vc_int);
739 elem_var->u.int_v = rdata_int_new();
740 elem_var->u.int_v->value = 0;
741
742 array->element[i] = elem_var;
743 }
744
745 /* Create array variable. */
746 array_var = rdata_var_new(vc_array);
747 array_var->u.array_v = array;
748
749 /* Create reference to the new array. */
750 run_reference(run, array_var, res);
751}
752
753/** Create new object. */
754static void run_new_object(run_t *run, stree_new_t *new_op,
755 tdata_item_t *titem, rdata_item_t **res)
756{
757 rdata_object_t *obj;
758 rdata_var_t *obj_var;
759
760 stree_symbol_t *csi_sym;
761 stree_csi_t *csi;
762 stree_csimbr_t *csimbr;
763
764 rdata_var_t *mbr_var;
765
766 list_node_t *node;
767
768#ifdef DEBUG_RUN_TRACE
769 printf("Create new object.\n");
770#endif
771 (void) run;
772 (void) new_op;
773
774 /* Lookup object CSI. */
775 assert(titem->tic == tic_tobject);
776 csi = titem->u.tobject->csi;
777 csi_sym = csi_to_symbol(csi);
778
779 /* Create the object. */
780 obj = rdata_object_new();
781 obj->class_sym = csi_sym;
782 intmap_init(&obj->fields);
783
784 obj_var = rdata_var_new(vc_object);
785 obj_var->u.object_v = obj;
786
787 /* Create object fields. */
788 node = list_first(&csi->members);
789 while (node != NULL) {
790 csimbr = list_node_data(node, stree_csimbr_t *);
791 if (csimbr->cc == csimbr_var) {
792 /* XXX Depends on member variable type. */
793 mbr_var = rdata_var_new(vc_int);
794 mbr_var->u.int_v = rdata_int_new();
795 mbr_var->u.int_v->value = 0;
796
797 intmap_set(&obj->fields, csimbr->u.var->name->sid,
798 mbr_var);
799 }
800
801 node = list_next(&csi->members, node);
802 }
803
804 /* Create reference to the new object. */
805 run_reference(run, obj_var, res);
806}
807
808/** Evaluate member acccess. */
809static void run_access(run_t *run, stree_access_t *access, rdata_item_t **res)
810{
811 rdata_item_t *rarg;
812
813#ifdef DEBUG_RUN_TRACE
814 printf("Run access operation.\n");
815#endif
816 run_expr(run, access->arg, &rarg);
817 if (rarg == NULL) {
818 printf("Error: Sub-expression has no value.\n");
819 exit(1);
820 }
821
822 run_access_item(run, access, rarg, res);
823}
824
825/** Evaluate member acccess (with base already evaluated). */
826static void run_access_item(run_t *run, stree_access_t *access,
827 rdata_item_t *arg, rdata_item_t **res)
828{
829 var_class_t vc;
830
831#ifdef DEBUG_RUN_TRACE
832 printf("Run access operation on pre-evaluated base.\n");
833#endif
834 vc = run_item_get_vc(run, arg);
835
836 switch (vc) {
837 case vc_ref:
838 run_access_ref(run, access, arg, res);
839 break;
840 case vc_deleg:
841 run_access_deleg(run, access, arg, res);
842 break;
843 case vc_object:
844 run_access_object(run, access, arg, res);
845 break;
846 default:
847 printf("Unimplemented: Using access operator ('.') "
848 "with unsupported data type (value/%d).\n", vc);
849 exit(1);
850 }
851}
852
853/** Evaluate reference acccess. */
854static void run_access_ref(run_t *run, stree_access_t *access,
855 rdata_item_t *arg, rdata_item_t **res)
856{
857 rdata_item_t *darg;
858
859 /* Implicitly dereference. */
860 run_dereference(run, arg, &darg);
861
862 if (run->thread_ar->bo_mode != bm_none) {
863 *res = run_recovery_item(run);
864 return;
865 }
866
867 /* Try again. */
868 run_access_item(run, access, darg, res);
869}
870
871/** Evaluate delegate-member acccess. */
872static void run_access_deleg(run_t *run, stree_access_t *access,
873 rdata_item_t *arg, rdata_item_t **res)
874{
875 rdata_item_t *arg_vi;
876 rdata_value_t *arg_val;
877 rdata_deleg_t *deleg_v;
878 stree_symbol_t *member;
879
880#ifdef DEBUG_RUN_TRACE
881 printf("Run delegate access operation.\n");
882#endif
883 run_cvt_value_item(run, arg, &arg_vi);
884 arg_val = arg_vi->u.value;
885 assert(arg_val->var->vc == vc_deleg);
886
887 deleg_v = arg_val->var->u.deleg_v;
888 if (deleg_v->obj != NULL || deleg_v->sym->sc != sc_csi) {
889 printf("Error: Using '.' with delegate to different object "
890 "than a CSI (%d).\n", deleg_v->sym->sc);
891 exit(1);
892 }
893
894 member = symbol_search_csi(run->program, deleg_v->sym->u.csi,
895 access->member_name);
896
897 if (member == NULL) {
898 printf("Error: CSI '");
899 symbol_print_fqn(deleg_v->sym);
900 printf("' has no member named '%s'.\n",
901 strtab_get_str(access->member_name->sid));
902 exit(1);
903 }
904
905#ifdef DEBUG_RUN_TRACE
906 printf("Found member '%s'.\n",
907 strtab_get_str(access->member_name->sid));
908#endif
909
910 /*
911 * Reuse existing item, value, var, deleg.
912 * XXX This is maybe not a good idea because it complicates memory
913 * management as there is not a single owner
914 */
915 deleg_v->sym = member;
916 *res = arg;
917}
918
919/** Evaluate object member acccess. */
920static void run_access_object(run_t *run, stree_access_t *access,
921 rdata_item_t *arg, rdata_item_t **res)
922{
923 stree_symbol_t *member;
924 rdata_var_t *object_var;
925 rdata_object_t *object;
926 rdata_item_t *ritem;
927 rdata_address_t *address;
928 rdata_addr_var_t *addr_var;
929 rdata_addr_prop_t *addr_prop;
930 rdata_aprop_named_t *aprop_named;
931 rdata_deleg_t *deleg_p;
932
933 rdata_value_t *value;
934 rdata_deleg_t *deleg_v;
935 rdata_var_t *var;
936
937#ifdef DEBUG_RUN_TRACE
938 printf("Run object access operation.\n");
939#endif
940 assert(arg->ic == ic_address);
941 assert(arg->u.address->ac == ac_var);
942 assert(arg->u.address->u.var_a->vref->vc == vc_object);
943
944 object_var = arg->u.address->u.var_a->vref;
945 object = object_var->u.object_v;
946
947 member = symbol_search_csi(run->program, object->class_sym->u.csi,
948 access->member_name);
949
950 if (member == NULL) {
951 printf("Error: Object of class '");
952 symbol_print_fqn(object->class_sym);
953 printf("' has no member named '%s'.\n",
954 strtab_get_str(access->member_name->sid));
955 exit(1);
956 }
957
958#ifdef DEBUG_RUN_TRACE
959 printf("Found member '%s'.\n",
960 strtab_get_str(access->member_name->sid));
961#endif
962
963 switch (member->sc) {
964 case sc_csi:
965 printf("Error: Accessing object member which is nested CSI.\n");
966 exit(1);
967 case sc_fun:
968 /* Construct delegate. */
969 ritem = rdata_item_new(ic_value);
970 value = rdata_value_new();
971 ritem->u.value = value;
972
973 var = rdata_var_new(vc_deleg);
974 value->var = var;
975 deleg_v = rdata_deleg_new();
976 var->u.deleg_v = deleg_v;
977
978 deleg_v->obj = arg->u.address->u.var_a->vref;
979 deleg_v->sym = member;
980 break;
981 case sc_var:
982 /* Construct variable address item. */
983 ritem = rdata_item_new(ic_address);
984 address = rdata_address_new(ac_var);
985 addr_var = rdata_addr_var_new();
986 ritem->u.address = address;
987 address->u.var_a = addr_var;
988
989 addr_var->vref = intmap_get(&object->fields,
990 access->member_name->sid);
991 assert(addr_var->vref != NULL);
992 break;
993 case sc_prop:
994 /* Construct named property address. */
995 ritem = rdata_item_new(ic_address);
996 address = rdata_address_new(ac_prop);
997 addr_prop = rdata_addr_prop_new(apc_named);
998 aprop_named = rdata_aprop_named_new();
999 ritem->u.address = address;
1000 address->u.prop_a = addr_prop;
1001 addr_prop->u.named = aprop_named;
1002
1003 deleg_p = rdata_deleg_new();
1004 deleg_p->obj = object_var;
1005 deleg_p->sym = member;
1006 addr_prop->u.named->prop_d = deleg_p;
1007 break;
1008 }
1009
1010 *res = ritem;
1011}
1012
1013/** Call a function. */
1014static void run_call(run_t *run, stree_call_t *call, rdata_item_t **res)
1015{
1016 rdata_item_t *rfun;
1017 rdata_deleg_t *deleg_v;
1018 list_t arg_vals;
1019 list_node_t *node;
1020 stree_expr_t *arg;
1021 rdata_item_t *rarg_i, *rarg_vi;
1022
1023 stree_fun_t *fun;
1024 run_proc_ar_t *proc_ar;
1025
1026#ifdef DEBUG_RUN_TRACE
1027 printf("Run call operation.\n");
1028#endif
1029 run_expr(run, call->fun, &rfun);
1030
1031 if (run->thread_ar->bo_mode != bm_none) {
1032 *res = run_recovery_item(run);
1033 return;
1034 }
1035
1036 if (rfun->ic != ic_value || rfun->u.value->var->vc != vc_deleg) {
1037 printf("Unimplemented: Call expression of this type.\n");
1038 exit(1);
1039 }
1040
1041 deleg_v = rfun->u.value->var->u.deleg_v;
1042
1043 if (deleg_v->sym->sc != sc_fun) {
1044 printf("Error: Called symbol is not a function.\n");
1045 exit(1);
1046 }
1047
1048#ifdef DEBUG_RUN_TRACE
1049 printf("Call function '");
1050 symbol_print_fqn(deleg_v->sym);
1051 printf("'\n");
1052#endif
1053 /* Evaluate function arguments. */
1054 list_init(&arg_vals);
1055 node = list_first(&call->args);
1056
1057 while (node != NULL) {
1058 arg = list_node_data(node, stree_expr_t *);
1059 run_expr(run, arg, &rarg_i);
1060 run_cvt_value_item(run, rarg_i, &rarg_vi);
1061
1062 list_append(&arg_vals, rarg_vi);
1063 node = list_next(&call->args, node);
1064 }
1065
1066 fun = symbol_to_fun(deleg_v->sym);
1067 assert(fun != NULL);
1068
1069 /* Create procedure activation record. */
1070 run_proc_ar_create(run, deleg_v->obj, fun->proc, &proc_ar);
1071
1072 /* Fill in argument values. */
1073 run_proc_ar_set_args(run, proc_ar, &arg_vals);
1074
1075 /* Run the function. */
1076 run_proc(run, proc_ar, res);
1077
1078#ifdef DEBUG_RUN_TRACE
1079 printf("Returned from function call.\n");
1080#endif
1081}
1082
1083/** Run index operation. */
1084static void run_index(run_t *run, stree_index_t *index, rdata_item_t **res)
1085{
1086 rdata_item_t *rbase;
1087 rdata_item_t *base_i;
1088 list_node_t *node;
1089 stree_expr_t *arg;
1090 rdata_item_t *rarg_i, *rarg_vi;
1091 var_class_t vc;
1092 list_t arg_vals;
1093
1094#ifdef DEBUG_RUN_TRACE
1095 printf("Run index operation.\n");
1096#endif
1097 run_expr(run, index->base, &rbase);
1098
1099 vc = run_item_get_vc(run, rbase);
1100
1101 /* Implicitly dereference. */
1102 if (vc == vc_ref) {
1103 run_dereference(run, rbase, &base_i);
1104 } else {
1105 base_i = rbase;
1106 }
1107
1108 vc = run_item_get_vc(run, base_i);
1109
1110 /* Evaluate arguments (indices). */
1111 node = list_first(&index->args);
1112 list_init(&arg_vals);
1113
1114 while (node != NULL) {
1115 arg = list_node_data(node, stree_expr_t *);
1116 run_expr(run, arg, &rarg_i);
1117 run_cvt_value_item(run, rarg_i, &rarg_vi);
1118
1119 list_append(&arg_vals, rarg_vi);
1120
1121 node = list_next(&index->args, node);
1122 }
1123
1124 switch (vc) {
1125 case vc_array:
1126 run_index_array(run, index, base_i, &arg_vals, res);
1127 break;
1128 case vc_object:
1129 run_index_object(run, index, base_i, &arg_vals, res);
1130 break;
1131 case vc_string:
1132 run_index_string(run, index, base_i, &arg_vals, res);
1133 break;
1134 default:
1135 printf("Error: Indexing object of bad type (%d).\n", vc);
1136 exit(1);
1137 }
1138}
1139
1140/** Run index operation on array. */
1141static void run_index_array(run_t *run, stree_index_t *index,
1142 rdata_item_t *base, list_t *args, rdata_item_t **res)
1143{
1144 list_node_t *node;
1145 rdata_array_t *array;
1146 rdata_item_t *arg;
1147
1148 int i;
1149 int elem_index;
1150 int arg_val;
1151
1152 rdata_item_t *ritem;
1153 rdata_address_t *address;
1154 rdata_addr_var_t *addr_var;
1155
1156#ifdef DEBUG_RUN_TRACE
1157 printf("Run array index operation.\n");
1158#endif
1159 (void) run;
1160 (void) index;
1161
1162 assert(base->ic == ic_address);
1163 assert(base->u.address->ac == ac_var);
1164 assert(base->u.address->u.var_a->vref->vc == vc_array);
1165 array = base->u.address->u.var_a->vref->u.array_v;
1166
1167 /*
1168 * Linear index of the desired element. Elements are stored in
1169 * lexicographic order with the last index changing the fastest.
1170 */
1171 elem_index = 0;
1172
1173 node = list_first(args);
1174 i = 0;
1175
1176 while (node != NULL) {
1177 if (i >= array->rank) {
1178 printf("Error: Too many indices for array of rank %d",
1179 array->rank);
1180 exit(1);
1181 }
1182
1183 arg = list_node_data(node, rdata_item_t *);
1184 assert(arg->ic == ic_value);
1185
1186 if (arg->u.value->var->vc != vc_int) {
1187 printf("Error: Array index is not an integer.\n");
1188 exit(1);
1189 }
1190
1191 arg_val = arg->u.value->var->u.int_v->value;
1192
1193 if (arg_val < 0 || arg_val >= array->extent[i]) {
1194 printf("Error: Array index (value: %d) is out of range.\n",
1195 arg_val);
1196 run_raise_error(run);
1197 *res = run_recovery_item(run);
1198 return;
1199 }
1200
1201 elem_index = elem_index * array->extent[i] + arg_val;
1202
1203 node = list_next(args, node);
1204 i += 1;
1205 }
1206
1207 if (i < array->rank) {
1208 printf("Error: Too few indices for array of rank %d",
1209 array->rank);
1210 exit(1);
1211 }
1212
1213 /* Construct variable address item. */
1214 ritem = rdata_item_new(ic_address);
1215 address = rdata_address_new(ac_var);
1216 addr_var = rdata_addr_var_new();
1217 ritem->u.address = address;
1218 address->u.var_a = addr_var;
1219
1220 addr_var->vref = array->element[elem_index];
1221
1222 *res = ritem;
1223}
1224
1225/** Index an object (via its indexer). */
1226static void run_index_object(run_t *run, stree_index_t *index,
1227 rdata_item_t *base, list_t *args, rdata_item_t **res)
1228{
1229 rdata_item_t *ritem;
1230 rdata_address_t *address;
1231 rdata_addr_prop_t *addr_prop;
1232 rdata_aprop_indexed_t *aprop_indexed;
1233 rdata_var_t *obj_var;
1234 stree_csi_t *obj_csi;
1235 rdata_deleg_t *object_d;
1236 stree_symbol_t *indexer_sym;
1237 stree_ident_t *indexer_ident;
1238
1239 list_node_t *node;
1240 rdata_item_t *arg;
1241
1242#ifdef DEBUG_RUN_TRACE
1243 printf("Run object index operation.\n");
1244#endif
1245 (void) index;
1246
1247 /* Construct property address item. */
1248 ritem = rdata_item_new(ic_address);
1249 address = rdata_address_new(ac_prop);
1250 addr_prop = rdata_addr_prop_new(apc_indexed);
1251 aprop_indexed = rdata_aprop_indexed_new();
1252 ritem->u.address = address;
1253 address->u.prop_a = addr_prop;
1254 addr_prop->u.indexed = aprop_indexed;
1255
1256 if (base->ic != ic_address || base->u.address->ac != ac_var) {
1257 /* XXX Several other cases can occur. */
1258 printf("Unimplemented: Indexing object varclass via something "
1259 "which is not a simple variable reference.\n");
1260 exit(1);
1261 }
1262
1263 /* Find indexer symbol. */
1264 obj_var = base->u.address->u.var_a->vref;
1265 assert(obj_var->vc == vc_object);
1266 indexer_ident = stree_ident_new();
1267 indexer_ident->sid = strtab_get_sid(INDEXER_IDENT);
1268 obj_csi = symbol_to_csi(obj_var->u.object_v->class_sym);
1269 assert(obj_csi != NULL);
1270 indexer_sym = symbol_search_csi(run->program, obj_csi, indexer_ident);
1271
1272 if (indexer_sym == NULL) {
1273 printf("Error: Accessing object which does not have an "
1274 "indexer.\n");
1275 exit(1);
1276 }
1277
1278 /* Construct delegate. */
1279 object_d = rdata_deleg_new();
1280 object_d->obj = obj_var;
1281 object_d->sym = indexer_sym;
1282 aprop_indexed->object_d = object_d;
1283
1284 /* Copy list of argument values. */
1285 list_init(&aprop_indexed->args);
1286
1287 node = list_first(args);
1288 while (node != NULL) {
1289 arg = list_node_data(node, rdata_item_t *);
1290 list_append(&aprop_indexed->args, arg);
1291 node = list_next(args, node);
1292 }
1293
1294 *res = ritem;
1295}
1296
1297/** Run index operation on string. */
1298static void run_index_string(run_t *run, stree_index_t *index,
1299 rdata_item_t *base, list_t *args, rdata_item_t **res)
1300{
1301 list_node_t *node;
1302 rdata_string_t *string;
1303 rdata_item_t *base_vi;
1304 rdata_item_t *arg;
1305
1306 int i;
1307 int elem_index;
1308 int arg_val;
1309 int rc;
1310
1311 rdata_value_t *value;
1312 rdata_var_t *cvar;
1313 rdata_item_t *ritem;
1314 int cval;
1315
1316#ifdef DEBUG_RUN_TRACE
1317 printf("Run string index operation.\n");
1318#endif
1319 (void) run;
1320 (void) index;
1321
1322 run_cvt_value_item(run, base, &base_vi);
1323 assert(base_vi->u.value->var->vc == vc_string);
1324 string = base->u.value->var->u.string_v;
1325
1326 /*
1327 * Linear index of the desired element. Elements are stored in
1328 * lexicographic order with the last index changing the fastest.
1329 */
1330 node = list_first(args);
1331 elem_index = 0;
1332
1333 i = 0;
1334 while (node != NULL) {
1335 if (i >= 1) {
1336 printf("Error: Too many indices string.\n");
1337 exit(1);
1338 }
1339
1340 arg = list_node_data(node, rdata_item_t *);
1341 assert(arg->ic == ic_value);
1342
1343 if (arg->u.value->var->vc != vc_int) {
1344 printf("Error: String index is not an integer.\n");
1345 exit(1);
1346 }
1347
1348 arg_val = arg->u.value->var->u.int_v->value;
1349 elem_index = arg_val;
1350
1351 node = list_next(args, node);
1352 i += 1;
1353 }
1354
1355 if (i < 1) {
1356 printf("Error: Too few indices for string.\n");
1357 exit(1);
1358 }
1359
1360 rc = os_str_get_char(string->value, elem_index, &cval);
1361 if (rc != EOK) {
1362 printf("Error: String index (value: %d) is out of range.\n",
1363 arg_val);
1364 exit(1);
1365 }
1366
1367 /* Construct character value. */
1368 ritem = rdata_item_new(ic_value);
1369 value = rdata_value_new();
1370 ritem->u.value = value;
1371
1372 cvar = rdata_var_new(vc_int);
1373 cvar->u.int_v = rdata_int_new();
1374 cvar->u.int_v->value = cval;
1375 value->var = cvar;
1376
1377 *res = ritem;
1378}
1379
1380/** Execute assignment. */
1381static void run_assign(run_t *run, stree_assign_t *assign, rdata_item_t **res)
1382{
1383 rdata_item_t *rdest_i, *rsrc_i;
1384 rdata_item_t *rsrc_vi;
1385 rdata_value_t *src_val;
1386
1387#ifdef DEBUG_RUN_TRACE
1388 printf("Run assign operation.\n");
1389#endif
1390 run_expr(run, assign->dest, &rdest_i);
1391 run_expr(run, assign->src, &rsrc_i);
1392
1393 run_cvt_value_item(run, rsrc_i, &rsrc_vi);
1394 assert(rsrc_vi->ic == ic_value);
1395 src_val = rsrc_vi->u.value;
1396
1397 if (rdest_i->ic != ic_address) {
1398 printf("Error: Address expression required on left side of "
1399 "assignment operator.\n");
1400 exit(1);
1401 }
1402
1403 run_address_write(run, rdest_i->u.address, rsrc_vi->u.value);
1404
1405 *res = NULL;
1406}
1407
1408/** Execute @c as conversion. */
1409static void run_as(run_t *run, stree_as_t *as_op, rdata_item_t **res)
1410{
1411 rdata_item_t *rarg_i;
1412 rdata_item_t *rarg_vi;
1413 rdata_item_t *rarg_di;
1414 rdata_var_t *arg_vref;
1415 tdata_item_t *dtype;
1416 run_proc_ar_t *proc_ar;
1417
1418 stree_symbol_t *obj_csi_sym;
1419 stree_csi_t *obj_csi;
1420
1421#ifdef DEBUG_RUN_TRACE
1422 printf("Run @c as conversion operation.\n");
1423#endif
1424 run_expr(run, as_op->arg, &rarg_i);
1425
1426 /*
1427 * This should always be a reference if the argument is indeed
1428 * a class instance.
1429 */
1430 assert(run_item_get_vc(run, rarg_i) == vc_ref);
1431 run_cvt_value_item(run, rarg_i, &rarg_vi);
1432 assert(rarg_vi->ic == ic_value);
1433
1434 if (rarg_vi->u.value->var->u.ref_v->vref == NULL) {
1435 /* Nil reference is always okay. */
1436 *res = rarg_vi;
1437 return;
1438 }
1439
1440 run_dereference(run, rarg_vi, &rarg_di);
1441
1442 /* Now we should have a variable address. */
1443 assert(rarg_di->ic == ic_address);
1444 assert(rarg_di->u.address->ac == ac_var);
1445
1446 arg_vref = rarg_di->u.address->u.var_a->vref;
1447
1448 proc_ar = run_get_current_proc_ar(run);
1449 /* XXX Memoize to avoid recomputing. */
1450 run_texpr(run->program, proc_ar->proc->outer_symbol->outer_csi,
1451 as_op->dtype, &dtype);
1452
1453 assert(arg_vref->vc == vc_object);
1454 obj_csi_sym = arg_vref->u.object_v->class_sym;
1455 obj_csi = symbol_to_csi(obj_csi_sym);
1456 assert(obj_csi != NULL);
1457
1458 if (tdata_is_csi_derived_from_ti(obj_csi, dtype) != b_true) {
1459 printf("Error: Run-time type conversion error. Object is "
1460 "of type '");
1461 symbol_print_fqn(obj_csi_sym);
1462 printf("' which is not derived from '");
1463 tdata_item_print(dtype);
1464 printf("'.\n");
1465 exit(1);
1466 }
1467
1468 *res = rarg_vi;
1469}
1470
1471/** Return boolean value of an item.
1472 *
1473 * Tries to interpret @a item as a boolean value. If it is not a boolean
1474 * value, this generates an error.
1475 *
1476 * XXX Currently int supplants the role of a true boolean type.
1477 */
1478bool_t run_item_boolean_value(run_t *run, rdata_item_t *item)
1479{
1480 rdata_item_t *vitem;
1481 rdata_var_t *var;
1482
1483 (void) run;
1484 run_cvt_value_item(run, item, &vitem);
1485
1486 assert(vitem->ic == ic_value);
1487 var = vitem->u.value->var;
1488
1489 if (var->vc != vc_int) {
1490 printf("Error: Boolean (int) expression expected.\n");
1491 exit(1);
1492 }
1493
1494 return (var->u.int_v->value != 0);
1495}
Note: See TracBrowser for help on using the repository browser.