source: mainline/uspace/app/sbi/src/run.c@ 3061bc1

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 3061bc1 was 1b20da0, checked in by Jiří Zárevúcky <zarevucky.jiri@…>, 8 years ago

style: Remove trailing whitespace on non-empty lines, in certain file types.

Command used: tools/srepl '\([^[:space:]]\)\s\+$' '\1' -- *.c *.h *.py *.sh *.s *.S *.ag

  • Property mode set to 100644
File size: 50.1 KB
RevLine 
[09ababb7]1/*
[051b3db8]2 * Copyright (c) 2011 Jiri Svoboda
[09ababb7]3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * - Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * - Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * - The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29/** @file Runner (executes the code). */
30
31#include <stdio.h>
32#include <stdlib.h>
33#include <assert.h>
[23de644]34#include "bigint.h"
[09ababb7]35#include "builtin.h"
[051bc69a]36#include "cspan.h"
[09ababb7]37#include "debug.h"
38#include "intmap.h"
39#include "list.h"
40#include "mytypes.h"
41#include "rdata.h"
42#include "run_expr.h"
[94d484a]43#include "run_texpr.h"
[09ababb7]44#include "stree.h"
45#include "strtab.h"
46#include "symbol.h"
[39e8406]47#include "tdata.h"
[09ababb7]48
49#include "run.h"
50
51static void run_block(run_t *run, stree_block_t *block);
[1ebc1a62]52static void run_exps(run_t *run, stree_exps_t *exps, rdata_item_t **res);
[09ababb7]53static void run_vdecl(run_t *run, stree_vdecl_t *vdecl);
54static void run_if(run_t *run, stree_if_t *if_s);
[051b3db8]55static void run_switch(run_t *run, stree_switch_t *switch_s);
[09ababb7]56static void run_while(run_t *run, stree_while_t *while_s);
[94d484a]57static void run_raise(run_t *run, stree_raise_t *raise_s);
[051bc69a]58static void run_break(run_t *run, stree_break_t *break_s);
[fa36f29]59static void run_return(run_t *run, stree_return_t *return_s);
[94d484a]60static void run_wef(run_t *run, stree_wef_t *wef_s);
61
62static bool_t run_exc_match(run_t *run, stree_except_t *except_c);
[23de644]63static stree_csi_t *run_exc_payload_get_csi(run_t *run);
64
[39e8406]65static rdata_var_t *run_aprop_get_tpos(run_t *run, rdata_address_t *aprop);
[09ababb7]66
[d0febca]67static void run_aprop_read(run_t *run, rdata_addr_prop_t *addr_prop,
68 rdata_item_t **ritem);
69static void run_aprop_write(run_t *run, rdata_addr_prop_t *addr_prop,
70 rdata_value_t *value);
71
[38aaacc2]72static void run_var_new_tprimitive(run_t *run, tdata_primitive_t *tprimitive,
73 rdata_var_t **rvar);
74static void run_var_new_null_ref(run_t *run, rdata_var_t **rvar);
75static void run_var_new_deleg(run_t *run, rdata_var_t **rvar);
[051bc69a]76static void run_var_new_enum(run_t *run, tdata_enum_t *tenum,
77 rdata_var_t **rvar);
[38aaacc2]78
79/** Initialize runner instance.
80 *
81 * @param run Runner object
82 */
[09ababb7]83void run_init(run_t *run)
84{
[fa36f29]85 (void) run;
[09ababb7]86}
87
[38aaacc2]88/** Run program.
89 *
90 * Associates the program @a prog with the runner object and executes
91 * it. If a run-time error occurs during the execution (e.g. an unhandled
92 * exception), @a run->error will be set to @c b_true when this function
93 * returns.
94 *
95 * @param run Runner object
96 * @param prog Program to run
97 */
[09ababb7]98void run_program(run_t *run, stree_program_t *prog)
99{
100 stree_symbol_t *main_fun_sym;
101 stree_fun_t *main_fun;
[c5cb943d]102 rdata_var_t *main_obj;
[09ababb7]103 stree_ident_t *fake_ident;
104 list_t main_args;
[d0febca]105 run_proc_ar_t *proc_ar;
[fa36f29]106 rdata_item_t *res;
[09ababb7]107
108 /* Note down link to program code. */
109 run->program = prog;
110
111 /* Initialize thread activation record. */
112 run->thread_ar = run_thread_ar_new();
[d0febca]113 list_init(&run->thread_ar->proc_ar);
[fa36f29]114 run->thread_ar->bo_mode = bm_none;
[09ababb7]115
[c5cb943d]116 /* Initialize global data structure. */
117 run_gdata_init(run);
118
[09ababb7]119 /*
[fa36f29]120 * Find entry point @c Main().
[09ababb7]121 */
122 fake_ident = stree_ident_new();
[fa36f29]123 fake_ident->sid = strtab_get_sid("Main");
124 main_fun_sym = symbol_find_epoint(prog, fake_ident);
125 if (main_fun_sym == NULL) {
126 printf("Error: Entry point 'Main' not found.\n");
[09ababb7]127 exit(1);
128 }
129
130 main_fun = symbol_to_fun(main_fun_sym);
[fa36f29]131 assert(main_fun != NULL);
[09ababb7]132
[c5cb943d]133 main_obj = run_fun_sobject_find(run, main_fun);
134
[09ababb7]135#ifdef DEBUG_RUN_TRACE
[39e8406]136 printf("Found function '"); symbol_print_fqn(main_fun_sym);
[09ababb7]137 printf("'.\n");
138#endif
139
[fa36f29]140 /* Run function @c main. */
[09ababb7]141 list_init(&main_args);
[c5cb943d]142 run_proc_ar_create(run, main_obj, main_fun->proc, &proc_ar);
[d0febca]143 run_proc_ar_set_args(run, proc_ar, &main_args);
144 run_proc(run, proc_ar, &res);
[051b3db8]145 run_proc_ar_destroy(run, proc_ar);
[94d484a]146
[23de644]147 run_exc_check_unhandled(run);
[09ababb7]148}
149
[c5cb943d]150/** Initialize global data.
151 *
152 * @param run Runner object
153 */
154void run_gdata_init(run_t *run)
155{
156 rdata_object_t *gobject;
157
158 run->gdata = rdata_var_new(vc_object);
159 gobject = rdata_object_new();
160 run->gdata->u.object_v = gobject;
161
162 gobject->class_sym = NULL;
163 gobject->static_obj = sn_static;
164 intmap_init(&gobject->fields);
165}
166
[38aaacc2]167/** Run procedure.
168 *
169 * Inserts the provided procedure AR @a proc_ar on the execution stack
170 * (in the thread AR) and executes the procedure. The return value
171 * of the procedure is stored to *(@a res). @c NULL is stored if the
172 * procedure returns no value.
173 *
174 * If the procedure execution bails out due to an exception, this
175 * can be determined by looking at @c bo_mode in thread AR. Also,
176 * in this case @c NULL is stored into *(@a res).
177 *
178 * @param run Runner object
179 * @param proc_ar Procedure activation record
180 * @param res Place to store procedure return value
181 */
[d0febca]182void run_proc(run_t *run, run_proc_ar_t *proc_ar, rdata_item_t **res)
[09ababb7]183{
[39e8406]184 stree_proc_t *proc;
[09ababb7]185 list_node_t *node;
186
[39e8406]187 proc = proc_ar->proc;
[09ababb7]188
189#ifdef DEBUG_RUN_TRACE
190 printf("Start executing function '");
[37f527b]191 symbol_print_fqn(proc->outer_symbol);
[09ababb7]192 printf("'.\n");
193#endif
[d0febca]194 /* Add procedure AR to the stack. */
195 list_append(&run->thread_ar->proc_ar, proc_ar);
[09ababb7]196
[d0febca]197 /* Run main procedure block. */
[39e8406]198 if (proc->body != NULL) {
199 run_block(run, proc->body);
[09ababb7]200 } else {
[39e8406]201 builtin_run_proc(run, proc);
[09ababb7]202 }
203
[fa36f29]204 /* Handle bailout. */
205 switch (run->thread_ar->bo_mode) {
206 case bm_stat:
[051bc69a]207 /* Break bailout was not caught. */
208 assert(b_false);
[dc12262]209 /* Fallthrough */
[d0febca]210 case bm_proc:
[fa36f29]211 run->thread_ar->bo_mode = bm_none;
212 break;
213 default:
214 break;
215 }
216
[09ababb7]217#ifdef DEBUG_RUN_TRACE
[d0febca]218 printf("Done executing procedure '");
[37f527b]219 symbol_print_fqn(proc->outer_symbol);
[09ababb7]220 printf("'.\n");
221
222 run_print_fun_bt(run);
223#endif
[d0febca]224 /* Remove procedure activation record from the stack. */
225 node = list_last(&run->thread_ar->proc_ar);
226 assert(list_node_data(node, run_proc_ar_t *) == proc_ar);
227 list_remove(&run->thread_ar->proc_ar, node);
228
229 /* Procedure should not return an address. */
230 assert(proc_ar->retval == NULL || proc_ar->retval->ic == ic_value);
231 *res = proc_ar->retval;
[09ababb7]232}
233
[38aaacc2]234/** Run code block.
235 *
236 * @param run Runner object
237 * @param block Block to run
238 */
[09ababb7]239static void run_block(run_t *run, stree_block_t *block)
240{
[d0febca]241 run_proc_ar_t *proc_ar;
[09ababb7]242 run_block_ar_t *block_ar;
243 list_node_t *node;
244 stree_stat_t *stat;
245
246#ifdef DEBUG_RUN_TRACE
247 printf("Executing one code block.\n");
248#endif
249
250 /* Create block activation record. */
251 block_ar = run_block_ar_new();
252 intmap_init(&block_ar->vars);
253
254 /* Add block activation record to the stack. */
[d0febca]255 proc_ar = run_get_current_proc_ar(run);
256 list_append(&proc_ar->block_ar, block_ar);
[09ababb7]257
258 node = list_first(&block->stats);
259 while (node != NULL) {
260 stat = list_node_data(node, stree_stat_t *);
[1ebc1a62]261 run_stat(run, stat, NULL);
[fa36f29]262
263 if (run->thread_ar->bo_mode != bm_none)
264 break;
265
[09ababb7]266 node = list_next(&block->stats, node);
267 }
268
269#ifdef DEBUG_RUN_TRACE
270 printf("Done executing code block.\n");
271#endif
272
273 /* Remove block activation record from the stack. */
[d0febca]274 node = list_last(&proc_ar->block_ar);
[09ababb7]275 assert(list_node_data(node, run_block_ar_t *) == block_ar);
[d0febca]276 list_remove(&proc_ar->block_ar, node);
[051b3db8]277
278 /* Deallocate block activation record. */
279 run_block_ar_destroy(run, block_ar);
[09ababb7]280}
281
[1ebc1a62]282/** Run statement.
283 *
284 * Executes a statement. If @a res is not NULL and the statement is an
285 * expression statement with a value, the value item will be stored to
286 * @a res.
287 *
[38aaacc2]288 * @param run Runner object
289 * @param stat Statement to run
290 * @param res Place to store exps result or NULL if not interested
[1ebc1a62]291 */
292void run_stat(run_t *run, stree_stat_t *stat, rdata_item_t **res)
[09ababb7]293{
294#ifdef DEBUG_RUN_TRACE
295 printf("Executing one statement %p.\n", stat);
296#endif
297
[1ebc1a62]298 if (res != NULL)
299 *res = NULL;
300
[09ababb7]301 switch (stat->sc) {
302 case st_exps:
[1ebc1a62]303 run_exps(run, stat->u.exp_s, res);
[09ababb7]304 break;
305 case st_vdecl:
306 run_vdecl(run, stat->u.vdecl_s);
307 break;
308 case st_if:
309 run_if(run, stat->u.if_s);
310 break;
[051b3db8]311 case st_switch:
312 run_switch(run, stat->u.switch_s);
313 break;
[09ababb7]314 case st_while:
315 run_while(run, stat->u.while_s);
316 break;
[94d484a]317 case st_raise:
318 run_raise(run, stat->u.raise_s);
319 break;
[051bc69a]320 case st_break:
321 run_break(run, stat->u.break_s);
322 break;
[fa36f29]323 case st_return:
324 run_return(run, stat->u.return_s);
325 break;
[09ababb7]326 case st_wef:
[94d484a]327 run_wef(run, stat->u.wef_s);
328 break;
329 case st_for:
[09ababb7]330 printf("Ignoring unimplemented statement type %d.\n", stat->sc);
331 break;
332 }
333}
334
[1ebc1a62]335/** Run expression statement.
336 *
337 * Executes an expression statement. If @a res is not NULL then the value
338 * of the expression (or NULL if it has no value) will be stored to @a res.
339 *
[38aaacc2]340 * @param run Runner object
341 * @param exps Expression statement to run
342 * @param res Place to store exps result or NULL if not interested
[1ebc1a62]343 */
344static void run_exps(run_t *run, stree_exps_t *exps, rdata_item_t **res)
[09ababb7]345{
346 rdata_item_t *rexpr;
347
348#ifdef DEBUG_RUN_TRACE
349 printf("Executing expression statement.\n");
350#endif
351 run_expr(run, exps->expr, &rexpr);
352
[051b3db8]353 /*
354 * If the expression has a value, the caller should have asked for it.
355 */
356 assert(res != NULL || rexpr == NULL);
357
[1ebc1a62]358 if (res != NULL)
359 *res = rexpr;
[09ababb7]360}
361
[38aaacc2]362/** Run variable declaration statement.
363 *
364 * @param run Runner object
365 * @param vdecl Variable declaration statement to run
366 */
[09ababb7]367static void run_vdecl(run_t *run, stree_vdecl_t *vdecl)
368{
369 run_block_ar_t *block_ar;
370 rdata_var_t *var, *old_var;
371
372#ifdef DEBUG_RUN_TRACE
373 printf("Executing variable declaration statement.\n");
374#endif
[38aaacc2]375 /* Create variable and initialize with default value. */
[051b3db8]376 run_var_new(run, vdecl->titem, &var);
[09ababb7]377
378 block_ar = run_get_current_block_ar(run);
379 old_var = (rdata_var_t *) intmap_get(&block_ar->vars, vdecl->name->sid);
380
381 if (old_var != NULL) {
382 printf("Error: Duplicate variable '%s'\n",
383 strtab_get_str(vdecl->name->sid));
384 exit(1);
385 }
386
387 intmap_set(&block_ar->vars, vdecl->name->sid, var);
388
389#ifdef DEBUG_RUN_TRACE
390 printf("Declared variable '%s'\n", strtab_get_str(vdecl->name->sid));
391#endif
392}
393
[38aaacc2]394/** Run @c if statement.
395 *
396 * @param run Runner object
397 * @param if_s If statement to run
398 */
[09ababb7]399static void run_if(run_t *run, stree_if_t *if_s)
400{
401 rdata_item_t *rcond;
[051bc69a]402 list_node_t *ifc_node;
403 stree_if_clause_t *ifc;
[051b3db8]404 bool_t rcond_b, clause_fired;
[09ababb7]405
406#ifdef DEBUG_RUN_TRACE
407 printf("Executing if statement.\n");
408#endif
[051bc69a]409 clause_fired = b_false;
410 ifc_node = list_first(&if_s->if_clauses);
411
412 /* Walk through all if/elif clauses and see if they fire. */
[09ababb7]413
[051bc69a]414 while (ifc_node != NULL) {
415 /* Get if/elif clause */
416 ifc = list_node_data(ifc_node, stree_if_clause_t *);
417
418 run_expr(run, ifc->cond, &rcond);
419 if (run_is_bo(run))
420 return;
421
[051b3db8]422 rcond_b = run_item_boolean_value(run, rcond);
423 rdata_item_destroy(rcond);
424
425 if (rcond_b == b_true) {
[09ababb7]426#ifdef DEBUG_RUN_TRACE
[051bc69a]427 printf("Taking non-default path.\n");
[09ababb7]428#endif
[051bc69a]429 run_block(run, ifc->block);
430 clause_fired = b_true;
431 break;
432 }
433
434 ifc_node = list_next(&if_s->if_clauses, ifc_node);
435 }
436
437 /* If no if/elif clause fired, invoke the else clause. */
438 if (clause_fired == b_false && if_s->else_block != NULL) {
[09ababb7]439#ifdef DEBUG_RUN_TRACE
[051bc69a]440 printf("Taking default path.\n");
[09ababb7]441#endif
[051bc69a]442 run_block(run, if_s->else_block);
[09ababb7]443 }
444
445#ifdef DEBUG_RUN_TRACE
446 printf("If statement terminated.\n");
447#endif
448}
449
[051b3db8]450/** Run @c switch statement.
451 *
452 * @param run Runner object
453 * @param switch_s Switch statement to run
454 */
455static void run_switch(run_t *run, stree_switch_t *switch_s)
456{
457 rdata_item_t *rsexpr, *rsexpr_vi;
458 rdata_item_t *rwexpr, *rwexpr_vi;
459 list_node_t *whenc_node;
460 stree_when_t *whenc;
461 list_node_t *expr_node;
462 stree_expr_t *expr;
463 bool_t clause_fired;
464 bool_t equal;
465
466#ifdef DEBUG_RUN_TRACE
467 printf("Executing switch statement.\n");
468#endif
469 rsexpr_vi = NULL;
470
471 /* Evaluate switch expression */
472 run_expr(run, switch_s->expr, &rsexpr);
473 if (run_is_bo(run))
474 goto cleanup;
475
476 /* Convert to value item */
477 run_cvt_value_item(run, rsexpr, &rsexpr_vi);
478 rdata_item_destroy(rsexpr);
479 if (run_is_bo(run))
480 goto cleanup;
481
482 clause_fired = b_false;
483 whenc_node = list_first(&switch_s->when_clauses);
484
485 /* Walk through all when clauses and see if they fire. */
486
487 while (whenc_node != NULL) {
488 /* Get when clause */
489 whenc = list_node_data(whenc_node, stree_when_t *);
490
491 expr_node = list_first(&whenc->exprs);
492
493 /* Walk through all expressions in the when clause */
494 while (expr_node != NULL) {
495 /* Get expression */
496 expr = list_node_data(expr_node, stree_expr_t *);
497
498 /* Evaluate expression */
499 run_expr(run, expr, &rwexpr);
500 if (run_is_bo(run))
501 goto cleanup;
502
503 /* Convert to value item */
504 run_cvt_value_item(run, rwexpr, &rwexpr_vi);
505 rdata_item_destroy(rwexpr);
506 if (run_is_bo(run)) {
507 rdata_item_destroy(rwexpr_vi);
508 goto cleanup;
509 }
510
511 /* Check if values are equal ('==') */
512 run_equal(run, rsexpr_vi->u.value,
513 rwexpr_vi->u.value, &equal);
514 rdata_item_destroy(rwexpr_vi);
515 if (run_is_bo(run))
516 goto cleanup;
517
518 if (equal) {
519#ifdef DEBUG_RUN_TRACE
520 printf("Taking non-default path.\n");
521#endif
522 run_block(run, whenc->block);
523 clause_fired = b_true;
524 break;
525 }
526
527 expr_node = list_next(&whenc->exprs, expr_node);
528 }
529
530 if (clause_fired)
531 break;
532
533 whenc_node = list_next(&switch_s->when_clauses, whenc_node);
534 }
535
536 /* If no when clause fired, invoke the else clause. */
537 if (clause_fired == b_false && switch_s->else_block != NULL) {
538#ifdef DEBUG_RUN_TRACE
539 printf("Taking default path.\n");
540#endif
541 run_block(run, switch_s->else_block);
542 }
543cleanup:
544 if (rsexpr_vi != NULL)
545 rdata_item_destroy(rsexpr_vi);
546
547#ifdef DEBUG_RUN_TRACE
548 printf("Switch statement terminated.\n");
549#endif
550}
551
[38aaacc2]552/** Run @c while statement.
553 *
554 * @param run Runner object
555 * @param while_s While statement to run
556 */
[09ababb7]557static void run_while(run_t *run, stree_while_t *while_s)
558{
559 rdata_item_t *rcond;
560
561#ifdef DEBUG_RUN_TRACE
562 printf("Executing while statement.\n");
563#endif
564 run_expr(run, while_s->cond, &rcond);
[23de644]565 if (run_is_bo(run))
566 return;
[09ababb7]567
568 while (run_item_boolean_value(run, rcond) == b_true) {
[051b3db8]569 rdata_item_destroy(rcond);
[09ababb7]570 run_block(run, while_s->body);
571 run_expr(run, while_s->cond, &rcond);
[23de644]572 if (run_is_bo(run))
[fa36f29]573 break;
[09ababb7]574 }
575
[051b3db8]576 if (rcond != NULL)
577 rdata_item_destroy(rcond);
578
[051bc69a]579 if (run->thread_ar->bo_mode == bm_stat) {
580 /* Bailout due to break statement */
581 run->thread_ar->bo_mode = bm_none;
582 }
583
[09ababb7]584#ifdef DEBUG_RUN_TRACE
585 printf("While statement terminated.\n");
586#endif
587}
588
[38aaacc2]589/** Run @c raise statement.
590 *
591 * @param run Runner object
592 * @param raise_s Raise statement to run
593 */
[94d484a]594static void run_raise(run_t *run, stree_raise_t *raise_s)
595{
596 rdata_item_t *rexpr;
597 rdata_item_t *rexpr_vi;
598
599#ifdef DEBUG_RUN_TRACE
600 printf("Executing raise statement.\n");
601#endif
602 run_expr(run, raise_s->expr, &rexpr);
[23de644]603 if (run_is_bo(run))
604 return;
605
[d0febca]606 run_cvt_value_item(run, rexpr, &rexpr_vi);
[051b3db8]607 rdata_item_destroy(rexpr);
608 if (run_is_bo(run))
609 return;
[94d484a]610
[051bc69a]611 /* Store expression cspan in thread AR. */
612 run->thread_ar->exc_cspan = raise_s->expr->cspan;
613
[94d484a]614 /* Store expression result in thread AR. */
[051b3db8]615 /* XXX rexpr_vi is leaked here, we only return ->u.value */
[94d484a]616 run->thread_ar->exc_payload = rexpr_vi->u.value;
617
618 /* Start exception bailout. */
619 run->thread_ar->bo_mode = bm_exc;
620}
621
[051bc69a]622/** Run @c break statement.
623 *
624 * Forces control to return from the active breakable statement by setting
625 * bailout mode to @c bm_stat.
626 *
627 * @param run Runner object
628 * @param break_s Break statement to run
629 */
630static void run_break(run_t *run, stree_break_t *break_s)
631{
632#ifdef DEBUG_RUN_TRACE
633 printf("Executing 'break' statement.\n");
634#endif
635 (void) break_s;
636
637 /* Force control to ascend and leave the procedure. */
638 if (run->thread_ar->bo_mode == bm_none)
639 run->thread_ar->bo_mode = bm_stat;
640}
641
[38aaacc2]642/** Run @c return statement.
643 *
644 * Sets the return value in procedure AR and forces control to return
645 * from the function by setting bailout mode to @c bm_proc.
646 *
647 * @param run Runner object
[051bc69a]648 * @param return_s Return statement to run
[38aaacc2]649 */
[fa36f29]650static void run_return(run_t *run, stree_return_t *return_s)
651{
652 rdata_item_t *rexpr;
[d0febca]653 rdata_item_t *rexpr_vi;
654 run_proc_ar_t *proc_ar;
[fa36f29]655
656#ifdef DEBUG_RUN_TRACE
657 printf("Executing return statement.\n");
658#endif
[051bc69a]659 if (return_s->expr != NULL) {
660 run_expr(run, return_s->expr, &rexpr);
661 if (run_is_bo(run))
662 return;
[23de644]663
[051bc69a]664 run_cvt_value_item(run, rexpr, &rexpr_vi);
[051b3db8]665 rdata_item_destroy(rexpr);
666 if (run_is_bo(run))
667 return;
[fa36f29]668
[051bc69a]669 /* Store expression result in procedure AR. */
670 proc_ar = run_get_current_proc_ar(run);
671 proc_ar->retval = rexpr_vi;
672 }
[fa36f29]673
[d0febca]674 /* Force control to ascend and leave the procedure. */
[fa36f29]675 if (run->thread_ar->bo_mode == bm_none)
[d0febca]676 run->thread_ar->bo_mode = bm_proc;
[fa36f29]677}
678
[38aaacc2]679/** Run @c with-except-finally statement.
680 *
681 * Note: 'With' clause is not implemented.
682 *
683 * @param run Runner object
684 * @param wef_s With-except-finally statement to run
685 */
[94d484a]686static void run_wef(run_t *run, stree_wef_t *wef_s)
687{
688 list_node_t *except_n;
689 stree_except_t *except_c;
690 rdata_value_t *exc_payload;
691 run_bailout_mode_t bo_mode;
692
693#ifdef DEBUG_RUN_TRACE
694 printf("Executing with-except-finally statement.\n");
695#endif
696 run_block(run, wef_s->with_block);
697
698 if (run->thread_ar->bo_mode == bm_exc) {
699#ifdef DEBUG_RUN_TRACE
700 printf("With statement detected exception.\n");
701#endif
702 /* Reset to normal execution. */
703 run->thread_ar->bo_mode = bm_none;
704
705 /* Look for an except block. */
706 except_n = list_first(&wef_s->except_clauses);
707 while (except_n != NULL) {
708 except_c = list_node_data(except_n, stree_except_t *);
709 if (run_exc_match(run, except_c))
710 break;
711
712 except_n = list_next(&wef_s->except_clauses, except_n);
713 }
714
715 /* If one was found, execute it. */
716 if (except_n != NULL)
717 run_block(run, except_c->block);
718
719 /* Execute finally block */
720 if (wef_s->finally_block != NULL) {
721 /* Put exception on the side temporarily. */
722 bo_mode = run->thread_ar->bo_mode;
723 exc_payload = run->thread_ar->exc_payload;
724
725 run->thread_ar->bo_mode = bm_none;
726 run->thread_ar->exc_payload = NULL;
727
728 run_block(run, wef_s->finally_block);
729
730 if (bo_mode == bm_exc) {
731 /*
732 * Restore the original exception. If another
733 * exception occured in the finally block (i.e.
734 * double fault), it is forgotten.
735 */
736 run->thread_ar->bo_mode = bm_exc;
737 run->thread_ar->exc_payload = exc_payload;
738 }
739 }
740 }
741
742#ifdef DEBUG_RUN_TRACE
743 printf("With-except-finally statement terminated.\n");
744#endif
745}
746
747/** Determine whether currently active exception matches @c except clause.
748 *
749 * Checks if the currently active exception in the runner object @c run
[23de644]750 * matches except clause @c except_c.
[94d484a]751 *
[38aaacc2]752 * @param run Runner object
753 * @param except_c @c except clause
754 * @return @c b_true if there is a match, @c b_false otherwise
[94d484a]755 */
756static bool_t run_exc_match(run_t *run, stree_except_t *except_c)
[23de644]757{
758 stree_csi_t *exc_csi;
759
760 /* Get CSI of active exception. */
761 exc_csi = run_exc_payload_get_csi(run);
762
763 /* Determine if active exc. is derived from type in exc. clause. */
[38aaacc2]764 /* XXX This is wrong, it does not work with generics. */
[051b3db8]765 return tdata_is_csi_derived_from_ti(exc_csi, except_c->titem);
[23de644]766}
767
768/** Return CSI of the active exception.
769 *
[38aaacc2]770 * @param run Runner object
771 * @return CSI of the active exception
[23de644]772 */
773static stree_csi_t *run_exc_payload_get_csi(run_t *run)
[94d484a]774{
775 rdata_value_t *payload;
776 rdata_var_t *payload_v;
777 rdata_object_t *payload_o;
778
779 payload = run->thread_ar->exc_payload;
780 assert(payload != NULL);
781
782 if (payload->var->vc != vc_ref) {
[23de644]783 /* XXX Prevent this via static type checking. */
[94d484a]784 printf("Error: Exception payload must be an object "
785 "(found type %d).\n", payload->var->vc);
786 exit(1);
787 }
788
789 payload_v = payload->var->u.ref_v->vref;
790 if (payload_v->vc != vc_object) {
[23de644]791 /* XXX Prevent this via static type checking. */
[94d484a]792 printf("Error: Exception payload must be an object "
793 "(found type %d).\n", payload_v->vc);
794 exit(1);
795 }
796
797 payload_o = payload_v->u.object_v;
798
799#ifdef DEBUG_RUN_TRACE
800 printf("Active exception: '");
[39e8406]801 symbol_print_fqn(payload_o->class_sym);
[94d484a]802 printf("'.\n");
803#endif
804 assert(payload_o->class_sym != NULL);
805 assert(payload_o->class_sym->sc == sc_csi);
806
[23de644]807 return payload_o->class_sym->u.csi;
808}
809
810
811/** Check for unhandled exception.
812 *
813 * Checks whether there is an active exception. If so, it prints an
814 * error message and raises a run-time error.
815 *
[38aaacc2]816 * @param run Runner object
[23de644]817 */
818void run_exc_check_unhandled(run_t *run)
819{
820 stree_csi_t *exc_csi;
821
822 if (run->thread_ar->bo_mode != bm_none) {
823 assert(run->thread_ar->bo_mode == bm_exc);
[94d484a]824
[23de644]825 exc_csi = run_exc_payload_get_csi(run);
826
[051bc69a]827 if (run->thread_ar->exc_cspan != NULL) {
828 cspan_print(run->thread_ar->exc_cspan);
829 putchar(' ');
830 }
831
[23de644]832 printf("Error: Unhandled exception '");
833 symbol_print_fqn(csi_to_symbol(exc_csi));
834 printf("'.\n");
835
836 run_raise_error(run);
837 }
[94d484a]838}
839
[1ebc1a62]840/** Raise an irrecoverable run-time error, start bailing out.
841 *
842 * Raises an error that cannot be handled by the user program.
[38aaacc2]843 *
844 * @param run Runner object
[1ebc1a62]845 */
846void run_raise_error(run_t *run)
847{
848 run->thread_ar->bo_mode = bm_error;
849 run->thread_ar->error = b_true;
850}
851
[38aaacc2]852/** Construct a special recovery item.
853 *
854 * @param run Runner object
855 */
[1ebc1a62]856rdata_item_t *run_recovery_item(run_t *run)
857{
858 (void) run;
859 return NULL;
860}
861
[38aaacc2]862/** Find a local variable in the currently active function.
863 *
864 * @param run Runner object
865 * @param name Name SID of the local variable
866 * @return Pointer to var node or @c NULL if not found
867 */
[09ababb7]868rdata_var_t *run_local_vars_lookup(run_t *run, sid_t name)
869{
[d0febca]870 run_proc_ar_t *proc_ar;
[09ababb7]871 run_block_ar_t *block_ar;
872 rdata_var_t *var;
873 list_node_t *node;
874
[d0febca]875 proc_ar = run_get_current_proc_ar(run);
876 node = list_last(&proc_ar->block_ar);
[09ababb7]877
878 /* Walk through all block activation records. */
879 while (node != NULL) {
880 block_ar = list_node_data(node, run_block_ar_t *);
881 var = intmap_get(&block_ar->vars, name);
882 if (var != NULL)
883 return var;
884
[d0febca]885 node = list_prev(&proc_ar->block_ar, node);
[09ababb7]886 }
887
888 /* No match */
889 return NULL;
890}
891
[38aaacc2]892/** Get current procedure activation record.
893 *
894 * @param run Runner object
895 * @return Active procedure AR
896 */
[d0febca]897run_proc_ar_t *run_get_current_proc_ar(run_t *run)
[09ababb7]898{
899 list_node_t *node;
900
[d0febca]901 node = list_last(&run->thread_ar->proc_ar);
902 return list_node_data(node, run_proc_ar_t *);
[09ababb7]903}
904
[38aaacc2]905/** Get current block activation record.
906 *
907 * @param run Runner object
908 * @return Active block AR
909 */
[09ababb7]910run_block_ar_t *run_get_current_block_ar(run_t *run)
911{
[d0febca]912 run_proc_ar_t *proc_ar;
[09ababb7]913 list_node_t *node;
914
[d0febca]915 proc_ar = run_get_current_proc_ar(run);
[09ababb7]916
[d0febca]917 node = list_last(&proc_ar->block_ar);
[09ababb7]918 return list_node_data(node, run_block_ar_t *);
919}
920
[38aaacc2]921/** Get current CSI.
922 *
923 * @param run Runner object
924 * @return Active CSI
925 */
[94d484a]926stree_csi_t *run_get_current_csi(run_t *run)
927{
[d0febca]928 run_proc_ar_t *proc_ar;
[94d484a]929
[d0febca]930 proc_ar = run_get_current_proc_ar(run);
[39e8406]931 return proc_ar->proc->outer_symbol->outer_csi;
[94d484a]932}
933
[c5cb943d]934/** Get static object (i.e. class object).
935 *
936 * Looks for a child static object named @a name in static object @a pobject.
937 * If the child does not exist yet, it is created.
938 *
939 * @param run Runner object
940 * @param csi CSI of the static object named @a name
941 * @param pobject Parent static object
942 * @param name Static object name
943 *
944 * @return Static (class) object of the given name
945 */
946rdata_var_t *run_sobject_get(run_t *run, stree_csi_t *csi,
947 rdata_var_t *pobj_var, sid_t name)
948{
949 rdata_object_t *pobject;
950 rdata_var_t *mbr_var;
951 rdata_var_t *rvar;
952 stree_ident_t *ident;
953
954 assert(pobj_var->vc == vc_object);
955 pobject = pobj_var->u.object_v;
956#ifdef DEBUG_RUN_TRACE
957 printf("Get static object '%s' in '", strtab_get_str(name));
958 if (pobject->class_sym != NULL)
959 symbol_print_fqn(pobject->class_sym);
960 else
961 printf("global");
962#endif
963
964 assert(pobject->static_obj == sn_static);
965
966 mbr_var = intmap_get(&pobject->fields, name);
967 if (mbr_var != NULL) {
968#ifdef DEBUG_RUN_TRACE
969 printf("Return exising static object (mbr_var=%p).\n", mbr_var);
970#endif
971 /* Return existing object. */
972 return mbr_var;
973 }
974
975 /* Construct new object. */
976#ifdef DEBUG_RUN_TRACE
977 printf("Construct new static object.\n");
978#endif
979 ident = stree_ident_new();
980 ident->sid = name;
981
982 run_new_csi_inst(run, csi, sn_static, &rvar);
983
984 /* Store static object reference for future use. */
985 intmap_set(&pobject->fields, name, rvar);
986
987 return rvar;
988}
989
990/** Get static object for CSI.
991 *
992 * In situations where we do not have the parent static object and need
993 * to find static object for a CSI from the gdata root we use this.
994 *
995 * This is only used in special cases such as when invoking the entry
996 * point. This is too slow to use during normal execution.
997 *
998 * @param run Runner object
999 * @param csi CSI to get static object of
1000 *
1001 * @return Static (class) object
1002 */
1003rdata_var_t *run_sobject_find(run_t *run, stree_csi_t *csi)
1004{
1005 rdata_var_t *pobj_var;
1006
1007 if (csi == NULL)
1008 return run->gdata;
1009
1010 assert(csi->ancr_state == ws_visited);
1011 pobj_var = run_sobject_find(run, csi_to_symbol(csi)->outer_csi);
1012
1013 return run_sobject_get(run, csi, pobj_var, csi->name->sid);
1014}
1015
1016/** Get static object for CSI containing function.
1017 *
1018 * This is used to obtain active object for invoking static function
1019 * @a fun. Only used in cases where we don't already have the object such
1020 * as when running the entry point. Otherwise this would be slow.
1021 *
1022 * @param run Runner object
1023 * @param fun Function to get static class object of
1024 *
1025 * @return Static (class) object
1026 */
1027rdata_var_t *run_fun_sobject_find(run_t *run, stree_fun_t *fun)
1028{
1029 return run_sobject_find(run, fun_to_symbol(fun)->outer_csi);
1030}
1031
[09ababb7]1032/** Construct variable from a value item.
1033 *
1034 * XXX This should be in fact implemented using existing code as:
1035 *
1036 * (1) Create a variable of the desired type.
1037 * (2) Initialize the variable with the provided value.
[38aaacc2]1038 *
1039 * @param item Value item (initial value for variable).
1040 * @param var Place to store new var node.
[09ababb7]1041 */
[fa36f29]1042void run_value_item_to_var(rdata_item_t *item, rdata_var_t **var)
[09ababb7]1043{
[38aaacc2]1044 rdata_bool_t *bool_v;
[074444f]1045 rdata_char_t *char_v;
[38aaacc2]1046 rdata_deleg_t *deleg_v;
[051bc69a]1047 rdata_enum_t *enum_v;
[09ababb7]1048 rdata_int_t *int_v;
1049 rdata_string_t *string_v;
[fa36f29]1050 rdata_ref_t *ref_v;
[09ababb7]1051 rdata_var_t *in_var;
1052
1053 assert(item->ic == ic_value);
1054 in_var = item->u.value->var;
1055
1056 switch (in_var->vc) {
[38aaacc2]1057 case vc_bool:
1058 *var = rdata_var_new(vc_bool);
1059 bool_v = rdata_bool_new();
1060
1061 (*var)->u.bool_v = bool_v;
1062 bool_v->value = item->u.value->var->u.bool_v->value;
1063 break;
[074444f]1064 case vc_char:
1065 *var = rdata_var_new(vc_char);
1066 char_v = rdata_char_new();
1067
1068 (*var)->u.char_v = char_v;
1069 bigint_clone(&item->u.value->var->u.char_v->value,
1070 &char_v->value);
1071 break;
[38aaacc2]1072 case vc_deleg:
1073 *var = rdata_var_new(vc_deleg);
1074 deleg_v = rdata_deleg_new();
1075
1076 (*var)->u.deleg_v = deleg_v;
1077 deleg_v->obj = item->u.value->var->u.deleg_v->obj;
1078 deleg_v->sym = item->u.value->var->u.deleg_v->sym;
1079 break;
[051bc69a]1080 case vc_enum:
1081 *var = rdata_var_new(vc_enum);
1082 enum_v = rdata_enum_new();
1083
1084 (*var)->u.enum_v = enum_v;
1085 enum_v->value = item->u.value->var->u.enum_v->value;
1086 break;
[09ababb7]1087 case vc_int:
1088 *var = rdata_var_new(vc_int);
1089 int_v = rdata_int_new();
1090
1091 (*var)->u.int_v = int_v;
[23de644]1092 bigint_clone(&item->u.value->var->u.int_v->value,
1093 &int_v->value);
[09ababb7]1094 break;
1095 case vc_string:
1096 *var = rdata_var_new(vc_string);
1097 string_v = rdata_string_new();
1098
1099 (*var)->u.string_v = string_v;
1100 string_v->value = item->u.value->var->u.string_v->value;
1101 break;
[fa36f29]1102 case vc_ref:
1103 *var = rdata_var_new(vc_ref);
1104 ref_v = rdata_ref_new();
1105
1106 (*var)->u.ref_v = ref_v;
1107 ref_v->vref = item->u.value->var->u.ref_v->vref;
1108 break;
[09ababb7]1109 default:
1110 printf("Error: Unimplemented argument type.\n");
1111 exit(1);
1112
1113 }
1114}
1115
[38aaacc2]1116/** Construct a procedure AR.
1117 *
1118 * @param run Runner object
1119 * @param obj Object whose procedure is being activated
1120 * @param proc Procedure that is being activated
1121 * @param rproc_ar Place to store pointer to new activation record
1122 */
[39e8406]1123void run_proc_ar_create(run_t *run, rdata_var_t *obj, stree_proc_t *proc,
1124 run_proc_ar_t **rproc_ar)
[fa36f29]1125{
[d0febca]1126 run_proc_ar_t *proc_ar;
1127 run_block_ar_t *block_ar;
[fa36f29]1128
1129 (void) run;
1130
[051b3db8]1131 /* Create procedure activation record. */
[d0febca]1132 proc_ar = run_proc_ar_new();
1133 proc_ar->obj = obj;
[39e8406]1134 proc_ar->proc = proc;
[d0febca]1135 list_init(&proc_ar->block_ar);
[fa36f29]1136
[d0febca]1137 proc_ar->retval = NULL;
1138
1139 /* Create special block activation record to hold function arguments. */
1140 block_ar = run_block_ar_new();
1141 intmap_init(&block_ar->vars);
1142 list_append(&proc_ar->block_ar, block_ar);
[fa36f29]1143
[d0febca]1144 *rproc_ar = proc_ar;
[fa36f29]1145}
1146
[051b3db8]1147/** Destroy a procedure AR.
1148 *
1149 * @param run Runner object
1150 * @param proc_ar Pointer to procedure activation record
1151 */
1152void run_proc_ar_destroy(run_t *run, run_proc_ar_t *proc_ar)
1153{
1154 list_node_t *ar_node;
1155 run_block_ar_t *block_ar;
1156
1157 (void) run;
1158
1159 /* Destroy special block activation record. */
1160 ar_node = list_first(&proc_ar->block_ar);
1161 block_ar = list_node_data(ar_node, run_block_ar_t *);
1162 list_remove(&proc_ar->block_ar, ar_node);
1163 run_block_ar_destroy(run, block_ar);
1164
1165 /* Destroy procedure activation record. */
1166 proc_ar->obj = NULL;
1167 proc_ar->proc = NULL;
1168 list_fini(&proc_ar->block_ar);
1169 proc_ar->retval = NULL;
1170 run_proc_ar_delete(proc_ar);
1171}
1172
1173
[d0febca]1174/** Fill arguments in a procedure AR.
1175 *
1176 * When invoking a procedure this is used to store the argument values
1177 * in the activation record.
[38aaacc2]1178 *
1179 * @param run Runner object
1180 * @param proc_ar Existing procedure activation record where to store
1181 * the values
1182 * @param arg_vals List of value items (rdata_item_t *) -- real
1183 * argument values
[d0febca]1184 */
1185void run_proc_ar_set_args(run_t *run, run_proc_ar_t *proc_ar, list_t *arg_vals)
[fa36f29]1186{
[051bc69a]1187 stree_ctor_t *ctor;
[fa36f29]1188 stree_fun_t *fun;
[d0febca]1189 stree_prop_t *prop;
1190 list_t *args;
1191 stree_proc_arg_t *varg;
[39e8406]1192 stree_symbol_t *outer_symbol;
[d0febca]1193
[fa36f29]1194 run_block_ar_t *block_ar;
[d0febca]1195 list_node_t *block_ar_n;
1196 list_node_t *rarg_n, *parg_n;
[94d484a]1197 list_node_t *cn;
[fa36f29]1198 rdata_item_t *rarg;
[d0febca]1199 stree_proc_arg_t *parg;
[fa36f29]1200 rdata_var_t *var;
[94d484a]1201 rdata_var_t *ref_var;
1202 rdata_ref_t *ref;
1203 rdata_array_t *array;
[051b3db8]1204 rdata_var_t *elem_var;
[94d484a]1205 int n_vargs, idx;
[fa36f29]1206
[39e8406]1207 (void) run;
1208
[d0febca]1209 /* AR should have been created with run_proc_ar_create(). */
[39e8406]1210 assert(proc_ar->proc != NULL);
1211 outer_symbol = proc_ar->proc->outer_symbol;
[fa36f29]1212
[051bc69a]1213 /* Make compiler happy. */
1214 args = NULL;
1215 varg = NULL;
1216
[d0febca]1217 /*
[39e8406]1218 * The procedure being activated should belong to a member function or
[d0febca]1219 * property getter/setter.
1220 */
[39e8406]1221 switch (outer_symbol->sc) {
[051bc69a]1222 case sc_ctor:
1223 ctor = symbol_to_ctor(outer_symbol);
1224 args = &ctor->sig->args;
1225 varg = ctor->sig->varg;
1226 break;
[d0febca]1227 case sc_fun:
[39e8406]1228 fun = symbol_to_fun(outer_symbol);
[38aaacc2]1229 args = &fun->sig->args;
1230 varg = fun->sig->varg;
[d0febca]1231 break;
1232 case sc_prop:
[39e8406]1233 prop = symbol_to_prop(outer_symbol);
[d0febca]1234 args = &prop->args;
1235 varg = prop->varg;
1236 break;
[051bc69a]1237 case sc_csi:
1238 case sc_deleg:
1239 case sc_enum:
1240 case sc_var:
[d0febca]1241 assert(b_false);
1242 }
[fa36f29]1243
[d0febca]1244 /* Fetch first block activation record. */
1245 block_ar_n = list_first(&proc_ar->block_ar);
1246 assert(block_ar_n != NULL);
1247 block_ar = list_node_data(block_ar_n, run_block_ar_t *);
[fa36f29]1248
1249 /* Declare local variables to hold argument values. */
[d0febca]1250 rarg_n = list_first(arg_vals);
1251 parg_n = list_first(args);
[fa36f29]1252
[d0febca]1253 while (parg_n != NULL) {
[fa36f29]1254 if (rarg_n == NULL) {
[39e8406]1255 printf("Error: Too few arguments to '");
1256 symbol_print_fqn(outer_symbol);
[fa36f29]1257 printf("'.\n");
1258 exit(1);
1259 }
1260
1261 rarg = list_node_data(rarg_n, rdata_item_t *);
[d0febca]1262 parg = list_node_data(parg_n, stree_proc_arg_t *);
[fa36f29]1263
1264 assert(rarg->ic == ic_value);
1265
1266 /* Construct a variable from the argument value. */
1267 run_value_item_to_var(rarg, &var);
1268
1269 /* Declare variable using name of formal argument. */
[d0febca]1270 intmap_set(&block_ar->vars, parg->name->sid, var);
[fa36f29]1271
[d0febca]1272 rarg_n = list_next(arg_vals, rarg_n);
1273 parg_n = list_next(args, parg_n);
[fa36f29]1274 }
1275
[d0febca]1276 if (varg != NULL) {
[94d484a]1277 /* Function is variadic. Count number of variadic arguments. */
1278 cn = rarg_n;
1279 n_vargs = 0;
1280 while (cn != NULL) {
1281 n_vargs += 1;
[d0febca]1282 cn = list_next(arg_vals, cn);
[94d484a]1283 }
1284
1285 /* Prepare array to store variadic arguments. */
1286 array = rdata_array_new(1);
1287 array->extent[0] = n_vargs;
1288 rdata_array_alloc_element(array);
1289
1290 /* Read variadic arguments. */
1291
1292 idx = 0;
1293 while (rarg_n != NULL) {
1294 rarg = list_node_data(rarg_n, rdata_item_t *);
1295 assert(rarg->ic == ic_value);
1296
[051b3db8]1297 run_value_item_to_var(rarg, &elem_var);
1298 array->element[idx] = elem_var;
[94d484a]1299
[d0febca]1300 rarg_n = list_next(arg_vals, rarg_n);
[94d484a]1301 idx += 1;
1302 }
1303
1304 var = rdata_var_new(vc_array);
1305 var->u.array_v = array;
1306
1307 /* Create reference to the new array. */
1308 ref_var = rdata_var_new(vc_ref);
1309 ref = rdata_ref_new();
1310 ref_var->u.ref_v = ref;
1311 ref->vref = var;
1312
1313 /* Declare variable using name of formal argument. */
[d0febca]1314 intmap_set(&block_ar->vars, varg->name->sid,
[94d484a]1315 ref_var);
1316 }
1317
[fa36f29]1318 /* Check for excess real parameters. */
1319 if (rarg_n != NULL) {
[39e8406]1320 printf("Error: Too many arguments to '");
1321 symbol_print_fqn(outer_symbol);
[fa36f29]1322 printf("'.\n");
1323 exit(1);
1324 }
1325}
1326
[d0febca]1327/** Fill setter argument in a procedure AR.
1328 *
1329 * When invoking a setter this is used to store its argument value in its
1330 * procedure activation record.
[38aaacc2]1331 *
1332 * @param run Runner object
1333 * @param proc_ar Existing procedure activation record where to store
1334 * the setter argument
1335 * @param arg_val Value items (rdata_item_t *) -- real argument value
[d0febca]1336 */
1337void run_proc_ar_set_setter_arg(run_t *run, run_proc_ar_t *proc_ar,
1338 rdata_item_t *arg_val)
1339{
1340 stree_prop_t *prop;
1341 run_block_ar_t *block_ar;
1342 list_node_t *block_ar_n;
1343 rdata_var_t *var;
1344
1345 (void) run;
1346
1347 /* AR should have been created with run_proc_ar_create(). */
[39e8406]1348 assert(proc_ar->proc != NULL);
[d0febca]1349
[39e8406]1350 /* The procedure being activated should belong to a property setter. */
1351 prop = symbol_to_prop(proc_ar->proc->outer_symbol);
[d0febca]1352 assert(prop != NULL);
[39e8406]1353 assert(proc_ar->proc == prop->setter);
[d0febca]1354
1355 /* Fetch first block activation record. */
1356 block_ar_n = list_first(&proc_ar->block_ar);
1357 assert(block_ar_n != NULL);
1358 block_ar = list_node_data(block_ar_n, run_block_ar_t *);
1359
1360 assert(arg_val->ic == ic_value);
1361
1362 /* Construct a variable from the argument value. */
1363 run_value_item_to_var(arg_val, &var);
1364
1365 /* Declare variable using name of formal argument. */
[39e8406]1366 intmap_set(&block_ar->vars, prop->setter_arg->name->sid, var);
[d0febca]1367}
1368
[38aaacc2]1369/** Print function activation backtrace.
1370 *
1371 * Prints a backtrace of activated functions for debugging purposes.
1372 *
1373 * @param run Runner object
1374 */
[09ababb7]1375void run_print_fun_bt(run_t *run)
1376{
1377 list_node_t *node;
[d0febca]1378 run_proc_ar_t *proc_ar;
[09ababb7]1379
1380 printf("Backtrace:\n");
[d0febca]1381 node = list_last(&run->thread_ar->proc_ar);
[09ababb7]1382 while (node != NULL) {
1383 printf(" * ");
[d0febca]1384 proc_ar = list_node_data(node, run_proc_ar_t *);
[39e8406]1385 symbol_print_fqn(proc_ar->proc->outer_symbol);
[09ababb7]1386 printf("\n");
1387
[d0febca]1388 node = list_prev(&run->thread_ar->proc_ar, node);
1389 }
1390}
1391
[051b3db8]1392/** Destroy a block AR.
1393 *
1394 * @param run Runner object
1395 * @param proc_ar Pointer to block activation record
1396 */
1397void run_block_ar_destroy(run_t *run, run_block_ar_t *block_ar)
1398{
1399 map_elem_t *elem;
1400 rdata_var_t *var;
1401 int key;
1402
1403 (void) run;
1404
1405 elem = intmap_first(&block_ar->vars);
1406 while (elem != NULL) {
1407 /* Destroy the variable */
1408 var = intmap_elem_get_value(elem);
1409 rdata_var_destroy(var);
1410
1411 /* Remove the map element */
1412 key = intmap_elem_get_key(elem);
1413 intmap_set(&block_ar->vars, key, NULL);
1414
1415 elem = intmap_first(&block_ar->vars);
1416 }
1417
1418 intmap_fini(&block_ar->vars);
1419 run_block_ar_delete(block_ar);
1420}
1421
[d0febca]1422/** Convert item to value item.
1423 *
1424 * If @a item is a value, we just return a copy. If @a item is an address,
1425 * we read from the address.
[38aaacc2]1426 *
1427 * @param run Runner object
1428 * @param item Input item (value or address)
1429 * @param ritem Place to store pointer to new value item
[d0febca]1430 */
1431void run_cvt_value_item(run_t *run, rdata_item_t *item, rdata_item_t **ritem)
1432{
1433 rdata_value_t *value;
1434
[1b20da0]1435 /*
[d0febca]1436 * This can happen when trying to use output of a function which
1437 * does not return a value.
1438 */
1439 if (item == NULL) {
1440 printf("Error: Sub-expression has no value.\n");
1441 exit(1);
1442 }
1443
1444 /* Address item. Perform read operation. */
1445 if (item->ic == ic_address) {
1446 run_address_read(run, item->u.address, ritem);
1447 return;
1448 }
1449
[051b3db8]1450 /* Make a copy of the var node within. */
[d0febca]1451 value = rdata_value_new();
[051b3db8]1452 rdata_var_copy(item->u.value->var, &value->var);
[d0febca]1453 *ritem = rdata_item_new(ic_value);
1454 (*ritem)->u.value = value;
1455}
1456
[39e8406]1457/** Get item var-class.
1458 *
1459 * Get var-class of @a item, regardless whether it is a value or address.
1460 * (I.e. the var class of the value or variable at the given address).
[38aaacc2]1461 *
1462 * @param run Runner object
1463 * @param item Value or address item
1464 * @return Varclass of @a item
[39e8406]1465 */
1466var_class_t run_item_get_vc(run_t *run, rdata_item_t *item)
1467{
1468 var_class_t vc;
1469 rdata_var_t *tpos;
1470
1471 (void) run;
1472
1473 switch (item->ic) {
1474 case ic_value:
1475 vc = item->u.value->var->vc;
1476 break;
1477 case ic_address:
1478 switch (item->u.address->ac) {
1479 case ac_var:
1480 vc = item->u.address->u.var_a->vref->vc;
1481 break;
1482 case ac_prop:
1483 /* Prefetch the value of the property. */
1484 tpos = run_aprop_get_tpos(run, item->u.address);
1485 vc = tpos->vc;
1486 break;
1487 default:
1488 assert(b_false);
1489 }
1490 break;
1491 default:
1492 assert(b_false);
1493 }
1494
1495 return vc;
1496}
1497
1498/** Get pointer to current var node in temporary copy in property address.
1499 *
1500 * A property address refers to a specific @c var node in a property.
1501 * This function will fetch a copy of the property value (by running
1502 * its getter) if there is not a temporary copy in the address yet.
1503 * It returns a pointer to the relevant @c var node in the temporary
1504 * copy.
1505 *
[38aaacc2]1506 * @param run Runner object
1507 * @param addr Address of class @c ac_prop
1508 * @return Pointer to var node
[39e8406]1509 */
1510static rdata_var_t *run_aprop_get_tpos(run_t *run, rdata_address_t *addr)
1511{
1512 rdata_item_t *ritem;
1513
1514 assert(addr->ac == ac_prop);
1515
1516 if (addr->u.prop_a->tvalue == NULL) {
1517 /* Fetch value of the property. */
1518 run_address_read(run, addr, &ritem);
1519 assert(ritem->ic == ic_value);
1520 addr->u.prop_a->tvalue = ritem->u.value;
1521 addr->u.prop_a->tpos = addr->u.prop_a->tvalue->var;
1522 }
1523
1524 return addr->u.prop_a->tpos;
1525}
[d0febca]1526
1527/** Read data from an address.
1528 *
[38aaacc2]1529 * Read value from the specified address.
1530 *
1531 * @param run Runner object
1532 * @param address Address to read
1533 * @param ritem Place to store pointer to the value that was read
[d0febca]1534 */
1535void run_address_read(run_t *run, rdata_address_t *address,
1536 rdata_item_t **ritem)
1537{
1538 (void) run;
[051b3db8]1539 assert(ritem != NULL);
[d0febca]1540
1541 switch (address->ac) {
1542 case ac_var:
1543 rdata_var_read(address->u.var_a->vref, ritem);
1544 break;
1545 case ac_prop:
1546 run_aprop_read(run, address->u.prop_a, ritem);
1547 break;
1548 }
1549
[051b3db8]1550 assert(*ritem == NULL || (*ritem)->ic == ic_value);
[d0febca]1551}
1552
1553/** Write data to an address.
1554 *
[38aaacc2]1555 * Store value @a value at address @a address.
1556 *
1557 * @param run Runner object
1558 * @param address Address to write
1559 * @param value Value to store at the address
[d0febca]1560 */
1561void run_address_write(run_t *run, rdata_address_t *address,
1562 rdata_value_t *value)
1563{
1564 (void) run;
1565
1566 switch (address->ac) {
1567 case ac_var:
1568 rdata_var_write(address->u.var_a->vref, value);
1569 break;
1570 case ac_prop:
1571 run_aprop_write(run, address->u.prop_a, value);
1572 break;
1573 }
1574}
1575
[38aaacc2]1576/** Read data from a property address.
1577 *
1578 * This involves invoking the property getter procedure.
1579 *
1580 * @param run Runner object.
1581 * @param addr_prop Property address to read.
1582 * @param ritem Place to store pointer to the value that was read.
1583 */
[d0febca]1584static void run_aprop_read(run_t *run, rdata_addr_prop_t *addr_prop,
1585 rdata_item_t **ritem)
1586{
1587 rdata_deleg_t *deleg;
1588 rdata_var_t *obj;
1589 stree_symbol_t *prop_sym;
1590 stree_prop_t *prop;
1591
1592 run_proc_ar_t *proc_ar;
1593
[39e8406]1594 rdata_var_t *cvar;
1595
[d0febca]1596#ifdef DEBUG_RUN_TRACE
1597 printf("Read from property.\n");
1598#endif
1599 /*
1600 * If @c tvalue is present, we need to use the relevant part from that
1601 * instead of re-reading the whole thing.
1602 */
1603 if (addr_prop->tvalue != NULL) {
[39e8406]1604 /* Copy the value */
1605 rdata_var_copy(addr_prop->tpos, &cvar);
1606 *ritem = rdata_item_new(ic_value);
1607 (*ritem)->u.value = rdata_value_new();
1608 (*ritem)->u.value->var = cvar;
1609 return;
[d0febca]1610 }
1611
1612 if (addr_prop->apc == apc_named)
1613 deleg = addr_prop->u.named->prop_d;
1614 else
1615 deleg = addr_prop->u.indexed->object_d;
1616
1617 obj = deleg->obj;
1618 prop_sym = deleg->sym;
1619 prop = symbol_to_prop(prop_sym);
1620 assert(prop != NULL);
1621
[39e8406]1622 if (prop->getter == NULL) {
[d0febca]1623 printf("Error: Property is not readable.\n");
1624 exit(1);
1625 }
1626
1627 /* Create procedure activation record. */
[39e8406]1628 run_proc_ar_create(run, obj, prop->getter, &proc_ar);
[d0febca]1629
1630 /* Fill in arguments (indices). */
1631 if (addr_prop->apc == apc_indexed) {
1632 run_proc_ar_set_args(run, proc_ar,
1633 &addr_prop->u.indexed->args);
1634 }
1635
1636 /* Run getter. */
1637 run_proc(run, proc_ar, ritem);
1638
[051b3db8]1639 /* Destroy procedure activation record. */
1640 run_proc_ar_destroy(run, proc_ar);
1641
[d0febca]1642#ifdef DEBUG_RUN_TRACE
1643 printf("Getter returns ");
1644 rdata_item_print(*ritem);
1645 printf(".\n");
1646 printf("Done reading from property.\n");
1647#endif
1648}
1649
[38aaacc2]1650/** Write data to a property address.
1651 *
1652 * This involves invoking the property setter procedure.
1653 *
1654 * @param run Runner object
1655 * @param addr_prop Property address to write
1656 * @param value Value to store at the address
1657 */
[d0febca]1658static void run_aprop_write(run_t *run, rdata_addr_prop_t *addr_prop,
1659 rdata_value_t *value)
1660{
1661 rdata_deleg_t *deleg;
1662 rdata_var_t *obj;
1663 stree_symbol_t *prop_sym;
1664 stree_prop_t *prop;
1665
1666 run_proc_ar_t *proc_ar;
1667 rdata_item_t *vitem;
1668 rdata_item_t *ritem;
1669
1670#ifdef DEBUG_RUN_TRACE
1671 printf("Write to property.\n");
1672#endif
1673 /* If @c tvalue is present, we need to modify it and write it back. */
1674 if (addr_prop->tvalue != NULL) {
1675 printf("Unimplemented: Read-modify-write property access.\n");
1676 exit(1);
1677 }
1678
1679 if (addr_prop->apc == apc_named)
1680 deleg = addr_prop->u.named->prop_d;
1681 else
1682 deleg = addr_prop->u.indexed->object_d;
1683
1684 obj = deleg->obj;
1685 prop_sym = deleg->sym;
1686 prop = symbol_to_prop(prop_sym);
1687 assert(prop != NULL);
1688
[39e8406]1689 if (prop->setter == NULL) {
[d0febca]1690 printf("Error: Property is not writable.\n");
1691 exit(1);
1692 }
1693
1694 vitem = rdata_item_new(ic_value);
1695 vitem->u.value = value;
1696
1697 /* Create procedure activation record. */
[39e8406]1698 run_proc_ar_create(run, obj, prop->setter, &proc_ar);
[d0febca]1699
1700 /* Fill in arguments (indices). */
1701 if (addr_prop->apc == apc_indexed) {
1702 run_proc_ar_set_args(run, proc_ar,
1703 &addr_prop->u.indexed->args);
1704 }
1705
1706 /* Fill in value argument for setter. */
1707 run_proc_ar_set_setter_arg(run, proc_ar, vitem);
1708
1709 /* Run setter. */
1710 run_proc(run, proc_ar, &ritem);
1711
1712 /* Setter should not return a value. */
1713 assert(ritem == NULL);
1714
[051b3db8]1715 /* Destroy procedure activation record. */
1716 run_proc_ar_destroy(run, proc_ar);
1717
[d0febca]1718#ifdef DEBUG_RUN_TRACE
1719 printf("Done writing to property.\n");
1720#endif
1721}
1722
1723/** Return reference to a variable.
1724 *
1725 * Constructs a reference (value item) pointing to @a var.
[38aaacc2]1726 *
1727 * @param run Runner object
1728 * @param var Variable node that is being referenced
1729 * @param res Place to store pointer to new reference.
[d0febca]1730 */
1731void run_reference(run_t *run, rdata_var_t *var, rdata_item_t **res)
1732{
1733 rdata_ref_t *ref;
1734 rdata_var_t *ref_var;
1735 rdata_value_t *ref_value;
1736 rdata_item_t *ref_item;
1737
1738 (void) run;
1739
1740 /* Create reference to the variable. */
1741 ref = rdata_ref_new();
1742 ref_var = rdata_var_new(vc_ref);
1743 ref->vref = var;
1744 ref_var->u.ref_v = ref;
1745
1746 /* Construct value of the reference to return. */
1747 ref_item = rdata_item_new(ic_value);
1748 ref_value = rdata_value_new();
1749 ref_item->u.value = ref_value;
1750 ref_value->var = ref_var;
1751
1752 *res = ref_item;
1753}
1754
1755/** Return address of reference target.
1756 *
1757 * Takes a reference (address or value) and returns the address (item) of
1758 * the target of the reference.
[38aaacc2]1759 *
1760 * @param run Runner object
1761 * @param ref Reference
[051bc69a]1762 * @param cspan Cspan to put into exception if reference is nil
1763 * or @c NULL if no cspan is provided.
[38aaacc2]1764 * @param rtitem Place to store pointer to the resulting address.
[d0febca]1765 */
[051bc69a]1766void run_dereference(run_t *run, rdata_item_t *ref, cspan_t *cspan,
1767 rdata_item_t **ritem)
[d0febca]1768{
1769 rdata_item_t *ref_val;
1770 rdata_item_t *item;
1771 rdata_address_t *address;
1772 rdata_addr_var_t *addr_var;
1773
1774#ifdef DEBUG_RUN_TRACE
1775 printf("run_dereference()\n");
1776#endif
1777 run_cvt_value_item(run, ref, &ref_val);
[051b3db8]1778 if (run_is_bo(run)) {
1779 *ritem = run_recovery_item(run);
1780 return;
1781 }
1782
[d0febca]1783 assert(ref_val->u.value->var->vc == vc_ref);
1784
1785 item = rdata_item_new(ic_address);
1786 address = rdata_address_new(ac_var);
1787 addr_var = rdata_addr_var_new();
1788 item->u.address = address;
1789 address->u.var_a = addr_var;
1790 addr_var->vref = ref_val->u.value->var->u.ref_v->vref;
1791
[051b3db8]1792 rdata_item_destroy(ref_val);
1793
[d0febca]1794 if (addr_var->vref == NULL) {
[23de644]1795#ifdef DEBUG_RUN_TRACE
[d0febca]1796 printf("Error: Accessing null reference.\n");
[23de644]1797#endif
1798 /* Raise Error.NilReference */
[051bc69a]1799 run_raise_exc(run, run->program->builtin->error_nilreference,
1800 cspan);
[1ebc1a62]1801 *ritem = run_recovery_item(run);
1802 return;
[09ababb7]1803 }
[d0febca]1804
1805#ifdef DEBUG_RUN_TRACE
1806 printf("vref set to %p\n", addr_var->vref);
1807#endif
1808 *ritem = item;
[09ababb7]1809}
1810
[23de644]1811/** Raise an exception of the given class.
1812 *
1813 * Used when the interpreter generates an exception due to a run-time
1814 * error (not for the @c raise statement).
1815 *
[38aaacc2]1816 * @param run Runner object
1817 * @param csi Exception class
[051bc69a]1818 * @param cspan Cspan of code that caused exception (for debugging)
[23de644]1819 */
[051bc69a]1820void run_raise_exc(run_t *run, stree_csi_t *csi, cspan_t *cspan)
[23de644]1821{
1822 rdata_item_t *exc_vi;
1823
[051bc69a]1824 /* Store exception cspan in thread AR. */
1825 run->thread_ar->exc_cspan = cspan;
1826
[23de644]1827 /* Create exception object. */
[c5cb943d]1828 run_new_csi_inst_ref(run, csi, sn_nonstatic, &exc_vi);
[23de644]1829 assert(exc_vi->ic == ic_value);
1830
1831 /* Store exception object in thread AR. */
1832 run->thread_ar->exc_payload = exc_vi->u.value;
1833
1834 /* Start exception bailout. */
1835 run->thread_ar->bo_mode = bm_exc;
1836}
1837
[38aaacc2]1838/** Determine if we are bailing out.
1839 *
1840 * @param run Runner object
1841 * @return @c b_true if we are bailing out, @c b_false otherwise
1842 */
[23de644]1843bool_t run_is_bo(run_t *run)
1844{
1845 return run->thread_ar->bo_mode != bm_none;
1846}
1847
[38aaacc2]1848/** Construct a new variable of the given type.
1849 *
1850 * The variable is allocated and initialized with a default value
1851 * based on type item @a ti. For reference types the default value
1852 * is a null reference. At this point this does not work for generic
1853 * types (we need RTTI).
1854 *
1855 * @param run Runner object
1856 * @param ti Type of variable to create (type item)
1857 * @param rvar Place to store pointer to new variable
1858 */
1859void run_var_new(run_t *run, tdata_item_t *ti, rdata_var_t **rvar)
1860{
1861 rdata_var_t *var;
1862
1863 switch (ti->tic) {
1864 case tic_tprimitive:
1865 run_var_new_tprimitive(run, ti->u.tprimitive, rvar);
1866 break;
1867 case tic_tobject:
1868 case tic_tarray:
1869 run_var_new_null_ref(run, rvar);
1870 break;
1871 case tic_tdeleg:
[051bc69a]1872 run_var_new_deleg(run, rvar);
1873 break;
1874 case tic_tebase:
1875 /*
1876 * One cannot declare variable of ebase type. It is just
1877 * type of expressions referring to enum types.
1878 */
1879 assert(b_false);
[dc12262]1880 /* Fallthrough */
[051bc69a]1881 case tic_tenum:
1882 run_var_new_enum(run, ti->u.tenum, rvar);
1883 break;
[38aaacc2]1884 case tic_tfun:
1885 run_var_new_deleg(run, rvar);
1886 break;
1887 case tic_tvref:
[1b20da0]1888 /*
[38aaacc2]1889 * XXX Need to obtain run-time value of type argument to
1890 * initialize variable properly.
1891 */
1892 var = rdata_var_new(vc_int);
1893 var->u.int_v = rdata_int_new();
1894 bigint_init(&var->u.int_v->value, 0);
1895 *rvar = var;
1896 break;
1897 case tic_ignore:
1898 assert(b_false);
1899 }
1900}
1901
1902/** Construct a new variable of primitive type.
1903 *
1904 * The variable is allocated and initialized with a default value
1905 * based on primitive type item @a tprimitive.
1906 *
1907 * @param run Runner object
1908 * @param ti Primitive type of variable to create
1909 * @param rvar Place to store pointer to new variable
1910 */
1911static void run_var_new_tprimitive(run_t *run, tdata_primitive_t *tprimitive,
1912 rdata_var_t **rvar)
1913{
1914 rdata_var_t *var;
1915
1916 (void) run;
1917
[6c39a907]1918 /* Make compiler happy. */
1919 var = NULL;
1920
[38aaacc2]1921 switch (tprimitive->tpc) {
1922 case tpc_bool:
1923 var = rdata_var_new(vc_bool);
1924 var->u.bool_v = rdata_bool_new();
1925 var->u.bool_v->value = b_false;
1926 break;
1927 case tpc_char:
1928 var = rdata_var_new(vc_char);
1929 var->u.char_v = rdata_char_new();
1930 bigint_init(&var->u.char_v->value, 0);
1931 break;
1932 case tpc_int:
1933 var = rdata_var_new(vc_int);
1934 var->u.int_v = rdata_int_new();
1935 bigint_init(&var->u.int_v->value, 0);
1936 break;
1937 case tpc_nil:
1938 assert(b_false);
[dc12262]1939 /* Fallthrough */
[38aaacc2]1940 case tpc_string:
1941 var = rdata_var_new(vc_string);
1942 var->u.string_v = rdata_string_new();
1943 var->u.string_v->value = "";
1944 break;
1945 case tpc_resource:
1946 var = rdata_var_new(vc_resource);
1947 var->u.resource_v = rdata_resource_new();
1948 var->u.resource_v->data = NULL;
1949 break;
1950 }
1951
1952 *rvar = var;
1953}
1954
1955/** Construct a new variable containing null reference.
1956 *
1957 * @param run Runner object
1958 * @param rvar Place to store pointer to new variable
1959 */
1960static void run_var_new_null_ref(run_t *run, rdata_var_t **rvar)
1961{
1962 rdata_var_t *var;
1963
1964 (void) run;
1965
1966 /* Return null reference. */
1967 var = rdata_var_new(vc_ref);
1968 var->u.ref_v = rdata_ref_new();
1969
1970 *rvar = var;
1971}
1972
1973/** Construct a new variable containing invalid delegate.
1974 *
1975 * @param run Runner object
1976 * @param rvar Place to store pointer to new variable
1977 */
1978static void run_var_new_deleg(run_t *run, rdata_var_t **rvar)
1979{
1980 rdata_var_t *var;
1981
1982 (void) run;
1983
1984 /* Return null reference. */
1985 var = rdata_var_new(vc_deleg);
1986 var->u.deleg_v = rdata_deleg_new();
1987
1988 *rvar = var;
1989}
1990
[051bc69a]1991/** Construct a new variable containing default value of an enum type.
1992 *
1993 * @param run Runner object
1994 * @param rvar Place to store pointer to new variable
1995 */
1996static void run_var_new_enum(run_t *run, tdata_enum_t *tenum,
1997 rdata_var_t **rvar)
1998{
1999 rdata_var_t *var;
2000 list_node_t *embr_n;
2001 stree_embr_t *embr;
2002
2003 (void) run;
2004
2005 /* Get first member of enum which will serve as default value. */
2006 embr_n = list_first(&tenum->enum_d->members);
2007 assert(embr_n != NULL);
2008
2009 embr = list_node_data(embr_n, stree_embr_t *);
2010
2011 /* Return null reference. */
2012 var = rdata_var_new(vc_enum);
2013 var->u.enum_v = rdata_enum_new();
2014 var->u.enum_v->value = embr;
2015
2016 *rvar = var;
2017}
2018
[38aaacc2]2019/** Construct a new thread activation record.
2020 *
2021 * @param run Runner object
2022 * @return New thread AR.
2023 */
[09ababb7]2024run_thread_ar_t *run_thread_ar_new(void)
2025{
2026 run_thread_ar_t *thread_ar;
2027
2028 thread_ar = calloc(1, sizeof(run_thread_ar_t));
2029 if (thread_ar == NULL) {
2030 printf("Memory allocation failed.\n");
2031 exit(1);
2032 }
2033
2034 return thread_ar;
2035}
2036
[051b3db8]2037/** Allocate a new procedure activation record.
[38aaacc2]2038 *
2039 * @return New procedure AR.
2040 */
[d0febca]2041run_proc_ar_t *run_proc_ar_new(void)
[09ababb7]2042{
[d0febca]2043 run_proc_ar_t *proc_ar;
[09ababb7]2044
[d0febca]2045 proc_ar = calloc(1, sizeof(run_proc_ar_t));
2046 if (proc_ar == NULL) {
[09ababb7]2047 printf("Memory allocation failed.\n");
2048 exit(1);
2049 }
2050
[d0febca]2051 return proc_ar;
[09ababb7]2052}
2053
[051b3db8]2054/** Deallocate a procedure activation record.
2055 *
2056 * @return New procedure AR.
2057 */
2058void run_proc_ar_delete(run_proc_ar_t *proc_ar)
2059{
2060 assert(proc_ar != NULL);
2061 free(proc_ar);
2062}
2063
2064/** Allocate a new block activation record.
[38aaacc2]2065 *
2066 * @param run Runner object
2067 * @return New block AR.
2068 */
[09ababb7]2069run_block_ar_t *run_block_ar_new(void)
2070{
2071 run_block_ar_t *block_ar;
2072
2073 block_ar = calloc(1, sizeof(run_block_ar_t));
2074 if (block_ar == NULL) {
2075 printf("Memory allocation failed.\n");
2076 exit(1);
2077 }
2078
2079 return block_ar;
2080}
[051b3db8]2081
2082/** Deallocate a new block activation record.
2083 *
2084 * @param run Runner object
2085 * @return New block AR.
2086 */
2087void run_block_ar_delete(run_block_ar_t *block_ar)
2088{
2089 assert(block_ar != NULL);
2090 free(block_ar);
2091}
Note: See TracBrowser for help on using the repository browser.