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

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

Update SBI to rev. 291.

  • Property mode set to 100644
File size: 61.4 KB
RevLine 
[09ababb7]1/*
2 * Copyright (c) 2010 Jiri Svoboda
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * - Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * - Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * - The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
[38aaacc2]29/** @file Run expressions. */
[09ababb7]30
31#include <stdio.h>
32#include <stdlib.h>
33#include <assert.h>
[23de644]34#include "bigint.h"
[09ababb7]35#include "debug.h"
[fa36f29]36#include "intmap.h"
[09ababb7]37#include "list.h"
38#include "mytypes.h"
[94d484a]39#include "os/os.h"
[09ababb7]40#include "rdata.h"
41#include "run.h"
[94d484a]42#include "run_texpr.h"
[09ababb7]43#include "symbol.h"
[d0febca]44#include "stree.h"
[09ababb7]45#include "strtab.h"
[39e8406]46#include "tdata.h"
[09ababb7]47
48#include "run_expr.h"
49
50static void run_nameref(run_t *run, stree_nameref_t *nameref,
51 rdata_item_t **res);
[fa36f29]52
[09ababb7]53static void run_literal(run_t *run, stree_literal_t *literal,
54 rdata_item_t **res);
[074444f]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);
[09ababb7]59static void run_lit_int(run_t *run, stree_lit_int_t *lit_int,
60 rdata_item_t **res);
[fa36f29]61static void run_lit_ref(run_t *run, stree_lit_ref_t *lit_ref,
62 rdata_item_t **res);
[09ababb7]63static void run_lit_string(run_t *run, stree_lit_string_t *lit_string,
64 rdata_item_t **res);
[fa36f29]65
66static void run_self_ref(run_t *run, stree_self_ref_t *self_ref,
67 rdata_item_t **res);
68
[09ababb7]69static void run_binop(run_t *run, stree_binop_t *binop, rdata_item_t **res);
[074444f]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);
[fa36f29]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);
[94d484a]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);
[fa36f29]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);
[051bc69a]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);
[fa36f29]82
[09ababb7]83static void run_unop(run_t *run, stree_unop_t *unop, rdata_item_t **res);
[051bc69a]84static void run_unop_bool(run_t *run, stree_unop_t *unop, rdata_value_t *val,
85 rdata_item_t **res);
[23de644]86static void run_unop_int(run_t *run, stree_unop_t *unop, rdata_value_t *val,
87 rdata_item_t **res);
88
[fa36f29]89static void run_new(run_t *run, stree_new_t *new_op, rdata_item_t **res);
[94d484a]90static void run_new_array(run_t *run, stree_new_t *new_op,
[39e8406]91 tdata_item_t *titem, rdata_item_t **res);
[94d484a]92static void run_new_object(run_t *run, stree_new_t *new_op,
[39e8406]93 tdata_item_t *titem, rdata_item_t **res);
[fa36f29]94
[051bc69a]95static void run_object_ctor(run_t *run, rdata_var_t *obj, list_t *arg_vals);
96
[09ababb7]97static void run_access(run_t *run, stree_access_t *access, rdata_item_t **res);
[fa36f29]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);
[c5cb943d]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);
[051bc69a]110static void run_access_symbol(run_t *run, stree_access_t *access,
111 rdata_item_t *arg, rdata_item_t **res);
[fa36f29]112
[09ababb7]113static void run_call(run_t *run, stree_call_t *call, rdata_item_t **res);
[051bc69a]114static void run_call_args(run_t *run, list_t *args, list_t *arg_vals);
115
[94d484a]116static void run_index(run_t *run, stree_index_t *index, rdata_item_t **res);
[d0febca]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);
[09ababb7]123static void run_assign(run_t *run, stree_assign_t *assign, rdata_item_t **res);
[37f527b]124static void run_as(run_t *run, stree_as_t *as_op, rdata_item_t **res);
[38aaacc2]125static void run_box(run_t *run, stree_box_t *box, rdata_item_t **res);
[09ababb7]126
[38aaacc2]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 */
[09ababb7]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;
[fa36f29]150 case ec_self_ref:
151 run_self_ref(run, expr->u.self_ref, res);
152 break;
[09ababb7]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;
[fa36f29]159 case ec_new:
160 run_new(run, expr->u.new_op, res);
161 break;
[09ababb7]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;
[94d484a]168 case ec_index:
169 run_index(run, expr->u.index, res);
170 break;
[09ababb7]171 case ec_assign:
172 run_assign(run, expr->u.assign, res);
173 break;
[37f527b]174 case ec_as:
175 run_as(run, expr->u.as_op, res);
176 break;
[38aaacc2]177 case ec_box:
178 run_box(run, expr->u.box, res);
179 break;
[09ababb7]180 }
181
182#ifdef DEBUG_RUN_TRACE
183 printf("Expression result: ");
184 rdata_item_print(*res);
185 printf(".\n");
186#endif
187}
188
[38aaacc2]189/** Evaluate name reference expression.
190 *
191 * @param run Runner object
192 * @param nameref Name reference
193 * @param res Place to store result
194 */
[09ababb7]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;
[d0febca]201 rdata_addr_var_t *addr_var;
[fa36f29]202 rdata_value_t *value;
[09ababb7]203 rdata_var_t *var;
204 rdata_deleg_t *deleg_v;
[051bc69a]205 rdata_symbol_t *symbol_v;
[09ababb7]206
[d0febca]207 run_proc_ar_t *proc_ar;
[fa36f29]208 stree_symbol_t *csi_sym;
209 stree_csi_t *csi;
210 rdata_object_t *obj;
211 rdata_var_t *member_var;
212
[c5cb943d]213 rdata_var_t *psobj;
214 rdata_var_t *sobj;
215 rdata_object_t *aobj;
216
[09ababb7]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);
[d0febca]228 address = rdata_address_new(ac_var);
229 addr_var = rdata_addr_var_new();
[09ababb7]230
231 item->u.address = address;
[d0febca]232 address->u.var_a = addr_var;
233 addr_var->vref = var;
[09ababb7]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
[fa36f29]246 /* Determine currently active object or CSI. */
[d0febca]247 proc_ar = run_get_current_proc_ar(run);
[c5cb943d]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) {
[fa36f29]255 csi = symbol_to_csi(csi_sym);
256 assert(csi != NULL);
257 } else {
[c5cb943d]258 /* This happens in interactive mode. */
259 csi = NULL;
[fa36f29]260 }
261
262 sym = symbol_lookup_in_csi(run->program, csi, nameref->name);
[09ababb7]263
[1ebc1a62]264 /* Existence should have been verified in type checking phase. */
265 assert(sym != NULL);
266
[09ababb7]267 switch (sym->sc) {
268 case sc_csi:
269#ifdef DEBUG_RUN_TRACE
[051bc69a]270 printf("Referencing CSI.\n");
[09ababb7]271#endif
[c5cb943d]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);
[09ababb7]276
[c5cb943d]277 /* Return reference to the object. */
278 run_reference(run, sobj, res);
[fa36f29]279 break;
[051bc69a]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;
[fa36f29]304 case sc_fun:
305 /* There should be no global functions. */
306 assert(csi != NULL);
307
[38aaacc2]308 if (symbol_search_csi(run->program, csi, nameref->name)
309 == NULL) {
[fa36f29]310 /* Function is not in the current object. */
311 printf("Error: Cannot access non-static member "
312 "function '");
[39e8406]313 symbol_print_fqn(sym);
[fa36f29]314 printf("' from nested CSI '");
[39e8406]315 symbol_print_fqn(csi_sym);
[fa36f29]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
[d0febca]330 deleg_v->obj = proc_ar->obj;
[fa36f29]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
[38aaacc2]342 if (symbol_search_csi(run->program, csi, nameref->name)
[c5cb943d]343 == NULL && !stree_symbol_is_static(sym)) {
[fa36f29]344 /* Variable is not in the current object. */
345 printf("Error: Cannot access non-static member "
346 "variable '");
[39e8406]347 symbol_print_fqn(sym);
[fa36f29]348 printf("' from nested CSI '");
[39e8406]349 symbol_print_fqn(csi_sym);
[fa36f29]350 printf("'.\n");
351 exit(1);
352 }
353
[c5cb943d]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
[fa36f29]370 /* Find member variable in object. */
[c5cb943d]371 member_var = intmap_get(&aobj->fields, nameref->name->sid);
[fa36f29]372 assert(member_var != NULL);
373
374 /* Return address of the variable. */
375 item = rdata_item_new(ic_address);
[d0febca]376 address = rdata_address_new(ac_var);
377 addr_var = rdata_addr_var_new();
[fa36f29]378
379 item->u.address = address;
[d0febca]380 address->u.var_a = addr_var;
381 addr_var->vref = member_var;
[fa36f29]382
[09ababb7]383 *res = item;
384 break;
[051bc69a]385 case sc_prop:
386 /* XXX TODO */
387 printf("Unimplemented: Property name reference.\n");
388 abort();
[09ababb7]389 break;
390 }
391}
392
[38aaacc2]393/** Evaluate literal.
394 *
395 * @param run Runner object
396 * @param literal Literal
397 * @param res Place to store result
398 */
[09ababb7]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) {
[074444f]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;
[09ababb7]412 case ltc_int:
413 run_lit_int(run, &literal->u.lit_int, res);
414 break;
[fa36f29]415 case ltc_ref:
416 run_lit_ref(run, &literal->u.lit_ref, res);
417 break;
[09ababb7]418 case ltc_string:
419 run_lit_string(run, &literal->u.lit_string, res);
420 break;
421 }
422}
423
[38aaacc2]424/** Evaluate Boolean literal.
425 *
426 * @param run Runner object
427 * @param lit_bool Boolean literal
428 * @param res Place to store result
429 */
[074444f]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
[38aaacc2]483/** Evaluate integer literal.
484 *
485 * @param run Runner object
486 * @param lit_int Integer literal
487 * @param res Place to store result
488 */
[09ababb7]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
[fa36f29]500 (void) run;
[09ababb7]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;
[23de644]510 bigint_clone(&lit_int->value, &int_v->value);
[09ababb7]511
512 *res = item;
513}
514
[38aaacc2]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 */
[fa36f29]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
[38aaacc2]548/** Evaluate string literal.
549 *
550 * @param run Runner object
551 * @param lit_string String literal
552 * @param res Place to store result
553 */
[09ababb7]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
[fa36f29]565 (void) run;
566
[09ababb7]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
[38aaacc2]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 */
[fa36f29]586static void run_self_ref(run_t *run, stree_self_ref_t *self_ref,
587 rdata_item_t **res)
588{
[d0febca]589 run_proc_ar_t *proc_ar;
[fa36f29]590
591#ifdef DEBUG_RUN_TRACE
592 printf("Run self reference.\n");
593#endif
594 (void) self_ref;
[d0febca]595 proc_ar = run_get_current_proc_ar(run);
[fa36f29]596
597 /* Return reference to the currently active object. */
[d0febca]598 run_reference(run, proc_ar->obj, res);
[fa36f29]599}
[09ababb7]600
[38aaacc2]601/** Evaluate binary operation.
602 *
603 * @param run Runner object
604 * @param binop Binary operation
605 * @param res Place to store result
606 */
[09ababb7]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);
[23de644]617 if (run_is_bo(run)) {
618 *res = NULL;
619 return;
620 }
621
[09ababb7]622 run_expr(run, binop->arg2, &rarg2_i);
[23de644]623 if (run_is_bo(run)) {
624 *res = NULL;
625 return;
626 }
[09ababb7]627
628#ifdef DEBUG_RUN_TRACE
629 printf("Check binop argument results.\n");
630#endif
631
[d0febca]632 run_cvt_value_item(run, rarg1_i, &rarg1_vi);
633 run_cvt_value_item(run, rarg2_i, &rarg2_vi);
[09ababb7]634
635 v1 = rarg1_vi->u.value;
636 v2 = rarg2_vi->u.value;
637
[fa36f29]638 if (v1->var->vc != v2->var->vc) {
639 printf("Unimplemented: Binary operation arguments have "
640 "different type.\n");
[09ababb7]641 exit(1);
642 }
643
[fa36f29]644 switch (v1->var->vc) {
[074444f]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;
[fa36f29]651 case vc_int:
652 run_binop_int(run, binop, v1, v2, res);
653 break;
[94d484a]654 case vc_string:
655 run_binop_string(run, binop, v1, v2, res);
656 break;
[fa36f29]657 case vc_ref:
658 run_binop_ref(run, binop, v1, v2, res);
659 break;
[051bc69a]660 case vc_enum:
661 run_binop_enum(run, binop, v1, v2, res);
662 break;
[074444f]663 case vc_deleg:
664 case vc_array:
665 case vc_object:
666 case vc_resource:
[051bc69a]667 case vc_symbol:
[074444f]668 assert(b_false);
669 }
670}
671
[38aaacc2]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 */
[074444f]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;
[051bc69a]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;
[074444f]735 }
736
737 *res = item;
738}
739
[38aaacc2]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*/
[074444f]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;
[051bc69a]803
804 case bo_and:
805 case bo_or:
[074444f]806 assert(b_false);
[fa36f29]807 }
[074444f]808
809 *res = item;
[fa36f29]810}
811
[38aaacc2]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*/
[fa36f29]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;
[074444f]827 rdata_bool_t *bool_v;
[fa36f29]828
[23de644]829 bigint_t *i1, *i2;
830 bigint_t diff;
831 bool_t done;
832 bool_t zf, nf;
[fa36f29]833
834 (void) run;
835
[09ababb7]836 item = rdata_item_new(ic_value);
837 value = rdata_value_new();
838
839 item->u.value = value;
840
[23de644]841 i1 = &v1->var->u.int_v->value;
842 i2 = &v2->var->u.int_v->value;
843
844 done = b_true;
[09ababb7]845
846 switch (binop->bc) {
847 case bo_plus:
[074444f]848 int_v = rdata_int_new();
[23de644]849 bigint_add(i1, i2, &int_v->value);
850 break;
851 case bo_minus:
[074444f]852 int_v = rdata_int_new();
[23de644]853 bigint_sub(i1, i2, &int_v->value);
854 break;
855 case bo_mult:
[074444f]856 int_v = rdata_int_new();
[23de644]857 bigint_mul(i1, i2, &int_v->value);
[09ababb7]858 break;
[23de644]859 default:
860 done = b_false;
861 break;
862 }
863
864 if (done) {
[074444f]865 var = rdata_var_new(vc_int);
866 var->u.int_v = int_v;
867 value->var = var;
[23de644]868 *res = item;
869 return;
870 }
871
[074444f]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
[23de644]877 /* Relational operation. */
878
879 bigint_sub(i1, i2, &diff);
880 zf = bigint_is_zero(&diff);
881 nf = bigint_is_negative(&diff);
[09ababb7]882
[23de644]883 switch (binop->bc) {
[051bc69a]884 case bo_plus:
885 case bo_minus:
886 case bo_mult:
887 assert(b_false);
888
[09ababb7]889 case bo_equal:
[074444f]890 bool_v->value = zf;
[09ababb7]891 break;
892 case bo_notequal:
[074444f]893 bool_v->value = !zf;
[09ababb7]894 break;
895 case bo_lt:
[074444f]896 bool_v->value = (!zf && nf);
[09ababb7]897 break;
898 case bo_gt:
[074444f]899 bool_v->value = (!zf && !nf);
[09ababb7]900 break;
901 case bo_lt_equal:
[074444f]902 bool_v->value = (zf || nf);
[09ababb7]903 break;
904 case bo_gt_equal:
[074444f]905 bool_v->value = !nf;
[09ababb7]906 break;
[051bc69a]907 case bo_and:
908 case bo_or:
[09ababb7]909 assert(b_false);
910 }
911
912 *res = item;
913}
914
[38aaacc2]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 */
[94d484a]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;
[051bc69a]930 rdata_bool_t *bool_v;
931 bool_t done;
932 bool_t zf;
[94d484a]933
[38aaacc2]934 const char *s1, *s2;
[94d484a]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
[051bc69a]946 done = b_true;
947
[94d484a]948 switch (binop->bc) {
949 case bo_plus:
950 /* Concatenate strings. */
[051bc69a]951 string_v = rdata_string_new();
[94d484a]952 string_v->value = os_str_acat(s1, s2);
953 break;
[051bc69a]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;
[94d484a]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
[38aaacc2]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 */
[fa36f29]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;
[074444f]1006 rdata_bool_t *bool_v;
[fa36f29]1007
1008 rdata_var_t *ref1, *ref2;
1009
1010 (void) run;
1011
1012 item = rdata_item_new(ic_value);
1013 value = rdata_value_new();
[074444f]1014 var = rdata_var_new(vc_bool);
1015 bool_v = rdata_bool_new();
[fa36f29]1016
1017 item->u.value = value;
1018 value->var = var;
[074444f]1019 var->u.bool_v = bool_v;
[fa36f29]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:
[074444f]1026 bool_v->value = (ref1 == ref2);
[fa36f29]1027 break;
1028 case bo_notequal:
[074444f]1029 bool_v->value = (ref1 != ref2);
[fa36f29]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
[051bc69a]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}
[fa36f29]1086
[38aaacc2]1087/** Evaluate unary operation.
1088 *
1089 * @param run Runner object
1090 * @param unop Unary operation
1091 * @param res Place to store result
1092 */
[09ababb7]1093static void run_unop(run_t *run, stree_unop_t *unop, rdata_item_t **res)
1094{
[23de644]1095 rdata_item_t *rarg_i;
1096 rdata_item_t *rarg_vi;
1097 rdata_value_t *val;
[09ababb7]1098
1099#ifdef DEBUG_RUN_TRACE
1100 printf("Run unary operation.\n");
1101#endif
[23de644]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) {
[051bc69a]1116 case vc_bool:
1117 run_unop_bool(run, unop, val, res);
1118 break;
[23de644]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 }
[09ababb7]1129}
1130
[051bc69a]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
[38aaacc2]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 */
[23de644]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;
[051bc69a]1204 case uo_not:
1205 assert(b_false);
[23de644]1206 }
1207
1208 *res = item;
1209}
1210
[38aaacc2]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 */
[fa36f29]1220static void run_new(run_t *run, stree_new_t *new_op, rdata_item_t **res)
[94d484a]1221{
[39e8406]1222 tdata_item_t *titem;
[94d484a]1223
1224#ifdef DEBUG_RUN_TRACE
1225 printf("Run 'new' operation.\n");
1226#endif
1227 /* Evaluate type expression */
[39e8406]1228 run_texpr(run->program, run_get_current_csi(run), new_op->texpr,
1229 &titem);
[94d484a]1230
1231 switch (titem->tic) {
1232 case tic_tarray:
1233 run_new_array(run, new_op, titem, res);
1234 break;
[39e8406]1235 case tic_tobject:
[94d484a]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
[38aaacc2]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 */
[94d484a]1252static void run_new_array(run_t *run, stree_new_t *new_op,
[39e8406]1253 tdata_item_t *titem, rdata_item_t **res)
[94d484a]1254{
[39e8406]1255 tdata_array_t *tarray;
[94d484a]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;
[23de644]1268 int rc;
1269 int iextent;
[94d484a]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);
[23de644]1298 if (run_is_bo(run)) {
1299 *res = NULL;
1300 return;
1301 }
1302
[d0febca]1303 run_cvt_value_item(run, rexpr, &rexpr_vi);
[94d484a]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
[23de644]1313 printf("Array extent: ");
1314 bigint_print(&rexpr_var->u.int_v->value);
1315 printf(".\n");
[94d484a]1316#endif
[23de644]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;
[94d484a]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) {
[38aaacc2]1339 /* Create and initialize element. */
1340 run_var_new(run, tarray->base_ti, &elem_var);
[94d484a]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. */
[d0febca]1350 run_reference(run, array_var, res);
[94d484a]1351}
1352
[38aaacc2]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 */
[94d484a]1360static void run_new_object(run_t *run, stree_new_t *new_op,
[39e8406]1361 tdata_item_t *titem, rdata_item_t **res)
[fa36f29]1362{
1363 stree_csi_t *csi;
[051bc69a]1364 rdata_item_t *obj_i;
1365 list_t arg_vals;
[fa36f29]1366
1367#ifdef DEBUG_RUN_TRACE
[94d484a]1368 printf("Create new object.\n");
[fa36f29]1369#endif
1370 /* Lookup object CSI. */
[39e8406]1371 assert(titem->tic == tic_tobject);
1372 csi = titem->u.tobject->csi;
[fa36f29]1373
[051bc69a]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
[23de644]1381 /* Create CSI instance. */
[c5cb943d]1382 run_new_csi_inst_ref(run, csi, sn_nonstatic, res);
[051bc69a]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);
[fa36f29]1389}
1390
[38aaacc2]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 */
[09ababb7]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);
[23de644]1407 if (run_is_bo(run)) {
1408 *res = NULL;
1409 return;
1410 }
1411
[fa36f29]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
[38aaacc2]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 */
[fa36f29]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;
[09ababb7]1431
1432#ifdef DEBUG_RUN_TRACE
[fa36f29]1433 printf("Run access operation on pre-evaluated base.\n");
[09ababb7]1434#endif
[39e8406]1435 vc = run_item_get_vc(run, arg);
[09ababb7]1436
[fa36f29]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;
[051bc69a]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:
[fa36f29]1458 printf("Unimplemented: Using access operator ('.') "
1459 "with unsupported data type (value/%d).\n", vc);
1460 exit(1);
1461 }
1462}
[09ababb7]1463
[38aaacc2]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 */
[fa36f29]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. */
[051bc69a]1477 run_dereference(run, arg, access->arg->cspan, &darg);
[fa36f29]1478
[1ebc1a62]1479 if (run->thread_ar->bo_mode != bm_none) {
1480 *res = run_recovery_item(run);
1481 return;
1482 }
1483
[fa36f29]1484 /* Try again. */
1485 run_access_item(run, access, darg, res);
1486}
1487
[c5cb943d]1488/** Evaluate delegate member acccess.
[38aaacc2]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 */
[fa36f29]1495static void run_access_deleg(run_t *run, stree_access_t *access,
1496 rdata_item_t *arg, rdata_item_t **res)
1497{
[c5cb943d]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;
[fa36f29]1548 stree_symbol_t *member;
[c5cb943d]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;
[09ababb7]1561
1562#ifdef DEBUG_RUN_TRACE
[c5cb943d]1563 printf("Run static object access operation.\n");
[fa36f29]1564#endif
[c5cb943d]1565 assert(obj_var->vc == vc_object);
1566 object = obj_var->u.object_v;
[fa36f29]1567
[c5cb943d]1568 assert(object->static_obj == sn_static);
[fa36f29]1569
[c5cb943d]1570 member = symbol_search_csi(run->program, object->class_sym->u.csi,
[fa36f29]1571 access->member_name);
1572
[074444f]1573 /* Member existence should be ensured by static type checking. */
1574 assert(member != NULL);
[fa36f29]1575
1576#ifdef DEBUG_RUN_TRACE
1577 printf("Found member '%s'.\n",
1578 strtab_get_str(access->member_name->sid));
[09ababb7]1579#endif
1580
[c5cb943d]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 }
[fa36f29]1657}
1658
[38aaacc2]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 */
[c5cb943d]1666static void run_access_object_nonstatic(run_t *run, stree_access_t *access,
1667 rdata_var_t *obj_var, rdata_item_t **res)
[fa36f29]1668{
1669 rdata_object_t *object;
[c5cb943d]1670 stree_symbol_t *member;
[fa36f29]1671 rdata_item_t *ritem;
1672 rdata_address_t *address;
[d0febca]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;
[fa36f29]1677
1678 rdata_value_t *value;
1679 rdata_deleg_t *deleg_v;
1680 rdata_var_t *var;
1681
1682#ifdef DEBUG_RUN_TRACE
[c5cb943d]1683 printf("Run nonstatic object access operation.\n");
[fa36f29]1684#endif
[c5cb943d]1685 assert(obj_var->vc == vc_object);
1686 object = obj_var->u.object_v;
[fa36f29]1687
[c5cb943d]1688 assert(object->static_obj == sn_nonstatic);
[fa36f29]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 '");
[39e8406]1695 symbol_print_fqn(object->class_sym);
[fa36f29]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
[6c39a907]1706 /* Make compiler happy. */
1707 ritem = NULL;
1708
[fa36f29]1709 switch (member->sc) {
1710 case sc_csi:
1711 printf("Error: Accessing object member which is nested CSI.\n");
1712 exit(1);
[c5cb943d]1713 case sc_ctor:
1714 /* It is not possible to reference a constructor explicitly. */
1715 assert(b_false);
[38aaacc2]1716 case sc_deleg:
1717 printf("Error: Accessing object member which is a delegate.\n");
1718 exit(1);
[051bc69a]1719 case sc_enum:
1720 printf("Error: Accessing object member which is an enum.\n");
1721 exit(1);
[fa36f29]1722 case sc_fun:
[38aaacc2]1723 /* Construct anonymous delegate. */
[fa36f29]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
[c5cb943d]1733 deleg_v->obj = obj_var;
[09ababb7]1734 deleg_v->sym = member;
[fa36f29]1735 break;
1736 case sc_var:
1737 /* Construct variable address item. */
1738 ritem = rdata_item_new(ic_address);
[d0febca]1739 address = rdata_address_new(ac_var);
1740 addr_var = rdata_addr_var_new();
[fa36f29]1741 ritem->u.address = address;
[d0febca]1742 address->u.var_a = addr_var;
[09ababb7]1743
[d0febca]1744 addr_var->vref = intmap_get(&object->fields,
[fa36f29]1745 access->member_name->sid);
[d0febca]1746 assert(addr_var->vref != NULL);
[fa36f29]1747 break;
1748 case sc_prop:
[d0febca]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();
[c5cb943d]1759 deleg_p->obj = obj_var;
[d0febca]1760 deleg_p->sym = member;
1761 addr_prop->u.named->prop_d = deleg_p;
1762 break;
[09ababb7]1763 }
1764
[fa36f29]1765 *res = ritem;
[09ababb7]1766}
1767
[051bc69a]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
[38aaacc2]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 */
[09ababb7]1831static void run_call(run_t *run, stree_call_t *call, rdata_item_t **res)
1832{
[38aaacc2]1833 rdata_item_t *rdeleg, *rdeleg_vi;
[09ababb7]1834 rdata_deleg_t *deleg_v;
1835 list_t arg_vals;
1836
[fa36f29]1837 stree_fun_t *fun;
[d0febca]1838 run_proc_ar_t *proc_ar;
[fa36f29]1839
[09ababb7]1840#ifdef DEBUG_RUN_TRACE
1841 printf("Run call operation.\n");
1842#endif
[38aaacc2]1843 run_expr(run, call->fun, &rdeleg);
[23de644]1844 if (run_is_bo(run)) {
1845 *res = NULL;
1846 return;
1847 }
[09ababb7]1848
[1ebc1a62]1849 if (run->thread_ar->bo_mode != bm_none) {
1850 *res = run_recovery_item(run);
1851 return;
1852 }
1853
[38aaacc2]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");
[1ebc1a62]1861 exit(1);
[09ababb7]1862 }
1863
[38aaacc2]1864 deleg_v = rdeleg_vi->u.value->var->u.deleg_v;
[09ababb7]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 '");
[39e8406]1873 symbol_print_fqn(deleg_v->sym);
[09ababb7]1874 printf("'\n");
1875#endif
1876 /* Evaluate function arguments. */
[051bc69a]1877 run_call_args(run, &call->args, &arg_vals);
1878 if (run_is_bo(run)) {
1879 *res = NULL;
1880 return;
[09ababb7]1881 }
1882
[fa36f29]1883 fun = symbol_to_fun(deleg_v->sym);
1884 assert(fun != NULL);
1885
[d0febca]1886 /* Create procedure activation record. */
[39e8406]1887 run_proc_ar_create(run, deleg_v->obj, fun->proc, &proc_ar);
[fa36f29]1888
1889 /* Fill in argument values. */
[d0febca]1890 run_proc_ar_set_args(run, proc_ar, &arg_vals);
[fa36f29]1891
1892 /* Run the function. */
[d0febca]1893 run_proc(run, proc_ar, res);
[09ababb7]1894
[051bc69a]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
[09ababb7]1902#ifdef DEBUG_RUN_TRACE
1903 printf("Returned from function call.\n");
1904#endif
1905}
1906
[051bc69a]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
[38aaacc2]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 */
[94d484a]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;
[d0febca]1955 list_t arg_vals;
[94d484a]1956
1957#ifdef DEBUG_RUN_TRACE
1958 printf("Run index operation.\n");
1959#endif
1960 run_expr(run, index->base, &rbase);
[23de644]1961 if (run_is_bo(run)) {
1962 *res = NULL;
1963 return;
1964 }
[94d484a]1965
[39e8406]1966 vc = run_item_get_vc(run, rbase);
[d0febca]1967
1968 /* Implicitly dereference. */
1969 if (vc == vc_ref) {
[051bc69a]1970 run_dereference(run, rbase, index->base->cspan, &base_i);
1971 if (run_is_bo(run)) {
1972 *res = NULL;
1973 return;
1974 }
[d0febca]1975 } else {
1976 base_i = rbase;
1977 }
1978
[39e8406]1979 vc = run_item_get_vc(run, base_i);
[d0febca]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);
[23de644]1988 if (run_is_bo(run)) {
1989 *res = NULL;
1990 return;
1991 }
1992
[d0febca]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);
[94d484a]2003 break;
[d0febca]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);
[94d484a]2009 break;
2010 default:
[d0febca]2011 printf("Error: Indexing object of bad type (%d).\n", vc);
[94d484a]2012 exit(1);
2013 }
[d0febca]2014}
[94d484a]2015
[38aaacc2]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 */
[d0febca]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;
[94d484a]2030
[d0febca]2031 int i;
2032 int elem_index;
2033 int arg_val;
[23de644]2034 int rc;
[94d484a]2035
[d0febca]2036 rdata_item_t *ritem;
2037 rdata_address_t *address;
2038 rdata_addr_var_t *addr_var;
[94d484a]2039
[d0febca]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;
[94d484a]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
[d0febca]2056 node = list_first(args);
[94d484a]2057 i = 0;
[d0febca]2058
[94d484a]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
[d0febca]2066 arg = list_node_data(node, rdata_item_t *);
2067 assert(arg->ic == ic_value);
[94d484a]2068
[d0febca]2069 if (arg->u.value->var->vc != vc_int) {
[94d484a]2070 printf("Error: Array index is not an integer.\n");
2071 exit(1);
2072 }
2073
[23de644]2074 rc = bigint_get_value_int(
2075 &arg->u.value->var->u.int_v->value,
2076 &arg_val);
[94d484a]2077
[23de644]2078 if (rc != EOK || arg_val < 0 || arg_val >= array->extent[i]) {
2079#ifdef DEBUG_RUN_TRACE
[94d484a]2080 printf("Error: Array index (value: %d) is out of range.\n",
2081 arg_val);
[23de644]2082#endif
2083 /* Raise Error.OutOfBounds */
2084 run_raise_exc(run,
[051bc69a]2085 run->program->builtin->error_outofbounds,
2086 index->expr->cspan);
2087 /* XXX It should be cspan of the argument. */
[1ebc1a62]2088 *res = run_recovery_item(run);
2089 return;
[94d484a]2090 }
2091
2092 elem_index = elem_index * array->extent[i] + arg_val;
2093
[d0febca]2094 node = list_next(args, node);
[94d484a]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);
[d0febca]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
[38aaacc2]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 */
[d0febca]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();
[94d484a]2150 ritem->u.address = address;
[d0febca]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 }
[94d484a]2160
[d0febca]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
[39e8406]2170 if (indexer_sym == NULL) {
2171 printf("Error: Accessing object which does not have an "
2172 "indexer.\n");
2173 exit(1);
2174 }
2175
[d0febca]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 }
[94d484a]2191
2192 *res = ritem;
2193}
2194
[38aaacc2]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 */
[d0febca]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;
[23de644]2214 int rc1, rc2;
[d0febca]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);
[23de644]2228 string = base_vi->u.value->var->u.string_v;
[d0febca]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
[23de644]2252 rc1 = bigint_get_value_int(
2253 &arg->u.value->var->u.int_v->value,
2254 &arg_val);
2255
[d0febca]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
[23de644]2267 if (rc1 == EOK)
2268 rc2 = os_str_get_char(string->value, elem_index, &cval);
2269
2270 if (rc1 != EOK || rc2 != EOK) {
[074444f]2271#ifdef DEBUG_RUN_TRACE
[d0febca]2272 printf("Error: String index (value: %d) is out of range.\n",
2273 arg_val);
[074444f]2274#endif
2275 /* Raise Error.OutOfBounds */
[051bc69a]2276 run_raise_exc(run, run->program->builtin->error_outofbounds,
2277 index->expr->cspan);
[074444f]2278 *res = run_recovery_item(run);
2279 return;
[d0febca]2280 }
2281
2282 /* Construct character value. */
2283 ritem = rdata_item_new(ic_value);
2284 value = rdata_value_new();
2285 ritem->u.value = value;
2286
[074444f]2287 cvar = rdata_var_new(vc_char);
2288 cvar->u.char_v = rdata_char_new();
2289 bigint_init(&cvar->u.char_v->value, cval);
[d0febca]2290 value->var = cvar;
2291
2292 *res = ritem;
2293}
2294
[38aaacc2]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*/
[09ababb7]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);
[23de644]2313 if (run_is_bo(run)) {
2314 *res = NULL;
2315 return;
2316 }
2317
[09ababb7]2318 run_expr(run, assign->src, &rsrc_i);
[23de644]2319 if (run_is_bo(run)) {
2320 *res = NULL;
2321 return;
2322 }
[09ababb7]2323
[d0febca]2324 run_cvt_value_item(run, rsrc_i, &rsrc_vi);
2325 assert(rsrc_vi->ic == ic_value);
[09ababb7]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
[d0febca]2333 run_address_write(run, rdest_i->u.address, rsrc_vi->u.value);
[09ababb7]2334
2335 *res = NULL;
2336}
2337
[38aaacc2]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 */
[37f527b]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);
[23de644]2360 if (run_is_bo(run)) {
2361 *res = NULL;
2362 return;
2363 }
[37f527b]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
[051bc69a]2379 run_dereference(run, rarg_vi, NULL, &rarg_di);
[37f527b]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
[38aaacc2]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:
[051bc69a]2457 case vc_enum:
[38aaacc2]2458 case vc_array:
2459 case vc_object:
2460 case vc_resource:
[051bc69a]2461 case vc_symbol:
[38aaacc2]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. */
[c5cb943d]2469 run_new_csi_inst_ref(run, csi, sn_nonstatic, res);
[38aaacc2]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
[c5cb943d]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
[38aaacc2]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 *
[c5cb943d]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 *
[38aaacc2]2530 * @param run Runner object
[c5cb943d]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
[38aaacc2]2534 * @param res Place to store result
2535 */
[c5cb943d]2536void run_new_csi_inst(run_t *run, stree_csi_t *csi, statns_t sn,
2537 rdata_var_t **res)
[23de644]2538{
2539 rdata_object_t *obj;
2540 rdata_var_t *obj_var;
2541
2542 stree_symbol_t *csi_sym;
2543 stree_csimbr_t *csimbr;
[c5cb943d]2544 stree_var_t *var;
2545 statns_t var_sn;
[23de644]2546
2547 rdata_var_t *mbr_var;
2548 list_node_t *node;
[38aaacc2]2549 tdata_item_t *field_ti;
[23de644]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;
[c5cb943d]2562 obj->static_obj = sn;
[23de644]2563 intmap_init(&obj->fields);
2564
2565 obj_var = rdata_var_new(vc_object);
2566 obj_var->u.object_v = obj;
2567
[c5cb943d]2568 /* For this CSI and all base CSIs */
[38aaacc2]2569 while (csi != NULL) {
[c5cb943d]2570
2571 /* For all members */
[38aaacc2]2572 node = list_first(&csi->members);
2573 while (node != NULL) {
2574 csimbr = list_node_data(node, stree_csimbr_t *);
[c5cb943d]2575
2576 /* Is it a member variable? */
[38aaacc2]2577 if (csimbr->cc == csimbr_var) {
[c5cb943d]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 }
[38aaacc2]2595 }
2596
2597 node = list_next(&csi->members, node);
[23de644]2598 }
2599
[38aaacc2]2600 /* Continue with base CSI */
2601 csi = csi->base_csi;
[23de644]2602 }
2603
[c5cb943d]2604 *res = obj_var;
[23de644]2605}
2606
[051bc69a]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
[09ababb7]2664/** Return boolean value of an item.
2665 *
[38aaacc2]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
[09ababb7]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
[fa36f29]2678 (void) run;
[d0febca]2679 run_cvt_value_item(run, item, &vitem);
[09ababb7]2680
2681 assert(vitem->ic == ic_value);
2682 var = vitem->u.value->var;
2683
[074444f]2684 assert(var->vc == vc_bool);
2685 return var->u.bool_v->value;
[09ababb7]2686}
Note: See TracBrowser for help on using the repository browser.