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

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

Merge mainline changes.

  • Property mode set to 100644
File size: 49.2 KB
Line 
1/*
2 * Copyright (c) 2010 Jiri Svoboda
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * - Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * - Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * - The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29/** @file Run expressions. */
30
31#include <stdio.h>
32#include <stdlib.h>
33#include <assert.h>
34#include "bigint.h"
35#include "debug.h"
36#include "intmap.h"
37#include "list.h"
38#include "mytypes.h"
39#include "os/os.h"
40#include "rdata.h"
41#include "run.h"
42#include "run_texpr.h"
43#include "symbol.h"
44#include "stree.h"
45#include "strtab.h"
46#include "tdata.h"
47
48#include "run_expr.h"
49
50static void run_nameref(run_t *run, stree_nameref_t *nameref,
51 rdata_item_t **res);
52
53static void run_literal(run_t *run, stree_literal_t *literal,
54 rdata_item_t **res);
55static void run_lit_bool(run_t *run, stree_lit_bool_t *lit_bool,
56 rdata_item_t **res);
57static void run_lit_char(run_t *run, stree_lit_char_t *lit_char,
58 rdata_item_t **res);
59static void run_lit_int(run_t *run, stree_lit_int_t *lit_int,
60 rdata_item_t **res);
61static void run_lit_ref(run_t *run, stree_lit_ref_t *lit_ref,
62 rdata_item_t **res);
63static void run_lit_string(run_t *run, stree_lit_string_t *lit_string,
64 rdata_item_t **res);
65
66static void run_self_ref(run_t *run, stree_self_ref_t *self_ref,
67 rdata_item_t **res);
68
69static void run_binop(run_t *run, stree_binop_t *binop, rdata_item_t **res);
70static void run_binop_bool(run_t *run, stree_binop_t *binop, rdata_value_t *v1,
71 rdata_value_t *v2, rdata_item_t **res);
72static void run_binop_char(run_t *run, stree_binop_t *binop, rdata_value_t *v1,
73 rdata_value_t *v2, rdata_item_t **res);
74static void run_binop_int(run_t *run, stree_binop_t *binop, rdata_value_t *v1,
75 rdata_value_t *v2, rdata_item_t **res);
76static void run_binop_string(run_t *run, stree_binop_t *binop, rdata_value_t *v1,
77 rdata_value_t *v2, rdata_item_t **res);
78static void run_binop_ref(run_t *run, stree_binop_t *binop, rdata_value_t *v1,
79 rdata_value_t *v2, rdata_item_t **res);
80
81static void run_unop(run_t *run, stree_unop_t *unop, rdata_item_t **res);
82static void run_unop_int(run_t *run, stree_unop_t *unop, rdata_value_t *val,
83 rdata_item_t **res);
84
85static void run_new(run_t *run, stree_new_t *new_op, rdata_item_t **res);
86static void run_new_array(run_t *run, stree_new_t *new_op,
87 tdata_item_t *titem, rdata_item_t **res);
88static void run_new_object(run_t *run, stree_new_t *new_op,
89 tdata_item_t *titem, rdata_item_t **res);
90
91static void run_access(run_t *run, stree_access_t *access, rdata_item_t **res);
92static void run_access_item(run_t *run, stree_access_t *access,
93 rdata_item_t *arg, rdata_item_t **res);
94static void run_access_ref(run_t *run, stree_access_t *access,
95 rdata_item_t *arg, rdata_item_t **res);
96static void run_access_deleg(run_t *run, stree_access_t *access,
97 rdata_item_t *arg, rdata_item_t **res);
98static void run_access_object(run_t *run, stree_access_t *access,
99 rdata_item_t *arg, rdata_item_t **res);
100
101static void run_call(run_t *run, stree_call_t *call, rdata_item_t **res);
102static void run_index(run_t *run, stree_index_t *index, rdata_item_t **res);
103static void run_index_array(run_t *run, stree_index_t *index,
104 rdata_item_t *base, list_t *args, rdata_item_t **res);
105static void run_index_object(run_t *run, stree_index_t *index,
106 rdata_item_t *base, list_t *args, rdata_item_t **res);
107static void run_index_string(run_t *run, stree_index_t *index,
108 rdata_item_t *base, list_t *args, rdata_item_t **res);
109static void run_assign(run_t *run, stree_assign_t *assign, rdata_item_t **res);
110static void run_as(run_t *run, stree_as_t *as_op, rdata_item_t **res);
111static void run_box(run_t *run, stree_box_t *box, rdata_item_t **res);
112
113/** Evaluate expression.
114 *
115 * Run the expression @a expr and store pointer to the result in *(@a res).
116 * If the expression has on value (assignment) then @c NULL is returned.
117 * @c NULL is also returned if an error or exception occurs.
118 *
119 * @param run Runner object
120 * @param expr Expression to run
121 * @param res Place to store result
122 */
123void run_expr(run_t *run, stree_expr_t *expr, rdata_item_t **res)
124{
125#ifdef DEBUG_RUN_TRACE
126 printf("Executing expression.\n");
127#endif
128
129 switch (expr->ec) {
130 case ec_nameref:
131 run_nameref(run, expr->u.nameref, res);
132 break;
133 case ec_literal:
134 run_literal(run, expr->u.literal, res);
135 break;
136 case ec_self_ref:
137 run_self_ref(run, expr->u.self_ref, res);
138 break;
139 case ec_binop:
140 run_binop(run, expr->u.binop, res);
141 break;
142 case ec_unop:
143 run_unop(run, expr->u.unop, res);
144 break;
145 case ec_new:
146 run_new(run, expr->u.new_op, res);
147 break;
148 case ec_access:
149 run_access(run, expr->u.access, res);
150 break;
151 case ec_call:
152 run_call(run, expr->u.call, res);
153 break;
154 case ec_index:
155 run_index(run, expr->u.index, res);
156 break;
157 case ec_assign:
158 run_assign(run, expr->u.assign, res);
159 break;
160 case ec_as:
161 run_as(run, expr->u.as_op, res);
162 break;
163 case ec_box:
164 run_box(run, expr->u.box, res);
165 break;
166 }
167
168#ifdef DEBUG_RUN_TRACE
169 printf("Expression result: ");
170 rdata_item_print(*res);
171 printf(".\n");
172#endif
173}
174
175/** Evaluate name reference expression.
176 *
177 * @param run Runner object
178 * @param nameref Name reference
179 * @param res Place to store result
180 */
181static void run_nameref(run_t *run, stree_nameref_t *nameref,
182 rdata_item_t **res)
183{
184 stree_symbol_t *sym;
185 rdata_item_t *item;
186 rdata_address_t *address;
187 rdata_addr_var_t *addr_var;
188 rdata_value_t *value;
189 rdata_var_t *var;
190 rdata_deleg_t *deleg_v;
191
192 run_proc_ar_t *proc_ar;
193 stree_symbol_t *csi_sym;
194 stree_csi_t *csi;
195 rdata_object_t *obj;
196 rdata_var_t *member_var;
197
198#ifdef DEBUG_RUN_TRACE
199 printf("Run nameref.\n");
200#endif
201
202 /*
203 * Look for a local variable.
204 */
205 var = run_local_vars_lookup(run, nameref->name->sid);
206 if (var != NULL) {
207 /* Found a local variable. */
208 item = rdata_item_new(ic_address);
209 address = rdata_address_new(ac_var);
210 addr_var = rdata_addr_var_new();
211
212 item->u.address = address;
213 address->u.var_a = addr_var;
214 addr_var->vref = var;
215
216 *res = item;
217#ifdef DEBUG_RUN_TRACE
218 printf("Found local variable.\n");
219#endif
220 return;
221 }
222
223 /*
224 * Look for a class-wide or global symbol.
225 */
226
227 /* Determine currently active object or CSI. */
228 proc_ar = run_get_current_proc_ar(run);
229 if (proc_ar->obj != NULL) {
230 assert(proc_ar->obj->vc == vc_object);
231 obj = proc_ar->obj->u.object_v;
232 csi_sym = obj->class_sym;
233 csi = symbol_to_csi(csi_sym);
234 assert(csi != NULL);
235 } else {
236 csi = proc_ar->proc->outer_symbol->outer_csi;
237 obj = NULL;
238 }
239
240 sym = symbol_lookup_in_csi(run->program, csi, nameref->name);
241
242 /* Existence should have been verified in type checking phase. */
243 assert(sym != NULL);
244
245 switch (sym->sc) {
246 case sc_csi:
247#ifdef DEBUG_RUN_TRACE
248 printf("Referencing class.\n");
249#endif
250 item = rdata_item_new(ic_value);
251 value = rdata_value_new();
252 var = rdata_var_new(vc_deleg);
253 deleg_v = rdata_deleg_new();
254
255 item->u.value = value;
256 value->var = var;
257 var->u.deleg_v = deleg_v;
258
259 deleg_v->obj = NULL;
260 deleg_v->sym = sym;
261 *res = item;
262 break;
263 case sc_fun:
264 /* There should be no global functions. */
265 assert(csi != NULL);
266
267 if (symbol_search_csi(run->program, csi, nameref->name)
268 == NULL) {
269 /* Function is not in the current object. */
270 printf("Error: Cannot access non-static member "
271 "function '");
272 symbol_print_fqn(sym);
273 printf("' from nested CSI '");
274 symbol_print_fqn(csi_sym);
275 printf("'.\n");
276 exit(1);
277 }
278
279 /* Construct delegate. */
280 item = rdata_item_new(ic_value);
281 value = rdata_value_new();
282 item->u.value = value;
283
284 var = rdata_var_new(vc_deleg);
285 deleg_v = rdata_deleg_new();
286 value->var = var;
287 var->u.deleg_v = deleg_v;
288
289 deleg_v->obj = proc_ar->obj;
290 deleg_v->sym = sym;
291
292 *res = item;
293 break;
294 case sc_var:
295#ifdef DEBUG_RUN_TRACE
296 printf("Referencing member variable.\n");
297#endif
298 /* There should be no global variables. */
299 assert(csi != NULL);
300
301 /* XXX Assume variable is not static for now. */
302 assert(obj != NULL);
303
304 if (symbol_search_csi(run->program, csi, nameref->name)
305 == NULL) {
306 /* Variable is not in the current object. */
307 printf("Error: Cannot access non-static member "
308 "variable '");
309 symbol_print_fqn(sym);
310 printf("' from nested CSI '");
311 symbol_print_fqn(csi_sym);
312 printf("'.\n");
313 exit(1);
314 }
315
316 /* Find member variable in object. */
317 member_var = intmap_get(&obj->fields, nameref->name->sid);
318 assert(member_var != NULL);
319
320 /* Return address of the variable. */
321 item = rdata_item_new(ic_address);
322 address = rdata_address_new(ac_var);
323 addr_var = rdata_addr_var_new();
324
325 item->u.address = address;
326 address->u.var_a = addr_var;
327 addr_var->vref = member_var;
328
329 *res = item;
330 break;
331 default:
332 printf("Referencing symbol class %d unimplemented.\n", sym->sc);
333 *res = NULL;
334 break;
335 }
336}
337
338/** Evaluate literal.
339 *
340 * @param run Runner object
341 * @param literal Literal
342 * @param res Place to store result
343 */
344static void run_literal(run_t *run, stree_literal_t *literal,
345 rdata_item_t **res)
346{
347#ifdef DEBUG_RUN_TRACE
348 printf("Run literal.\n");
349#endif
350 switch (literal->ltc) {
351 case ltc_bool:
352 run_lit_bool(run, &literal->u.lit_bool, res);
353 break;
354 case ltc_char:
355 run_lit_char(run, &literal->u.lit_char, res);
356 break;
357 case ltc_int:
358 run_lit_int(run, &literal->u.lit_int, res);
359 break;
360 case ltc_ref:
361 run_lit_ref(run, &literal->u.lit_ref, res);
362 break;
363 case ltc_string:
364 run_lit_string(run, &literal->u.lit_string, res);
365 break;
366 }
367}
368
369/** Evaluate Boolean literal.
370 *
371 * @param run Runner object
372 * @param lit_bool Boolean literal
373 * @param res Place to store result
374 */
375static void run_lit_bool(run_t *run, stree_lit_bool_t *lit_bool,
376 rdata_item_t **res)
377{
378 rdata_item_t *item;
379 rdata_value_t *value;
380 rdata_var_t *var;
381 rdata_bool_t *bool_v;
382
383#ifdef DEBUG_RUN_TRACE
384 printf("Run Boolean literal.\n");
385#endif
386 (void) run;
387
388 item = rdata_item_new(ic_value);
389 value = rdata_value_new();
390 var = rdata_var_new(vc_bool);
391 bool_v = rdata_bool_new();
392
393 item->u.value = value;
394 value->var = var;
395 var->u.bool_v = bool_v;
396 bool_v->value = lit_bool->value;
397
398 *res = item;
399}
400
401/** Evaluate character literal. */
402static void run_lit_char(run_t *run, stree_lit_char_t *lit_char,
403 rdata_item_t **res)
404{
405 rdata_item_t *item;
406 rdata_value_t *value;
407 rdata_var_t *var;
408 rdata_char_t *char_v;
409
410#ifdef DEBUG_RUN_TRACE
411 printf("Run character literal.\n");
412#endif
413 (void) run;
414
415 item = rdata_item_new(ic_value);
416 value = rdata_value_new();
417 var = rdata_var_new(vc_char);
418 char_v = rdata_char_new();
419
420 item->u.value = value;
421 value->var = var;
422 var->u.char_v = char_v;
423 bigint_clone(&lit_char->value, &char_v->value);
424
425 *res = item;
426}
427
428/** Evaluate integer literal.
429 *
430 * @param run Runner object
431 * @param lit_int Integer literal
432 * @param res Place to store result
433 */
434static void run_lit_int(run_t *run, stree_lit_int_t *lit_int,
435 rdata_item_t **res)
436{
437 rdata_item_t *item;
438 rdata_value_t *value;
439 rdata_var_t *var;
440 rdata_int_t *int_v;
441
442#ifdef DEBUG_RUN_TRACE
443 printf("Run integer literal.\n");
444#endif
445 (void) run;
446
447 item = rdata_item_new(ic_value);
448 value = rdata_value_new();
449 var = rdata_var_new(vc_int);
450 int_v = rdata_int_new();
451
452 item->u.value = value;
453 value->var = var;
454 var->u.int_v = int_v;
455 bigint_clone(&lit_int->value, &int_v->value);
456
457 *res = item;
458}
459
460/** Evaluate reference literal (@c nil).
461 *
462 * @param run Runner object
463 * @param lit_ref Reference literal
464 * @param res Place to store result
465 */
466static void run_lit_ref(run_t *run, stree_lit_ref_t *lit_ref,
467 rdata_item_t **res)
468{
469 rdata_item_t *item;
470 rdata_value_t *value;
471 rdata_var_t *var;
472 rdata_ref_t *ref_v;
473
474#ifdef DEBUG_RUN_TRACE
475 printf("Run reference literal (nil).\n");
476#endif
477 (void) run;
478 (void) lit_ref;
479
480 item = rdata_item_new(ic_value);
481 value = rdata_value_new();
482 var = rdata_var_new(vc_ref);
483 ref_v = rdata_ref_new();
484
485 item->u.value = value;
486 value->var = var;
487 var->u.ref_v = ref_v;
488 ref_v->vref = NULL;
489
490 *res = item;
491}
492
493/** Evaluate string literal.
494 *
495 * @param run Runner object
496 * @param lit_string String literal
497 * @param res Place to store result
498 */
499static void run_lit_string(run_t *run, stree_lit_string_t *lit_string,
500 rdata_item_t **res)
501{
502 rdata_item_t *item;
503 rdata_value_t *value;
504 rdata_var_t *var;
505 rdata_string_t *string_v;
506
507#ifdef DEBUG_RUN_TRACE
508 printf("Run integer literal.\n");
509#endif
510 (void) run;
511
512 item = rdata_item_new(ic_value);
513 value = rdata_value_new();
514 var = rdata_var_new(vc_string);
515 string_v = rdata_string_new();
516
517 item->u.value = value;
518 value->var = var;
519 var->u.string_v = string_v;
520 string_v->value = lit_string->value;
521
522 *res = item;
523}
524
525/** Evaluate @c self reference.
526 *
527 * @param run Runner object
528 * @param self_ref Self reference
529 * @param res Place to store result
530 */
531static void run_self_ref(run_t *run, stree_self_ref_t *self_ref,
532 rdata_item_t **res)
533{
534 run_proc_ar_t *proc_ar;
535
536#ifdef DEBUG_RUN_TRACE
537 printf("Run self reference.\n");
538#endif
539 (void) self_ref;
540 proc_ar = run_get_current_proc_ar(run);
541
542 /* Return reference to the currently active object. */
543 run_reference(run, proc_ar->obj, res);
544}
545
546/** Evaluate binary operation.
547 *
548 * @param run Runner object
549 * @param binop Binary operation
550 * @param res Place to store result
551 */
552static void run_binop(run_t *run, stree_binop_t *binop, rdata_item_t **res)
553{
554 rdata_item_t *rarg1_i, *rarg2_i;
555 rdata_item_t *rarg1_vi, *rarg2_vi;
556 rdata_value_t *v1, *v2;
557
558#ifdef DEBUG_RUN_TRACE
559 printf("Run binary operation.\n");
560#endif
561 run_expr(run, binop->arg1, &rarg1_i);
562 if (run_is_bo(run)) {
563 *res = NULL;
564 return;
565 }
566
567 run_expr(run, binop->arg2, &rarg2_i);
568 if (run_is_bo(run)) {
569 *res = NULL;
570 return;
571 }
572
573 switch (binop->bc) {
574 case bo_plus:
575 case bo_minus:
576 case bo_mult:
577 case bo_equal:
578 case bo_notequal:
579 case bo_lt:
580 case bo_gt:
581 case bo_lt_equal:
582 case bo_gt_equal:
583 /* These are implemented so far. */
584 break;
585 default:
586 printf("Unimplemented: Binary operation type %d.\n",
587 binop->bc);
588 exit(1);
589 }
590
591#ifdef DEBUG_RUN_TRACE
592 printf("Check binop argument results.\n");
593#endif
594
595 run_cvt_value_item(run, rarg1_i, &rarg1_vi);
596 run_cvt_value_item(run, rarg2_i, &rarg2_vi);
597
598 v1 = rarg1_vi->u.value;
599 v2 = rarg2_vi->u.value;
600
601 if (v1->var->vc != v2->var->vc) {
602 printf("Unimplemented: Binary operation arguments have "
603 "different type.\n");
604 exit(1);
605 }
606
607 switch (v1->var->vc) {
608 case vc_bool:
609 run_binop_bool(run, binop, v1, v2, res);
610 break;
611 case vc_char:
612 run_binop_char(run, binop, v1, v2, res);
613 break;
614 case vc_int:
615 run_binop_int(run, binop, v1, v2, res);
616 break;
617 case vc_string:
618 run_binop_string(run, binop, v1, v2, res);
619 break;
620 case vc_ref:
621 run_binop_ref(run, binop, v1, v2, res);
622 break;
623 case vc_deleg:
624 case vc_array:
625 case vc_object:
626 case vc_resource:
627 assert(b_false);
628 }
629}
630
631/** Evaluate binary operation on bool arguments.
632 *
633 * @param run Runner object
634 * @param binop Binary operation
635 * @param v1 Value of first argument
636 * @param v2 Value of second argument
637 * @param res Place to store result
638 */
639static void run_binop_bool(run_t *run, stree_binop_t *binop, rdata_value_t *v1,
640 rdata_value_t *v2, rdata_item_t **res)
641{
642 rdata_item_t *item;
643 rdata_value_t *value;
644 rdata_var_t *var;
645 rdata_bool_t *bool_v;
646
647 bool_t b1, b2;
648
649 (void) run;
650
651 item = rdata_item_new(ic_value);
652 value = rdata_value_new();
653 var = rdata_var_new(vc_bool);
654 bool_v = rdata_bool_new();
655
656 item->u.value = value;
657 value->var = var;
658 var->u.bool_v = bool_v;
659
660 b1 = v1->var->u.bool_v->value;
661 b2 = v2->var->u.bool_v->value;
662
663 switch (binop->bc) {
664 case bo_plus:
665 case bo_minus:
666 case bo_mult:
667 assert(b_false);
668
669 case bo_equal:
670 bool_v->value = (b1 == b2);
671 break;
672 case bo_notequal:
673 bool_v->value = (b1 != b2);
674 break;
675 case bo_lt:
676 bool_v->value = (b1 == b_false) && (b2 == b_true);
677 break;
678 case bo_gt:
679 bool_v->value = (b1 == b_true) && (b2 == b_false);
680 break;
681 case bo_lt_equal:
682 bool_v->value = (b1 == b_false) || (b2 == b_true);
683 break;
684 case bo_gt_equal:
685 bool_v->value = (b1 == b_true) || (b2 == b_false);
686 break;
687 }
688
689 *res = item;
690}
691
692/** Evaluate binary operation on char arguments.
693 *
694 * @param run Runner object
695 * @param binop Binary operation
696 * @param v1 Value of first argument
697 * @param v2 Value of second argument
698 * @param res Place to store result
699*/
700static void run_binop_char(run_t *run, stree_binop_t *binop, rdata_value_t *v1,
701 rdata_value_t *v2, rdata_item_t **res)
702{
703 rdata_item_t *item;
704 rdata_value_t *value;
705 rdata_var_t *var;
706 rdata_bool_t *bool_v;
707
708 bigint_t *c1, *c2;
709 bigint_t diff;
710 bool_t zf, nf;
711
712 (void) run;
713
714 item = rdata_item_new(ic_value);
715 value = rdata_value_new();
716
717 item->u.value = value;
718
719 c1 = &v1->var->u.char_v->value;
720 c2 = &v2->var->u.char_v->value;
721
722 var = rdata_var_new(vc_bool);
723 bool_v = rdata_bool_new();
724 var->u.bool_v = bool_v;
725 value->var = var;
726
727 bigint_sub(c1, c2, &diff);
728 zf = bigint_is_zero(&diff);
729 nf = bigint_is_negative(&diff);
730
731 switch (binop->bc) {
732 case bo_plus:
733 case bo_minus:
734 case bo_mult:
735 assert(b_false);
736
737 case bo_equal:
738 bool_v->value = zf;
739 break;
740 case bo_notequal:
741 bool_v->value = !zf;
742 break;
743 case bo_lt:
744 bool_v->value = (!zf && nf);
745 break;
746 case bo_gt:
747 bool_v->value = (!zf && !nf);
748 break;
749 case bo_lt_equal:
750 bool_v->value = (zf || nf);
751 break;
752 case bo_gt_equal:
753 bool_v->value = !nf;
754 break;
755 default:
756 assert(b_false);
757 }
758
759 *res = item;
760}
761
762/** Evaluate binary operation on int arguments.
763 *
764 * @param run Runner object
765 * @param binop Binary operation
766 * @param v1 Value of first argument
767 * @param v2 Value of second argument
768 * @param res Place to store result
769*/
770static void run_binop_int(run_t *run, stree_binop_t *binop, rdata_value_t *v1,
771 rdata_value_t *v2, rdata_item_t **res)
772{
773 rdata_item_t *item;
774 rdata_value_t *value;
775 rdata_var_t *var;
776 rdata_int_t *int_v;
777 rdata_bool_t *bool_v;
778
779 bigint_t *i1, *i2;
780 bigint_t diff;
781 bool_t done;
782 bool_t zf, nf;
783
784 (void) run;
785
786 item = rdata_item_new(ic_value);
787 value = rdata_value_new();
788
789 item->u.value = value;
790
791 i1 = &v1->var->u.int_v->value;
792 i2 = &v2->var->u.int_v->value;
793
794 done = b_true;
795
796 switch (binop->bc) {
797 case bo_plus:
798 int_v = rdata_int_new();
799 bigint_add(i1, i2, &int_v->value);
800 break;
801 case bo_minus:
802 int_v = rdata_int_new();
803 bigint_sub(i1, i2, &int_v->value);
804 break;
805 case bo_mult:
806 int_v = rdata_int_new();
807 bigint_mul(i1, i2, &int_v->value);
808 break;
809 default:
810 done = b_false;
811 break;
812 }
813
814 if (done) {
815 var = rdata_var_new(vc_int);
816 var->u.int_v = int_v;
817 value->var = var;
818 *res = item;
819 return;
820 }
821
822 var = rdata_var_new(vc_bool);
823 bool_v = rdata_bool_new();
824 var->u.bool_v = bool_v;
825 value->var = var;
826
827 /* Relational operation. */
828
829 bigint_sub(i1, i2, &diff);
830 zf = bigint_is_zero(&diff);
831 nf = bigint_is_negative(&diff);
832
833 switch (binop->bc) {
834 case bo_equal:
835 bool_v->value = zf;
836 break;
837 case bo_notequal:
838 bool_v->value = !zf;
839 break;
840 case bo_lt:
841 bool_v->value = (!zf && nf);
842 break;
843 case bo_gt:
844 bool_v->value = (!zf && !nf);
845 break;
846 case bo_lt_equal:
847 bool_v->value = (zf || nf);
848 break;
849 case bo_gt_equal:
850 bool_v->value = !nf;
851 break;
852 default:
853 assert(b_false);
854 }
855
856 *res = item;
857}
858
859/** Evaluate binary operation on string arguments.
860 *
861 * @param run Runner object
862 * @param binop Binary operation
863 * @param v1 Value of first argument
864 * @param v2 Value of second argument
865 * @param res Place to store result
866 */
867static void run_binop_string(run_t *run, stree_binop_t *binop, rdata_value_t *v1,
868 rdata_value_t *v2, rdata_item_t **res)
869{
870 rdata_item_t *item;
871 rdata_value_t *value;
872 rdata_var_t *var;
873 rdata_string_t *string_v;
874
875 const char *s1, *s2;
876
877 (void) run;
878
879 item = rdata_item_new(ic_value);
880 value = rdata_value_new();
881 var = rdata_var_new(vc_string);
882 string_v = rdata_string_new();
883
884 item->u.value = value;
885 value->var = var;
886 var->u.string_v = string_v;
887
888 s1 = v1->var->u.string_v->value;
889 s2 = v2->var->u.string_v->value;
890
891 switch (binop->bc) {
892 case bo_plus:
893 /* Concatenate strings. */
894 string_v->value = os_str_acat(s1, s2);
895 break;
896 default:
897 printf("Error: Invalid binary operation on string "
898 "arguments (%d).\n", binop->bc);
899 assert(b_false);
900 }
901
902 *res = item;
903}
904
905/** Evaluate binary operation on ref arguments.
906 *
907 * @param run Runner object
908 * @param binop Binary operation
909 * @param v1 Value of first argument
910 * @param v2 Value of second argument
911 * @param res Place to store result
912 */
913static void run_binop_ref(run_t *run, stree_binop_t *binop, rdata_value_t *v1,
914 rdata_value_t *v2, rdata_item_t **res)
915{
916 rdata_item_t *item;
917 rdata_value_t *value;
918 rdata_var_t *var;
919 rdata_bool_t *bool_v;
920
921 rdata_var_t *ref1, *ref2;
922
923 (void) run;
924
925 item = rdata_item_new(ic_value);
926 value = rdata_value_new();
927 var = rdata_var_new(vc_bool);
928 bool_v = rdata_bool_new();
929
930 item->u.value = value;
931 value->var = var;
932 var->u.bool_v = bool_v;
933
934 ref1 = v1->var->u.ref_v->vref;
935 ref2 = v2->var->u.ref_v->vref;
936
937 switch (binop->bc) {
938 case bo_equal:
939 bool_v->value = (ref1 == ref2);
940 break;
941 case bo_notequal:
942 bool_v->value = (ref1 != ref2);
943 break;
944 default:
945 printf("Error: Invalid binary operation on reference "
946 "arguments (%d).\n", binop->bc);
947 assert(b_false);
948 }
949
950 *res = item;
951}
952
953
954/** Evaluate unary operation.
955 *
956 * @param run Runner object
957 * @param unop Unary operation
958 * @param res Place to store result
959 */
960static void run_unop(run_t *run, stree_unop_t *unop, rdata_item_t **res)
961{
962 rdata_item_t *rarg_i;
963 rdata_item_t *rarg_vi;
964 rdata_value_t *val;
965
966#ifdef DEBUG_RUN_TRACE
967 printf("Run unary operation.\n");
968#endif
969 run_expr(run, unop->arg, &rarg_i);
970 if (run_is_bo(run)) {
971 *res = NULL;
972 return;
973 }
974
975#ifdef DEBUG_RUN_TRACE
976 printf("Check unop argument result.\n");
977#endif
978 run_cvt_value_item(run, rarg_i, &rarg_vi);
979
980 val = rarg_vi->u.value;
981
982 switch (val->var->vc) {
983 case vc_int:
984 run_unop_int(run, unop, val, res);
985 break;
986 default:
987 printf("Unimplemented: Unrary operation argument of "
988 "type %d.\n", val->var->vc);
989 run_raise_error(run);
990 *res = NULL;
991 break;
992 }
993}
994
995/** Evaluate unary operation on int argument.
996 *
997 * @param run Runner object
998 * @param unop Unary operation
999 * @param val Value of argument
1000 * @param res Place to store result
1001 */
1002static void run_unop_int(run_t *run, stree_unop_t *unop, rdata_value_t *val,
1003 rdata_item_t **res)
1004{
1005 rdata_item_t *item;
1006 rdata_value_t *value;
1007 rdata_var_t *var;
1008 rdata_int_t *int_v;
1009
1010 (void) run;
1011
1012 item = rdata_item_new(ic_value);
1013 value = rdata_value_new();
1014 var = rdata_var_new(vc_int);
1015 int_v = rdata_int_new();
1016
1017 item->u.value = value;
1018 value->var = var;
1019 var->u.int_v = int_v;
1020
1021 switch (unop->uc) {
1022 case uo_plus:
1023 bigint_clone(&val->var->u.int_v->value, &int_v->value);
1024 break;
1025 case uo_minus:
1026 bigint_reverse_sign(&val->var->u.int_v->value,
1027 &int_v->value);
1028 break;
1029 }
1030
1031 *res = item;
1032}
1033
1034
1035/** Evaluate @c new operation.
1036 *
1037 * Evaluates operation per the @c new operator that creates a new
1038 * instance of some type.
1039 *
1040 * @param run Runner object
1041 * @param unop Unary operation
1042 * @param res Place to store result
1043 */
1044static void run_new(run_t *run, stree_new_t *new_op, rdata_item_t **res)
1045{
1046 tdata_item_t *titem;
1047
1048#ifdef DEBUG_RUN_TRACE
1049 printf("Run 'new' operation.\n");
1050#endif
1051 /* Evaluate type expression */
1052 run_texpr(run->program, run_get_current_csi(run), new_op->texpr,
1053 &titem);
1054
1055 switch (titem->tic) {
1056 case tic_tarray:
1057 run_new_array(run, new_op, titem, res);
1058 break;
1059 case tic_tobject:
1060 run_new_object(run, new_op, titem, res);
1061 break;
1062 default:
1063 printf("Error: Invalid argument to operator 'new', "
1064 "expected object.\n");
1065 exit(1);
1066 }
1067}
1068
1069/** Create new array.
1070 *
1071 * @param run Runner object
1072 * @param new_op New operation
1073 * @param titem Type of new var node (tic_tarray)
1074 * @param res Place to store result
1075 */
1076static void run_new_array(run_t *run, stree_new_t *new_op,
1077 tdata_item_t *titem, rdata_item_t **res)
1078{
1079 tdata_array_t *tarray;
1080 rdata_array_t *array;
1081 rdata_var_t *array_var;
1082 rdata_var_t *elem_var;
1083
1084 rdata_item_t *rexpr, *rexpr_vi;
1085 rdata_var_t *rexpr_var;
1086
1087 stree_expr_t *expr;
1088
1089 list_node_t *node;
1090 int length;
1091 int i;
1092 int rc;
1093 int iextent;
1094
1095#ifdef DEBUG_RUN_TRACE
1096 printf("Create new array.\n");
1097#endif
1098 (void) run;
1099 (void) new_op;
1100
1101 assert(titem->tic == tic_tarray);
1102 tarray = titem->u.tarray;
1103
1104 /* Create the array. */
1105 assert(titem->u.tarray->rank > 0);
1106 array = rdata_array_new(titem->u.tarray->rank);
1107
1108 /* Compute extents. */
1109 node = list_first(&tarray->extents);
1110 if (node == NULL) {
1111 printf("Error: Extents must be specified when constructing "
1112 "an array with 'new'.\n");
1113 exit(1);
1114 }
1115
1116 i = 0; length = 1;
1117 while (node != NULL) {
1118 expr = list_node_data(node, stree_expr_t *);
1119
1120 /* Evaluate extent argument. */
1121 run_expr(run, expr, &rexpr);
1122 if (run_is_bo(run)) {
1123 *res = NULL;
1124 return;
1125 }
1126
1127 run_cvt_value_item(run, rexpr, &rexpr_vi);
1128 assert(rexpr_vi->ic == ic_value);
1129 rexpr_var = rexpr_vi->u.value->var;
1130
1131 if (rexpr_var->vc != vc_int) {
1132 printf("Error: Array extent must be an integer.\n");
1133 exit(1);
1134 }
1135
1136#ifdef DEBUG_RUN_TRACE
1137 printf("Array extent: ");
1138 bigint_print(&rexpr_var->u.int_v->value);
1139 printf(".\n");
1140#endif
1141 rc = bigint_get_value_int(&rexpr_var->u.int_v->value,
1142 &iextent);
1143 if (rc != EOK) {
1144 printf("Memory allocation failed (big int used).\n");
1145 exit(1);
1146 }
1147
1148 array->extent[i] = iextent;
1149 length = length * array->extent[i];
1150
1151 node = list_next(&tarray->extents, node);
1152 i += 1;
1153 }
1154
1155 array->element = calloc(length, sizeof(rdata_var_t *));
1156 if (array->element == NULL) {
1157 printf("Memory allocation failed.\n");
1158 exit(1);
1159 }
1160
1161 /* Create member variables */
1162 for (i = 0; i < length; ++i) {
1163 /* Create and initialize element. */
1164 run_var_new(run, tarray->base_ti, &elem_var);
1165
1166 array->element[i] = elem_var;
1167 }
1168
1169 /* Create array variable. */
1170 array_var = rdata_var_new(vc_array);
1171 array_var->u.array_v = array;
1172
1173 /* Create reference to the new array. */
1174 run_reference(run, array_var, res);
1175}
1176
1177/** Create new object.
1178 *
1179 * @param run Runner object
1180 * @param new_op New operation
1181 * @param titem Type of new var node (tic_tobject)
1182 * @param res Place to store result
1183 */
1184static void run_new_object(run_t *run, stree_new_t *new_op,
1185 tdata_item_t *titem, rdata_item_t **res)
1186{
1187 stree_csi_t *csi;
1188
1189#ifdef DEBUG_RUN_TRACE
1190 printf("Create new object.\n");
1191#endif
1192 (void) new_op;
1193
1194 /* Lookup object CSI. */
1195 assert(titem->tic == tic_tobject);
1196 csi = titem->u.tobject->csi;
1197
1198 /* Create CSI instance. */
1199 run_new_csi_inst(run, csi, res);
1200}
1201
1202/** Evaluate member acccess.
1203 *
1204 * Evaluate operation per the member access ('.') operator.
1205 *
1206 * @param run Runner object
1207 * @param access Access operation
1208 * @param res Place to store result
1209 */
1210static void run_access(run_t *run, stree_access_t *access, rdata_item_t **res)
1211{
1212 rdata_item_t *rarg;
1213
1214#ifdef DEBUG_RUN_TRACE
1215 printf("Run access operation.\n");
1216#endif
1217 run_expr(run, access->arg, &rarg);
1218 if (run_is_bo(run)) {
1219 *res = NULL;
1220 return;
1221 }
1222
1223 if (rarg == NULL) {
1224 printf("Error: Sub-expression has no value.\n");
1225 exit(1);
1226 }
1227
1228 run_access_item(run, access, rarg, res);
1229}
1230
1231/** Evaluate member acccess (with base already evaluated).
1232 *
1233 * @param run Runner object
1234 * @param access Access operation
1235 * @param arg Evaluated base expression
1236 * @param res Place to store result
1237 */
1238static void run_access_item(run_t *run, stree_access_t *access,
1239 rdata_item_t *arg, rdata_item_t **res)
1240{
1241 var_class_t vc;
1242
1243#ifdef DEBUG_RUN_TRACE
1244 printf("Run access operation on pre-evaluated base.\n");
1245#endif
1246 vc = run_item_get_vc(run, arg);
1247
1248 switch (vc) {
1249 case vc_ref:
1250 run_access_ref(run, access, arg, res);
1251 break;
1252 case vc_deleg:
1253 run_access_deleg(run, access, arg, res);
1254 break;
1255 case vc_object:
1256 run_access_object(run, access, arg, res);
1257 break;
1258 default:
1259 printf("Unimplemented: Using access operator ('.') "
1260 "with unsupported data type (value/%d).\n", vc);
1261 exit(1);
1262 }
1263}
1264
1265/** Evaluate reference acccess.
1266 *
1267 * @param run Runner object
1268 * @param access Access operation
1269 * @param arg Evaluated base expression
1270 * @param res Place to store result
1271 */
1272static void run_access_ref(run_t *run, stree_access_t *access,
1273 rdata_item_t *arg, rdata_item_t **res)
1274{
1275 rdata_item_t *darg;
1276
1277 /* Implicitly dereference. */
1278 run_dereference(run, arg, &darg);
1279
1280 if (run->thread_ar->bo_mode != bm_none) {
1281 *res = run_recovery_item(run);
1282 return;
1283 }
1284
1285 /* Try again. */
1286 run_access_item(run, access, darg, res);
1287}
1288
1289/** Evaluate delegate-member acccess.
1290 *
1291 * @param run Runner object
1292 * @param access Access operation
1293 * @param arg Evaluated base expression
1294 * @param res Place to store result
1295 */
1296static void run_access_deleg(run_t *run, stree_access_t *access,
1297 rdata_item_t *arg, rdata_item_t **res)
1298{
1299 rdata_item_t *arg_vi;
1300 rdata_value_t *arg_val;
1301 rdata_deleg_t *deleg_v;
1302 stree_symbol_t *member;
1303
1304#ifdef DEBUG_RUN_TRACE
1305 printf("Run delegate access operation.\n");
1306#endif
1307 run_cvt_value_item(run, arg, &arg_vi);
1308 arg_val = arg_vi->u.value;
1309 assert(arg_val->var->vc == vc_deleg);
1310
1311 deleg_v = arg_val->var->u.deleg_v;
1312 if (deleg_v->obj != NULL || deleg_v->sym->sc != sc_csi) {
1313 printf("Error: Using '.' with delegate to different object "
1314 "than a CSI (%d).\n", deleg_v->sym->sc);
1315 exit(1);
1316 }
1317
1318 member = symbol_search_csi(run->program, deleg_v->sym->u.csi,
1319 access->member_name);
1320
1321 /* Member existence should be ensured by static type checking. */
1322 assert(member != NULL);
1323
1324#ifdef DEBUG_RUN_TRACE
1325 printf("Found member '%s'.\n",
1326 strtab_get_str(access->member_name->sid));
1327#endif
1328
1329 /*
1330 * Reuse existing item, value, var, deleg.
1331 * XXX This is maybe not a good idea because it complicates memory
1332 * management as there is not a single owner
1333 */
1334 deleg_v->sym = member;
1335 *res = arg;
1336}
1337
1338/** Evaluate object member acccess.
1339 *
1340 * @param run Runner object
1341 * @param access Access operation
1342 * @param arg Evaluated base expression
1343 * @param res Place to store result
1344 */
1345static void run_access_object(run_t *run, stree_access_t *access,
1346 rdata_item_t *arg, rdata_item_t **res)
1347{
1348 stree_symbol_t *member;
1349 rdata_var_t *object_var;
1350 rdata_object_t *object;
1351 rdata_item_t *ritem;
1352 rdata_address_t *address;
1353 rdata_addr_var_t *addr_var;
1354 rdata_addr_prop_t *addr_prop;
1355 rdata_aprop_named_t *aprop_named;
1356 rdata_deleg_t *deleg_p;
1357
1358 rdata_value_t *value;
1359 rdata_deleg_t *deleg_v;
1360 rdata_var_t *var;
1361
1362#ifdef DEBUG_RUN_TRACE
1363 printf("Run object access operation.\n");
1364#endif
1365 assert(arg->ic == ic_address);
1366 assert(arg->u.address->ac == ac_var);
1367 assert(arg->u.address->u.var_a->vref->vc == vc_object);
1368
1369 object_var = arg->u.address->u.var_a->vref;
1370 object = object_var->u.object_v;
1371
1372 member = symbol_search_csi(run->program, object->class_sym->u.csi,
1373 access->member_name);
1374
1375 if (member == NULL) {
1376 printf("Error: Object of class '");
1377 symbol_print_fqn(object->class_sym);
1378 printf("' has no member named '%s'.\n",
1379 strtab_get_str(access->member_name->sid));
1380 exit(1);
1381 }
1382
1383#ifdef DEBUG_RUN_TRACE
1384 printf("Found member '%s'.\n",
1385 strtab_get_str(access->member_name->sid));
1386#endif
1387
1388 switch (member->sc) {
1389 case sc_csi:
1390 printf("Error: Accessing object member which is nested CSI.\n");
1391 exit(1);
1392 case sc_deleg:
1393 printf("Error: Accessing object member which is a delegate.\n");
1394 exit(1);
1395 case sc_fun:
1396 /* Construct anonymous delegate. */
1397 ritem = rdata_item_new(ic_value);
1398 value = rdata_value_new();
1399 ritem->u.value = value;
1400
1401 var = rdata_var_new(vc_deleg);
1402 value->var = var;
1403 deleg_v = rdata_deleg_new();
1404 var->u.deleg_v = deleg_v;
1405
1406 deleg_v->obj = arg->u.address->u.var_a->vref;
1407 deleg_v->sym = member;
1408 break;
1409 case sc_var:
1410 /* Construct variable address item. */
1411 ritem = rdata_item_new(ic_address);
1412 address = rdata_address_new(ac_var);
1413 addr_var = rdata_addr_var_new();
1414 ritem->u.address = address;
1415 address->u.var_a = addr_var;
1416
1417 addr_var->vref = intmap_get(&object->fields,
1418 access->member_name->sid);
1419 assert(addr_var->vref != NULL);
1420 break;
1421 case sc_prop:
1422 /* Construct named property address. */
1423 ritem = rdata_item_new(ic_address);
1424 address = rdata_address_new(ac_prop);
1425 addr_prop = rdata_addr_prop_new(apc_named);
1426 aprop_named = rdata_aprop_named_new();
1427 ritem->u.address = address;
1428 address->u.prop_a = addr_prop;
1429 addr_prop->u.named = aprop_named;
1430
1431 deleg_p = rdata_deleg_new();
1432 deleg_p->obj = object_var;
1433 deleg_p->sym = member;
1434 addr_prop->u.named->prop_d = deleg_p;
1435 break;
1436 default:
1437 ritem = NULL;
1438 }
1439
1440 *res = ritem;
1441}
1442
1443/** Call a function.
1444 *
1445 * Call a function and return the result in @a res.
1446 *
1447 * @param run Runner object
1448 * @param call Call operation
1449 * @param res Place to store result
1450 */
1451static void run_call(run_t *run, stree_call_t *call, rdata_item_t **res)
1452{
1453 rdata_item_t *rdeleg, *rdeleg_vi;
1454 rdata_deleg_t *deleg_v;
1455 list_t arg_vals;
1456 list_node_t *node;
1457 stree_expr_t *arg;
1458 rdata_item_t *rarg_i, *rarg_vi;
1459
1460 stree_fun_t *fun;
1461 run_proc_ar_t *proc_ar;
1462
1463#ifdef DEBUG_RUN_TRACE
1464 printf("Run call operation.\n");
1465#endif
1466 run_expr(run, call->fun, &rdeleg);
1467 if (run_is_bo(run)) {
1468 *res = NULL;
1469 return;
1470 }
1471
1472 if (run->thread_ar->bo_mode != bm_none) {
1473 *res = run_recovery_item(run);
1474 return;
1475 }
1476
1477 run_cvt_value_item(run, rdeleg, &rdeleg_vi);
1478 assert(rdeleg_vi->ic == ic_value);
1479
1480 if (rdeleg_vi->u.value->var->vc != vc_deleg) {
1481 printf("Unimplemented: Call expression of this type (");
1482 rdata_item_print(rdeleg_vi);
1483 printf(").\n");
1484 exit(1);
1485 }
1486
1487 deleg_v = rdeleg_vi->u.value->var->u.deleg_v;
1488
1489 if (deleg_v->sym->sc != sc_fun) {
1490 printf("Error: Called symbol is not a function.\n");
1491 exit(1);
1492 }
1493
1494#ifdef DEBUG_RUN_TRACE
1495 printf("Call function '");
1496 symbol_print_fqn(deleg_v->sym);
1497 printf("'\n");
1498#endif
1499 /* Evaluate function arguments. */
1500 list_init(&arg_vals);
1501 node = list_first(&call->args);
1502
1503 while (node != NULL) {
1504 arg = list_node_data(node, stree_expr_t *);
1505 run_expr(run, arg, &rarg_i);
1506 if (run_is_bo(run)) {
1507 *res = NULL;
1508 return;
1509 }
1510
1511 run_cvt_value_item(run, rarg_i, &rarg_vi);
1512
1513 list_append(&arg_vals, rarg_vi);
1514 node = list_next(&call->args, node);
1515 }
1516
1517 fun = symbol_to_fun(deleg_v->sym);
1518 assert(fun != NULL);
1519
1520 /* Create procedure activation record. */
1521 run_proc_ar_create(run, deleg_v->obj, fun->proc, &proc_ar);
1522
1523 /* Fill in argument values. */
1524 run_proc_ar_set_args(run, proc_ar, &arg_vals);
1525
1526 /* Run the function. */
1527 run_proc(run, proc_ar, res);
1528
1529#ifdef DEBUG_RUN_TRACE
1530 printf("Returned from function call.\n");
1531#endif
1532}
1533
1534/** Run index operation.
1535 *
1536 * Evaluate operation per the indexing ('[', ']') operator.
1537 *
1538 * @param run Runner object
1539 * @param index Index operation
1540 * @param res Place to store result
1541 */
1542static void run_index(run_t *run, stree_index_t *index, rdata_item_t **res)
1543{
1544 rdata_item_t *rbase;
1545 rdata_item_t *base_i;
1546 list_node_t *node;
1547 stree_expr_t *arg;
1548 rdata_item_t *rarg_i, *rarg_vi;
1549 var_class_t vc;
1550 list_t arg_vals;
1551
1552#ifdef DEBUG_RUN_TRACE
1553 printf("Run index operation.\n");
1554#endif
1555 run_expr(run, index->base, &rbase);
1556 if (run_is_bo(run)) {
1557 *res = NULL;
1558 return;
1559 }
1560
1561 vc = run_item_get_vc(run, rbase);
1562
1563 /* Implicitly dereference. */
1564 if (vc == vc_ref) {
1565 run_dereference(run, rbase, &base_i);
1566 } else {
1567 base_i = rbase;
1568 }
1569
1570 vc = run_item_get_vc(run, base_i);
1571
1572 /* Evaluate arguments (indices). */
1573 node = list_first(&index->args);
1574 list_init(&arg_vals);
1575
1576 while (node != NULL) {
1577 arg = list_node_data(node, stree_expr_t *);
1578 run_expr(run, arg, &rarg_i);
1579 if (run_is_bo(run)) {
1580 *res = NULL;
1581 return;
1582 }
1583
1584 run_cvt_value_item(run, rarg_i, &rarg_vi);
1585
1586 list_append(&arg_vals, rarg_vi);
1587
1588 node = list_next(&index->args, node);
1589 }
1590
1591 switch (vc) {
1592 case vc_array:
1593 run_index_array(run, index, base_i, &arg_vals, res);
1594 break;
1595 case vc_object:
1596 run_index_object(run, index, base_i, &arg_vals, res);
1597 break;
1598 case vc_string:
1599 run_index_string(run, index, base_i, &arg_vals, res);
1600 break;
1601 default:
1602 printf("Error: Indexing object of bad type (%d).\n", vc);
1603 exit(1);
1604 }
1605}
1606
1607/** Run index operation on array.
1608 *
1609 * @param run Runner object
1610 * @param index Index operation
1611 * @param base Evaluated base expression
1612 * @param args Evaluated indices (list of rdata_item_t)
1613 * @param res Place to store result
1614 */
1615static void run_index_array(run_t *run, stree_index_t *index,
1616 rdata_item_t *base, list_t *args, rdata_item_t **res)
1617{
1618 list_node_t *node;
1619 rdata_array_t *array;
1620 rdata_item_t *arg;
1621
1622 int i;
1623 int elem_index;
1624 int arg_val;
1625 int rc;
1626
1627 rdata_item_t *ritem;
1628 rdata_address_t *address;
1629 rdata_addr_var_t *addr_var;
1630
1631#ifdef DEBUG_RUN_TRACE
1632 printf("Run array index operation.\n");
1633#endif
1634 (void) run;
1635 (void) index;
1636
1637 assert(base->ic == ic_address);
1638 assert(base->u.address->ac == ac_var);
1639 assert(base->u.address->u.var_a->vref->vc == vc_array);
1640 array = base->u.address->u.var_a->vref->u.array_v;
1641
1642 /*
1643 * Linear index of the desired element. Elements are stored in
1644 * lexicographic order with the last index changing the fastest.
1645 */
1646 elem_index = 0;
1647
1648 node = list_first(args);
1649 i = 0;
1650
1651 while (node != NULL) {
1652 if (i >= array->rank) {
1653 printf("Error: Too many indices for array of rank %d",
1654 array->rank);
1655 exit(1);
1656 }
1657
1658 arg = list_node_data(node, rdata_item_t *);
1659 assert(arg->ic == ic_value);
1660
1661 if (arg->u.value->var->vc != vc_int) {
1662 printf("Error: Array index is not an integer.\n");
1663 exit(1);
1664 }
1665
1666 rc = bigint_get_value_int(
1667 &arg->u.value->var->u.int_v->value,
1668 &arg_val);
1669
1670 if (rc != EOK || arg_val < 0 || arg_val >= array->extent[i]) {
1671#ifdef DEBUG_RUN_TRACE
1672 printf("Error: Array index (value: %d) is out of range.\n",
1673 arg_val);
1674#endif
1675 /* Raise Error.OutOfBounds */
1676 run_raise_exc(run,
1677 run->program->builtin->error_outofbounds);
1678 *res = run_recovery_item(run);
1679 return;
1680 }
1681
1682 elem_index = elem_index * array->extent[i] + arg_val;
1683
1684 node = list_next(args, node);
1685 i += 1;
1686 }
1687
1688 if (i < array->rank) {
1689 printf("Error: Too few indices for array of rank %d",
1690 array->rank);
1691 exit(1);
1692 }
1693
1694 /* Construct variable address item. */
1695 ritem = rdata_item_new(ic_address);
1696 address = rdata_address_new(ac_var);
1697 addr_var = rdata_addr_var_new();
1698 ritem->u.address = address;
1699 address->u.var_a = addr_var;
1700
1701 addr_var->vref = array->element[elem_index];
1702
1703 *res = ritem;
1704}
1705
1706/** Index an object (via its indexer).
1707 *
1708 * @param run Runner object
1709 * @param index Index operation
1710 * @param base Evaluated base expression
1711 * @param args Evaluated indices (list of rdata_item_t)
1712 * @param res Place to store result
1713 */
1714static void run_index_object(run_t *run, stree_index_t *index,
1715 rdata_item_t *base, list_t *args, rdata_item_t **res)
1716{
1717 rdata_item_t *ritem;
1718 rdata_address_t *address;
1719 rdata_addr_prop_t *addr_prop;
1720 rdata_aprop_indexed_t *aprop_indexed;
1721 rdata_var_t *obj_var;
1722 stree_csi_t *obj_csi;
1723 rdata_deleg_t *object_d;
1724 stree_symbol_t *indexer_sym;
1725 stree_ident_t *indexer_ident;
1726
1727 list_node_t *node;
1728 rdata_item_t *arg;
1729
1730#ifdef DEBUG_RUN_TRACE
1731 printf("Run object index operation.\n");
1732#endif
1733 (void) index;
1734
1735 /* Construct property address item. */
1736 ritem = rdata_item_new(ic_address);
1737 address = rdata_address_new(ac_prop);
1738 addr_prop = rdata_addr_prop_new(apc_indexed);
1739 aprop_indexed = rdata_aprop_indexed_new();
1740 ritem->u.address = address;
1741 address->u.prop_a = addr_prop;
1742 addr_prop->u.indexed = aprop_indexed;
1743
1744 if (base->ic != ic_address || base->u.address->ac != ac_var) {
1745 /* XXX Several other cases can occur. */
1746 printf("Unimplemented: Indexing object varclass via something "
1747 "which is not a simple variable reference.\n");
1748 exit(1);
1749 }
1750
1751 /* Find indexer symbol. */
1752 obj_var = base->u.address->u.var_a->vref;
1753 assert(obj_var->vc == vc_object);
1754 indexer_ident = stree_ident_new();
1755 indexer_ident->sid = strtab_get_sid(INDEXER_IDENT);
1756 obj_csi = symbol_to_csi(obj_var->u.object_v->class_sym);
1757 assert(obj_csi != NULL);
1758 indexer_sym = symbol_search_csi(run->program, obj_csi, indexer_ident);
1759
1760 if (indexer_sym == NULL) {
1761 printf("Error: Accessing object which does not have an "
1762 "indexer.\n");
1763 exit(1);
1764 }
1765
1766 /* Construct delegate. */
1767 object_d = rdata_deleg_new();
1768 object_d->obj = obj_var;
1769 object_d->sym = indexer_sym;
1770 aprop_indexed->object_d = object_d;
1771
1772 /* Copy list of argument values. */
1773 list_init(&aprop_indexed->args);
1774
1775 node = list_first(args);
1776 while (node != NULL) {
1777 arg = list_node_data(node, rdata_item_t *);
1778 list_append(&aprop_indexed->args, arg);
1779 node = list_next(args, node);
1780 }
1781
1782 *res = ritem;
1783}
1784
1785/** Run index operation on string.
1786 *
1787 * @param run Runner object
1788 * @param index Index operation
1789 * @param base Evaluated base expression
1790 * @param args Evaluated indices (list of rdata_item_t)
1791 * @param res Place to store result
1792 */
1793static void run_index_string(run_t *run, stree_index_t *index,
1794 rdata_item_t *base, list_t *args, rdata_item_t **res)
1795{
1796 list_node_t *node;
1797 rdata_string_t *string;
1798 rdata_item_t *base_vi;
1799 rdata_item_t *arg;
1800
1801 int i;
1802 int elem_index;
1803 int arg_val;
1804 int rc1, rc2;
1805
1806 rdata_value_t *value;
1807 rdata_var_t *cvar;
1808 rdata_item_t *ritem;
1809 int cval;
1810
1811#ifdef DEBUG_RUN_TRACE
1812 printf("Run string index operation.\n");
1813#endif
1814 (void) run;
1815 (void) index;
1816
1817 run_cvt_value_item(run, base, &base_vi);
1818 assert(base_vi->u.value->var->vc == vc_string);
1819 string = base_vi->u.value->var->u.string_v;
1820
1821 /*
1822 * Linear index of the desired element. Elements are stored in
1823 * lexicographic order with the last index changing the fastest.
1824 */
1825 node = list_first(args);
1826 elem_index = 0;
1827
1828 i = 0;
1829 while (node != NULL) {
1830 if (i >= 1) {
1831 printf("Error: Too many indices string.\n");
1832 exit(1);
1833 }
1834
1835 arg = list_node_data(node, rdata_item_t *);
1836 assert(arg->ic == ic_value);
1837
1838 if (arg->u.value->var->vc != vc_int) {
1839 printf("Error: String index is not an integer.\n");
1840 exit(1);
1841 }
1842
1843 rc1 = bigint_get_value_int(
1844 &arg->u.value->var->u.int_v->value,
1845 &arg_val);
1846
1847 elem_index = arg_val;
1848
1849 node = list_next(args, node);
1850 i += 1;
1851 }
1852
1853 if (i < 1) {
1854 printf("Error: Too few indices for string.\n");
1855 exit(1);
1856 }
1857
1858 if (rc1 == EOK)
1859 rc2 = os_str_get_char(string->value, elem_index, &cval);
1860
1861 if (rc1 != EOK || rc2 != EOK) {
1862#ifdef DEBUG_RUN_TRACE
1863 printf("Error: String index (value: %d) is out of range.\n",
1864 arg_val);
1865#endif
1866 /* Raise Error.OutOfBounds */
1867 run_raise_exc(run, run->program->builtin->error_outofbounds);
1868 *res = run_recovery_item(run);
1869 return;
1870 }
1871
1872 /* Construct character value. */
1873 ritem = rdata_item_new(ic_value);
1874 value = rdata_value_new();
1875 ritem->u.value = value;
1876
1877 cvar = rdata_var_new(vc_char);
1878 cvar->u.char_v = rdata_char_new();
1879 bigint_init(&cvar->u.char_v->value, cval);
1880 value->var = cvar;
1881
1882 *res = ritem;
1883}
1884
1885/** Run assignment.
1886 *
1887 * Executes an assignment. @c NULL is always stored to @a res because
1888 * an assignment does not have a value.
1889 *
1890 * @param run Runner object
1891 * @param assign Assignment expression
1892 * @param res Place to store result
1893*/
1894static void run_assign(run_t *run, stree_assign_t *assign, rdata_item_t **res)
1895{
1896 rdata_item_t *rdest_i, *rsrc_i;
1897 rdata_item_t *rsrc_vi;
1898 rdata_value_t *src_val;
1899
1900#ifdef DEBUG_RUN_TRACE
1901 printf("Run assign operation.\n");
1902#endif
1903 run_expr(run, assign->dest, &rdest_i);
1904 if (run_is_bo(run)) {
1905 *res = NULL;
1906 return;
1907 }
1908
1909 run_expr(run, assign->src, &rsrc_i);
1910 if (run_is_bo(run)) {
1911 *res = NULL;
1912 return;
1913 }
1914
1915 run_cvt_value_item(run, rsrc_i, &rsrc_vi);
1916 assert(rsrc_vi->ic == ic_value);
1917 src_val = rsrc_vi->u.value;
1918
1919 if (rdest_i->ic != ic_address) {
1920 printf("Error: Address expression required on left side of "
1921 "assignment operator.\n");
1922 exit(1);
1923 }
1924
1925 run_address_write(run, rdest_i->u.address, rsrc_vi->u.value);
1926
1927 *res = NULL;
1928}
1929
1930/** Execute @c as conversion.
1931 *
1932 * @param run Runner object
1933 * @param as_op @c as conversion expression
1934 * @param res Place to store result
1935 */
1936static void run_as(run_t *run, stree_as_t *as_op, rdata_item_t **res)
1937{
1938 rdata_item_t *rarg_i;
1939 rdata_item_t *rarg_vi;
1940 rdata_item_t *rarg_di;
1941 rdata_var_t *arg_vref;
1942 tdata_item_t *dtype;
1943 run_proc_ar_t *proc_ar;
1944
1945 stree_symbol_t *obj_csi_sym;
1946 stree_csi_t *obj_csi;
1947
1948#ifdef DEBUG_RUN_TRACE
1949 printf("Run @c as conversion operation.\n");
1950#endif
1951 run_expr(run, as_op->arg, &rarg_i);
1952 if (run_is_bo(run)) {
1953 *res = NULL;
1954 return;
1955 }
1956
1957 /*
1958 * This should always be a reference if the argument is indeed
1959 * a class instance.
1960 */
1961 assert(run_item_get_vc(run, rarg_i) == vc_ref);
1962 run_cvt_value_item(run, rarg_i, &rarg_vi);
1963 assert(rarg_vi->ic == ic_value);
1964
1965 if (rarg_vi->u.value->var->u.ref_v->vref == NULL) {
1966 /* Nil reference is always okay. */
1967 *res = rarg_vi;
1968 return;
1969 }
1970
1971 run_dereference(run, rarg_vi, &rarg_di);
1972
1973 /* Now we should have a variable address. */
1974 assert(rarg_di->ic == ic_address);
1975 assert(rarg_di->u.address->ac == ac_var);
1976
1977 arg_vref = rarg_di->u.address->u.var_a->vref;
1978
1979 proc_ar = run_get_current_proc_ar(run);
1980 /* XXX Memoize to avoid recomputing. */
1981 run_texpr(run->program, proc_ar->proc->outer_symbol->outer_csi,
1982 as_op->dtype, &dtype);
1983
1984 assert(arg_vref->vc == vc_object);
1985 obj_csi_sym = arg_vref->u.object_v->class_sym;
1986 obj_csi = symbol_to_csi(obj_csi_sym);
1987 assert(obj_csi != NULL);
1988
1989 if (tdata_is_csi_derived_from_ti(obj_csi, dtype) != b_true) {
1990 printf("Error: Run-time type conversion error. Object is "
1991 "of type '");
1992 symbol_print_fqn(obj_csi_sym);
1993 printf("' which is not derived from '");
1994 tdata_item_print(dtype);
1995 printf("'.\n");
1996 exit(1);
1997 }
1998
1999 *res = rarg_vi;
2000}
2001
2002/** Execute boxing operation.
2003 *
2004 * XXX We can scrap this special operation once we have constructors.
2005 *
2006 * @param run Runner object
2007 * @param box Boxing operation
2008 * @param res Place to store result
2009 */
2010static void run_box(run_t *run, stree_box_t *box, rdata_item_t **res)
2011{
2012 rdata_item_t *rarg_i;
2013 rdata_item_t *rarg_vi;
2014
2015 stree_symbol_t *csi_sym;
2016 stree_csi_t *csi;
2017 builtin_t *bi;
2018 rdata_var_t *var;
2019 rdata_object_t *object;
2020
2021 sid_t mbr_name_sid;
2022 rdata_var_t *mbr_var;
2023
2024#ifdef DEBUG_RUN_TRACE
2025 printf("Run boxing operation.\n");
2026#endif
2027 run_expr(run, box->arg, &rarg_i);
2028 if (run_is_bo(run)) {
2029 *res = NULL;
2030 return;
2031 }
2032
2033 run_cvt_value_item(run, rarg_i, &rarg_vi);
2034 assert(rarg_vi->ic == ic_value);
2035
2036 bi = run->program->builtin;
2037
2038 /* Just to keep the compiler happy. */
2039 csi_sym = NULL;
2040
2041 switch (rarg_vi->u.value->var->vc) {
2042 case vc_bool: csi_sym = bi->boxed_bool; break;
2043 case vc_char: csi_sym = bi->boxed_char; break;
2044 case vc_int: csi_sym = bi->boxed_int; break;
2045 case vc_string: csi_sym = bi->boxed_string; break;
2046
2047 case vc_ref:
2048 case vc_deleg:
2049 case vc_array:
2050 case vc_object:
2051 case vc_resource:
2052 assert(b_false);
2053 }
2054
2055 csi = symbol_to_csi(csi_sym);
2056 assert(csi != NULL);
2057
2058 /* Construct object of the relevant boxed type. */
2059 run_new_csi_inst(run, csi, res);
2060
2061 /* Set the 'Value' field */
2062
2063 assert((*res)->ic == ic_value);
2064 assert((*res)->u.value->var->vc == vc_ref);
2065 var = (*res)->u.value->var->u.ref_v->vref;
2066 assert(var->vc == vc_object);
2067 object = var->u.object_v;
2068
2069 mbr_name_sid = strtab_get_sid("Value");
2070 mbr_var = intmap_get(&object->fields, mbr_name_sid);
2071 assert(mbr_var != NULL);
2072
2073 rdata_var_write(mbr_var, rarg_vi->u.value);
2074}
2075
2076/** Create new CSI instance.
2077 *
2078 * Create a new object, instance of @a csi.
2079 * XXX This does not work with generics as @a csi cannot specify a generic
2080 * type.
2081 *
2082 * Initialize the fields with default values of their types, but do not
2083 * run any constructor.
2084 *
2085 * @param run Runner object
2086 * @param as_op @c as conversion expression
2087 * @param res Place to store result
2088 */
2089void run_new_csi_inst(run_t *run, stree_csi_t *csi, rdata_item_t **res)
2090{
2091 rdata_object_t *obj;
2092 rdata_var_t *obj_var;
2093
2094 stree_symbol_t *csi_sym;
2095 stree_csimbr_t *csimbr;
2096
2097 rdata_var_t *mbr_var;
2098 list_node_t *node;
2099 tdata_item_t *field_ti;
2100
2101 csi_sym = csi_to_symbol(csi);
2102
2103#ifdef DEBUG_RUN_TRACE
2104 printf("Create new instance of CSI '");
2105 symbol_print_fqn(csi_sym);
2106 printf("'.\n");
2107#endif
2108
2109 /* Create the object. */
2110 obj = rdata_object_new();
2111 obj->class_sym = csi_sym;
2112 intmap_init(&obj->fields);
2113
2114 obj_var = rdata_var_new(vc_object);
2115 obj_var->u.object_v = obj;
2116
2117 /* Create object fields. */
2118 while (csi != NULL) {
2119 node = list_first(&csi->members);
2120 while (node != NULL) {
2121 csimbr = list_node_data(node, stree_csimbr_t *);
2122 if (csimbr->cc == csimbr_var) {
2123 /* Compute field type. XXX Memoize. */
2124 run_texpr(run->program, csi,
2125 csimbr->u.var->type,
2126 &field_ti);
2127
2128 /* Create and initialize field. */
2129 run_var_new(run, field_ti, &mbr_var);
2130
2131 /* Add to field map. */
2132 intmap_set(&obj->fields,
2133 csimbr->u.var->name->sid,
2134 mbr_var);
2135 }
2136
2137 node = list_next(&csi->members, node);
2138 }
2139
2140 /* Continue with base CSI */
2141 csi = csi->base_csi;
2142 }
2143
2144 /* Create reference to the new object. */
2145 run_reference(run, obj_var, res);
2146}
2147
2148/** Return boolean value of an item.
2149 *
2150 * Try to interpret @a item as a boolean value. If it is not a boolean
2151 * value, generate an error.
2152 *
2153 * @param run Runner object
2154 * @param item Input item
2155 * @return Resulting boolean value
2156 */
2157bool_t run_item_boolean_value(run_t *run, rdata_item_t *item)
2158{
2159 rdata_item_t *vitem;
2160 rdata_var_t *var;
2161
2162 (void) run;
2163 run_cvt_value_item(run, item, &vitem);
2164
2165 assert(vitem->ic == ic_value);
2166 var = vitem->u.value->var;
2167
2168 assert(var->vc == vc_bool);
2169 return var->u.bool_v->value;
2170}
Note: See TracBrowser for help on using the repository browser.