source: mainline/uspace/app/sbi/src/run.c@ 883fedc

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

Update for mainline changes.

  • Property mode set to 100644
File size: 39.2 KB
Line 
1/*
2 * Copyright (c) 2010 Jiri Svoboda
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * - Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * - Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * - The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29/** @file Runner (executes the code). */
30
31#include <stdio.h>
32#include <stdlib.h>
33#include <assert.h>
34#include "bigint.h"
35#include "builtin.h"
36#include "debug.h"
37#include "intmap.h"
38#include "list.h"
39#include "mytypes.h"
40#include "rdata.h"
41#include "run_expr.h"
42#include "run_texpr.h"
43#include "stree.h"
44#include "strtab.h"
45#include "symbol.h"
46#include "tdata.h"
47
48#include "run.h"
49
50static void run_block(run_t *run, stree_block_t *block);
51static void run_exps(run_t *run, stree_exps_t *exps, rdata_item_t **res);
52static void run_vdecl(run_t *run, stree_vdecl_t *vdecl);
53static void run_if(run_t *run, stree_if_t *if_s);
54static void run_while(run_t *run, stree_while_t *while_s);
55static void run_raise(run_t *run, stree_raise_t *raise_s);
56static void run_return(run_t *run, stree_return_t *return_s);
57static void run_wef(run_t *run, stree_wef_t *wef_s);
58
59static bool_t run_exc_match(run_t *run, stree_except_t *except_c);
60static stree_csi_t *run_exc_payload_get_csi(run_t *run);
61
62static rdata_var_t *run_aprop_get_tpos(run_t *run, rdata_address_t *aprop);
63
64static void run_aprop_read(run_t *run, rdata_addr_prop_t *addr_prop,
65 rdata_item_t **ritem);
66static void run_aprop_write(run_t *run, rdata_addr_prop_t *addr_prop,
67 rdata_value_t *value);
68
69static void run_var_new_tprimitive(run_t *run, tdata_primitive_t *tprimitive,
70 rdata_var_t **rvar);
71static void run_var_new_null_ref(run_t *run, rdata_var_t **rvar);
72static void run_var_new_deleg(run_t *run, rdata_var_t **rvar);
73
74
75/** Initialize runner instance.
76 *
77 * @param run Runner object
78 */
79void run_init(run_t *run)
80{
81 (void) run;
82}
83
84/** Run program.
85 *
86 * Associates the program @a prog with the runner object and executes
87 * it. If a run-time error occurs during the execution (e.g. an unhandled
88 * exception), @a run->error will be set to @c b_true when this function
89 * returns.
90 *
91 * @param run Runner object
92 * @param prog Program to run
93 */
94void run_program(run_t *run, stree_program_t *prog)
95{
96 stree_symbol_t *main_fun_sym;
97 stree_fun_t *main_fun;
98 stree_ident_t *fake_ident;
99 list_t main_args;
100 run_proc_ar_t *proc_ar;
101 rdata_item_t *res;
102
103 /* Note down link to program code. */
104 run->program = prog;
105
106 /* Initialize thread activation record. */
107 run->thread_ar = run_thread_ar_new();
108 list_init(&run->thread_ar->proc_ar);
109 run->thread_ar->bo_mode = bm_none;
110
111 /*
112 * Find entry point @c Main().
113 */
114 fake_ident = stree_ident_new();
115 fake_ident->sid = strtab_get_sid("Main");
116 main_fun_sym = symbol_find_epoint(prog, fake_ident);
117 if (main_fun_sym == NULL) {
118 printf("Error: Entry point 'Main' not found.\n");
119 exit(1);
120 }
121
122 main_fun = symbol_to_fun(main_fun_sym);
123 assert(main_fun != NULL);
124
125#ifdef DEBUG_RUN_TRACE
126 printf("Found function '"); symbol_print_fqn(main_fun_sym);
127 printf("'.\n");
128#endif
129
130 /* Run function @c main. */
131 list_init(&main_args);
132 run_proc_ar_create(run, NULL, main_fun->proc, &proc_ar);
133 run_proc_ar_set_args(run, proc_ar, &main_args);
134 run_proc(run, proc_ar, &res);
135
136 run_exc_check_unhandled(run);
137}
138
139/** Run procedure.
140 *
141 * Inserts the provided procedure AR @a proc_ar on the execution stack
142 * (in the thread AR) and executes the procedure. The return value
143 * of the procedure is stored to *(@a res). @c NULL is stored if the
144 * procedure returns no value.
145 *
146 * If the procedure execution bails out due to an exception, this
147 * can be determined by looking at @c bo_mode in thread AR. Also,
148 * in this case @c NULL is stored into *(@a res).
149 *
150 * @param run Runner object
151 * @param proc_ar Procedure activation record
152 * @param res Place to store procedure return value
153 */
154void run_proc(run_t *run, run_proc_ar_t *proc_ar, rdata_item_t **res)
155{
156 stree_proc_t *proc;
157 list_node_t *node;
158
159 proc = proc_ar->proc;
160
161#ifdef DEBUG_RUN_TRACE
162 printf("Start executing function '");
163 symbol_print_fqn(proc->outer_symbol);
164 printf("'.\n");
165#endif
166 /* Add procedure AR to the stack. */
167 list_append(&run->thread_ar->proc_ar, proc_ar);
168
169 /* Run main procedure block. */
170 if (proc->body != NULL) {
171 run_block(run, proc->body);
172 } else {
173 builtin_run_proc(run, proc);
174 }
175
176 /* Handle bailout. */
177 switch (run->thread_ar->bo_mode) {
178 case bm_stat:
179 printf("Error: Misplaced 'break' statement.\n");
180 exit(1);
181 case bm_proc:
182 run->thread_ar->bo_mode = bm_none;
183 break;
184 default:
185 break;
186 }
187
188#ifdef DEBUG_RUN_TRACE
189 printf("Done executing procedure '");
190 symbol_print_fqn(proc->outer_symbol);
191 printf("'.\n");
192
193 run_print_fun_bt(run);
194#endif
195 /* Remove procedure activation record from the stack. */
196 node = list_last(&run->thread_ar->proc_ar);
197 assert(list_node_data(node, run_proc_ar_t *) == proc_ar);
198 list_remove(&run->thread_ar->proc_ar, node);
199
200 /* Procedure should not return an address. */
201 assert(proc_ar->retval == NULL || proc_ar->retval->ic == ic_value);
202 *res = proc_ar->retval;
203}
204
205/** Run code block.
206 *
207 * @param run Runner object
208 * @param block Block to run
209 */
210static void run_block(run_t *run, stree_block_t *block)
211{
212 run_proc_ar_t *proc_ar;
213 run_block_ar_t *block_ar;
214 list_node_t *node;
215 stree_stat_t *stat;
216
217#ifdef DEBUG_RUN_TRACE
218 printf("Executing one code block.\n");
219#endif
220
221 /* Create block activation record. */
222 block_ar = run_block_ar_new();
223 intmap_init(&block_ar->vars);
224
225 /* Add block activation record to the stack. */
226 proc_ar = run_get_current_proc_ar(run);
227 list_append(&proc_ar->block_ar, block_ar);
228
229 node = list_first(&block->stats);
230 while (node != NULL) {
231 stat = list_node_data(node, stree_stat_t *);
232 run_stat(run, stat, NULL);
233
234 if (run->thread_ar->bo_mode != bm_none)
235 break;
236
237 node = list_next(&block->stats, node);
238 }
239
240#ifdef DEBUG_RUN_TRACE
241 printf("Done executing code block.\n");
242#endif
243
244 /* Remove block activation record from the stack. */
245 node = list_last(&proc_ar->block_ar);
246 assert(list_node_data(node, run_block_ar_t *) == block_ar);
247 list_remove(&proc_ar->block_ar, node);
248}
249
250/** Run statement.
251 *
252 * Executes a statement. If @a res is not NULL and the statement is an
253 * expression statement with a value, the value item will be stored to
254 * @a res.
255 *
256 * @param run Runner object
257 * @param stat Statement to run
258 * @param res Place to store exps result or NULL if not interested
259 */
260void run_stat(run_t *run, stree_stat_t *stat, rdata_item_t **res)
261{
262#ifdef DEBUG_RUN_TRACE
263 printf("Executing one statement %p.\n", stat);
264#endif
265
266 if (res != NULL)
267 *res = NULL;
268
269 switch (stat->sc) {
270 case st_exps:
271 run_exps(run, stat->u.exp_s, res);
272 break;
273 case st_vdecl:
274 run_vdecl(run, stat->u.vdecl_s);
275 break;
276 case st_if:
277 run_if(run, stat->u.if_s);
278 break;
279 case st_while:
280 run_while(run, stat->u.while_s);
281 break;
282 case st_raise:
283 run_raise(run, stat->u.raise_s);
284 break;
285 case st_return:
286 run_return(run, stat->u.return_s);
287 break;
288 case st_wef:
289 run_wef(run, stat->u.wef_s);
290 break;
291 case st_for:
292 printf("Ignoring unimplemented statement type %d.\n", stat->sc);
293 break;
294 default:
295 assert(b_false);
296 }
297}
298
299/** Run expression statement.
300 *
301 * Executes an expression statement. If @a res is not NULL then the value
302 * of the expression (or NULL if it has no value) will be stored to @a res.
303 *
304 * @param run Runner object
305 * @param exps Expression statement to run
306 * @param res Place to store exps result or NULL if not interested
307 */
308static void run_exps(run_t *run, stree_exps_t *exps, rdata_item_t **res)
309{
310 rdata_item_t *rexpr;
311
312#ifdef DEBUG_RUN_TRACE
313 printf("Executing expression statement.\n");
314#endif
315 run_expr(run, exps->expr, &rexpr);
316
317 if (res != NULL)
318 *res = rexpr;
319}
320
321/** Run variable declaration statement.
322 *
323 * @param run Runner object
324 * @param vdecl Variable declaration statement to run
325 */
326static void run_vdecl(run_t *run, stree_vdecl_t *vdecl)
327{
328 run_block_ar_t *block_ar;
329 rdata_var_t *var, *old_var;
330 tdata_item_t *var_ti;
331
332#ifdef DEBUG_RUN_TRACE
333 printf("Executing variable declaration statement.\n");
334#endif
335 /* Compute variable type. XXX Memoize. */
336 run_texpr(run->program, run_get_current_csi(run), vdecl->type,
337 &var_ti);
338
339 /* Create variable and initialize with default value. */
340 run_var_new(run, var_ti, &var);
341
342 block_ar = run_get_current_block_ar(run);
343 old_var = (rdata_var_t *) intmap_get(&block_ar->vars, vdecl->name->sid);
344
345 if (old_var != NULL) {
346 printf("Error: Duplicate variable '%s'\n",
347 strtab_get_str(vdecl->name->sid));
348 exit(1);
349 }
350
351 intmap_set(&block_ar->vars, vdecl->name->sid, var);
352
353#ifdef DEBUG_RUN_TRACE
354 printf("Declared variable '%s'\n", strtab_get_str(vdecl->name->sid));
355#endif
356}
357
358/** Run @c if statement.
359 *
360 * @param run Runner object
361 * @param if_s If statement to run
362 */
363static void run_if(run_t *run, stree_if_t *if_s)
364{
365 rdata_item_t *rcond;
366
367#ifdef DEBUG_RUN_TRACE
368 printf("Executing if statement.\n");
369#endif
370 run_expr(run, if_s->cond, &rcond);
371 if (run_is_bo(run))
372 return;
373
374 if (run_item_boolean_value(run, rcond) == b_true) {
375#ifdef DEBUG_RUN_TRACE
376 printf("Taking true path.\n");
377#endif
378 run_block(run, if_s->if_block);
379 } else {
380#ifdef DEBUG_RUN_TRACE
381 printf("Taking false path.\n");
382#endif
383 if (if_s->else_block != NULL)
384 run_block(run, if_s->else_block);
385 }
386
387#ifdef DEBUG_RUN_TRACE
388 printf("If statement terminated.\n");
389#endif
390}
391
392/** Run @c while statement.
393 *
394 * @param run Runner object
395 * @param while_s While statement to run
396 */
397static void run_while(run_t *run, stree_while_t *while_s)
398{
399 rdata_item_t *rcond;
400
401#ifdef DEBUG_RUN_TRACE
402 printf("Executing while statement.\n");
403#endif
404 run_expr(run, while_s->cond, &rcond);
405 if (run_is_bo(run))
406 return;
407
408 while (run_item_boolean_value(run, rcond) == b_true) {
409 run_block(run, while_s->body);
410 run_expr(run, while_s->cond, &rcond);
411 if (run_is_bo(run))
412 return;
413
414 if (run->thread_ar->bo_mode != bm_none)
415 break;
416 }
417
418#ifdef DEBUG_RUN_TRACE
419 printf("While statement terminated.\n");
420#endif
421}
422
423/** Run @c raise statement.
424 *
425 * @param run Runner object
426 * @param raise_s Raise statement to run
427 */
428static void run_raise(run_t *run, stree_raise_t *raise_s)
429{
430 rdata_item_t *rexpr;
431 rdata_item_t *rexpr_vi;
432
433#ifdef DEBUG_RUN_TRACE
434 printf("Executing raise statement.\n");
435#endif
436 run_expr(run, raise_s->expr, &rexpr);
437 if (run_is_bo(run))
438 return;
439
440 run_cvt_value_item(run, rexpr, &rexpr_vi);
441
442 /* Store expression result in thread AR. */
443 run->thread_ar->exc_payload = rexpr_vi->u.value;
444
445 /* Start exception bailout. */
446 run->thread_ar->bo_mode = bm_exc;
447}
448
449/** Run @c return statement.
450 *
451 * Sets the return value in procedure AR and forces control to return
452 * from the function by setting bailout mode to @c bm_proc.
453 *
454 * @param run Runner object
455 * @param raise_s Return statement to run
456 */
457static void run_return(run_t *run, stree_return_t *return_s)
458{
459 rdata_item_t *rexpr;
460 rdata_item_t *rexpr_vi;
461 run_proc_ar_t *proc_ar;
462
463#ifdef DEBUG_RUN_TRACE
464 printf("Executing return statement.\n");
465#endif
466 run_expr(run, return_s->expr, &rexpr);
467 if (run_is_bo(run))
468 return;
469
470 run_cvt_value_item(run, rexpr, &rexpr_vi);
471
472 /* Store expression result in procedure AR. */
473 proc_ar = run_get_current_proc_ar(run);
474 proc_ar->retval = rexpr_vi;
475
476 /* Force control to ascend and leave the procedure. */
477 if (run->thread_ar->bo_mode == bm_none)
478 run->thread_ar->bo_mode = bm_proc;
479}
480
481/** Run @c with-except-finally statement.
482 *
483 * Note: 'With' clause is not implemented.
484 *
485 * @param run Runner object
486 * @param wef_s With-except-finally statement to run
487 */
488static void run_wef(run_t *run, stree_wef_t *wef_s)
489{
490 list_node_t *except_n;
491 stree_except_t *except_c;
492 rdata_value_t *exc_payload;
493 run_bailout_mode_t bo_mode;
494
495#ifdef DEBUG_RUN_TRACE
496 printf("Executing with-except-finally statement.\n");
497#endif
498 run_block(run, wef_s->with_block);
499
500 if (run->thread_ar->bo_mode == bm_exc) {
501#ifdef DEBUG_RUN_TRACE
502 printf("With statement detected exception.\n");
503#endif
504 /* Reset to normal execution. */
505 run->thread_ar->bo_mode = bm_none;
506
507 /* Look for an except block. */
508 except_n = list_first(&wef_s->except_clauses);
509 while (except_n != NULL) {
510 except_c = list_node_data(except_n, stree_except_t *);
511 if (run_exc_match(run, except_c))
512 break;
513
514 except_n = list_next(&wef_s->except_clauses, except_n);
515 }
516
517 /* If one was found, execute it. */
518 if (except_n != NULL)
519 run_block(run, except_c->block);
520
521 /* Execute finally block */
522 if (wef_s->finally_block != NULL) {
523 /* Put exception on the side temporarily. */
524 bo_mode = run->thread_ar->bo_mode;
525 exc_payload = run->thread_ar->exc_payload;
526
527 run->thread_ar->bo_mode = bm_none;
528 run->thread_ar->exc_payload = NULL;
529
530 run_block(run, wef_s->finally_block);
531
532 if (bo_mode == bm_exc) {
533 /*
534 * Restore the original exception. If another
535 * exception occured in the finally block (i.e.
536 * double fault), it is forgotten.
537 */
538 run->thread_ar->bo_mode = bm_exc;
539 run->thread_ar->exc_payload = exc_payload;
540 }
541 }
542 }
543
544#ifdef DEBUG_RUN_TRACE
545 printf("With-except-finally statement terminated.\n");
546#endif
547}
548
549/** Determine whether currently active exception matches @c except clause.
550 *
551 * Checks if the currently active exception in the runner object @c run
552 * matches except clause @c except_c.
553 *
554 * @param run Runner object
555 * @param except_c @c except clause
556 * @return @c b_true if there is a match, @c b_false otherwise
557 */
558static bool_t run_exc_match(run_t *run, stree_except_t *except_c)
559{
560 stree_csi_t *exc_csi;
561 tdata_item_t *etype;
562
563 /* Get CSI of active exception. */
564 exc_csi = run_exc_payload_get_csi(run);
565
566 /* Evaluate type expression in except clause. */
567 run_texpr(run->program, run_get_current_csi(run), except_c->etype,
568 &etype);
569
570 /* Determine if active exc. is derived from type in exc. clause. */
571 /* XXX This is wrong, it does not work with generics. */
572 return tdata_is_csi_derived_from_ti(exc_csi, etype);
573}
574
575/** Return CSI of the active exception.
576 *
577 * @param run Runner object
578 * @return CSI of the active exception
579 */
580static stree_csi_t *run_exc_payload_get_csi(run_t *run)
581{
582 rdata_value_t *payload;
583 rdata_var_t *payload_v;
584 rdata_object_t *payload_o;
585
586 payload = run->thread_ar->exc_payload;
587 assert(payload != NULL);
588
589 if (payload->var->vc != vc_ref) {
590 /* XXX Prevent this via static type checking. */
591 printf("Error: Exception payload must be an object "
592 "(found type %d).\n", payload->var->vc);
593 exit(1);
594 }
595
596 payload_v = payload->var->u.ref_v->vref;
597 if (payload_v->vc != vc_object) {
598 /* XXX Prevent this via static type checking. */
599 printf("Error: Exception payload must be an object "
600 "(found type %d).\n", payload_v->vc);
601 exit(1);
602 }
603
604 payload_o = payload_v->u.object_v;
605
606#ifdef DEBUG_RUN_TRACE
607 printf("Active exception: '");
608 symbol_print_fqn(payload_o->class_sym);
609 printf("'.\n");
610#endif
611 assert(payload_o->class_sym != NULL);
612 assert(payload_o->class_sym->sc == sc_csi);
613
614 return payload_o->class_sym->u.csi;
615}
616
617
618/** Check for unhandled exception.
619 *
620 * Checks whether there is an active exception. If so, it prints an
621 * error message and raises a run-time error.
622 *
623 * @param run Runner object
624 */
625void run_exc_check_unhandled(run_t *run)
626{
627 stree_csi_t *exc_csi;
628
629 if (run->thread_ar->bo_mode != bm_none) {
630 assert(run->thread_ar->bo_mode == bm_exc);
631
632 exc_csi = run_exc_payload_get_csi(run);
633
634 printf("Error: Unhandled exception '");
635 symbol_print_fqn(csi_to_symbol(exc_csi));
636 printf("'.\n");
637
638 run_raise_error(run);
639 }
640}
641
642/** Raise an irrecoverable run-time error, start bailing out.
643 *
644 * Raises an error that cannot be handled by the user program.
645 *
646 * @param run Runner object
647 */
648void run_raise_error(run_t *run)
649{
650 run->thread_ar->bo_mode = bm_error;
651 run->thread_ar->error = b_true;
652}
653
654/** Construct a special recovery item.
655 *
656 * @param run Runner object
657 */
658rdata_item_t *run_recovery_item(run_t *run)
659{
660 (void) run;
661 return NULL;
662}
663
664/** Find a local variable in the currently active function.
665 *
666 * @param run Runner object
667 * @param name Name SID of the local variable
668 * @return Pointer to var node or @c NULL if not found
669 */
670rdata_var_t *run_local_vars_lookup(run_t *run, sid_t name)
671{
672 run_proc_ar_t *proc_ar;
673 run_block_ar_t *block_ar;
674 rdata_var_t *var;
675 list_node_t *node;
676
677 proc_ar = run_get_current_proc_ar(run);
678 node = list_last(&proc_ar->block_ar);
679
680 /* Walk through all block activation records. */
681 while (node != NULL) {
682 block_ar = list_node_data(node, run_block_ar_t *);
683 var = intmap_get(&block_ar->vars, name);
684 if (var != NULL)
685 return var;
686
687 node = list_prev(&proc_ar->block_ar, node);
688 }
689
690 /* No match */
691 return NULL;
692}
693
694/** Get current procedure activation record.
695 *
696 * @param run Runner object
697 * @return Active procedure AR
698 */
699run_proc_ar_t *run_get_current_proc_ar(run_t *run)
700{
701 list_node_t *node;
702
703 node = list_last(&run->thread_ar->proc_ar);
704 return list_node_data(node, run_proc_ar_t *);
705}
706
707/** Get current block activation record.
708 *
709 * @param run Runner object
710 * @return Active block AR
711 */
712run_block_ar_t *run_get_current_block_ar(run_t *run)
713{
714 run_proc_ar_t *proc_ar;
715 list_node_t *node;
716
717 proc_ar = run_get_current_proc_ar(run);
718
719 node = list_last(&proc_ar->block_ar);
720 return list_node_data(node, run_block_ar_t *);
721}
722
723/** Get current CSI.
724 *
725 * @param run Runner object
726 * @return Active CSI
727 */
728stree_csi_t *run_get_current_csi(run_t *run)
729{
730 run_proc_ar_t *proc_ar;
731
732 proc_ar = run_get_current_proc_ar(run);
733 return proc_ar->proc->outer_symbol->outer_csi;
734}
735
736/** Construct variable from a value item.
737 *
738 * XXX This should be in fact implemented using existing code as:
739 *
740 * (1) Create a variable of the desired type.
741 * (2) Initialize the variable with the provided value.
742 *
743 * @param item Value item (initial value for variable).
744 * @param var Place to store new var node.
745 */
746void run_value_item_to_var(rdata_item_t *item, rdata_var_t **var)
747{
748 rdata_bool_t *bool_v;
749 rdata_char_t *char_v;
750 rdata_deleg_t *deleg_v;
751 rdata_int_t *int_v;
752 rdata_string_t *string_v;
753 rdata_ref_t *ref_v;
754 rdata_var_t *in_var;
755
756 assert(item->ic == ic_value);
757 in_var = item->u.value->var;
758
759 switch (in_var->vc) {
760 case vc_bool:
761 *var = rdata_var_new(vc_bool);
762 bool_v = rdata_bool_new();
763
764 (*var)->u.bool_v = bool_v;
765 bool_v->value = item->u.value->var->u.bool_v->value;
766 break;
767 case vc_char:
768 *var = rdata_var_new(vc_char);
769 char_v = rdata_char_new();
770
771 (*var)->u.char_v = char_v;
772 bigint_clone(&item->u.value->var->u.char_v->value,
773 &char_v->value);
774 break;
775 case vc_deleg:
776 *var = rdata_var_new(vc_deleg);
777 deleg_v = rdata_deleg_new();
778
779 (*var)->u.deleg_v = deleg_v;
780 deleg_v->obj = item->u.value->var->u.deleg_v->obj;
781 deleg_v->sym = item->u.value->var->u.deleg_v->sym;
782 break;
783 case vc_int:
784 *var = rdata_var_new(vc_int);
785 int_v = rdata_int_new();
786
787 (*var)->u.int_v = int_v;
788 bigint_clone(&item->u.value->var->u.int_v->value,
789 &int_v->value);
790 break;
791 case vc_string:
792 *var = rdata_var_new(vc_string);
793 string_v = rdata_string_new();
794
795 (*var)->u.string_v = string_v;
796 string_v->value = item->u.value->var->u.string_v->value;
797 break;
798 case vc_ref:
799 *var = rdata_var_new(vc_ref);
800 ref_v = rdata_ref_new();
801
802 (*var)->u.ref_v = ref_v;
803 ref_v->vref = item->u.value->var->u.ref_v->vref;
804 break;
805 default:
806 printf("Error: Unimplemented argument type.\n");
807 exit(1);
808
809 }
810}
811
812/** Construct a procedure AR.
813 *
814 * @param run Runner object
815 * @param obj Object whose procedure is being activated
816 * @param proc Procedure that is being activated
817 * @param rproc_ar Place to store pointer to new activation record
818 */
819void run_proc_ar_create(run_t *run, rdata_var_t *obj, stree_proc_t *proc,
820 run_proc_ar_t **rproc_ar)
821{
822 run_proc_ar_t *proc_ar;
823 run_block_ar_t *block_ar;
824
825 (void) run;
826
827 /* Create function activation record. */
828 proc_ar = run_proc_ar_new();
829 proc_ar->obj = obj;
830 proc_ar->proc = proc;
831 list_init(&proc_ar->block_ar);
832
833 proc_ar->retval = NULL;
834
835 /* Create special block activation record to hold function arguments. */
836 block_ar = run_block_ar_new();
837 intmap_init(&block_ar->vars);
838 list_append(&proc_ar->block_ar, block_ar);
839
840 *rproc_ar = proc_ar;
841}
842
843/** Fill arguments in a procedure AR.
844 *
845 * When invoking a procedure this is used to store the argument values
846 * in the activation record.
847 *
848 * @param run Runner object
849 * @param proc_ar Existing procedure activation record where to store
850 * the values
851 * @param arg_vals List of value items (rdata_item_t *) -- real
852 * argument values
853 */
854void run_proc_ar_set_args(run_t *run, run_proc_ar_t *proc_ar, list_t *arg_vals)
855{
856 stree_fun_t *fun;
857 stree_prop_t *prop;
858 list_t *args;
859 stree_proc_arg_t *varg;
860 stree_symbol_t *outer_symbol;
861
862 run_block_ar_t *block_ar;
863 list_node_t *block_ar_n;
864 list_node_t *rarg_n, *parg_n;
865 list_node_t *cn;
866 rdata_item_t *rarg;
867 stree_proc_arg_t *parg;
868 rdata_var_t *var;
869 rdata_var_t *ref_var;
870 rdata_ref_t *ref;
871 rdata_array_t *array;
872 int n_vargs, idx;
873
874 (void) run;
875
876 /* AR should have been created with run_proc_ar_create(). */
877 assert(proc_ar->proc != NULL);
878 outer_symbol = proc_ar->proc->outer_symbol;
879
880 /*
881 * The procedure being activated should belong to a member function or
882 * property getter/setter.
883 */
884 switch (outer_symbol->sc) {
885 case sc_fun:
886 fun = symbol_to_fun(outer_symbol);
887 args = &fun->sig->args;
888 varg = fun->sig->varg;
889 break;
890 case sc_prop:
891 prop = symbol_to_prop(outer_symbol);
892 args = &prop->args;
893 varg = prop->varg;
894 break;
895 default:
896 assert(b_false);
897 }
898
899 /* Fetch first block activation record. */
900 block_ar_n = list_first(&proc_ar->block_ar);
901 assert(block_ar_n != NULL);
902 block_ar = list_node_data(block_ar_n, run_block_ar_t *);
903
904 /* Declare local variables to hold argument values. */
905 rarg_n = list_first(arg_vals);
906 parg_n = list_first(args);
907
908 while (parg_n != NULL) {
909 if (rarg_n == NULL) {
910 printf("Error: Too few arguments to '");
911 symbol_print_fqn(outer_symbol);
912 printf("'.\n");
913 exit(1);
914 }
915
916 rarg = list_node_data(rarg_n, rdata_item_t *);
917 parg = list_node_data(parg_n, stree_proc_arg_t *);
918
919 assert(rarg->ic == ic_value);
920
921 /* Construct a variable from the argument value. */
922 run_value_item_to_var(rarg, &var);
923
924 /* Declare variable using name of formal argument. */
925 intmap_set(&block_ar->vars, parg->name->sid, var);
926
927 rarg_n = list_next(arg_vals, rarg_n);
928 parg_n = list_next(args, parg_n);
929 }
930
931 if (varg != NULL) {
932 /* Function is variadic. Count number of variadic arguments. */
933 cn = rarg_n;
934 n_vargs = 0;
935 while (cn != NULL) {
936 n_vargs += 1;
937 cn = list_next(arg_vals, cn);
938 }
939
940 /* Prepare array to store variadic arguments. */
941 array = rdata_array_new(1);
942 array->extent[0] = n_vargs;
943 rdata_array_alloc_element(array);
944
945 /* Read variadic arguments. */
946
947 idx = 0;
948 while (rarg_n != NULL) {
949 rarg = list_node_data(rarg_n, rdata_item_t *);
950 assert(rarg->ic == ic_value);
951
952 rdata_var_write(array->element[idx], rarg->u.value);
953
954 rarg_n = list_next(arg_vals, rarg_n);
955 idx += 1;
956 }
957
958 var = rdata_var_new(vc_array);
959 var->u.array_v = array;
960
961 /* Create reference to the new array. */
962 ref_var = rdata_var_new(vc_ref);
963 ref = rdata_ref_new();
964 ref_var->u.ref_v = ref;
965 ref->vref = var;
966
967 /* Declare variable using name of formal argument. */
968 intmap_set(&block_ar->vars, varg->name->sid,
969 ref_var);
970 }
971
972 /* Check for excess real parameters. */
973 if (rarg_n != NULL) {
974 printf("Error: Too many arguments to '");
975 symbol_print_fqn(outer_symbol);
976 printf("'.\n");
977 exit(1);
978 }
979}
980
981/** Fill setter argument in a procedure AR.
982 *
983 * When invoking a setter this is used to store its argument value in its
984 * procedure activation record.
985 *
986 * @param run Runner object
987 * @param proc_ar Existing procedure activation record where to store
988 * the setter argument
989 * @param arg_val Value items (rdata_item_t *) -- real argument value
990 */
991void run_proc_ar_set_setter_arg(run_t *run, run_proc_ar_t *proc_ar,
992 rdata_item_t *arg_val)
993{
994 stree_prop_t *prop;
995 run_block_ar_t *block_ar;
996 list_node_t *block_ar_n;
997 rdata_var_t *var;
998
999 (void) run;
1000
1001 /* AR should have been created with run_proc_ar_create(). */
1002 assert(proc_ar->proc != NULL);
1003
1004 /* The procedure being activated should belong to a property setter. */
1005 prop = symbol_to_prop(proc_ar->proc->outer_symbol);
1006 assert(prop != NULL);
1007 assert(proc_ar->proc == prop->setter);
1008
1009 /* Fetch first block activation record. */
1010 block_ar_n = list_first(&proc_ar->block_ar);
1011 assert(block_ar_n != NULL);
1012 block_ar = list_node_data(block_ar_n, run_block_ar_t *);
1013
1014 assert(arg_val->ic == ic_value);
1015
1016 /* Construct a variable from the argument value. */
1017 run_value_item_to_var(arg_val, &var);
1018
1019 /* Declare variable using name of formal argument. */
1020 intmap_set(&block_ar->vars, prop->setter_arg->name->sid, var);
1021}
1022
1023/** Print function activation backtrace.
1024 *
1025 * Prints a backtrace of activated functions for debugging purposes.
1026 *
1027 * @param run Runner object
1028 */
1029void run_print_fun_bt(run_t *run)
1030{
1031 list_node_t *node;
1032 run_proc_ar_t *proc_ar;
1033
1034 printf("Backtrace:\n");
1035 node = list_last(&run->thread_ar->proc_ar);
1036 while (node != NULL) {
1037 printf(" * ");
1038 proc_ar = list_node_data(node, run_proc_ar_t *);
1039 symbol_print_fqn(proc_ar->proc->outer_symbol);
1040 printf("\n");
1041
1042 node = list_prev(&run->thread_ar->proc_ar, node);
1043 }
1044}
1045
1046/** Convert item to value item.
1047 *
1048 * If @a item is a value, we just return a copy. If @a item is an address,
1049 * we read from the address.
1050 *
1051 * @param run Runner object
1052 * @param item Input item (value or address)
1053 * @param ritem Place to store pointer to new value item
1054 */
1055void run_cvt_value_item(run_t *run, rdata_item_t *item, rdata_item_t **ritem)
1056{
1057 rdata_value_t *value;
1058
1059 /*
1060 * This can happen when trying to use output of a function which
1061 * does not return a value.
1062 */
1063 if (item == NULL) {
1064 printf("Error: Sub-expression has no value.\n");
1065 exit(1);
1066 }
1067
1068 /* Address item. Perform read operation. */
1069 if (item->ic == ic_address) {
1070 run_address_read(run, item->u.address, ritem);
1071 return;
1072 }
1073
1074 /* It already is a value, we can share the @c var. */
1075 value = rdata_value_new();
1076 value->var = item->u.value->var;
1077 *ritem = rdata_item_new(ic_value);
1078 (*ritem)->u.value = value;
1079}
1080
1081/** Get item var-class.
1082 *
1083 * Get var-class of @a item, regardless whether it is a value or address.
1084 * (I.e. the var class of the value or variable at the given address).
1085 *
1086 * @param run Runner object
1087 * @param item Value or address item
1088 * @return Varclass of @a item
1089 */
1090var_class_t run_item_get_vc(run_t *run, rdata_item_t *item)
1091{
1092 var_class_t vc;
1093 rdata_var_t *tpos;
1094
1095 (void) run;
1096
1097 switch (item->ic) {
1098 case ic_value:
1099 vc = item->u.value->var->vc;
1100 break;
1101 case ic_address:
1102 switch (item->u.address->ac) {
1103 case ac_var:
1104 vc = item->u.address->u.var_a->vref->vc;
1105 break;
1106 case ac_prop:
1107 /* Prefetch the value of the property. */
1108 tpos = run_aprop_get_tpos(run, item->u.address);
1109 vc = tpos->vc;
1110 break;
1111 default:
1112 assert(b_false);
1113 }
1114 break;
1115 default:
1116 assert(b_false);
1117 }
1118
1119 return vc;
1120}
1121
1122/** Get pointer to current var node in temporary copy in property address.
1123 *
1124 * A property address refers to a specific @c var node in a property.
1125 * This function will fetch a copy of the property value (by running
1126 * its getter) if there is not a temporary copy in the address yet.
1127 * It returns a pointer to the relevant @c var node in the temporary
1128 * copy.
1129 *
1130 * @param run Runner object
1131 * @param addr Address of class @c ac_prop
1132 * @return Pointer to var node
1133 */
1134static rdata_var_t *run_aprop_get_tpos(run_t *run, rdata_address_t *addr)
1135{
1136 rdata_item_t *ritem;
1137
1138 assert(addr->ac == ac_prop);
1139
1140 if (addr->u.prop_a->tvalue == NULL) {
1141 /* Fetch value of the property. */
1142 run_address_read(run, addr, &ritem);
1143 assert(ritem->ic == ic_value);
1144 addr->u.prop_a->tvalue = ritem->u.value;
1145 addr->u.prop_a->tpos = addr->u.prop_a->tvalue->var;
1146 }
1147
1148 return addr->u.prop_a->tpos;
1149}
1150
1151/** Read data from an address.
1152 *
1153 * Read value from the specified address.
1154 *
1155 * @param run Runner object
1156 * @param address Address to read
1157 * @param ritem Place to store pointer to the value that was read
1158 */
1159void run_address_read(run_t *run, rdata_address_t *address,
1160 rdata_item_t **ritem)
1161{
1162 (void) run;
1163
1164 switch (address->ac) {
1165 case ac_var:
1166 rdata_var_read(address->u.var_a->vref, ritem);
1167 break;
1168 case ac_prop:
1169 run_aprop_read(run, address->u.prop_a, ritem);
1170 break;
1171 }
1172
1173 assert((*ritem)->ic == ic_value);
1174}
1175
1176/** Write data to an address.
1177 *
1178 * Store value @a value at address @a address.
1179 *
1180 * @param run Runner object
1181 * @param address Address to write
1182 * @param value Value to store at the address
1183 */
1184void run_address_write(run_t *run, rdata_address_t *address,
1185 rdata_value_t *value)
1186{
1187 (void) run;
1188
1189 switch (address->ac) {
1190 case ac_var:
1191 rdata_var_write(address->u.var_a->vref, value);
1192 break;
1193 case ac_prop:
1194 run_aprop_write(run, address->u.prop_a, value);
1195 break;
1196 }
1197}
1198
1199/** Read data from a property address.
1200 *
1201 * This involves invoking the property getter procedure.
1202 *
1203 * @param run Runner object.
1204 * @param addr_prop Property address to read.
1205 * @param ritem Place to store pointer to the value that was read.
1206 */
1207static void run_aprop_read(run_t *run, rdata_addr_prop_t *addr_prop,
1208 rdata_item_t **ritem)
1209{
1210 rdata_deleg_t *deleg;
1211 rdata_var_t *obj;
1212 stree_symbol_t *prop_sym;
1213 stree_prop_t *prop;
1214
1215 run_proc_ar_t *proc_ar;
1216
1217 rdata_var_t *cvar;
1218
1219#ifdef DEBUG_RUN_TRACE
1220 printf("Read from property.\n");
1221#endif
1222 /*
1223 * If @c tvalue is present, we need to use the relevant part from that
1224 * instead of re-reading the whole thing.
1225 */
1226 if (addr_prop->tvalue != NULL) {
1227 /* Copy the value */
1228 rdata_var_copy(addr_prop->tpos, &cvar);
1229 *ritem = rdata_item_new(ic_value);
1230 (*ritem)->u.value = rdata_value_new();
1231 (*ritem)->u.value->var = cvar;
1232 return;
1233 }
1234
1235 if (addr_prop->apc == apc_named)
1236 deleg = addr_prop->u.named->prop_d;
1237 else
1238 deleg = addr_prop->u.indexed->object_d;
1239
1240 obj = deleg->obj;
1241 prop_sym = deleg->sym;
1242 prop = symbol_to_prop(prop_sym);
1243 assert(prop != NULL);
1244
1245 if (prop->getter == NULL) {
1246 printf("Error: Property is not readable.\n");
1247 exit(1);
1248 }
1249
1250 /* Create procedure activation record. */
1251 run_proc_ar_create(run, obj, prop->getter, &proc_ar);
1252
1253 /* Fill in arguments (indices). */
1254 if (addr_prop->apc == apc_indexed) {
1255 run_proc_ar_set_args(run, proc_ar,
1256 &addr_prop->u.indexed->args);
1257 }
1258
1259 /* Run getter. */
1260 run_proc(run, proc_ar, ritem);
1261
1262#ifdef DEBUG_RUN_TRACE
1263 printf("Getter returns ");
1264 rdata_item_print(*ritem);
1265 printf(".\n");
1266 printf("Done reading from property.\n");
1267#endif
1268}
1269
1270/** Write data to a property address.
1271 *
1272 * This involves invoking the property setter procedure.
1273 *
1274 * @param run Runner object
1275 * @param addr_prop Property address to write
1276 * @param value Value to store at the address
1277 */
1278static void run_aprop_write(run_t *run, rdata_addr_prop_t *addr_prop,
1279 rdata_value_t *value)
1280{
1281 rdata_deleg_t *deleg;
1282 rdata_var_t *obj;
1283 stree_symbol_t *prop_sym;
1284 stree_prop_t *prop;
1285
1286 run_proc_ar_t *proc_ar;
1287 rdata_item_t *vitem;
1288 rdata_item_t *ritem;
1289
1290#ifdef DEBUG_RUN_TRACE
1291 printf("Write to property.\n");
1292#endif
1293 /* If @c tvalue is present, we need to modify it and write it back. */
1294 if (addr_prop->tvalue != NULL) {
1295 printf("Unimplemented: Read-modify-write property access.\n");
1296 exit(1);
1297 }
1298
1299 if (addr_prop->apc == apc_named)
1300 deleg = addr_prop->u.named->prop_d;
1301 else
1302 deleg = addr_prop->u.indexed->object_d;
1303
1304 obj = deleg->obj;
1305 prop_sym = deleg->sym;
1306 prop = symbol_to_prop(prop_sym);
1307 assert(prop != NULL);
1308
1309 if (prop->setter == NULL) {
1310 printf("Error: Property is not writable.\n");
1311 exit(1);
1312 }
1313
1314 vitem = rdata_item_new(ic_value);
1315 vitem->u.value = value;
1316
1317 /* Create procedure activation record. */
1318 run_proc_ar_create(run, obj, prop->setter, &proc_ar);
1319
1320 /* Fill in arguments (indices). */
1321 if (addr_prop->apc == apc_indexed) {
1322 run_proc_ar_set_args(run, proc_ar,
1323 &addr_prop->u.indexed->args);
1324 }
1325
1326 /* Fill in value argument for setter. */
1327 run_proc_ar_set_setter_arg(run, proc_ar, vitem);
1328
1329 /* Run setter. */
1330 run_proc(run, proc_ar, &ritem);
1331
1332 /* Setter should not return a value. */
1333 assert(ritem == NULL);
1334
1335#ifdef DEBUG_RUN_TRACE
1336 printf("Done writing to property.\n");
1337#endif
1338}
1339
1340/** Return reference to a variable.
1341 *
1342 * Constructs a reference (value item) pointing to @a var.
1343 *
1344 * @param run Runner object
1345 * @param var Variable node that is being referenced
1346 * @param res Place to store pointer to new reference.
1347 */
1348void run_reference(run_t *run, rdata_var_t *var, rdata_item_t **res)
1349{
1350 rdata_ref_t *ref;
1351 rdata_var_t *ref_var;
1352 rdata_value_t *ref_value;
1353 rdata_item_t *ref_item;
1354
1355 (void) run;
1356
1357 /* Create reference to the variable. */
1358 ref = rdata_ref_new();
1359 ref_var = rdata_var_new(vc_ref);
1360 ref->vref = var;
1361 ref_var->u.ref_v = ref;
1362
1363 /* Construct value of the reference to return. */
1364 ref_item = rdata_item_new(ic_value);
1365 ref_value = rdata_value_new();
1366 ref_item->u.value = ref_value;
1367 ref_value->var = ref_var;
1368
1369 *res = ref_item;
1370}
1371
1372/** Return address of reference target.
1373 *
1374 * Takes a reference (address or value) and returns the address (item) of
1375 * the target of the reference.
1376 *
1377 * @param run Runner object
1378 * @param ref Reference
1379 * @param rtitem Place to store pointer to the resulting address.
1380 */
1381void run_dereference(run_t *run, rdata_item_t *ref, rdata_item_t **ritem)
1382{
1383 rdata_item_t *ref_val;
1384 rdata_item_t *item;
1385 rdata_address_t *address;
1386 rdata_addr_var_t *addr_var;
1387
1388#ifdef DEBUG_RUN_TRACE
1389 printf("run_dereference()\n");
1390#endif
1391 run_cvt_value_item(run, ref, &ref_val);
1392 assert(ref_val->u.value->var->vc == vc_ref);
1393
1394 item = rdata_item_new(ic_address);
1395 address = rdata_address_new(ac_var);
1396 addr_var = rdata_addr_var_new();
1397 item->u.address = address;
1398 address->u.var_a = addr_var;
1399 addr_var->vref = ref_val->u.value->var->u.ref_v->vref;
1400
1401 if (addr_var->vref == NULL) {
1402#ifdef DEBUG_RUN_TRACE
1403 printf("Error: Accessing null reference.\n");
1404#endif
1405 /* Raise Error.NilReference */
1406 run_raise_exc(run, run->program->builtin->error_nilreference);
1407 *ritem = run_recovery_item(run);
1408 return;
1409 }
1410
1411#ifdef DEBUG_RUN_TRACE
1412 printf("vref set to %p\n", addr_var->vref);
1413#endif
1414 *ritem = item;
1415}
1416
1417/** Raise an exception of the given class.
1418 *
1419 * Used when the interpreter generates an exception due to a run-time
1420 * error (not for the @c raise statement).
1421 *
1422 * @param run Runner object
1423 * @param csi Exception class
1424 */
1425void run_raise_exc(run_t *run, stree_csi_t *csi)
1426{
1427 rdata_item_t *exc_vi;
1428
1429 /* Create exception object. */
1430 run_new_csi_inst(run, csi, &exc_vi);
1431 assert(exc_vi->ic == ic_value);
1432
1433 /* Store exception object in thread AR. */
1434 run->thread_ar->exc_payload = exc_vi->u.value;
1435
1436 /* Start exception bailout. */
1437 run->thread_ar->bo_mode = bm_exc;
1438}
1439
1440/** Determine if we are bailing out.
1441 *
1442 * @param run Runner object
1443 * @return @c b_true if we are bailing out, @c b_false otherwise
1444 */
1445bool_t run_is_bo(run_t *run)
1446{
1447 return run->thread_ar->bo_mode != bm_none;
1448}
1449
1450/** Construct a new variable of the given type.
1451 *
1452 * The variable is allocated and initialized with a default value
1453 * based on type item @a ti. For reference types the default value
1454 * is a null reference. At this point this does not work for generic
1455 * types (we need RTTI).
1456 *
1457 * @param run Runner object
1458 * @param ti Type of variable to create (type item)
1459 * @param rvar Place to store pointer to new variable
1460 */
1461void run_var_new(run_t *run, tdata_item_t *ti, rdata_var_t **rvar)
1462{
1463 rdata_var_t *var;
1464
1465 switch (ti->tic) {
1466 case tic_tprimitive:
1467 run_var_new_tprimitive(run, ti->u.tprimitive, rvar);
1468 break;
1469 case tic_tobject:
1470 case tic_tarray:
1471 run_var_new_null_ref(run, rvar);
1472 break;
1473 case tic_tdeleg:
1474 case tic_tfun:
1475 run_var_new_deleg(run, rvar);
1476 break;
1477 case tic_tvref:
1478 /*
1479 * XXX Need to obtain run-time value of type argument to
1480 * initialize variable properly.
1481 */
1482 var = rdata_var_new(vc_int);
1483 var->u.int_v = rdata_int_new();
1484 bigint_init(&var->u.int_v->value, 0);
1485 *rvar = var;
1486 break;
1487 case tic_ignore:
1488 assert(b_false);
1489 }
1490}
1491
1492/** Construct a new variable of primitive type.
1493 *
1494 * The variable is allocated and initialized with a default value
1495 * based on primitive type item @a tprimitive.
1496 *
1497 * @param run Runner object
1498 * @param ti Primitive type of variable to create
1499 * @param rvar Place to store pointer to new variable
1500 */
1501static void run_var_new_tprimitive(run_t *run, tdata_primitive_t *tprimitive,
1502 rdata_var_t **rvar)
1503{
1504 rdata_var_t *var;
1505
1506 (void) run;
1507
1508 /* Make compiler happy. */
1509 var = NULL;
1510
1511 switch (tprimitive->tpc) {
1512 case tpc_bool:
1513 var = rdata_var_new(vc_bool);
1514 var->u.bool_v = rdata_bool_new();
1515 var->u.bool_v->value = b_false;
1516 break;
1517 case tpc_char:
1518 var = rdata_var_new(vc_char);
1519 var->u.char_v = rdata_char_new();
1520 bigint_init(&var->u.char_v->value, 0);
1521 break;
1522 case tpc_int:
1523 var = rdata_var_new(vc_int);
1524 var->u.int_v = rdata_int_new();
1525 bigint_init(&var->u.int_v->value, 0);
1526 break;
1527 case tpc_nil:
1528 assert(b_false);
1529 case tpc_string:
1530 var = rdata_var_new(vc_string);
1531 var->u.string_v = rdata_string_new();
1532 var->u.string_v->value = "";
1533 break;
1534 case tpc_resource:
1535 var = rdata_var_new(vc_resource);
1536 var->u.resource_v = rdata_resource_new();
1537 var->u.resource_v->data = NULL;
1538 break;
1539 }
1540
1541 *rvar = var;
1542}
1543
1544/** Construct a new variable containing null reference.
1545 *
1546 * @param run Runner object
1547 * @param rvar Place to store pointer to new variable
1548 */
1549static void run_var_new_null_ref(run_t *run, rdata_var_t **rvar)
1550{
1551 rdata_var_t *var;
1552
1553 (void) run;
1554
1555 /* Return null reference. */
1556 var = rdata_var_new(vc_ref);
1557 var->u.ref_v = rdata_ref_new();
1558
1559 *rvar = var;
1560}
1561
1562/** Construct a new variable containing invalid delegate.
1563 *
1564 * @param run Runner object
1565 * @param rvar Place to store pointer to new variable
1566 */
1567static void run_var_new_deleg(run_t *run, rdata_var_t **rvar)
1568{
1569 rdata_var_t *var;
1570
1571 (void) run;
1572
1573 /* Return null reference. */
1574 var = rdata_var_new(vc_deleg);
1575 var->u.deleg_v = rdata_deleg_new();
1576
1577 *rvar = var;
1578}
1579
1580/** Construct a new thread activation record.
1581 *
1582 * @param run Runner object
1583 * @return New thread AR.
1584 */
1585run_thread_ar_t *run_thread_ar_new(void)
1586{
1587 run_thread_ar_t *thread_ar;
1588
1589 thread_ar = calloc(1, sizeof(run_thread_ar_t));
1590 if (thread_ar == NULL) {
1591 printf("Memory allocation failed.\n");
1592 exit(1);
1593 }
1594
1595 return thread_ar;
1596}
1597
1598/** Construct a new procedure activation record.
1599 *
1600 * @param run Runner object
1601 * @return New procedure AR.
1602 */
1603run_proc_ar_t *run_proc_ar_new(void)
1604{
1605 run_proc_ar_t *proc_ar;
1606
1607 proc_ar = calloc(1, sizeof(run_proc_ar_t));
1608 if (proc_ar == NULL) {
1609 printf("Memory allocation failed.\n");
1610 exit(1);
1611 }
1612
1613 return proc_ar;
1614}
1615
1616/** Construct a new block activation record.
1617 *
1618 * @param run Runner object
1619 * @return New block AR.
1620 */
1621run_block_ar_t *run_block_ar_new(void)
1622{
1623 run_block_ar_t *block_ar;
1624
1625 block_ar = calloc(1, sizeof(run_block_ar_t));
1626 if (block_ar == NULL) {
1627 printf("Memory allocation failed.\n");
1628 exit(1);
1629 }
1630
1631 return block_ar;
1632}
Note: See TracBrowser for help on using the repository browser.