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

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

Update SBI to rev. 291.

  • Property mode set to 100644
File size: 61.4 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);
80static void run_binop_enum(run_t *run, stree_binop_t *binop, rdata_value_t *v1,
81 rdata_value_t *v2, rdata_item_t **res);
82
83static void run_unop(run_t *run, stree_unop_t *unop, rdata_item_t **res);
84static void run_unop_bool(run_t *run, stree_unop_t *unop, rdata_value_t *val,
85 rdata_item_t **res);
86static void run_unop_int(run_t *run, stree_unop_t *unop, rdata_value_t *val,
87 rdata_item_t **res);
88
89static void run_new(run_t *run, stree_new_t *new_op, rdata_item_t **res);
90static void run_new_array(run_t *run, stree_new_t *new_op,
91 tdata_item_t *titem, rdata_item_t **res);
92static void run_new_object(run_t *run, stree_new_t *new_op,
93 tdata_item_t *titem, rdata_item_t **res);
94
95static void run_object_ctor(run_t *run, rdata_var_t *obj, list_t *arg_vals);
96
97static void run_access(run_t *run, stree_access_t *access, rdata_item_t **res);
98static void run_access_item(run_t *run, stree_access_t *access,
99 rdata_item_t *arg, rdata_item_t **res);
100static void run_access_ref(run_t *run, stree_access_t *access,
101 rdata_item_t *arg, rdata_item_t **res);
102static void run_access_deleg(run_t *run, stree_access_t *access,
103 rdata_item_t *arg, rdata_item_t **res);
104static void run_access_object(run_t *run, stree_access_t *access,
105 rdata_item_t *arg, rdata_item_t **res);
106static void run_access_object_static(run_t *run, stree_access_t *access,
107 rdata_var_t *obj_var, rdata_item_t **res);
108static void run_access_object_nonstatic(run_t *run, stree_access_t *access,
109 rdata_var_t *obj_var, rdata_item_t **res);
110static void run_access_symbol(run_t *run, stree_access_t *access,
111 rdata_item_t *arg, rdata_item_t **res);
112
113static void run_call(run_t *run, stree_call_t *call, rdata_item_t **res);
114static void run_call_args(run_t *run, list_t *args, list_t *arg_vals);
115
116static void run_index(run_t *run, stree_index_t *index, rdata_item_t **res);
117static void run_index_array(run_t *run, stree_index_t *index,
118 rdata_item_t *base, list_t *args, rdata_item_t **res);
119static void run_index_object(run_t *run, stree_index_t *index,
120 rdata_item_t *base, list_t *args, rdata_item_t **res);
121static void run_index_string(run_t *run, stree_index_t *index,
122 rdata_item_t *base, list_t *args, rdata_item_t **res);
123static void run_assign(run_t *run, stree_assign_t *assign, rdata_item_t **res);
124static void run_as(run_t *run, stree_as_t *as_op, rdata_item_t **res);
125static void run_box(run_t *run, stree_box_t *box, rdata_item_t **res);
126
127/** Evaluate expression.
128 *
129 * Run the expression @a expr and store pointer to the result in *(@a res).
130 * If the expression has on value (assignment) then @c NULL is returned.
131 * @c NULL is also returned if an error or exception occurs.
132 *
133 * @param run Runner object
134 * @param expr Expression to run
135 * @param res Place to store result
136 */
137void run_expr(run_t *run, stree_expr_t *expr, rdata_item_t **res)
138{
139#ifdef DEBUG_RUN_TRACE
140 printf("Executing expression.\n");
141#endif
142
143 switch (expr->ec) {
144 case ec_nameref:
145 run_nameref(run, expr->u.nameref, res);
146 break;
147 case ec_literal:
148 run_literal(run, expr->u.literal, res);
149 break;
150 case ec_self_ref:
151 run_self_ref(run, expr->u.self_ref, res);
152 break;
153 case ec_binop:
154 run_binop(run, expr->u.binop, res);
155 break;
156 case ec_unop:
157 run_unop(run, expr->u.unop, res);
158 break;
159 case ec_new:
160 run_new(run, expr->u.new_op, res);
161 break;
162 case ec_access:
163 run_access(run, expr->u.access, res);
164 break;
165 case ec_call:
166 run_call(run, expr->u.call, res);
167 break;
168 case ec_index:
169 run_index(run, expr->u.index, res);
170 break;
171 case ec_assign:
172 run_assign(run, expr->u.assign, res);
173 break;
174 case ec_as:
175 run_as(run, expr->u.as_op, res);
176 break;
177 case ec_box:
178 run_box(run, expr->u.box, res);
179 break;
180 }
181
182#ifdef DEBUG_RUN_TRACE
183 printf("Expression result: ");
184 rdata_item_print(*res);
185 printf(".\n");
186#endif
187}
188
189/** Evaluate name reference expression.
190 *
191 * @param run Runner object
192 * @param nameref Name reference
193 * @param res Place to store result
194 */
195static void run_nameref(run_t *run, stree_nameref_t *nameref,
196 rdata_item_t **res)
197{
198 stree_symbol_t *sym;
199 rdata_item_t *item;
200 rdata_address_t *address;
201 rdata_addr_var_t *addr_var;
202 rdata_value_t *value;
203 rdata_var_t *var;
204 rdata_deleg_t *deleg_v;
205 rdata_symbol_t *symbol_v;
206
207 run_proc_ar_t *proc_ar;
208 stree_symbol_t *csi_sym;
209 stree_csi_t *csi;
210 rdata_object_t *obj;
211 rdata_var_t *member_var;
212
213 rdata_var_t *psobj;
214 rdata_var_t *sobj;
215 rdata_object_t *aobj;
216
217#ifdef DEBUG_RUN_TRACE
218 printf("Run nameref.\n");
219#endif
220
221 /*
222 * Look for a local variable.
223 */
224 var = run_local_vars_lookup(run, nameref->name->sid);
225 if (var != NULL) {
226 /* Found a local variable. */
227 item = rdata_item_new(ic_address);
228 address = rdata_address_new(ac_var);
229 addr_var = rdata_addr_var_new();
230
231 item->u.address = address;
232 address->u.var_a = addr_var;
233 addr_var->vref = var;
234
235 *res = item;
236#ifdef DEBUG_RUN_TRACE
237 printf("Found local variable.\n");
238#endif
239 return;
240 }
241
242 /*
243 * Look for a class-wide or global symbol.
244 */
245
246 /* Determine currently active object or CSI. */
247 proc_ar = run_get_current_proc_ar(run);
248
249 assert (proc_ar->obj != NULL);
250 assert(proc_ar->obj->vc == vc_object);
251 obj = proc_ar->obj->u.object_v;
252 csi_sym = obj->class_sym;
253
254 if (csi_sym != NULL) {
255 csi = symbol_to_csi(csi_sym);
256 assert(csi != NULL);
257 } else {
258 /* This happens in interactive mode. */
259 csi = NULL;
260 }
261
262 sym = symbol_lookup_in_csi(run->program, csi, nameref->name);
263
264 /* Existence should have been verified in type checking phase. */
265 assert(sym != NULL);
266
267 switch (sym->sc) {
268 case sc_csi:
269#ifdef DEBUG_RUN_TRACE
270 printf("Referencing CSI.\n");
271#endif
272 /* Obtain static object for the referenced CSI. */
273 psobj = run->gdata; /* XXX */
274 sobj = run_sobject_get(run, sym->u.csi, psobj,
275 nameref->name->sid);
276
277 /* Return reference to the object. */
278 run_reference(run, sobj, res);
279 break;
280 case sc_ctor:
281 /* It is not possible to reference a constructor explicitly. */
282 assert(b_false);
283 case sc_enum:
284#ifdef DEBUG_RUN_TRACE
285 printf("Referencing enum.\n");
286#endif
287 item = rdata_item_new(ic_value);
288 value = rdata_value_new();
289 var = rdata_var_new(vc_symbol);
290 symbol_v = rdata_symbol_new();
291
292 item->u.value = value;
293 value->var = var;
294 var->u.symbol_v = symbol_v;
295
296 symbol_v->sym = sym;
297 *res = item;
298 break;
299 case sc_deleg:
300 /* XXX TODO */
301 printf("Unimplemented: Delegate name reference.\n");
302 abort();
303 break;
304 case sc_fun:
305 /* There should be no global functions. */
306 assert(csi != NULL);
307
308 if (symbol_search_csi(run->program, csi, nameref->name)
309 == NULL) {
310 /* Function is not in the current object. */
311 printf("Error: Cannot access non-static member "
312 "function '");
313 symbol_print_fqn(sym);
314 printf("' from nested CSI '");
315 symbol_print_fqn(csi_sym);
316 printf("'.\n");
317 exit(1);
318 }
319
320 /* Construct delegate. */
321 item = rdata_item_new(ic_value);
322 value = rdata_value_new();
323 item->u.value = value;
324
325 var = rdata_var_new(vc_deleg);
326 deleg_v = rdata_deleg_new();
327 value->var = var;
328 var->u.deleg_v = deleg_v;
329
330 deleg_v->obj = proc_ar->obj;
331 deleg_v->sym = sym;
332
333 *res = item;
334 break;
335 case sc_var:
336#ifdef DEBUG_RUN_TRACE
337 printf("Referencing member variable.\n");
338#endif
339 /* There should be no global variables. */
340 assert(csi != NULL);
341
342 if (symbol_search_csi(run->program, csi, nameref->name)
343 == NULL && !stree_symbol_is_static(sym)) {
344 /* Variable is not in the current object. */
345 printf("Error: Cannot access non-static member "
346 "variable '");
347 symbol_print_fqn(sym);
348 printf("' from nested CSI '");
349 symbol_print_fqn(csi_sym);
350 printf("'.\n");
351 exit(1);
352 }
353
354 if (stree_symbol_is_static(sym)) {
355 /*
356 * XXX This is too slow!
357 *
358 * However fixing this is non-trivial. We would
359 * have to have pointer to static object available
360 * for each object (therefore also for each object
361 * type).
362 */
363 sobj = run_sobject_find(run, sym->outer_csi);
364 assert(sobj->vc == vc_object);
365 aobj = sobj->u.object_v;
366 } else {
367 aobj = obj;
368 }
369
370 /* Find member variable in object. */
371 member_var = intmap_get(&aobj->fields, nameref->name->sid);
372 assert(member_var != NULL);
373
374 /* Return address of the variable. */
375 item = rdata_item_new(ic_address);
376 address = rdata_address_new(ac_var);
377 addr_var = rdata_addr_var_new();
378
379 item->u.address = address;
380 address->u.var_a = addr_var;
381 addr_var->vref = member_var;
382
383 *res = item;
384 break;
385 case sc_prop:
386 /* XXX TODO */
387 printf("Unimplemented: Property name reference.\n");
388 abort();
389 break;
390 }
391}
392
393/** Evaluate literal.
394 *
395 * @param run Runner object
396 * @param literal Literal
397 * @param res Place to store result
398 */
399static void run_literal(run_t *run, stree_literal_t *literal,
400 rdata_item_t **res)
401{
402#ifdef DEBUG_RUN_TRACE
403 printf("Run literal.\n");
404#endif
405 switch (literal->ltc) {
406 case ltc_bool:
407 run_lit_bool(run, &literal->u.lit_bool, res);
408 break;
409 case ltc_char:
410 run_lit_char(run, &literal->u.lit_char, res);
411 break;
412 case ltc_int:
413 run_lit_int(run, &literal->u.lit_int, res);
414 break;
415 case ltc_ref:
416 run_lit_ref(run, &literal->u.lit_ref, res);
417 break;
418 case ltc_string:
419 run_lit_string(run, &literal->u.lit_string, res);
420 break;
421 }
422}
423
424/** Evaluate Boolean literal.
425 *
426 * @param run Runner object
427 * @param lit_bool Boolean literal
428 * @param res Place to store result
429 */
430static void run_lit_bool(run_t *run, stree_lit_bool_t *lit_bool,
431 rdata_item_t **res)
432{
433 rdata_item_t *item;
434 rdata_value_t *value;
435 rdata_var_t *var;
436 rdata_bool_t *bool_v;
437
438#ifdef DEBUG_RUN_TRACE
439 printf("Run Boolean literal.\n");
440#endif
441 (void) run;
442
443 item = rdata_item_new(ic_value);
444 value = rdata_value_new();
445 var = rdata_var_new(vc_bool);
446 bool_v = rdata_bool_new();
447
448 item->u.value = value;
449 value->var = var;
450 var->u.bool_v = bool_v;
451 bool_v->value = lit_bool->value;
452
453 *res = item;
454}
455
456/** Evaluate character literal. */
457static void run_lit_char(run_t *run, stree_lit_char_t *lit_char,
458 rdata_item_t **res)
459{
460 rdata_item_t *item;
461 rdata_value_t *value;
462 rdata_var_t *var;
463 rdata_char_t *char_v;
464
465#ifdef DEBUG_RUN_TRACE
466 printf("Run character literal.\n");
467#endif
468 (void) run;
469
470 item = rdata_item_new(ic_value);
471 value = rdata_value_new();
472 var = rdata_var_new(vc_char);
473 char_v = rdata_char_new();
474
475 item->u.value = value;
476 value->var = var;
477 var->u.char_v = char_v;
478 bigint_clone(&lit_char->value, &char_v->value);
479
480 *res = item;
481}
482
483/** Evaluate integer literal.
484 *
485 * @param run Runner object
486 * @param lit_int Integer literal
487 * @param res Place to store result
488 */
489static void run_lit_int(run_t *run, stree_lit_int_t *lit_int,
490 rdata_item_t **res)
491{
492 rdata_item_t *item;
493 rdata_value_t *value;
494 rdata_var_t *var;
495 rdata_int_t *int_v;
496
497#ifdef DEBUG_RUN_TRACE
498 printf("Run integer literal.\n");
499#endif
500 (void) run;
501
502 item = rdata_item_new(ic_value);
503 value = rdata_value_new();
504 var = rdata_var_new(vc_int);
505 int_v = rdata_int_new();
506
507 item->u.value = value;
508 value->var = var;
509 var->u.int_v = int_v;
510 bigint_clone(&lit_int->value, &int_v->value);
511
512 *res = item;
513}
514
515/** Evaluate reference literal (@c nil).
516 *
517 * @param run Runner object
518 * @param lit_ref Reference literal
519 * @param res Place to store result
520 */
521static void run_lit_ref(run_t *run, stree_lit_ref_t *lit_ref,
522 rdata_item_t **res)
523{
524 rdata_item_t *item;
525 rdata_value_t *value;
526 rdata_var_t *var;
527 rdata_ref_t *ref_v;
528
529#ifdef DEBUG_RUN_TRACE
530 printf("Run reference literal (nil).\n");
531#endif
532 (void) run;
533 (void) lit_ref;
534
535 item = rdata_item_new(ic_value);
536 value = rdata_value_new();
537 var = rdata_var_new(vc_ref);
538 ref_v = rdata_ref_new();
539
540 item->u.value = value;
541 value->var = var;
542 var->u.ref_v = ref_v;
543 ref_v->vref = NULL;
544
545 *res = item;
546}
547
548/** Evaluate string literal.
549 *
550 * @param run Runner object
551 * @param lit_string String literal
552 * @param res Place to store result
553 */
554static void run_lit_string(run_t *run, stree_lit_string_t *lit_string,
555 rdata_item_t **res)
556{
557 rdata_item_t *item;
558 rdata_value_t *value;
559 rdata_var_t *var;
560 rdata_string_t *string_v;
561
562#ifdef DEBUG_RUN_TRACE
563 printf("Run integer literal.\n");
564#endif
565 (void) run;
566
567 item = rdata_item_new(ic_value);
568 value = rdata_value_new();
569 var = rdata_var_new(vc_string);
570 string_v = rdata_string_new();
571
572 item->u.value = value;
573 value->var = var;
574 var->u.string_v = string_v;
575 string_v->value = lit_string->value;
576
577 *res = item;
578}
579
580/** Evaluate @c self reference.
581 *
582 * @param run Runner object
583 * @param self_ref Self reference
584 * @param res Place to store result
585 */
586static void run_self_ref(run_t *run, stree_self_ref_t *self_ref,
587 rdata_item_t **res)
588{
589 run_proc_ar_t *proc_ar;
590
591#ifdef DEBUG_RUN_TRACE
592 printf("Run self reference.\n");
593#endif
594 (void) self_ref;
595 proc_ar = run_get_current_proc_ar(run);
596
597 /* Return reference to the currently active object. */
598 run_reference(run, proc_ar->obj, res);
599}
600
601/** Evaluate binary operation.
602 *
603 * @param run Runner object
604 * @param binop Binary operation
605 * @param res Place to store result
606 */
607static void run_binop(run_t *run, stree_binop_t *binop, rdata_item_t **res)
608{
609 rdata_item_t *rarg1_i, *rarg2_i;
610 rdata_item_t *rarg1_vi, *rarg2_vi;
611 rdata_value_t *v1, *v2;
612
613#ifdef DEBUG_RUN_TRACE
614 printf("Run binary operation.\n");
615#endif
616 run_expr(run, binop->arg1, &rarg1_i);
617 if (run_is_bo(run)) {
618 *res = NULL;
619 return;
620 }
621
622 run_expr(run, binop->arg2, &rarg2_i);
623 if (run_is_bo(run)) {
624 *res = NULL;
625 return;
626 }
627
628#ifdef DEBUG_RUN_TRACE
629 printf("Check binop argument results.\n");
630#endif
631
632 run_cvt_value_item(run, rarg1_i, &rarg1_vi);
633 run_cvt_value_item(run, rarg2_i, &rarg2_vi);
634
635 v1 = rarg1_vi->u.value;
636 v2 = rarg2_vi->u.value;
637
638 if (v1->var->vc != v2->var->vc) {
639 printf("Unimplemented: Binary operation arguments have "
640 "different type.\n");
641 exit(1);
642 }
643
644 switch (v1->var->vc) {
645 case vc_bool:
646 run_binop_bool(run, binop, v1, v2, res);
647 break;
648 case vc_char:
649 run_binop_char(run, binop, v1, v2, res);
650 break;
651 case vc_int:
652 run_binop_int(run, binop, v1, v2, res);
653 break;
654 case vc_string:
655 run_binop_string(run, binop, v1, v2, res);
656 break;
657 case vc_ref:
658 run_binop_ref(run, binop, v1, v2, res);
659 break;
660 case vc_enum:
661 run_binop_enum(run, binop, v1, v2, res);
662 break;
663 case vc_deleg:
664 case vc_array:
665 case vc_object:
666 case vc_resource:
667 case vc_symbol:
668 assert(b_false);
669 }
670}
671
672/** Evaluate binary operation on bool arguments.
673 *
674 * @param run Runner object
675 * @param binop Binary operation
676 * @param v1 Value of first argument
677 * @param v2 Value of second argument
678 * @param res Place to store result
679 */
680static void run_binop_bool(run_t *run, stree_binop_t *binop, rdata_value_t *v1,
681 rdata_value_t *v2, rdata_item_t **res)
682{
683 rdata_item_t *item;
684 rdata_value_t *value;
685 rdata_var_t *var;
686 rdata_bool_t *bool_v;
687
688 bool_t b1, b2;
689
690 (void) run;
691
692 item = rdata_item_new(ic_value);
693 value = rdata_value_new();
694 var = rdata_var_new(vc_bool);
695 bool_v = rdata_bool_new();
696
697 item->u.value = value;
698 value->var = var;
699 var->u.bool_v = bool_v;
700
701 b1 = v1->var->u.bool_v->value;
702 b2 = v2->var->u.bool_v->value;
703
704 switch (binop->bc) {
705 case bo_plus:
706 case bo_minus:
707 case bo_mult:
708 assert(b_false);
709
710 case bo_equal:
711 bool_v->value = (b1 == b2);
712 break;
713 case bo_notequal:
714 bool_v->value = (b1 != b2);
715 break;
716 case bo_lt:
717 bool_v->value = (b1 == b_false) && (b2 == b_true);
718 break;
719 case bo_gt:
720 bool_v->value = (b1 == b_true) && (b2 == b_false);
721 break;
722 case bo_lt_equal:
723 bool_v->value = (b1 == b_false) || (b2 == b_true);
724 break;
725 case bo_gt_equal:
726 bool_v->value = (b1 == b_true) || (b2 == b_false);
727 break;
728
729 case bo_and:
730 bool_v->value = (b1 == b_true) && (b2 == b_true);
731 break;
732 case bo_or:
733 bool_v->value = (b1 == b_true) || (b2 == b_true);
734 break;
735 }
736
737 *res = item;
738}
739
740/** Evaluate binary operation on char arguments.
741 *
742 * @param run Runner object
743 * @param binop Binary operation
744 * @param v1 Value of first argument
745 * @param v2 Value of second argument
746 * @param res Place to store result
747*/
748static void run_binop_char(run_t *run, stree_binop_t *binop, rdata_value_t *v1,
749 rdata_value_t *v2, rdata_item_t **res)
750{
751 rdata_item_t *item;
752 rdata_value_t *value;
753 rdata_var_t *var;
754 rdata_bool_t *bool_v;
755
756 bigint_t *c1, *c2;
757 bigint_t diff;
758 bool_t zf, nf;
759
760 (void) run;
761
762 item = rdata_item_new(ic_value);
763 value = rdata_value_new();
764
765 item->u.value = value;
766
767 c1 = &v1->var->u.char_v->value;
768 c2 = &v2->var->u.char_v->value;
769
770 var = rdata_var_new(vc_bool);
771 bool_v = rdata_bool_new();
772 var->u.bool_v = bool_v;
773 value->var = var;
774
775 bigint_sub(c1, c2, &diff);
776 zf = bigint_is_zero(&diff);
777 nf = bigint_is_negative(&diff);
778
779 switch (binop->bc) {
780 case bo_plus:
781 case bo_minus:
782 case bo_mult:
783 assert(b_false);
784
785 case bo_equal:
786 bool_v->value = zf;
787 break;
788 case bo_notequal:
789 bool_v->value = !zf;
790 break;
791 case bo_lt:
792 bool_v->value = (!zf && nf);
793 break;
794 case bo_gt:
795 bool_v->value = (!zf && !nf);
796 break;
797 case bo_lt_equal:
798 bool_v->value = (zf || nf);
799 break;
800 case bo_gt_equal:
801 bool_v->value = !nf;
802 break;
803
804 case bo_and:
805 case bo_or:
806 assert(b_false);
807 }
808
809 *res = item;
810}
811
812/** Evaluate binary operation on int arguments.
813 *
814 * @param run Runner object
815 * @param binop Binary operation
816 * @param v1 Value of first argument
817 * @param v2 Value of second argument
818 * @param res Place to store result
819*/
820static void run_binop_int(run_t *run, stree_binop_t *binop, rdata_value_t *v1,
821 rdata_value_t *v2, rdata_item_t **res)
822{
823 rdata_item_t *item;
824 rdata_value_t *value;
825 rdata_var_t *var;
826 rdata_int_t *int_v;
827 rdata_bool_t *bool_v;
828
829 bigint_t *i1, *i2;
830 bigint_t diff;
831 bool_t done;
832 bool_t zf, nf;
833
834 (void) run;
835
836 item = rdata_item_new(ic_value);
837 value = rdata_value_new();
838
839 item->u.value = value;
840
841 i1 = &v1->var->u.int_v->value;
842 i2 = &v2->var->u.int_v->value;
843
844 done = b_true;
845
846 switch (binop->bc) {
847 case bo_plus:
848 int_v = rdata_int_new();
849 bigint_add(i1, i2, &int_v->value);
850 break;
851 case bo_minus:
852 int_v = rdata_int_new();
853 bigint_sub(i1, i2, &int_v->value);
854 break;
855 case bo_mult:
856 int_v = rdata_int_new();
857 bigint_mul(i1, i2, &int_v->value);
858 break;
859 default:
860 done = b_false;
861 break;
862 }
863
864 if (done) {
865 var = rdata_var_new(vc_int);
866 var->u.int_v = int_v;
867 value->var = var;
868 *res = item;
869 return;
870 }
871
872 var = rdata_var_new(vc_bool);
873 bool_v = rdata_bool_new();
874 var->u.bool_v = bool_v;
875 value->var = var;
876
877 /* Relational operation. */
878
879 bigint_sub(i1, i2, &diff);
880 zf = bigint_is_zero(&diff);
881 nf = bigint_is_negative(&diff);
882
883 switch (binop->bc) {
884 case bo_plus:
885 case bo_minus:
886 case bo_mult:
887 assert(b_false);
888
889 case bo_equal:
890 bool_v->value = zf;
891 break;
892 case bo_notequal:
893 bool_v->value = !zf;
894 break;
895 case bo_lt:
896 bool_v->value = (!zf && nf);
897 break;
898 case bo_gt:
899 bool_v->value = (!zf && !nf);
900 break;
901 case bo_lt_equal:
902 bool_v->value = (zf || nf);
903 break;
904 case bo_gt_equal:
905 bool_v->value = !nf;
906 break;
907 case bo_and:
908 case bo_or:
909 assert(b_false);
910 }
911
912 *res = item;
913}
914
915/** Evaluate binary operation on string arguments.
916 *
917 * @param run Runner object
918 * @param binop Binary operation
919 * @param v1 Value of first argument
920 * @param v2 Value of second argument
921 * @param res Place to store result
922 */
923static void run_binop_string(run_t *run, stree_binop_t *binop, rdata_value_t *v1,
924 rdata_value_t *v2, rdata_item_t **res)
925{
926 rdata_item_t *item;
927 rdata_value_t *value;
928 rdata_var_t *var;
929 rdata_string_t *string_v;
930 rdata_bool_t *bool_v;
931 bool_t done;
932 bool_t zf;
933
934 const char *s1, *s2;
935
936 (void) run;
937
938 item = rdata_item_new(ic_value);
939 value = rdata_value_new();
940
941 item->u.value = value;
942
943 s1 = v1->var->u.string_v->value;
944 s2 = v2->var->u.string_v->value;
945
946 done = b_true;
947
948 switch (binop->bc) {
949 case bo_plus:
950 /* Concatenate strings. */
951 string_v = rdata_string_new();
952 string_v->value = os_str_acat(s1, s2);
953 break;
954 default:
955 done = b_false;
956 break;
957 }
958
959 if (done) {
960 var = rdata_var_new(vc_string);
961 var->u.string_v = string_v;
962 value->var = var;
963 *res = item;
964 return;
965 }
966
967 var = rdata_var_new(vc_bool);
968 bool_v = rdata_bool_new();
969 var->u.bool_v = bool_v;
970 value->var = var;
971
972 /* Relational operation. */
973
974 zf = os_str_cmp(s1, s2) == 0;
975
976 switch (binop->bc) {
977 case bo_equal:
978 bool_v->value = zf;
979 break;
980 case bo_notequal:
981 bool_v->value = !zf;
982 break;
983 default:
984 printf("Error: Invalid binary operation on string "
985 "arguments (%d).\n", binop->bc);
986 assert(b_false);
987 }
988
989 *res = item;
990}
991
992/** Evaluate binary operation on ref arguments.
993 *
994 * @param run Runner object
995 * @param binop Binary operation
996 * @param v1 Value of first argument
997 * @param v2 Value of second argument
998 * @param res Place to store result
999 */
1000static void run_binop_ref(run_t *run, stree_binop_t *binop, rdata_value_t *v1,
1001 rdata_value_t *v2, rdata_item_t **res)
1002{
1003 rdata_item_t *item;
1004 rdata_value_t *value;
1005 rdata_var_t *var;
1006 rdata_bool_t *bool_v;
1007
1008 rdata_var_t *ref1, *ref2;
1009
1010 (void) run;
1011
1012 item = rdata_item_new(ic_value);
1013 value = rdata_value_new();
1014 var = rdata_var_new(vc_bool);
1015 bool_v = rdata_bool_new();
1016
1017 item->u.value = value;
1018 value->var = var;
1019 var->u.bool_v = bool_v;
1020
1021 ref1 = v1->var->u.ref_v->vref;
1022 ref2 = v2->var->u.ref_v->vref;
1023
1024 switch (binop->bc) {
1025 case bo_equal:
1026 bool_v->value = (ref1 == ref2);
1027 break;
1028 case bo_notequal:
1029 bool_v->value = (ref1 != ref2);
1030 break;
1031 default:
1032 printf("Error: Invalid binary operation on reference "
1033 "arguments (%d).\n", binop->bc);
1034 assert(b_false);
1035 }
1036
1037 *res = item;
1038}
1039
1040/** Evaluate binary operation on enum arguments.
1041 *
1042 * @param run Runner object
1043 * @param binop Binary operation
1044 * @param v1 Value of first argument
1045 * @param v2 Value of second argument
1046 * @param res Place to store result
1047 */
1048static void run_binop_enum(run_t *run, stree_binop_t *binop, rdata_value_t *v1,
1049 rdata_value_t *v2, rdata_item_t **res)
1050{
1051 rdata_item_t *item;
1052 rdata_value_t *value;
1053 rdata_var_t *var;
1054 rdata_bool_t *bool_v;
1055
1056 rdata_var_t *ref1, *ref2;
1057
1058 (void) run;
1059
1060 item = rdata_item_new(ic_value);
1061 value = rdata_value_new();
1062 var = rdata_var_new(vc_bool);
1063 bool_v = rdata_bool_new();
1064
1065 item->u.value = value;
1066 value->var = var;
1067 var->u.bool_v = bool_v;
1068
1069 ref1 = v1->var->u.ref_v->vref;
1070 ref2 = v2->var->u.ref_v->vref;
1071
1072 switch (binop->bc) {
1073 case bo_equal:
1074 bool_v->value = (ref1 == ref2);
1075 break;
1076 case bo_notequal:
1077 bool_v->value = (ref1 != ref2);
1078 break;
1079 default:
1080 /* Should have been caught by static typing. */
1081 assert(b_false);
1082 }
1083
1084 *res = item;
1085}
1086
1087/** Evaluate unary operation.
1088 *
1089 * @param run Runner object
1090 * @param unop Unary operation
1091 * @param res Place to store result
1092 */
1093static void run_unop(run_t *run, stree_unop_t *unop, rdata_item_t **res)
1094{
1095 rdata_item_t *rarg_i;
1096 rdata_item_t *rarg_vi;
1097 rdata_value_t *val;
1098
1099#ifdef DEBUG_RUN_TRACE
1100 printf("Run unary operation.\n");
1101#endif
1102 run_expr(run, unop->arg, &rarg_i);
1103 if (run_is_bo(run)) {
1104 *res = NULL;
1105 return;
1106 }
1107
1108#ifdef DEBUG_RUN_TRACE
1109 printf("Check unop argument result.\n");
1110#endif
1111 run_cvt_value_item(run, rarg_i, &rarg_vi);
1112
1113 val = rarg_vi->u.value;
1114
1115 switch (val->var->vc) {
1116 case vc_bool:
1117 run_unop_bool(run, unop, val, res);
1118 break;
1119 case vc_int:
1120 run_unop_int(run, unop, val, res);
1121 break;
1122 default:
1123 printf("Unimplemented: Unrary operation argument of "
1124 "type %d.\n", val->var->vc);
1125 run_raise_error(run);
1126 *res = NULL;
1127 break;
1128 }
1129}
1130
1131/** Evaluate unary operation on bool argument.
1132 *
1133 * @param run Runner object
1134 * @param unop Unary operation
1135 * @param val Value of argument
1136 * @param res Place to store result
1137 */
1138static void run_unop_bool(run_t *run, stree_unop_t *unop, rdata_value_t *val,
1139 rdata_item_t **res)
1140{
1141 rdata_item_t *item;
1142 rdata_value_t *value;
1143 rdata_var_t *var;
1144 rdata_bool_t *bool_v;
1145
1146 (void) run;
1147
1148 item = rdata_item_new(ic_value);
1149 value = rdata_value_new();
1150 var = rdata_var_new(vc_bool);
1151 bool_v = rdata_bool_new();
1152
1153 item->u.value = value;
1154 value->var = var;
1155 var->u.bool_v = bool_v;
1156
1157 switch (unop->uc) {
1158 case uo_plus:
1159 case uo_minus:
1160 assert(b_false);
1161
1162 case uo_not:
1163 bool_v->value = !val->var->u.bool_v->value;
1164 break;
1165 }
1166
1167 *res = item;
1168}
1169
1170/** Evaluate unary operation on int argument.
1171 *
1172 * @param run Runner object
1173 * @param unop Unary operation
1174 * @param val Value of argument
1175 * @param res Place to store result
1176 */
1177static void run_unop_int(run_t *run, stree_unop_t *unop, rdata_value_t *val,
1178 rdata_item_t **res)
1179{
1180 rdata_item_t *item;
1181 rdata_value_t *value;
1182 rdata_var_t *var;
1183 rdata_int_t *int_v;
1184
1185 (void) run;
1186
1187 item = rdata_item_new(ic_value);
1188 value = rdata_value_new();
1189 var = rdata_var_new(vc_int);
1190 int_v = rdata_int_new();
1191
1192 item->u.value = value;
1193 value->var = var;
1194 var->u.int_v = int_v;
1195
1196 switch (unop->uc) {
1197 case uo_plus:
1198 bigint_clone(&val->var->u.int_v->value, &int_v->value);
1199 break;
1200 case uo_minus:
1201 bigint_reverse_sign(&val->var->u.int_v->value,
1202 &int_v->value);
1203 break;
1204 case uo_not:
1205 assert(b_false);
1206 }
1207
1208 *res = item;
1209}
1210
1211/** Evaluate @c new operation.
1212 *
1213 * Evaluates operation per the @c new operator that creates a new
1214 * instance of some type.
1215 *
1216 * @param run Runner object
1217 * @param unop Unary operation
1218 * @param res Place to store result
1219 */
1220static void run_new(run_t *run, stree_new_t *new_op, rdata_item_t **res)
1221{
1222 tdata_item_t *titem;
1223
1224#ifdef DEBUG_RUN_TRACE
1225 printf("Run 'new' operation.\n");
1226#endif
1227 /* Evaluate type expression */
1228 run_texpr(run->program, run_get_current_csi(run), new_op->texpr,
1229 &titem);
1230
1231 switch (titem->tic) {
1232 case tic_tarray:
1233 run_new_array(run, new_op, titem, res);
1234 break;
1235 case tic_tobject:
1236 run_new_object(run, new_op, titem, res);
1237 break;
1238 default:
1239 printf("Error: Invalid argument to operator 'new', "
1240 "expected object.\n");
1241 exit(1);
1242 }
1243}
1244
1245/** Create new array.
1246 *
1247 * @param run Runner object
1248 * @param new_op New operation
1249 * @param titem Type of new var node (tic_tarray)
1250 * @param res Place to store result
1251 */
1252static void run_new_array(run_t *run, stree_new_t *new_op,
1253 tdata_item_t *titem, rdata_item_t **res)
1254{
1255 tdata_array_t *tarray;
1256 rdata_array_t *array;
1257 rdata_var_t *array_var;
1258 rdata_var_t *elem_var;
1259
1260 rdata_item_t *rexpr, *rexpr_vi;
1261 rdata_var_t *rexpr_var;
1262
1263 stree_expr_t *expr;
1264
1265 list_node_t *node;
1266 int length;
1267 int i;
1268 int rc;
1269 int iextent;
1270
1271#ifdef DEBUG_RUN_TRACE
1272 printf("Create new array.\n");
1273#endif
1274 (void) run;
1275 (void) new_op;
1276
1277 assert(titem->tic == tic_tarray);
1278 tarray = titem->u.tarray;
1279
1280 /* Create the array. */
1281 assert(titem->u.tarray->rank > 0);
1282 array = rdata_array_new(titem->u.tarray->rank);
1283
1284 /* Compute extents. */
1285 node = list_first(&tarray->extents);
1286 if (node == NULL) {
1287 printf("Error: Extents must be specified when constructing "
1288 "an array with 'new'.\n");
1289 exit(1);
1290 }
1291
1292 i = 0; length = 1;
1293 while (node != NULL) {
1294 expr = list_node_data(node, stree_expr_t *);
1295
1296 /* Evaluate extent argument. */
1297 run_expr(run, expr, &rexpr);
1298 if (run_is_bo(run)) {
1299 *res = NULL;
1300 return;
1301 }
1302
1303 run_cvt_value_item(run, rexpr, &rexpr_vi);
1304 assert(rexpr_vi->ic == ic_value);
1305 rexpr_var = rexpr_vi->u.value->var;
1306
1307 if (rexpr_var->vc != vc_int) {
1308 printf("Error: Array extent must be an integer.\n");
1309 exit(1);
1310 }
1311
1312#ifdef DEBUG_RUN_TRACE
1313 printf("Array extent: ");
1314 bigint_print(&rexpr_var->u.int_v->value);
1315 printf(".\n");
1316#endif
1317 rc = bigint_get_value_int(&rexpr_var->u.int_v->value,
1318 &iextent);
1319 if (rc != EOK) {
1320 printf("Memory allocation failed (big int used).\n");
1321 exit(1);
1322 }
1323
1324 array->extent[i] = iextent;
1325 length = length * array->extent[i];
1326
1327 node = list_next(&tarray->extents, node);
1328 i += 1;
1329 }
1330
1331 array->element = calloc(length, sizeof(rdata_var_t *));
1332 if (array->element == NULL) {
1333 printf("Memory allocation failed.\n");
1334 exit(1);
1335 }
1336
1337 /* Create member variables */
1338 for (i = 0; i < length; ++i) {
1339 /* Create and initialize element. */
1340 run_var_new(run, tarray->base_ti, &elem_var);
1341
1342 array->element[i] = elem_var;
1343 }
1344
1345 /* Create array variable. */
1346 array_var = rdata_var_new(vc_array);
1347 array_var->u.array_v = array;
1348
1349 /* Create reference to the new array. */
1350 run_reference(run, array_var, res);
1351}
1352
1353/** Create new object.
1354 *
1355 * @param run Runner object
1356 * @param new_op New operation
1357 * @param titem Type of new var node (tic_tobject)
1358 * @param res Place to store result
1359 */
1360static void run_new_object(run_t *run, stree_new_t *new_op,
1361 tdata_item_t *titem, rdata_item_t **res)
1362{
1363 stree_csi_t *csi;
1364 rdata_item_t *obj_i;
1365 list_t arg_vals;
1366
1367#ifdef DEBUG_RUN_TRACE
1368 printf("Create new object.\n");
1369#endif
1370 /* Lookup object CSI. */
1371 assert(titem->tic == tic_tobject);
1372 csi = titem->u.tobject->csi;
1373
1374 /* Evaluate constructor arguments. */
1375 run_call_args(run, &new_op->ctor_args, &arg_vals);
1376 if (run_is_bo(run)) {
1377 *res = NULL;
1378 return;
1379 }
1380
1381 /* Create CSI instance. */
1382 run_new_csi_inst_ref(run, csi, sn_nonstatic, res);
1383
1384 /* Run the constructor. */
1385 run_dereference(run, *res, NULL, &obj_i);
1386 assert(obj_i->ic == ic_address);
1387 assert(obj_i->u.address->ac == ac_var);
1388 run_object_ctor(run, obj_i->u.address->u.var_a->vref, &arg_vals);
1389}
1390
1391/** Evaluate member acccess.
1392 *
1393 * Evaluate operation per the member access ('.') operator.
1394 *
1395 * @param run Runner object
1396 * @param access Access operation
1397 * @param res Place to store result
1398 */
1399static void run_access(run_t *run, stree_access_t *access, rdata_item_t **res)
1400{
1401 rdata_item_t *rarg;
1402
1403#ifdef DEBUG_RUN_TRACE
1404 printf("Run access operation.\n");
1405#endif
1406 run_expr(run, access->arg, &rarg);
1407 if (run_is_bo(run)) {
1408 *res = NULL;
1409 return;
1410 }
1411
1412 if (rarg == NULL) {
1413 printf("Error: Sub-expression has no value.\n");
1414 exit(1);
1415 }
1416
1417 run_access_item(run, access, rarg, res);
1418}
1419
1420/** Evaluate member acccess (with base already evaluated).
1421 *
1422 * @param run Runner object
1423 * @param access Access operation
1424 * @param arg Evaluated base expression
1425 * @param res Place to store result
1426 */
1427static void run_access_item(run_t *run, stree_access_t *access,
1428 rdata_item_t *arg, rdata_item_t **res)
1429{
1430 var_class_t vc;
1431
1432#ifdef DEBUG_RUN_TRACE
1433 printf("Run access operation on pre-evaluated base.\n");
1434#endif
1435 vc = run_item_get_vc(run, arg);
1436
1437 switch (vc) {
1438 case vc_ref:
1439 run_access_ref(run, access, arg, res);
1440 break;
1441 case vc_deleg:
1442 run_access_deleg(run, access, arg, res);
1443 break;
1444 case vc_object:
1445 run_access_object(run, access, arg, res);
1446 break;
1447 case vc_symbol:
1448 run_access_symbol(run, access, arg, res);
1449 break;
1450
1451 case vc_bool:
1452 case vc_char:
1453 case vc_enum:
1454 case vc_int:
1455 case vc_string:
1456 case vc_array:
1457 case vc_resource:
1458 printf("Unimplemented: Using access operator ('.') "
1459 "with unsupported data type (value/%d).\n", vc);
1460 exit(1);
1461 }
1462}
1463
1464/** Evaluate reference acccess.
1465 *
1466 * @param run Runner object
1467 * @param access Access operation
1468 * @param arg Evaluated base expression
1469 * @param res Place to store result
1470 */
1471static void run_access_ref(run_t *run, stree_access_t *access,
1472 rdata_item_t *arg, rdata_item_t **res)
1473{
1474 rdata_item_t *darg;
1475
1476 /* Implicitly dereference. */
1477 run_dereference(run, arg, access->arg->cspan, &darg);
1478
1479 if (run->thread_ar->bo_mode != bm_none) {
1480 *res = run_recovery_item(run);
1481 return;
1482 }
1483
1484 /* Try again. */
1485 run_access_item(run, access, darg, res);
1486}
1487
1488/** Evaluate delegate member acccess.
1489 *
1490 * @param run Runner object
1491 * @param access Access operation
1492 * @param arg Evaluated base expression
1493 * @param res Place to store result
1494 */
1495static void run_access_deleg(run_t *run, stree_access_t *access,
1496 rdata_item_t *arg, rdata_item_t **res)
1497{
1498 (void) run;
1499 (void) access;
1500 (void) arg;
1501 (void) res;
1502
1503 printf("Error: Using '.' with delegate.\n");
1504 exit(1);
1505}
1506
1507/** Evaluate object member acccess.
1508 *
1509 * @param run Runner object
1510 * @param access Access operation
1511 * @param arg Evaluated base expression
1512 * @param res Place to store result
1513 */
1514static void run_access_object(run_t *run, stree_access_t *access,
1515 rdata_item_t *arg, rdata_item_t **res)
1516{
1517 rdata_var_t *obj_var;
1518 rdata_object_t *object;
1519
1520#ifdef DEBUG_RUN_TRACE
1521 printf("Run object access operation.\n");
1522#endif
1523 assert(arg->ic == ic_address);
1524 assert(arg->u.address->ac == ac_var);
1525
1526 obj_var = arg->u.address->u.var_a->vref;
1527 assert(obj_var->vc == vc_object);
1528
1529 object = obj_var->u.object_v;
1530
1531 if (object->static_obj == sn_static)
1532 run_access_object_static(run, access, obj_var, res);
1533 else
1534 run_access_object_nonstatic(run, access, obj_var, res);
1535}
1536
1537/** Evaluate static object member acccess.
1538 *
1539 * @param run Runner object
1540 * @param access Access operation
1541 * @param arg Evaluated base expression
1542 * @param res Place to store result
1543 */
1544static void run_access_object_static(run_t *run, stree_access_t *access,
1545 rdata_var_t *obj_var, rdata_item_t **res)
1546{
1547 rdata_object_t *object;
1548 stree_symbol_t *member;
1549 stree_csi_t *member_csi;
1550
1551 rdata_deleg_t *deleg_v;
1552 rdata_item_t *ritem;
1553 rdata_value_t *rvalue;
1554 rdata_var_t *rvar;
1555 rdata_address_t *address;
1556 rdata_addr_var_t *addr_var;
1557 rdata_addr_prop_t *addr_prop;
1558 rdata_aprop_named_t *aprop_named;
1559 rdata_deleg_t *deleg_p;
1560 rdata_var_t *mvar;
1561
1562#ifdef DEBUG_RUN_TRACE
1563 printf("Run static object access operation.\n");
1564#endif
1565 assert(obj_var->vc == vc_object);
1566 object = obj_var->u.object_v;
1567
1568 assert(object->static_obj == sn_static);
1569
1570 member = symbol_search_csi(run->program, object->class_sym->u.csi,
1571 access->member_name);
1572
1573 /* Member existence should be ensured by static type checking. */
1574 assert(member != NULL);
1575
1576#ifdef DEBUG_RUN_TRACE
1577 printf("Found member '%s'.\n",
1578 strtab_get_str(access->member_name->sid));
1579#endif
1580
1581 switch (member->sc) {
1582 case sc_csi:
1583 /* Get child static object. */
1584 member_csi = symbol_to_csi(member);
1585 assert(member_csi != NULL);
1586
1587 mvar = run_sobject_get(run, member_csi, obj_var,
1588 access->member_name->sid);
1589
1590 ritem = rdata_item_new(ic_address);
1591 address = rdata_address_new(ac_var);
1592 ritem->u.address = address;
1593
1594 addr_var = rdata_addr_var_new();
1595 address->u.var_a = addr_var;
1596 addr_var->vref = mvar;
1597
1598 *res = ritem;
1599 break;
1600 case sc_ctor:
1601 /* It is not possible to reference a constructor explicitly. */
1602 assert(b_false);
1603 case sc_deleg:
1604 printf("Error: Accessing object member which is a delegate.\n");
1605 exit(1);
1606 case sc_enum:
1607 printf("Error: Accessing object member which is an enum.\n");
1608 exit(1);
1609 case sc_fun:
1610 /* Construct anonymous delegate. */
1611 ritem = rdata_item_new(ic_value);
1612 rvalue = rdata_value_new();
1613 ritem->u.value = rvalue;
1614
1615 rvar = rdata_var_new(vc_deleg);
1616 rvalue->var = rvar;
1617
1618 deleg_v = rdata_deleg_new();
1619 rvar->u.deleg_v = deleg_v;
1620
1621 deleg_v->obj = obj_var;
1622 deleg_v->sym = member;
1623 *res = ritem;
1624 break;
1625 case sc_var:
1626 /* Get static object member variable. */
1627 mvar = intmap_get(&object->fields, access->member_name->sid);
1628
1629 ritem = rdata_item_new(ic_address);
1630 address = rdata_address_new(ac_var);
1631 ritem->u.address = address;
1632
1633 addr_var = rdata_addr_var_new();
1634 address->u.var_a = addr_var;
1635 addr_var->vref = mvar;
1636
1637 *res = ritem;
1638 break;
1639 case sc_prop:
1640 /* Construct named property address. */
1641 ritem = rdata_item_new(ic_address);
1642 address = rdata_address_new(ac_prop);
1643 addr_prop = rdata_addr_prop_new(apc_named);
1644 aprop_named = rdata_aprop_named_new();
1645 ritem->u.address = address;
1646 address->u.prop_a = addr_prop;
1647 addr_prop->u.named = aprop_named;
1648
1649 deleg_p = rdata_deleg_new();
1650 deleg_p->obj = obj_var;
1651 deleg_p->sym = member;
1652 addr_prop->u.named->prop_d = deleg_p;
1653
1654 *res = ritem;
1655 break;
1656 }
1657}
1658
1659/** Evaluate object member acccess.
1660 *
1661 * @param run Runner object
1662 * @param access Access operation
1663 * @param arg Evaluated base expression
1664 * @param res Place to store result
1665 */
1666static void run_access_object_nonstatic(run_t *run, stree_access_t *access,
1667 rdata_var_t *obj_var, rdata_item_t **res)
1668{
1669 rdata_object_t *object;
1670 stree_symbol_t *member;
1671 rdata_item_t *ritem;
1672 rdata_address_t *address;
1673 rdata_addr_var_t *addr_var;
1674 rdata_addr_prop_t *addr_prop;
1675 rdata_aprop_named_t *aprop_named;
1676 rdata_deleg_t *deleg_p;
1677
1678 rdata_value_t *value;
1679 rdata_deleg_t *deleg_v;
1680 rdata_var_t *var;
1681
1682#ifdef DEBUG_RUN_TRACE
1683 printf("Run nonstatic object access operation.\n");
1684#endif
1685 assert(obj_var->vc == vc_object);
1686 object = obj_var->u.object_v;
1687
1688 assert(object->static_obj == sn_nonstatic);
1689
1690 member = symbol_search_csi(run->program, object->class_sym->u.csi,
1691 access->member_name);
1692
1693 if (member == NULL) {
1694 printf("Error: Object of class '");
1695 symbol_print_fqn(object->class_sym);
1696 printf("' has no member named '%s'.\n",
1697 strtab_get_str(access->member_name->sid));
1698 exit(1);
1699 }
1700
1701#ifdef DEBUG_RUN_TRACE
1702 printf("Found member '%s'.\n",
1703 strtab_get_str(access->member_name->sid));
1704#endif
1705
1706 /* Make compiler happy. */
1707 ritem = NULL;
1708
1709 switch (member->sc) {
1710 case sc_csi:
1711 printf("Error: Accessing object member which is nested CSI.\n");
1712 exit(1);
1713 case sc_ctor:
1714 /* It is not possible to reference a constructor explicitly. */
1715 assert(b_false);
1716 case sc_deleg:
1717 printf("Error: Accessing object member which is a delegate.\n");
1718 exit(1);
1719 case sc_enum:
1720 printf("Error: Accessing object member which is an enum.\n");
1721 exit(1);
1722 case sc_fun:
1723 /* Construct anonymous delegate. */
1724 ritem = rdata_item_new(ic_value);
1725 value = rdata_value_new();
1726 ritem->u.value = value;
1727
1728 var = rdata_var_new(vc_deleg);
1729 value->var = var;
1730 deleg_v = rdata_deleg_new();
1731 var->u.deleg_v = deleg_v;
1732
1733 deleg_v->obj = obj_var;
1734 deleg_v->sym = member;
1735 break;
1736 case sc_var:
1737 /* Construct variable address item. */
1738 ritem = rdata_item_new(ic_address);
1739 address = rdata_address_new(ac_var);
1740 addr_var = rdata_addr_var_new();
1741 ritem->u.address = address;
1742 address->u.var_a = addr_var;
1743
1744 addr_var->vref = intmap_get(&object->fields,
1745 access->member_name->sid);
1746 assert(addr_var->vref != NULL);
1747 break;
1748 case sc_prop:
1749 /* Construct named property address. */
1750 ritem = rdata_item_new(ic_address);
1751 address = rdata_address_new(ac_prop);
1752 addr_prop = rdata_addr_prop_new(apc_named);
1753 aprop_named = rdata_aprop_named_new();
1754 ritem->u.address = address;
1755 address->u.prop_a = addr_prop;
1756 addr_prop->u.named = aprop_named;
1757
1758 deleg_p = rdata_deleg_new();
1759 deleg_p->obj = obj_var;
1760 deleg_p->sym = member;
1761 addr_prop->u.named->prop_d = deleg_p;
1762 break;
1763 }
1764
1765 *res = ritem;
1766}
1767
1768/** Evaluate symbol member acccess.
1769 *
1770 * @param run Runner object
1771 * @param access Access operation
1772 * @param arg Evaluated base expression
1773 * @param res Place to store result
1774 */
1775static void run_access_symbol(run_t *run, stree_access_t *access,
1776 rdata_item_t *arg, rdata_item_t **res)
1777{
1778 rdata_item_t *arg_vi;
1779 rdata_value_t *arg_val;
1780 rdata_symbol_t *symbol_v;
1781 stree_embr_t *embr;
1782
1783 rdata_item_t *ritem;
1784 rdata_value_t *rvalue;
1785 rdata_var_t *rvar;
1786 rdata_enum_t *enum_v;
1787
1788#ifdef DEBUG_RUN_TRACE
1789 printf("Run symbol access operation.\n");
1790#endif
1791 run_cvt_value_item(run, arg, &arg_vi);
1792 arg_val = arg_vi->u.value;
1793 assert(arg_val->var->vc == vc_symbol);
1794
1795 symbol_v = arg_val->var->u.symbol_v;
1796
1797 /* XXX Port CSI symbol reference to using vc_symbol */
1798 assert(symbol_v->sym->sc == sc_enum);
1799
1800 embr = stree_enum_find_mbr(symbol_v->sym->u.enum_d,
1801 access->member_name);
1802
1803 /* Member existence should be ensured by static type checking. */
1804 assert(embr != NULL);
1805
1806#ifdef DEBUG_RUN_TRACE
1807 printf("Found enum member '%s'.\n",
1808 strtab_get_str(access->member_name->sid));
1809#endif
1810 ritem = rdata_item_new(ic_value);
1811 rvalue = rdata_value_new();
1812 rvar = rdata_var_new(vc_enum);
1813 enum_v = rdata_enum_new();
1814
1815 ritem->u.value = rvalue;
1816 rvalue->var = rvar;
1817 rvar->u.enum_v = enum_v;
1818 enum_v->value = embr;
1819
1820 *res = ritem;
1821}
1822
1823/** Call a function.
1824 *
1825 * Call a function and return the result in @a res.
1826 *
1827 * @param run Runner object
1828 * @param call Call operation
1829 * @param res Place to store result
1830 */
1831static void run_call(run_t *run, stree_call_t *call, rdata_item_t **res)
1832{
1833 rdata_item_t *rdeleg, *rdeleg_vi;
1834 rdata_deleg_t *deleg_v;
1835 list_t arg_vals;
1836
1837 stree_fun_t *fun;
1838 run_proc_ar_t *proc_ar;
1839
1840#ifdef DEBUG_RUN_TRACE
1841 printf("Run call operation.\n");
1842#endif
1843 run_expr(run, call->fun, &rdeleg);
1844 if (run_is_bo(run)) {
1845 *res = NULL;
1846 return;
1847 }
1848
1849 if (run->thread_ar->bo_mode != bm_none) {
1850 *res = run_recovery_item(run);
1851 return;
1852 }
1853
1854 run_cvt_value_item(run, rdeleg, &rdeleg_vi);
1855 assert(rdeleg_vi->ic == ic_value);
1856
1857 if (rdeleg_vi->u.value->var->vc != vc_deleg) {
1858 printf("Unimplemented: Call expression of this type (");
1859 rdata_item_print(rdeleg_vi);
1860 printf(").\n");
1861 exit(1);
1862 }
1863
1864 deleg_v = rdeleg_vi->u.value->var->u.deleg_v;
1865
1866 if (deleg_v->sym->sc != sc_fun) {
1867 printf("Error: Called symbol is not a function.\n");
1868 exit(1);
1869 }
1870
1871#ifdef DEBUG_RUN_TRACE
1872 printf("Call function '");
1873 symbol_print_fqn(deleg_v->sym);
1874 printf("'\n");
1875#endif
1876 /* Evaluate function arguments. */
1877 run_call_args(run, &call->args, &arg_vals);
1878 if (run_is_bo(run)) {
1879 *res = NULL;
1880 return;
1881 }
1882
1883 fun = symbol_to_fun(deleg_v->sym);
1884 assert(fun != NULL);
1885
1886 /* Create procedure activation record. */
1887 run_proc_ar_create(run, deleg_v->obj, fun->proc, &proc_ar);
1888
1889 /* Fill in argument values. */
1890 run_proc_ar_set_args(run, proc_ar, &arg_vals);
1891
1892 /* Run the function. */
1893 run_proc(run, proc_ar, res);
1894
1895 if (!run_is_bo(run) && fun->sig->rtype != NULL && *res == NULL) {
1896 printf("Error: Function '");
1897 symbol_print_fqn(deleg_v->sym);
1898 printf("' did not return a value.\n");
1899 exit(1);
1900 }
1901
1902#ifdef DEBUG_RUN_TRACE
1903 printf("Returned from function call.\n");
1904#endif
1905}
1906
1907/** Evaluate call arguments.
1908 *
1909 * Evaluate arguments to function or constructor.
1910 *
1911 * @param run Runner object
1912 * @param args Real arguments (list of stree_expr_t)
1913 * @param arg_vals Address of uninitialized list to store argument values
1914 * (list of rdata_item_t).
1915 */
1916static void run_call_args(run_t *run, list_t *args, list_t *arg_vals)
1917{
1918 list_node_t *arg_n;
1919 stree_expr_t *arg;
1920 rdata_item_t *rarg_i, *rarg_vi;
1921
1922 /* Evaluate function arguments. */
1923 list_init(arg_vals);
1924 arg_n = list_first(args);
1925
1926 while (arg_n != NULL) {
1927 arg = list_node_data(arg_n, stree_expr_t *);
1928 run_expr(run, arg, &rarg_i);
1929 if (run_is_bo(run))
1930 return;
1931
1932 run_cvt_value_item(run, rarg_i, &rarg_vi);
1933
1934 list_append(arg_vals, rarg_vi);
1935 arg_n = list_next(args, arg_n);
1936 }
1937}
1938
1939/** Run index operation.
1940 *
1941 * Evaluate operation per the indexing ('[', ']') operator.
1942 *
1943 * @param run Runner object
1944 * @param index Index operation
1945 * @param res Place to store result
1946 */
1947static void run_index(run_t *run, stree_index_t *index, rdata_item_t **res)
1948{
1949 rdata_item_t *rbase;
1950 rdata_item_t *base_i;
1951 list_node_t *node;
1952 stree_expr_t *arg;
1953 rdata_item_t *rarg_i, *rarg_vi;
1954 var_class_t vc;
1955 list_t arg_vals;
1956
1957#ifdef DEBUG_RUN_TRACE
1958 printf("Run index operation.\n");
1959#endif
1960 run_expr(run, index->base, &rbase);
1961 if (run_is_bo(run)) {
1962 *res = NULL;
1963 return;
1964 }
1965
1966 vc = run_item_get_vc(run, rbase);
1967
1968 /* Implicitly dereference. */
1969 if (vc == vc_ref) {
1970 run_dereference(run, rbase, index->base->cspan, &base_i);
1971 if (run_is_bo(run)) {
1972 *res = NULL;
1973 return;
1974 }
1975 } else {
1976 base_i = rbase;
1977 }
1978
1979 vc = run_item_get_vc(run, base_i);
1980
1981 /* Evaluate arguments (indices). */
1982 node = list_first(&index->args);
1983 list_init(&arg_vals);
1984
1985 while (node != NULL) {
1986 arg = list_node_data(node, stree_expr_t *);
1987 run_expr(run, arg, &rarg_i);
1988 if (run_is_bo(run)) {
1989 *res = NULL;
1990 return;
1991 }
1992
1993 run_cvt_value_item(run, rarg_i, &rarg_vi);
1994
1995 list_append(&arg_vals, rarg_vi);
1996
1997 node = list_next(&index->args, node);
1998 }
1999
2000 switch (vc) {
2001 case vc_array:
2002 run_index_array(run, index, base_i, &arg_vals, res);
2003 break;
2004 case vc_object:
2005 run_index_object(run, index, base_i, &arg_vals, res);
2006 break;
2007 case vc_string:
2008 run_index_string(run, index, base_i, &arg_vals, res);
2009 break;
2010 default:
2011 printf("Error: Indexing object of bad type (%d).\n", vc);
2012 exit(1);
2013 }
2014}
2015
2016/** Run index operation on array.
2017 *
2018 * @param run Runner object
2019 * @param index Index operation
2020 * @param base Evaluated base expression
2021 * @param args Evaluated indices (list of rdata_item_t)
2022 * @param res Place to store result
2023 */
2024static void run_index_array(run_t *run, stree_index_t *index,
2025 rdata_item_t *base, list_t *args, rdata_item_t **res)
2026{
2027 list_node_t *node;
2028 rdata_array_t *array;
2029 rdata_item_t *arg;
2030
2031 int i;
2032 int elem_index;
2033 int arg_val;
2034 int rc;
2035
2036 rdata_item_t *ritem;
2037 rdata_address_t *address;
2038 rdata_addr_var_t *addr_var;
2039
2040#ifdef DEBUG_RUN_TRACE
2041 printf("Run array index operation.\n");
2042#endif
2043 (void) run;
2044
2045 assert(base->ic == ic_address);
2046 assert(base->u.address->ac == ac_var);
2047 assert(base->u.address->u.var_a->vref->vc == vc_array);
2048 array = base->u.address->u.var_a->vref->u.array_v;
2049
2050 /*
2051 * Linear index of the desired element. Elements are stored in
2052 * lexicographic order with the last index changing the fastest.
2053 */
2054 elem_index = 0;
2055
2056 node = list_first(args);
2057 i = 0;
2058
2059 while (node != NULL) {
2060 if (i >= array->rank) {
2061 printf("Error: Too many indices for array of rank %d",
2062 array->rank);
2063 exit(1);
2064 }
2065
2066 arg = list_node_data(node, rdata_item_t *);
2067 assert(arg->ic == ic_value);
2068
2069 if (arg->u.value->var->vc != vc_int) {
2070 printf("Error: Array index is not an integer.\n");
2071 exit(1);
2072 }
2073
2074 rc = bigint_get_value_int(
2075 &arg->u.value->var->u.int_v->value,
2076 &arg_val);
2077
2078 if (rc != EOK || arg_val < 0 || arg_val >= array->extent[i]) {
2079#ifdef DEBUG_RUN_TRACE
2080 printf("Error: Array index (value: %d) is out of range.\n",
2081 arg_val);
2082#endif
2083 /* Raise Error.OutOfBounds */
2084 run_raise_exc(run,
2085 run->program->builtin->error_outofbounds,
2086 index->expr->cspan);
2087 /* XXX It should be cspan of the argument. */
2088 *res = run_recovery_item(run);
2089 return;
2090 }
2091
2092 elem_index = elem_index * array->extent[i] + arg_val;
2093
2094 node = list_next(args, node);
2095 i += 1;
2096 }
2097
2098 if (i < array->rank) {
2099 printf("Error: Too few indices for array of rank %d",
2100 array->rank);
2101 exit(1);
2102 }
2103
2104 /* Construct variable address item. */
2105 ritem = rdata_item_new(ic_address);
2106 address = rdata_address_new(ac_var);
2107 addr_var = rdata_addr_var_new();
2108 ritem->u.address = address;
2109 address->u.var_a = addr_var;
2110
2111 addr_var->vref = array->element[elem_index];
2112
2113 *res = ritem;
2114}
2115
2116/** Index an object (via its indexer).
2117 *
2118 * @param run Runner object
2119 * @param index Index operation
2120 * @param base Evaluated base expression
2121 * @param args Evaluated indices (list of rdata_item_t)
2122 * @param res Place to store result
2123 */
2124static void run_index_object(run_t *run, stree_index_t *index,
2125 rdata_item_t *base, list_t *args, rdata_item_t **res)
2126{
2127 rdata_item_t *ritem;
2128 rdata_address_t *address;
2129 rdata_addr_prop_t *addr_prop;
2130 rdata_aprop_indexed_t *aprop_indexed;
2131 rdata_var_t *obj_var;
2132 stree_csi_t *obj_csi;
2133 rdata_deleg_t *object_d;
2134 stree_symbol_t *indexer_sym;
2135 stree_ident_t *indexer_ident;
2136
2137 list_node_t *node;
2138 rdata_item_t *arg;
2139
2140#ifdef DEBUG_RUN_TRACE
2141 printf("Run object index operation.\n");
2142#endif
2143 (void) index;
2144
2145 /* Construct property address item. */
2146 ritem = rdata_item_new(ic_address);
2147 address = rdata_address_new(ac_prop);
2148 addr_prop = rdata_addr_prop_new(apc_indexed);
2149 aprop_indexed = rdata_aprop_indexed_new();
2150 ritem->u.address = address;
2151 address->u.prop_a = addr_prop;
2152 addr_prop->u.indexed = aprop_indexed;
2153
2154 if (base->ic != ic_address || base->u.address->ac != ac_var) {
2155 /* XXX Several other cases can occur. */
2156 printf("Unimplemented: Indexing object varclass via something "
2157 "which is not a simple variable reference.\n");
2158 exit(1);
2159 }
2160
2161 /* Find indexer symbol. */
2162 obj_var = base->u.address->u.var_a->vref;
2163 assert(obj_var->vc == vc_object);
2164 indexer_ident = stree_ident_new();
2165 indexer_ident->sid = strtab_get_sid(INDEXER_IDENT);
2166 obj_csi = symbol_to_csi(obj_var->u.object_v->class_sym);
2167 assert(obj_csi != NULL);
2168 indexer_sym = symbol_search_csi(run->program, obj_csi, indexer_ident);
2169
2170 if (indexer_sym == NULL) {
2171 printf("Error: Accessing object which does not have an "
2172 "indexer.\n");
2173 exit(1);
2174 }
2175
2176 /* Construct delegate. */
2177 object_d = rdata_deleg_new();
2178 object_d->obj = obj_var;
2179 object_d->sym = indexer_sym;
2180 aprop_indexed->object_d = object_d;
2181
2182 /* Copy list of argument values. */
2183 list_init(&aprop_indexed->args);
2184
2185 node = list_first(args);
2186 while (node != NULL) {
2187 arg = list_node_data(node, rdata_item_t *);
2188 list_append(&aprop_indexed->args, arg);
2189 node = list_next(args, node);
2190 }
2191
2192 *res = ritem;
2193}
2194
2195/** Run index operation on string.
2196 *
2197 * @param run Runner object
2198 * @param index Index operation
2199 * @param base Evaluated base expression
2200 * @param args Evaluated indices (list of rdata_item_t)
2201 * @param res Place to store result
2202 */
2203static void run_index_string(run_t *run, stree_index_t *index,
2204 rdata_item_t *base, list_t *args, rdata_item_t **res)
2205{
2206 list_node_t *node;
2207 rdata_string_t *string;
2208 rdata_item_t *base_vi;
2209 rdata_item_t *arg;
2210
2211 int i;
2212 int elem_index;
2213 int arg_val;
2214 int rc1, rc2;
2215
2216 rdata_value_t *value;
2217 rdata_var_t *cvar;
2218 rdata_item_t *ritem;
2219 int cval;
2220
2221#ifdef DEBUG_RUN_TRACE
2222 printf("Run string index operation.\n");
2223#endif
2224 (void) run;
2225
2226 run_cvt_value_item(run, base, &base_vi);
2227 assert(base_vi->u.value->var->vc == vc_string);
2228 string = base_vi->u.value->var->u.string_v;
2229
2230 /*
2231 * Linear index of the desired element. Elements are stored in
2232 * lexicographic order with the last index changing the fastest.
2233 */
2234 node = list_first(args);
2235 elem_index = 0;
2236
2237 i = 0;
2238 while (node != NULL) {
2239 if (i >= 1) {
2240 printf("Error: Too many indices string.\n");
2241 exit(1);
2242 }
2243
2244 arg = list_node_data(node, rdata_item_t *);
2245 assert(arg->ic == ic_value);
2246
2247 if (arg->u.value->var->vc != vc_int) {
2248 printf("Error: String index is not an integer.\n");
2249 exit(1);
2250 }
2251
2252 rc1 = bigint_get_value_int(
2253 &arg->u.value->var->u.int_v->value,
2254 &arg_val);
2255
2256 elem_index = arg_val;
2257
2258 node = list_next(args, node);
2259 i += 1;
2260 }
2261
2262 if (i < 1) {
2263 printf("Error: Too few indices for string.\n");
2264 exit(1);
2265 }
2266
2267 if (rc1 == EOK)
2268 rc2 = os_str_get_char(string->value, elem_index, &cval);
2269
2270 if (rc1 != EOK || rc2 != EOK) {
2271#ifdef DEBUG_RUN_TRACE
2272 printf("Error: String index (value: %d) is out of range.\n",
2273 arg_val);
2274#endif
2275 /* Raise Error.OutOfBounds */
2276 run_raise_exc(run, run->program->builtin->error_outofbounds,
2277 index->expr->cspan);
2278 *res = run_recovery_item(run);
2279 return;
2280 }
2281
2282 /* Construct character value. */
2283 ritem = rdata_item_new(ic_value);
2284 value = rdata_value_new();
2285 ritem->u.value = value;
2286
2287 cvar = rdata_var_new(vc_char);
2288 cvar->u.char_v = rdata_char_new();
2289 bigint_init(&cvar->u.char_v->value, cval);
2290 value->var = cvar;
2291
2292 *res = ritem;
2293}
2294
2295/** Run assignment.
2296 *
2297 * Executes an assignment. @c NULL is always stored to @a res because
2298 * an assignment does not have a value.
2299 *
2300 * @param run Runner object
2301 * @param assign Assignment expression
2302 * @param res Place to store result
2303*/
2304static void run_assign(run_t *run, stree_assign_t *assign, rdata_item_t **res)
2305{
2306 rdata_item_t *rdest_i, *rsrc_i;
2307 rdata_item_t *rsrc_vi;
2308
2309#ifdef DEBUG_RUN_TRACE
2310 printf("Run assign operation.\n");
2311#endif
2312 run_expr(run, assign->dest, &rdest_i);
2313 if (run_is_bo(run)) {
2314 *res = NULL;
2315 return;
2316 }
2317
2318 run_expr(run, assign->src, &rsrc_i);
2319 if (run_is_bo(run)) {
2320 *res = NULL;
2321 return;
2322 }
2323
2324 run_cvt_value_item(run, rsrc_i, &rsrc_vi);
2325 assert(rsrc_vi->ic == ic_value);
2326
2327 if (rdest_i->ic != ic_address) {
2328 printf("Error: Address expression required on left side of "
2329 "assignment operator.\n");
2330 exit(1);
2331 }
2332
2333 run_address_write(run, rdest_i->u.address, rsrc_vi->u.value);
2334
2335 *res = NULL;
2336}
2337
2338/** Execute @c as conversion.
2339 *
2340 * @param run Runner object
2341 * @param as_op @c as conversion expression
2342 * @param res Place to store result
2343 */
2344static void run_as(run_t *run, stree_as_t *as_op, rdata_item_t **res)
2345{
2346 rdata_item_t *rarg_i;
2347 rdata_item_t *rarg_vi;
2348 rdata_item_t *rarg_di;
2349 rdata_var_t *arg_vref;
2350 tdata_item_t *dtype;
2351 run_proc_ar_t *proc_ar;
2352
2353 stree_symbol_t *obj_csi_sym;
2354 stree_csi_t *obj_csi;
2355
2356#ifdef DEBUG_RUN_TRACE
2357 printf("Run @c as conversion operation.\n");
2358#endif
2359 run_expr(run, as_op->arg, &rarg_i);
2360 if (run_is_bo(run)) {
2361 *res = NULL;
2362 return;
2363 }
2364
2365 /*
2366 * This should always be a reference if the argument is indeed
2367 * a class instance.
2368 */
2369 assert(run_item_get_vc(run, rarg_i) == vc_ref);
2370 run_cvt_value_item(run, rarg_i, &rarg_vi);
2371 assert(rarg_vi->ic == ic_value);
2372
2373 if (rarg_vi->u.value->var->u.ref_v->vref == NULL) {
2374 /* Nil reference is always okay. */
2375 *res = rarg_vi;
2376 return;
2377 }
2378
2379 run_dereference(run, rarg_vi, NULL, &rarg_di);
2380
2381 /* Now we should have a variable address. */
2382 assert(rarg_di->ic == ic_address);
2383 assert(rarg_di->u.address->ac == ac_var);
2384
2385 arg_vref = rarg_di->u.address->u.var_a->vref;
2386
2387 proc_ar = run_get_current_proc_ar(run);
2388 /* XXX Memoize to avoid recomputing. */
2389 run_texpr(run->program, proc_ar->proc->outer_symbol->outer_csi,
2390 as_op->dtype, &dtype);
2391
2392 assert(arg_vref->vc == vc_object);
2393 obj_csi_sym = arg_vref->u.object_v->class_sym;
2394 obj_csi = symbol_to_csi(obj_csi_sym);
2395 assert(obj_csi != NULL);
2396
2397 if (tdata_is_csi_derived_from_ti(obj_csi, dtype) != b_true) {
2398 printf("Error: Run-time type conversion error. Object is "
2399 "of type '");
2400 symbol_print_fqn(obj_csi_sym);
2401 printf("' which is not derived from '");
2402 tdata_item_print(dtype);
2403 printf("'.\n");
2404 exit(1);
2405 }
2406
2407 *res = rarg_vi;
2408}
2409
2410/** Execute boxing operation.
2411 *
2412 * XXX We can scrap this special operation once we have constructors.
2413 *
2414 * @param run Runner object
2415 * @param box Boxing operation
2416 * @param res Place to store result
2417 */
2418static void run_box(run_t *run, stree_box_t *box, rdata_item_t **res)
2419{
2420 rdata_item_t *rarg_i;
2421 rdata_item_t *rarg_vi;
2422
2423 stree_symbol_t *csi_sym;
2424 stree_csi_t *csi;
2425 builtin_t *bi;
2426 rdata_var_t *var;
2427 rdata_object_t *object;
2428
2429 sid_t mbr_name_sid;
2430 rdata_var_t *mbr_var;
2431
2432#ifdef DEBUG_RUN_TRACE
2433 printf("Run boxing operation.\n");
2434#endif
2435 run_expr(run, box->arg, &rarg_i);
2436 if (run_is_bo(run)) {
2437 *res = NULL;
2438 return;
2439 }
2440
2441 run_cvt_value_item(run, rarg_i, &rarg_vi);
2442 assert(rarg_vi->ic == ic_value);
2443
2444 bi = run->program->builtin;
2445
2446 /* Just to keep the compiler happy. */
2447 csi_sym = NULL;
2448
2449 switch (rarg_vi->u.value->var->vc) {
2450 case vc_bool: csi_sym = bi->boxed_bool; break;
2451 case vc_char: csi_sym = bi->boxed_char; break;
2452 case vc_int: csi_sym = bi->boxed_int; break;
2453 case vc_string: csi_sym = bi->boxed_string; break;
2454
2455 case vc_ref:
2456 case vc_deleg:
2457 case vc_enum:
2458 case vc_array:
2459 case vc_object:
2460 case vc_resource:
2461 case vc_symbol:
2462 assert(b_false);
2463 }
2464
2465 csi = symbol_to_csi(csi_sym);
2466 assert(csi != NULL);
2467
2468 /* Construct object of the relevant boxed type. */
2469 run_new_csi_inst_ref(run, csi, sn_nonstatic, res);
2470
2471 /* Set the 'Value' field */
2472
2473 assert((*res)->ic == ic_value);
2474 assert((*res)->u.value->var->vc == vc_ref);
2475 var = (*res)->u.value->var->u.ref_v->vref;
2476 assert(var->vc == vc_object);
2477 object = var->u.object_v;
2478
2479 mbr_name_sid = strtab_get_sid("Value");
2480 mbr_var = intmap_get(&object->fields, mbr_name_sid);
2481 assert(mbr_var != NULL);
2482
2483 rdata_var_write(mbr_var, rarg_vi->u.value);
2484}
2485
2486/** Create new CSI instance and return reference to it.
2487 *
2488 * Create a new object, instance of @a csi.
2489 * XXX This does not work with generics as @a csi cannot specify a generic
2490 * type.
2491 *
2492 * Initialize the fields with default values of their types, but do not
2493 * run any constructor.
2494 *
2495 * If @a sn is @c sn_nonstatic a regular object is created, containing all
2496 * non-static member variables. If @a sn is @c sn_static a static object
2497 * is created, containing all static member variables.
2498 *
2499 * @param run Runner object
2500 * @param csi CSI to create instance of
2501 * @param sn @c sn_static to create a static (class) object,
2502 * @c sn_nonstatic to create a regular object
2503 * @param res Place to store result
2504 */
2505void run_new_csi_inst_ref(run_t *run, stree_csi_t *csi, statns_t sn,
2506 rdata_item_t **res)
2507{
2508 rdata_var_t *obj_var;
2509
2510 /* Create object. */
2511 run_new_csi_inst(run, csi, sn, &obj_var);
2512
2513 /* Create reference to the new object. */
2514 run_reference(run, obj_var, res);
2515}
2516
2517/** Create new CSI instance.
2518 *
2519 * Create a new object, instance of @a csi.
2520 * XXX This does not work with generics as @a csi cannot specify a generic
2521 * type.
2522 *
2523 * Initialize the fields with default values of their types, but do not
2524 * run any constructor.
2525 *
2526 * If @a sn is @c sn_nonstatic a regular object is created, containing all
2527 * non-static member variables. If @a sn is @c sn_static a static object
2528 * is created, containing all static member variables.
2529 *
2530 * @param run Runner object
2531 * @param csi CSI to create instance of
2532 * @param sn @c sn_static to create a static (class) object,
2533 * @c sn_nonstatic to create a regular object
2534 * @param res Place to store result
2535 */
2536void run_new_csi_inst(run_t *run, stree_csi_t *csi, statns_t sn,
2537 rdata_var_t **res)
2538{
2539 rdata_object_t *obj;
2540 rdata_var_t *obj_var;
2541
2542 stree_symbol_t *csi_sym;
2543 stree_csimbr_t *csimbr;
2544 stree_var_t *var;
2545 statns_t var_sn;
2546
2547 rdata_var_t *mbr_var;
2548 list_node_t *node;
2549 tdata_item_t *field_ti;
2550
2551 csi_sym = csi_to_symbol(csi);
2552
2553#ifdef DEBUG_RUN_TRACE
2554 printf("Create new instance of CSI '");
2555 symbol_print_fqn(csi_sym);
2556 printf("'.\n");
2557#endif
2558
2559 /* Create the object. */
2560 obj = rdata_object_new();
2561 obj->class_sym = csi_sym;
2562 obj->static_obj = sn;
2563 intmap_init(&obj->fields);
2564
2565 obj_var = rdata_var_new(vc_object);
2566 obj_var->u.object_v = obj;
2567
2568 /* For this CSI and all base CSIs */
2569 while (csi != NULL) {
2570
2571 /* For all members */
2572 node = list_first(&csi->members);
2573 while (node != NULL) {
2574 csimbr = list_node_data(node, stree_csimbr_t *);
2575
2576 /* Is it a member variable? */
2577 if (csimbr->cc == csimbr_var) {
2578 var = csimbr->u.var;
2579
2580 /* Is it static/nonstatic? */
2581 var_sn = stree_symbol_has_attr(
2582 var_to_symbol(var), sac_static);
2583 if (var_sn == sn) {
2584 /* Compute field type. XXX Memoize. */
2585 run_texpr(run->program, csi, var->type,
2586 &field_ti);
2587
2588 /* Create and initialize field. */
2589 run_var_new(run, field_ti, &mbr_var);
2590
2591 /* Add to field map. */
2592 intmap_set(&obj->fields, var->name->sid,
2593 mbr_var);
2594 }
2595 }
2596
2597 node = list_next(&csi->members, node);
2598 }
2599
2600 /* Continue with base CSI */
2601 csi = csi->base_csi;
2602 }
2603
2604 *res = obj_var;
2605}
2606
2607/** Run constructor on an object.
2608 *
2609 * @param run Runner object
2610 * @param obj Object to run constructor on
2611 * @param arg_vals Argument values (list of rdata_item_t)
2612 */
2613static void run_object_ctor(run_t *run, rdata_var_t *obj, list_t *arg_vals)
2614{
2615 stree_ident_t *ctor_ident;
2616 stree_symbol_t *csi_sym;
2617 stree_csi_t *csi;
2618 stree_symbol_t *ctor_sym;
2619 stree_ctor_t *ctor;
2620 run_proc_ar_t *proc_ar;
2621 rdata_item_t *res;
2622
2623 csi_sym = obj->u.object_v->class_sym;
2624 csi = symbol_to_csi(csi_sym);
2625 assert(csi != NULL);
2626
2627#ifdef DEBUG_RUN_TRACE
2628 printf("Run object constructor from CSI '");
2629 symbol_print_fqn(csi_sym);
2630 printf("'.\n");
2631#endif
2632 ctor_ident = stree_ident_new();
2633 ctor_ident->sid = strtab_get_sid(CTOR_IDENT);
2634
2635 /* Find constructor. */
2636 ctor_sym = symbol_search_csi_no_base(run->program, csi, ctor_ident);
2637 if (ctor_sym == NULL) {
2638#ifdef DEBUG_RUN_TRACE
2639 printf("No constructor found.\n");
2640#endif
2641 return;
2642 }
2643
2644 ctor = symbol_to_ctor(ctor_sym);
2645 assert(ctor != NULL);
2646
2647 /* Create procedure activation record. */
2648 run_proc_ar_create(run, obj, ctor->proc, &proc_ar);
2649
2650 /* Fill in argument values. */
2651 run_proc_ar_set_args(run, proc_ar, arg_vals);
2652
2653 /* Run the procedure. */
2654 run_proc(run, proc_ar, &res);
2655
2656 /* Constructor does not return a value. */
2657 assert(res == NULL);
2658
2659#ifdef DEBUG_RUN_TRACE
2660 printf("Returned from constructor..\n");
2661#endif
2662}
2663
2664/** Return boolean value of an item.
2665 *
2666 * Try to interpret @a item as a boolean value. If it is not a boolean
2667 * value, generate an error.
2668 *
2669 * @param run Runner object
2670 * @param item Input item
2671 * @return Resulting boolean value
2672 */
2673bool_t run_item_boolean_value(run_t *run, rdata_item_t *item)
2674{
2675 rdata_item_t *vitem;
2676 rdata_var_t *var;
2677
2678 (void) run;
2679 run_cvt_value_item(run, item, &vitem);
2680
2681 assert(vitem->ic == ic_value);
2682 var = vitem->u.value->var;
2683
2684 assert(var->vc == vc_bool);
2685 return var->u.bool_v->value;
2686}
Note: See TracBrowser for help on using the repository browser.