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

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

Update SBI to rev. 144.

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