run.c

00001 /*
00002  * Copyright (c) 2011 Jiri Svoboda
00003  * All rights reserved.
00004  *
00005  * Redistribution and use in source and binary forms, with or without
00006  * modification, are permitted provided that the following conditions
00007  * are met:
00008  *
00009  * - Redistributions of source code must retain the above copyright
00010  *   notice, this list of conditions and the following disclaimer.
00011  * - Redistributions in binary form must reproduce the above copyright
00012  *   notice, this list of conditions and the following disclaimer in the
00013  *   documentation and/or other materials provided with the distribution.
00014  * - The name of the author may not be used to endorse or promote products
00015  *   derived from this software without specific prior written permission.
00016  *
00017  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
00018  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
00019  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
00020  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
00021  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
00022  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
00023  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
00024  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
00025  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
00026  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00027  */
00028 
00031 #include <stdio.h>
00032 #include <stdlib.h>
00033 #include <assert.h>
00034 #include "bigint.h"
00035 #include "builtin.h"
00036 #include "cspan.h"
00037 #include "debug.h"
00038 #include "intmap.h"
00039 #include "list.h"
00040 #include "mytypes.h"
00041 #include "rdata.h"
00042 #include "run_expr.h"
00043 #include "run_texpr.h"
00044 #include "stree.h"
00045 #include "strtab.h"
00046 #include "symbol.h"
00047 #include "tdata.h"
00048 
00049 #include "run.h"
00050 
00051 static void run_block(run_t *run, stree_block_t *block);
00052 static void run_exps(run_t *run, stree_exps_t *exps, rdata_item_t **res);
00053 static void run_vdecl(run_t *run, stree_vdecl_t *vdecl);
00054 static void run_if(run_t *run, stree_if_t *if_s);
00055 static void run_switch(run_t *run, stree_switch_t *switch_s);
00056 static void run_while(run_t *run, stree_while_t *while_s);
00057 static void run_raise(run_t *run, stree_raise_t *raise_s);
00058 static void run_break(run_t *run, stree_break_t *break_s);
00059 static void run_return(run_t *run, stree_return_t *return_s);
00060 static void run_wef(run_t *run, stree_wef_t *wef_s);
00061 
00062 static bool_t run_exc_match(run_t *run, stree_except_t *except_c);
00063 static stree_csi_t *run_exc_payload_get_csi(run_t *run);
00064 
00065 static rdata_var_t *run_aprop_get_tpos(run_t *run, rdata_address_t *aprop);
00066 
00067 static void run_aprop_read(run_t *run, rdata_addr_prop_t *addr_prop,
00068     rdata_item_t **ritem);
00069 static void run_aprop_write(run_t *run, rdata_addr_prop_t *addr_prop,
00070     rdata_value_t *value);
00071 
00072 static void run_var_new_tprimitive(run_t *run, tdata_primitive_t *tprimitive,
00073     rdata_var_t **rvar);
00074 static void run_var_new_null_ref(run_t *run, rdata_var_t **rvar);
00075 static void run_var_new_deleg(run_t *run, rdata_var_t **rvar);
00076 static void run_var_new_enum(run_t *run, tdata_enum_t *tenum,
00077     rdata_var_t **rvar);
00078 
00083 void run_init(run_t *run)
00084 {
00085         (void) run;
00086 }
00087 
00098 void run_program(run_t *run, stree_program_t *prog)
00099 {
00100         stree_symbol_t *main_fun_sym;
00101         stree_fun_t *main_fun;
00102         rdata_var_t *main_obj;
00103         stree_ident_t *fake_ident;
00104         list_t main_args;
00105         run_proc_ar_t *proc_ar;
00106         rdata_item_t *res;
00107 
00108         /* Note down link to program code. */
00109         run->program = prog;
00110 
00111         /* Initialize thread activation record. */
00112         run->thread_ar = run_thread_ar_new();
00113         list_init(&run->thread_ar->proc_ar);
00114         run->thread_ar->bo_mode = bm_none;
00115 
00116         /* Initialize global data structure. */
00117         run_gdata_init(run);
00118 
00119         /*
00120          * Find entry point @c Main().
00121          */
00122         fake_ident = stree_ident_new();
00123         fake_ident->sid = strtab_get_sid("Main");
00124         main_fun_sym = symbol_find_epoint(prog, fake_ident);
00125         if (main_fun_sym == NULL) {
00126                 printf("Error: Entry point 'Main' not found.\n");
00127                 exit(1);
00128         }
00129 
00130         main_fun = symbol_to_fun(main_fun_sym);
00131         assert(main_fun != NULL);
00132 
00133         main_obj = run_fun_sobject_find(run, main_fun);
00134 
00135 #ifdef DEBUG_RUN_TRACE
00136         printf("Found function '"); symbol_print_fqn(main_fun_sym);
00137         printf("'.\n");
00138 #endif
00139 
00140         /* Run function @c main. */
00141         list_init(&main_args);
00142         run_proc_ar_create(run, main_obj, main_fun->proc, &proc_ar);
00143         run_proc_ar_set_args(run, proc_ar, &main_args);
00144         run_proc(run, proc_ar, &res);
00145         run_proc_ar_destroy(run, proc_ar);
00146 
00147         run_exc_check_unhandled(run);
00148 }
00149 
00154 void run_gdata_init(run_t *run)
00155 {
00156         rdata_object_t *gobject;
00157 
00158         run->gdata = rdata_var_new(vc_object);
00159         gobject = rdata_object_new();
00160         run->gdata->u.object_v = gobject;
00161 
00162         gobject->class_sym = NULL;
00163         gobject->static_obj = sn_static;
00164         intmap_init(&gobject->fields);
00165 }
00166 
00182 void run_proc(run_t *run, run_proc_ar_t *proc_ar, rdata_item_t **res)
00183 {
00184         stree_proc_t *proc;
00185         list_node_t *node;
00186 
00187         proc = proc_ar->proc;
00188 
00189 #ifdef DEBUG_RUN_TRACE
00190         printf("Start executing function '");
00191         symbol_print_fqn(proc->outer_symbol);
00192         printf("'.\n");
00193 #endif
00194         /* Add procedure AR to the stack. */
00195         list_append(&run->thread_ar->proc_ar, proc_ar);
00196 
00197         /* Run main procedure block. */
00198         if (proc->body != NULL) {
00199                 run_block(run, proc->body);
00200         } else {
00201                 builtin_run_proc(run, proc);
00202         }
00203 
00204         /* Handle bailout. */
00205         switch (run->thread_ar->bo_mode) {
00206         case bm_stat:
00207                 /* Break bailout was not caught. */
00208                 assert(b_false);
00209         case bm_proc:
00210                 run->thread_ar->bo_mode = bm_none;
00211                 break;
00212         default:
00213                 break;
00214         }
00215 
00216 #ifdef DEBUG_RUN_TRACE
00217         printf("Done executing procedure '");
00218         symbol_print_fqn(proc->outer_symbol);
00219         printf("'.\n");
00220 
00221         run_print_fun_bt(run);
00222 #endif
00223         /* Remove procedure activation record from the stack. */
00224         node = list_last(&run->thread_ar->proc_ar);
00225         assert(list_node_data(node, run_proc_ar_t *) == proc_ar);
00226         list_remove(&run->thread_ar->proc_ar, node);
00227 
00228         /* Procedure should not return an address. */
00229         assert(proc_ar->retval == NULL || proc_ar->retval->ic == ic_value);
00230         *res = proc_ar->retval;
00231 }
00232 
00238 static void run_block(run_t *run, stree_block_t *block)
00239 {
00240         run_proc_ar_t *proc_ar;
00241         run_block_ar_t *block_ar;
00242         list_node_t *node;
00243         stree_stat_t *stat;
00244 
00245 #ifdef DEBUG_RUN_TRACE
00246         printf("Executing one code block.\n");
00247 #endif
00248 
00249         /* Create block activation record. */
00250         block_ar = run_block_ar_new();
00251         intmap_init(&block_ar->vars);
00252 
00253         /* Add block activation record to the stack. */
00254         proc_ar = run_get_current_proc_ar(run);
00255         list_append(&proc_ar->block_ar, block_ar);
00256 
00257         node = list_first(&block->stats);
00258         while (node != NULL) {
00259                 stat = list_node_data(node, stree_stat_t *);
00260                 run_stat(run, stat, NULL);
00261 
00262                 if (run->thread_ar->bo_mode != bm_none)
00263                         break;
00264 
00265                 node = list_next(&block->stats, node);
00266         }
00267 
00268 #ifdef DEBUG_RUN_TRACE
00269         printf("Done executing code block.\n");
00270 #endif
00271 
00272         /* Remove block activation record from the stack. */
00273         node = list_last(&proc_ar->block_ar);
00274         assert(list_node_data(node, run_block_ar_t *) == block_ar);
00275         list_remove(&proc_ar->block_ar, node);
00276 
00277         /* Deallocate block activation record. */
00278         run_block_ar_destroy(run, block_ar);
00279 }
00280 
00291 void run_stat(run_t *run, stree_stat_t *stat, rdata_item_t **res)
00292 {
00293 #ifdef DEBUG_RUN_TRACE
00294         printf("Executing one statement %p.\n", stat);
00295 #endif
00296 
00297         if (res != NULL)
00298                 *res = NULL;
00299 
00300         switch (stat->sc) {
00301         case st_exps:
00302                 run_exps(run, stat->u.exp_s, res);
00303                 break;
00304         case st_vdecl:
00305                 run_vdecl(run, stat->u.vdecl_s);
00306                 break;
00307         case st_if:
00308                 run_if(run, stat->u.if_s);
00309                 break;
00310         case st_switch:
00311                 run_switch(run, stat->u.switch_s);
00312                 break;
00313         case st_while:
00314                 run_while(run, stat->u.while_s);
00315                 break;
00316         case st_raise:
00317                 run_raise(run, stat->u.raise_s);
00318                 break;
00319         case st_break:
00320                 run_break(run, stat->u.break_s);
00321                 break;
00322         case st_return:
00323                 run_return(run, stat->u.return_s);
00324                 break;
00325         case st_wef:
00326                 run_wef(run, stat->u.wef_s);
00327                 break;
00328         case st_for:
00329                 printf("Ignoring unimplemented statement type %d.\n", stat->sc);
00330                 break;
00331         }
00332 }
00333 
00343 static void run_exps(run_t *run, stree_exps_t *exps, rdata_item_t **res)
00344 {
00345         rdata_item_t *rexpr;
00346 
00347 #ifdef DEBUG_RUN_TRACE
00348         printf("Executing expression statement.\n");
00349 #endif
00350         run_expr(run, exps->expr, &rexpr);
00351 
00352         /*
00353          * If the expression has a value, the caller should have asked for it.
00354          */
00355         assert(res != NULL || rexpr == NULL);
00356 
00357         if (res != NULL)
00358                 *res = rexpr;
00359 }
00360 
00366 static void run_vdecl(run_t *run, stree_vdecl_t *vdecl)
00367 {
00368         run_block_ar_t *block_ar;
00369         rdata_var_t *var, *old_var;
00370 
00371 #ifdef DEBUG_RUN_TRACE
00372         printf("Executing variable declaration statement.\n");
00373 #endif
00374         /* Create variable and initialize with default value. */
00375         run_var_new(run, vdecl->titem, &var);
00376 
00377         block_ar = run_get_current_block_ar(run);
00378         old_var = (rdata_var_t *) intmap_get(&block_ar->vars, vdecl->name->sid);
00379 
00380         if (old_var != NULL) {
00381                 printf("Error: Duplicate variable '%s'\n",
00382                     strtab_get_str(vdecl->name->sid));
00383                 exit(1);
00384         }
00385 
00386         intmap_set(&block_ar->vars, vdecl->name->sid, var);
00387 
00388 #ifdef DEBUG_RUN_TRACE
00389         printf("Declared variable '%s'\n", strtab_get_str(vdecl->name->sid));
00390 #endif
00391 }
00392 
00398 static void run_if(run_t *run, stree_if_t *if_s)
00399 {
00400         rdata_item_t *rcond;
00401         list_node_t *ifc_node;
00402         stree_if_clause_t *ifc;
00403         bool_t rcond_b, clause_fired;
00404 
00405 #ifdef DEBUG_RUN_TRACE
00406         printf("Executing if statement.\n");
00407 #endif
00408         clause_fired = b_false;
00409         ifc_node = list_first(&if_s->if_clauses);
00410 
00411         /* Walk through all if/elif clauses and see if they fire. */
00412 
00413         while (ifc_node != NULL) {
00414                 /* Get if/elif clause */
00415                 ifc = list_node_data(ifc_node, stree_if_clause_t *);
00416 
00417                 run_expr(run, ifc->cond, &rcond);
00418                 if (run_is_bo(run))
00419                         return;
00420 
00421                 rcond_b = run_item_boolean_value(run, rcond);
00422                 rdata_item_destroy(rcond);
00423 
00424                 if (rcond_b == b_true) {
00425 #ifdef DEBUG_RUN_TRACE
00426                         printf("Taking non-default path.\n");
00427 #endif
00428                         run_block(run, ifc->block);
00429                         clause_fired = b_true;
00430                         break;
00431                 }
00432 
00433                 ifc_node = list_next(&if_s->if_clauses, ifc_node);
00434         }
00435 
00436         /* If no if/elif clause fired, invoke the else clause. */
00437         if (clause_fired == b_false && if_s->else_block != NULL) {
00438 #ifdef DEBUG_RUN_TRACE
00439                 printf("Taking default path.\n");
00440 #endif
00441                 run_block(run, if_s->else_block);
00442         }
00443 
00444 #ifdef DEBUG_RUN_TRACE
00445         printf("If statement terminated.\n");
00446 #endif
00447 }
00448 
00454 static void run_switch(run_t *run, stree_switch_t *switch_s)
00455 {
00456         rdata_item_t *rsexpr, *rsexpr_vi;
00457         rdata_item_t *rwexpr, *rwexpr_vi;
00458         list_node_t *whenc_node;
00459         stree_when_t *whenc;
00460         list_node_t *expr_node;
00461         stree_expr_t *expr;
00462         bool_t clause_fired;
00463         bool_t equal;
00464 
00465 #ifdef DEBUG_RUN_TRACE
00466         printf("Executing switch statement.\n");
00467 #endif
00468         rsexpr_vi = NULL;
00469 
00470         /* Evaluate switch expression */
00471         run_expr(run, switch_s->expr, &rsexpr);
00472         if (run_is_bo(run))
00473                 goto cleanup;
00474 
00475         /* Convert to value item */
00476         run_cvt_value_item(run, rsexpr, &rsexpr_vi);
00477         rdata_item_destroy(rsexpr);
00478         if (run_is_bo(run))
00479                 goto cleanup;
00480 
00481         clause_fired = b_false;
00482         whenc_node = list_first(&switch_s->when_clauses);
00483 
00484         /* Walk through all when clauses and see if they fire. */
00485 
00486         while (whenc_node != NULL) {
00487                 /* Get when clause */
00488                 whenc = list_node_data(whenc_node, stree_when_t *);
00489 
00490                 expr_node = list_first(&whenc->exprs);
00491 
00492                 /* Walk through all expressions in the when clause */
00493                 while (expr_node != NULL) {
00494                         /* Get expression */
00495                         expr = list_node_data(expr_node, stree_expr_t *);
00496 
00497                         /* Evaluate expression */
00498                         run_expr(run, expr, &rwexpr);
00499                         if (run_is_bo(run))
00500                                 goto cleanup;
00501 
00502                         /* Convert to value item */
00503                         run_cvt_value_item(run, rwexpr, &rwexpr_vi);
00504                         rdata_item_destroy(rwexpr);
00505                         if (run_is_bo(run)) {
00506                                 rdata_item_destroy(rwexpr_vi);
00507                                 goto cleanup;
00508                         }
00509 
00510                         /* Check if values are equal ('==') */
00511                         run_equal(run, rsexpr_vi->u.value,
00512                             rwexpr_vi->u.value, &equal);
00513                         rdata_item_destroy(rwexpr_vi);
00514                         if (run_is_bo(run))
00515                                 goto cleanup;
00516 
00517                         if (equal) {
00518 #ifdef DEBUG_RUN_TRACE
00519                                 printf("Taking non-default path.\n");
00520 #endif
00521                                 run_block(run, whenc->block);
00522                                 clause_fired = b_true;
00523                                 break;
00524                         }
00525 
00526                         expr_node = list_next(&whenc->exprs, expr_node);
00527                 }
00528 
00529                 if (clause_fired)
00530                         break;
00531 
00532                 whenc_node = list_next(&switch_s->when_clauses, whenc_node);
00533         }
00534 
00535         /* If no when clause fired, invoke the else clause. */
00536         if (clause_fired == b_false && switch_s->else_block != NULL) {
00537 #ifdef DEBUG_RUN_TRACE
00538                 printf("Taking default path.\n");
00539 #endif
00540                 run_block(run, switch_s->else_block);
00541         }
00542 cleanup:
00543         if (rsexpr_vi != NULL)
00544                 rdata_item_destroy(rsexpr_vi);
00545 
00546 #ifdef DEBUG_RUN_TRACE
00547         printf("Switch statement terminated.\n");
00548 #endif
00549 }
00550 
00556 static void run_while(run_t *run, stree_while_t *while_s)
00557 {
00558         rdata_item_t *rcond;
00559 
00560 #ifdef DEBUG_RUN_TRACE
00561         printf("Executing while statement.\n");
00562 #endif
00563         run_expr(run, while_s->cond, &rcond);
00564         if (run_is_bo(run))
00565                 return;
00566 
00567         while (run_item_boolean_value(run, rcond) == b_true) {
00568                 rdata_item_destroy(rcond);
00569                 run_block(run, while_s->body);
00570                 run_expr(run, while_s->cond, &rcond);
00571                 if (run_is_bo(run))
00572                         break;
00573         }
00574 
00575         if (rcond != NULL)
00576                 rdata_item_destroy(rcond);
00577 
00578         if (run->thread_ar->bo_mode == bm_stat) {
00579                 /* Bailout due to break statement */
00580                 run->thread_ar->bo_mode = bm_none;
00581         }
00582 
00583 #ifdef DEBUG_RUN_TRACE
00584         printf("While statement terminated.\n");
00585 #endif
00586 }
00587 
00593 static void run_raise(run_t *run, stree_raise_t *raise_s)
00594 {
00595         rdata_item_t *rexpr;
00596         rdata_item_t *rexpr_vi;
00597 
00598 #ifdef DEBUG_RUN_TRACE
00599         printf("Executing raise statement.\n");
00600 #endif
00601         run_expr(run, raise_s->expr, &rexpr);
00602         if (run_is_bo(run))
00603                 return;
00604 
00605         run_cvt_value_item(run, rexpr, &rexpr_vi);
00606         rdata_item_destroy(rexpr);
00607         if (run_is_bo(run))
00608                 return;
00609 
00610         /* Store expression cspan in thread AR. */
00611         run->thread_ar->exc_cspan = raise_s->expr->cspan;
00612 
00613         /* Store expression result in thread AR. */
00614         /* XXX rexpr_vi is leaked here, we only return ->u.value */
00615         run->thread_ar->exc_payload = rexpr_vi->u.value;
00616 
00617         /* Start exception bailout. */
00618         run->thread_ar->bo_mode = bm_exc;
00619 }
00620 
00629 static void run_break(run_t *run, stree_break_t *break_s)
00630 {
00631 #ifdef DEBUG_RUN_TRACE
00632         printf("Executing 'break' statement.\n");
00633 #endif
00634         (void) break_s;
00635 
00636         /* Force control to ascend and leave the procedure. */
00637         if (run->thread_ar->bo_mode == bm_none)
00638                 run->thread_ar->bo_mode = bm_stat;
00639 }
00640 
00649 static void run_return(run_t *run, stree_return_t *return_s)
00650 {
00651         rdata_item_t *rexpr;
00652         rdata_item_t *rexpr_vi;
00653         run_proc_ar_t *proc_ar;
00654 
00655 #ifdef DEBUG_RUN_TRACE
00656         printf("Executing return statement.\n");
00657 #endif
00658         if (return_s->expr != NULL) {
00659                 run_expr(run, return_s->expr, &rexpr);
00660                 if (run_is_bo(run))
00661                         return;
00662 
00663                 run_cvt_value_item(run, rexpr, &rexpr_vi);
00664                 rdata_item_destroy(rexpr);
00665                 if (run_is_bo(run))
00666                         return;
00667 
00668                 /* Store expression result in procedure AR. */
00669                 proc_ar = run_get_current_proc_ar(run);
00670                 proc_ar->retval = rexpr_vi;
00671         }
00672 
00673         /* Force control to ascend and leave the procedure. */
00674         if (run->thread_ar->bo_mode == bm_none)
00675                 run->thread_ar->bo_mode = bm_proc;
00676 }
00677 
00685 static void run_wef(run_t *run, stree_wef_t *wef_s)
00686 {
00687         list_node_t *except_n;
00688         stree_except_t *except_c;
00689         rdata_value_t *exc_payload;
00690         run_bailout_mode_t bo_mode;
00691 
00692 #ifdef DEBUG_RUN_TRACE
00693         printf("Executing with-except-finally statement.\n");
00694 #endif
00695         run_block(run, wef_s->with_block);
00696 
00697         if (run->thread_ar->bo_mode == bm_exc) {
00698 #ifdef DEBUG_RUN_TRACE
00699                 printf("With statement detected exception.\n");
00700 #endif
00701                 /* Reset to normal execution. */
00702                 run->thread_ar->bo_mode = bm_none;
00703 
00704                 /* Look for an except block. */
00705                 except_n = list_first(&wef_s->except_clauses);
00706                 while (except_n != NULL) {
00707                         except_c = list_node_data(except_n, stree_except_t *);
00708                         if (run_exc_match(run, except_c))
00709                                 break;
00710 
00711                         except_n = list_next(&wef_s->except_clauses, except_n);
00712                 }
00713 
00714                 /* If one was found, execute it. */
00715                 if (except_n != NULL)
00716                         run_block(run, except_c->block);
00717 
00718                 /* Execute finally block */
00719                 if (wef_s->finally_block != NULL) {
00720                         /* Put exception on the side temporarily. */
00721                         bo_mode = run->thread_ar->bo_mode;
00722                         exc_payload = run->thread_ar->exc_payload;
00723 
00724                         run->thread_ar->bo_mode = bm_none;
00725                         run->thread_ar->exc_payload = NULL;
00726 
00727                         run_block(run, wef_s->finally_block);
00728 
00729                         if (bo_mode == bm_exc) {
00730                                 /*
00731                                  * Restore the original exception. If another
00732                                  * exception occured in the finally block (i.e.
00733                                  * double fault), it is forgotten.
00734                                  */
00735                                 run->thread_ar->bo_mode = bm_exc;
00736                                 run->thread_ar->exc_payload = exc_payload;
00737                         }
00738                 }
00739         }
00740 
00741 #ifdef DEBUG_RUN_TRACE
00742         printf("With-except-finally statement terminated.\n");
00743 #endif
00744 }
00745 
00755 static bool_t run_exc_match(run_t *run, stree_except_t *except_c)
00756 {
00757         stree_csi_t *exc_csi;
00758 
00759         /* Get CSI of active exception. */
00760         exc_csi = run_exc_payload_get_csi(run);
00761 
00762         /* Determine if active exc. is derived from type in exc. clause. */
00763         /* XXX This is wrong, it does not work with generics. */
00764         return tdata_is_csi_derived_from_ti(exc_csi, except_c->titem);
00765 }
00766 
00772 static stree_csi_t *run_exc_payload_get_csi(run_t *run)
00773 {
00774         rdata_value_t *payload;
00775         rdata_var_t *payload_v;
00776         rdata_object_t *payload_o;
00777 
00778         payload = run->thread_ar->exc_payload;
00779         assert(payload != NULL);
00780 
00781         if (payload->var->vc != vc_ref) {
00782                 /* XXX Prevent this via static type checking. */
00783                 printf("Error: Exception payload must be an object "
00784                     "(found type %d).\n", payload->var->vc);
00785                 exit(1);
00786         }
00787 
00788         payload_v = payload->var->u.ref_v->vref;
00789         if (payload_v->vc != vc_object) {
00790                 /* XXX Prevent this via static type checking. */
00791                 printf("Error: Exception payload must be an object "
00792                     "(found type %d).\n", payload_v->vc);
00793                 exit(1);
00794         }
00795 
00796         payload_o = payload_v->u.object_v;
00797 
00798 #ifdef DEBUG_RUN_TRACE
00799         printf("Active exception: '");
00800         symbol_print_fqn(payload_o->class_sym);
00801         printf("'.\n");
00802 #endif
00803         assert(payload_o->class_sym != NULL);
00804         assert(payload_o->class_sym->sc == sc_csi);
00805 
00806         return payload_o->class_sym->u.csi;
00807 }
00808 
00809 
00817 void run_exc_check_unhandled(run_t *run)
00818 {
00819         stree_csi_t *exc_csi;
00820 
00821         if (run->thread_ar->bo_mode != bm_none) {
00822                 assert(run->thread_ar->bo_mode == bm_exc);
00823 
00824                 exc_csi = run_exc_payload_get_csi(run);
00825 
00826                 if (run->thread_ar->exc_cspan != NULL) {
00827                         cspan_print(run->thread_ar->exc_cspan);
00828                         putchar(' ');
00829                 }
00830 
00831                 printf("Error: Unhandled exception '");
00832                 symbol_print_fqn(csi_to_symbol(exc_csi));
00833                 printf("'.\n");
00834 
00835                 run_raise_error(run);
00836         }
00837 }
00838 
00845 void run_raise_error(run_t *run)
00846 {
00847         run->thread_ar->bo_mode = bm_error;
00848         run->thread_ar->error = b_true;
00849 }
00850 
00855 rdata_item_t *run_recovery_item(run_t *run)
00856 {
00857         (void) run;
00858         return NULL;
00859 }
00860 
00867 rdata_var_t *run_local_vars_lookup(run_t *run, sid_t name)
00868 {
00869         run_proc_ar_t *proc_ar;
00870         run_block_ar_t *block_ar;
00871         rdata_var_t *var;
00872         list_node_t *node;
00873 
00874         proc_ar = run_get_current_proc_ar(run);
00875         node = list_last(&proc_ar->block_ar);
00876 
00877         /* Walk through all block activation records. */
00878         while (node != NULL) {
00879                 block_ar = list_node_data(node, run_block_ar_t *);
00880                 var = intmap_get(&block_ar->vars, name);
00881                 if (var != NULL)
00882                         return var;
00883 
00884                 node = list_prev(&proc_ar->block_ar, node);
00885         }
00886 
00887         /* No match */
00888         return NULL;
00889 }
00890 
00896 run_proc_ar_t *run_get_current_proc_ar(run_t *run)
00897 {
00898         list_node_t *node;
00899 
00900         node = list_last(&run->thread_ar->proc_ar);
00901         return list_node_data(node, run_proc_ar_t *);
00902 }
00903 
00909 run_block_ar_t *run_get_current_block_ar(run_t *run)
00910 {
00911         run_proc_ar_t *proc_ar;
00912         list_node_t *node;
00913 
00914         proc_ar = run_get_current_proc_ar(run);
00915 
00916         node = list_last(&proc_ar->block_ar);
00917         return list_node_data(node, run_block_ar_t *);
00918 }
00919 
00925 stree_csi_t *run_get_current_csi(run_t *run)
00926 {
00927         run_proc_ar_t *proc_ar;
00928 
00929         proc_ar = run_get_current_proc_ar(run);
00930         return proc_ar->proc->outer_symbol->outer_csi;
00931 }
00932 
00945 rdata_var_t *run_sobject_get(run_t *run, stree_csi_t *csi,
00946     rdata_var_t *pobj_var, sid_t name)
00947 {
00948         rdata_object_t *pobject;
00949         rdata_var_t *mbr_var;
00950         rdata_var_t *rvar;
00951         stree_ident_t *ident;
00952 
00953         assert(pobj_var->vc == vc_object);
00954         pobject = pobj_var->u.object_v;
00955 #ifdef DEBUG_RUN_TRACE
00956         printf("Get static object '%s' in '", strtab_get_str(name));
00957         if (pobject->class_sym != NULL)
00958                 symbol_print_fqn(pobject->class_sym);
00959         else
00960                 printf("global");
00961 #endif
00962 
00963         assert(pobject->static_obj == sn_static);
00964 
00965         mbr_var = intmap_get(&pobject->fields, name);
00966         if (mbr_var != NULL) {
00967 #ifdef DEBUG_RUN_TRACE
00968                 printf("Return exising static object (mbr_var=%p).\n", mbr_var);
00969 #endif
00970                 /* Return existing object. */
00971                 return mbr_var;
00972         }
00973 
00974         /* Construct new object. */
00975 #ifdef DEBUG_RUN_TRACE
00976         printf("Construct new static object.\n");
00977 #endif
00978         ident = stree_ident_new();
00979         ident->sid = name;
00980 
00981         run_new_csi_inst(run, csi, sn_static, &rvar);
00982 
00983         /* Store static object reference for future use. */
00984         intmap_set(&pobject->fields, name, rvar);
00985 
00986         return rvar;
00987 }
00988 
01002 rdata_var_t *run_sobject_find(run_t *run, stree_csi_t *csi)
01003 {
01004         rdata_var_t *pobj_var;
01005 
01006         if (csi == NULL)
01007                 return run->gdata;
01008 
01009         assert(csi->ancr_state == ws_visited);
01010         pobj_var = run_sobject_find(run, csi_to_symbol(csi)->outer_csi);
01011 
01012         return run_sobject_get(run, csi, pobj_var, csi->name->sid);
01013 }
01014 
01026 rdata_var_t *run_fun_sobject_find(run_t *run, stree_fun_t *fun)
01027 {
01028         return run_sobject_find(run, fun_to_symbol(fun)->outer_csi);
01029 }
01030 
01041 void run_value_item_to_var(rdata_item_t *item, rdata_var_t **var)
01042 {
01043         rdata_bool_t *bool_v;
01044         rdata_char_t *char_v;
01045         rdata_deleg_t *deleg_v;
01046         rdata_enum_t *enum_v;
01047         rdata_int_t *int_v;
01048         rdata_string_t *string_v;
01049         rdata_ref_t *ref_v;
01050         rdata_var_t *in_var;
01051 
01052         assert(item->ic == ic_value);
01053         in_var = item->u.value->var;
01054 
01055         switch (in_var->vc) {
01056         case vc_bool:
01057                 *var = rdata_var_new(vc_bool);
01058                 bool_v = rdata_bool_new();
01059 
01060                 (*var)->u.bool_v = bool_v;
01061                 bool_v->value = item->u.value->var->u.bool_v->value;
01062                 break;
01063         case vc_char:
01064                 *var = rdata_var_new(vc_char);
01065                 char_v = rdata_char_new();
01066 
01067                 (*var)->u.char_v = char_v;
01068                 bigint_clone(&item->u.value->var->u.char_v->value,
01069                     &char_v->value);
01070                 break;
01071         case vc_deleg:
01072                 *var = rdata_var_new(vc_deleg);
01073                 deleg_v = rdata_deleg_new();
01074 
01075                 (*var)->u.deleg_v = deleg_v;
01076                 deleg_v->obj = item->u.value->var->u.deleg_v->obj;
01077                 deleg_v->sym = item->u.value->var->u.deleg_v->sym;
01078                 break;
01079         case vc_enum:
01080                 *var = rdata_var_new(vc_enum);
01081                 enum_v = rdata_enum_new();
01082 
01083                 (*var)->u.enum_v = enum_v;
01084                 enum_v->value = item->u.value->var->u.enum_v->value;
01085                 break;
01086         case vc_int:
01087                 *var = rdata_var_new(vc_int);
01088                 int_v = rdata_int_new();
01089 
01090                 (*var)->u.int_v = int_v;
01091                 bigint_clone(&item->u.value->var->u.int_v->value,
01092                     &int_v->value);
01093                 break;
01094         case vc_string:
01095                 *var = rdata_var_new(vc_string);
01096                 string_v = rdata_string_new();
01097 
01098                 (*var)->u.string_v = string_v;
01099                 string_v->value = item->u.value->var->u.string_v->value;
01100                 break;
01101         case vc_ref:
01102                 *var = rdata_var_new(vc_ref);
01103                 ref_v = rdata_ref_new();
01104 
01105                 (*var)->u.ref_v = ref_v;
01106                 ref_v->vref = item->u.value->var->u.ref_v->vref;
01107                 break;
01108         default:
01109                 printf("Error: Unimplemented argument type.\n");
01110                 exit(1);
01111 
01112         }
01113 }
01114 
01122 void run_proc_ar_create(run_t *run, rdata_var_t *obj, stree_proc_t *proc,
01123     run_proc_ar_t **rproc_ar)
01124 {
01125         run_proc_ar_t *proc_ar;
01126         run_block_ar_t *block_ar;
01127 
01128         (void) run;
01129 
01130         /* Create procedure activation record. */
01131         proc_ar = run_proc_ar_new();
01132         proc_ar->obj = obj;
01133         proc_ar->proc = proc;
01134         list_init(&proc_ar->block_ar);
01135 
01136         proc_ar->retval = NULL;
01137 
01138         /* Create special block activation record to hold function arguments. */
01139         block_ar = run_block_ar_new();
01140         intmap_init(&block_ar->vars);
01141         list_append(&proc_ar->block_ar, block_ar);
01142 
01143         *rproc_ar = proc_ar;
01144 }
01145 
01151 void run_proc_ar_destroy(run_t *run, run_proc_ar_t *proc_ar)
01152 {
01153         list_node_t *ar_node;
01154         run_block_ar_t *block_ar;
01155 
01156         (void) run;
01157 
01158         /* Destroy special block activation record. */
01159         ar_node = list_first(&proc_ar->block_ar);
01160         block_ar = list_node_data(ar_node, run_block_ar_t *);
01161         list_remove(&proc_ar->block_ar, ar_node);
01162         run_block_ar_destroy(run, block_ar);
01163 
01164         /* Destroy procedure activation record. */
01165         proc_ar->obj = NULL;
01166         proc_ar->proc = NULL;
01167         list_fini(&proc_ar->block_ar);
01168         proc_ar->retval = NULL;
01169         run_proc_ar_delete(proc_ar);
01170 }
01171 
01172 
01184 void run_proc_ar_set_args(run_t *run, run_proc_ar_t *proc_ar, list_t *arg_vals)
01185 {
01186         stree_ctor_t *ctor;
01187         stree_fun_t *fun;
01188         stree_prop_t *prop;
01189         list_t *args;
01190         stree_proc_arg_t *varg;
01191         stree_symbol_t *outer_symbol;
01192 
01193         run_block_ar_t *block_ar;
01194         list_node_t *block_ar_n;
01195         list_node_t *rarg_n, *parg_n;
01196         list_node_t *cn;
01197         rdata_item_t *rarg;
01198         stree_proc_arg_t *parg;
01199         rdata_var_t *var;
01200         rdata_var_t *ref_var;
01201         rdata_ref_t *ref;
01202         rdata_array_t *array;
01203         rdata_var_t *elem_var;
01204         int n_vargs, idx;
01205 
01206         (void) run;
01207 
01208         /* AR should have been created with run_proc_ar_create(). */
01209         assert(proc_ar->proc != NULL);
01210         outer_symbol = proc_ar->proc->outer_symbol;
01211 
01212         /* Make compiler happy. */
01213         args = NULL;
01214         varg = NULL;
01215 
01216         /*
01217          * The procedure being activated should belong to a member function or
01218          * property getter/setter.
01219          */
01220         switch (outer_symbol->sc) {
01221         case sc_ctor:
01222                 ctor = symbol_to_ctor(outer_symbol);
01223                 args = &ctor->sig->args;
01224                 varg = ctor->sig->varg;
01225                 break;
01226         case sc_fun:
01227                 fun = symbol_to_fun(outer_symbol);
01228                 args = &fun->sig->args;
01229                 varg = fun->sig->varg;
01230                 break;
01231         case sc_prop:
01232                 prop = symbol_to_prop(outer_symbol);
01233                 args = &prop->args;
01234                 varg = prop->varg;
01235                 break;
01236         case sc_csi:
01237         case sc_deleg:
01238         case sc_enum:
01239         case sc_var:
01240                 assert(b_false);
01241         }
01242 
01243         /* Fetch first block activation record. */
01244         block_ar_n = list_first(&proc_ar->block_ar);
01245         assert(block_ar_n != NULL);
01246         block_ar = list_node_data(block_ar_n, run_block_ar_t *);
01247 
01248         /* Declare local variables to hold argument values. */
01249         rarg_n = list_first(arg_vals);
01250         parg_n = list_first(args);
01251 
01252         while (parg_n != NULL) {
01253                 if (rarg_n == NULL) {
01254                         printf("Error: Too few arguments to '");
01255                         symbol_print_fqn(outer_symbol);
01256                         printf("'.\n");
01257                         exit(1);
01258                 }
01259 
01260                 rarg = list_node_data(rarg_n, rdata_item_t *);
01261                 parg = list_node_data(parg_n, stree_proc_arg_t *);
01262 
01263                 assert(rarg->ic == ic_value);
01264 
01265                 /* Construct a variable from the argument value. */
01266                 run_value_item_to_var(rarg, &var);
01267 
01268                 /* Declare variable using name of formal argument. */
01269                 intmap_set(&block_ar->vars, parg->name->sid, var);
01270 
01271                 rarg_n = list_next(arg_vals, rarg_n);
01272                 parg_n = list_next(args, parg_n);
01273         }
01274 
01275         if (varg != NULL) {
01276                 /* Function is variadic. Count number of variadic arguments. */
01277                 cn = rarg_n;
01278                 n_vargs = 0;
01279                 while (cn != NULL) {
01280                         n_vargs += 1;
01281                         cn = list_next(arg_vals, cn);
01282                 }
01283 
01284                 /* Prepare array to store variadic arguments. */
01285                 array = rdata_array_new(1);
01286                 array->extent[0] = n_vargs;
01287                 rdata_array_alloc_element(array);
01288 
01289                 /* Read variadic arguments. */
01290 
01291                 idx = 0;
01292                 while (rarg_n != NULL) {
01293                         rarg = list_node_data(rarg_n, rdata_item_t *);
01294                         assert(rarg->ic == ic_value);
01295 
01296                         run_value_item_to_var(rarg, &elem_var);
01297                         array->element[idx] = elem_var;
01298 
01299                         rarg_n = list_next(arg_vals, rarg_n);
01300                         idx += 1;
01301                 }
01302 
01303                 var = rdata_var_new(vc_array);
01304                 var->u.array_v = array;
01305 
01306                 /* Create reference to the new array. */
01307                 ref_var = rdata_var_new(vc_ref);
01308                 ref = rdata_ref_new();
01309                 ref_var->u.ref_v = ref;
01310                 ref->vref = var;
01311 
01312                 /* Declare variable using name of formal argument. */
01313                 intmap_set(&block_ar->vars, varg->name->sid,
01314                     ref_var);
01315         }
01316 
01317         /* Check for excess real parameters. */
01318         if (rarg_n != NULL) {
01319                 printf("Error: Too many arguments to '");
01320                 symbol_print_fqn(outer_symbol);
01321                 printf("'.\n");
01322                 exit(1);
01323         }
01324 }
01325 
01336 void run_proc_ar_set_setter_arg(run_t *run, run_proc_ar_t *proc_ar,
01337     rdata_item_t *arg_val)
01338 {
01339         stree_prop_t *prop;
01340         run_block_ar_t *block_ar;
01341         list_node_t *block_ar_n;
01342         rdata_var_t *var;
01343 
01344         (void) run;
01345 
01346         /* AR should have been created with run_proc_ar_create(). */
01347         assert(proc_ar->proc != NULL);
01348 
01349         /* The procedure being activated should belong to a property setter. */
01350         prop = symbol_to_prop(proc_ar->proc->outer_symbol);
01351         assert(prop != NULL);
01352         assert(proc_ar->proc == prop->setter);
01353 
01354         /* Fetch first block activation record. */
01355         block_ar_n = list_first(&proc_ar->block_ar);
01356         assert(block_ar_n != NULL);
01357         block_ar = list_node_data(block_ar_n, run_block_ar_t *);
01358 
01359         assert(arg_val->ic == ic_value);
01360 
01361         /* Construct a variable from the argument value. */
01362         run_value_item_to_var(arg_val, &var);
01363 
01364         /* Declare variable using name of formal argument. */
01365         intmap_set(&block_ar->vars, prop->setter_arg->name->sid, var);
01366 }
01367 
01374 void run_print_fun_bt(run_t *run)
01375 {
01376         list_node_t *node;
01377         run_proc_ar_t *proc_ar;
01378 
01379         printf("Backtrace:\n");
01380         node = list_last(&run->thread_ar->proc_ar);
01381         while (node != NULL) {
01382                 printf(" * ");
01383                 proc_ar = list_node_data(node, run_proc_ar_t *);
01384                 symbol_print_fqn(proc_ar->proc->outer_symbol);
01385                 printf("\n");
01386 
01387                 node = list_prev(&run->thread_ar->proc_ar, node);
01388         }
01389 }
01390 
01396 void run_block_ar_destroy(run_t *run, run_block_ar_t *block_ar)
01397 {
01398         map_elem_t *elem;
01399         rdata_var_t *var;
01400         int key;
01401 
01402         (void) run;
01403 
01404         elem = intmap_first(&block_ar->vars);
01405         while (elem != NULL) {
01406                 /* Destroy the variable */
01407                 var = intmap_elem_get_value(elem);
01408                 rdata_var_destroy(var);
01409 
01410                 /* Remove the map element */
01411                 key = intmap_elem_get_key(elem);
01412                 intmap_set(&block_ar->vars, key, NULL);
01413 
01414                 elem = intmap_first(&block_ar->vars);
01415         }
01416 
01417         intmap_fini(&block_ar->vars);
01418         run_block_ar_delete(block_ar);
01419 }
01420 
01430 void run_cvt_value_item(run_t *run, rdata_item_t *item, rdata_item_t **ritem)
01431 {
01432         rdata_value_t *value;
01433 
01434         /* 
01435          * This can happen when trying to use output of a function which
01436          * does not return a value.
01437          */
01438         if (item == NULL) {
01439                 printf("Error: Sub-expression has no value.\n");
01440                 exit(1);
01441         }
01442 
01443         /* Address item. Perform read operation. */
01444         if (item->ic == ic_address) {
01445                 run_address_read(run, item->u.address, ritem);
01446                 return;
01447         }
01448 
01449         /* Make a copy of the var node within. */
01450         value = rdata_value_new();
01451         rdata_var_copy(item->u.value->var, &value->var);
01452         *ritem = rdata_item_new(ic_value);
01453         (*ritem)->u.value = value;
01454 }
01455 
01465 var_class_t run_item_get_vc(run_t *run, rdata_item_t *item)
01466 {
01467         var_class_t vc;
01468         rdata_var_t *tpos;
01469 
01470         (void) run;
01471 
01472         switch (item->ic) {
01473         case ic_value:
01474                 vc = item->u.value->var->vc;
01475                 break;
01476         case ic_address:
01477                 switch (item->u.address->ac) {
01478                 case ac_var:
01479                         vc = item->u.address->u.var_a->vref->vc;
01480                         break;
01481                 case ac_prop:
01482                         /* Prefetch the value of the property. */
01483                         tpos = run_aprop_get_tpos(run, item->u.address);
01484                         vc = tpos->vc;
01485                         break;
01486                 default:
01487                         assert(b_false);
01488                 }
01489                 break;
01490         default:
01491                 assert(b_false);
01492         }
01493 
01494         return vc;
01495 }
01496 
01509 static rdata_var_t *run_aprop_get_tpos(run_t *run, rdata_address_t *addr)
01510 {
01511         rdata_item_t *ritem;
01512 
01513         assert(addr->ac == ac_prop);
01514 
01515         if (addr->u.prop_a->tvalue == NULL) {
01516                 /* Fetch value of the property. */
01517                 run_address_read(run, addr, &ritem);
01518                 assert(ritem->ic == ic_value);
01519                 addr->u.prop_a->tvalue = ritem->u.value;
01520                 addr->u.prop_a->tpos = addr->u.prop_a->tvalue->var;
01521         }
01522 
01523         return addr->u.prop_a->tpos;
01524 }
01525 
01534 void run_address_read(run_t *run, rdata_address_t *address,
01535     rdata_item_t **ritem)
01536 {
01537         (void) run;
01538         assert(ritem != NULL);
01539 
01540         switch (address->ac) {
01541         case ac_var:
01542                 rdata_var_read(address->u.var_a->vref, ritem);
01543                 break;
01544         case ac_prop:
01545                 run_aprop_read(run, address->u.prop_a, ritem);
01546                 break;
01547         }
01548 
01549         assert(*ritem == NULL || (*ritem)->ic == ic_value);
01550 }
01551 
01560 void run_address_write(run_t *run, rdata_address_t *address,
01561     rdata_value_t *value)
01562 {
01563         (void) run;
01564 
01565         switch (address->ac) {
01566         case ac_var:
01567                 rdata_var_write(address->u.var_a->vref, value);
01568                 break;
01569         case ac_prop:
01570                 run_aprop_write(run, address->u.prop_a, value);
01571                 break;
01572         }
01573 }
01574 
01583 static void run_aprop_read(run_t *run, rdata_addr_prop_t *addr_prop,
01584     rdata_item_t **ritem)
01585 {
01586         rdata_deleg_t *deleg;
01587         rdata_var_t *obj;
01588         stree_symbol_t *prop_sym;
01589         stree_prop_t *prop;
01590 
01591         run_proc_ar_t *proc_ar;
01592 
01593         rdata_var_t *cvar;
01594 
01595 #ifdef DEBUG_RUN_TRACE
01596         printf("Read from property.\n");
01597 #endif
01598         /*
01599          * If @c tvalue is present, we need to use the relevant part from that
01600          * instead of re-reading the whole thing.
01601          */
01602         if (addr_prop->tvalue != NULL) {
01603                 /* Copy the value */
01604                 rdata_var_copy(addr_prop->tpos, &cvar);
01605                 *ritem = rdata_item_new(ic_value);
01606                 (*ritem)->u.value = rdata_value_new();
01607                 (*ritem)->u.value->var = cvar;
01608                 return;
01609         }
01610 
01611         if (addr_prop->apc == apc_named)
01612                 deleg = addr_prop->u.named->prop_d;
01613         else
01614                 deleg = addr_prop->u.indexed->object_d;
01615 
01616         obj = deleg->obj;
01617         prop_sym = deleg->sym;
01618         prop = symbol_to_prop(prop_sym);
01619         assert(prop != NULL);
01620 
01621         if (prop->getter == NULL) {
01622                 printf("Error: Property is not readable.\n");
01623                 exit(1);
01624         }
01625 
01626         /* Create procedure activation record. */
01627         run_proc_ar_create(run, obj, prop->getter, &proc_ar);
01628 
01629         /* Fill in arguments (indices). */
01630         if (addr_prop->apc == apc_indexed) {
01631                 run_proc_ar_set_args(run, proc_ar,
01632                     &addr_prop->u.indexed->args);
01633         }
01634 
01635         /* Run getter. */
01636         run_proc(run, proc_ar, ritem);
01637 
01638         /* Destroy procedure activation record. */
01639         run_proc_ar_destroy(run, proc_ar);
01640 
01641 #ifdef DEBUG_RUN_TRACE
01642         printf("Getter returns ");
01643         rdata_item_print(*ritem);
01644         printf(".\n");
01645         printf("Done reading from property.\n");
01646 #endif
01647 }
01648 
01657 static void run_aprop_write(run_t *run, rdata_addr_prop_t *addr_prop,
01658     rdata_value_t *value)
01659 {
01660         rdata_deleg_t *deleg;
01661         rdata_var_t *obj;
01662         stree_symbol_t *prop_sym;
01663         stree_prop_t *prop;
01664 
01665         run_proc_ar_t *proc_ar;
01666         rdata_item_t *vitem;
01667         rdata_item_t *ritem;
01668 
01669 #ifdef DEBUG_RUN_TRACE
01670         printf("Write to property.\n");
01671 #endif
01672         /* If @c tvalue is present, we need to modify it and write it back. */
01673         if (addr_prop->tvalue != NULL) {
01674                 printf("Unimplemented: Read-modify-write property access.\n");
01675                 exit(1);
01676         }
01677 
01678         if (addr_prop->apc == apc_named)
01679                 deleg = addr_prop->u.named->prop_d;
01680         else
01681                 deleg = addr_prop->u.indexed->object_d;
01682 
01683         obj = deleg->obj;
01684         prop_sym = deleg->sym;
01685         prop = symbol_to_prop(prop_sym);
01686         assert(prop != NULL);
01687 
01688         if (prop->setter == NULL) {
01689                 printf("Error: Property is not writable.\n");
01690                 exit(1);
01691         }
01692 
01693         vitem = rdata_item_new(ic_value);
01694         vitem->u.value = value;
01695 
01696         /* Create procedure activation record. */
01697         run_proc_ar_create(run, obj, prop->setter, &proc_ar);
01698 
01699         /* Fill in arguments (indices). */
01700         if (addr_prop->apc == apc_indexed) {
01701                 run_proc_ar_set_args(run, proc_ar,
01702                     &addr_prop->u.indexed->args);
01703         }
01704 
01705         /* Fill in value argument for setter. */
01706         run_proc_ar_set_setter_arg(run, proc_ar, vitem);
01707 
01708         /* Run setter. */
01709         run_proc(run, proc_ar, &ritem);
01710 
01711         /* Setter should not return a value. */
01712         assert(ritem == NULL);
01713 
01714         /* Destroy procedure activation record. */
01715         run_proc_ar_destroy(run, proc_ar);
01716 
01717 #ifdef DEBUG_RUN_TRACE
01718         printf("Done writing to property.\n");
01719 #endif
01720 }
01721 
01730 void run_reference(run_t *run, rdata_var_t *var, rdata_item_t **res)
01731 {
01732         rdata_ref_t *ref;
01733         rdata_var_t *ref_var;
01734         rdata_value_t *ref_value;
01735         rdata_item_t *ref_item;
01736 
01737         (void) run;
01738 
01739         /* Create reference to the variable. */
01740         ref = rdata_ref_new();
01741         ref_var = rdata_var_new(vc_ref);
01742         ref->vref = var;
01743         ref_var->u.ref_v = ref;
01744 
01745         /* Construct value of the reference to return. */
01746         ref_item = rdata_item_new(ic_value);
01747         ref_value = rdata_value_new();
01748         ref_item->u.value = ref_value;
01749         ref_value->var = ref_var;
01750 
01751         *res = ref_item;
01752 }
01753 
01765 void run_dereference(run_t *run, rdata_item_t *ref, cspan_t *cspan,
01766     rdata_item_t **ritem)
01767 {
01768         rdata_item_t *ref_val;
01769         rdata_item_t *item;
01770         rdata_address_t *address;
01771         rdata_addr_var_t *addr_var;
01772 
01773 #ifdef DEBUG_RUN_TRACE
01774         printf("run_dereference()\n");
01775 #endif
01776         run_cvt_value_item(run, ref, &ref_val);
01777         if (run_is_bo(run)) {
01778                 *ritem = run_recovery_item(run);
01779                 return;
01780         }
01781 
01782         assert(ref_val->u.value->var->vc == vc_ref);
01783 
01784         item = rdata_item_new(ic_address);
01785         address = rdata_address_new(ac_var);
01786         addr_var = rdata_addr_var_new();
01787         item->u.address = address;
01788         address->u.var_a = addr_var;
01789         addr_var->vref = ref_val->u.value->var->u.ref_v->vref;
01790 
01791         rdata_item_destroy(ref_val);
01792 
01793         if (addr_var->vref == NULL) {
01794 #ifdef DEBUG_RUN_TRACE
01795                 printf("Error: Accessing null reference.\n");
01796 #endif
01797                 /* Raise Error.NilReference */
01798                 run_raise_exc(run, run->program->builtin->error_nilreference,
01799                     cspan);
01800                 *ritem = run_recovery_item(run);
01801                 return;
01802         }
01803 
01804 #ifdef DEBUG_RUN_TRACE
01805         printf("vref set to %p\n", addr_var->vref);
01806 #endif
01807         *ritem = item;
01808 }
01809 
01819 void run_raise_exc(run_t *run, stree_csi_t *csi, cspan_t *cspan)
01820 {
01821         rdata_item_t *exc_vi;
01822 
01823         /* Store exception cspan in thread AR. */
01824         run->thread_ar->exc_cspan = cspan;
01825 
01826         /* Create exception object. */
01827         run_new_csi_inst_ref(run, csi, sn_nonstatic, &exc_vi);
01828         assert(exc_vi->ic == ic_value);
01829 
01830         /* Store exception object in thread AR. */
01831         run->thread_ar->exc_payload = exc_vi->u.value;
01832 
01833         /* Start exception bailout. */
01834         run->thread_ar->bo_mode = bm_exc;
01835 }
01836 
01842 bool_t run_is_bo(run_t *run)
01843 {
01844         return run->thread_ar->bo_mode != bm_none;
01845 }
01846 
01858 void run_var_new(run_t *run, tdata_item_t *ti, rdata_var_t **rvar)
01859 {
01860         rdata_var_t *var;
01861 
01862         switch (ti->tic) {
01863         case tic_tprimitive:
01864                 run_var_new_tprimitive(run, ti->u.tprimitive, rvar);
01865                 break;
01866         case tic_tobject:
01867         case tic_tarray:
01868                 run_var_new_null_ref(run, rvar);
01869                 break;
01870         case tic_tdeleg:
01871                 run_var_new_deleg(run, rvar);
01872                 break;
01873         case tic_tebase:
01874                 /*
01875                  * One cannot declare variable of ebase type. It is just
01876                  * type of expressions referring to enum types.
01877                  */
01878                 assert(b_false);
01879         case tic_tenum:
01880                 run_var_new_enum(run, ti->u.tenum, rvar);
01881                 break;
01882         case tic_tfun:
01883                 run_var_new_deleg(run, rvar);
01884                 break;
01885         case tic_tvref:
01886                 /* 
01887                  * XXX Need to obtain run-time value of type argument to
01888                  * initialize variable properly.
01889                  */
01890                 var = rdata_var_new(vc_int);
01891                 var->u.int_v = rdata_int_new();
01892                 bigint_init(&var->u.int_v->value, 0);
01893                 *rvar = var;
01894                 break;
01895         case tic_ignore:
01896                 assert(b_false);
01897         }
01898 }
01899 
01909 static void run_var_new_tprimitive(run_t *run, tdata_primitive_t *tprimitive,
01910     rdata_var_t **rvar)
01911 {
01912         rdata_var_t *var;
01913 
01914         (void) run;
01915 
01916         /* Make compiler happy. */
01917         var = NULL;
01918 
01919         switch (tprimitive->tpc) {
01920         case tpc_bool:
01921                 var = rdata_var_new(vc_bool);
01922                 var->u.bool_v = rdata_bool_new();
01923                 var->u.bool_v->value = b_false;
01924                 break;
01925         case tpc_char:
01926                 var = rdata_var_new(vc_char);
01927                 var->u.char_v = rdata_char_new();
01928                 bigint_init(&var->u.char_v->value, 0);
01929                 break;
01930         case tpc_int:
01931                 var = rdata_var_new(vc_int);
01932                 var->u.int_v = rdata_int_new();
01933                 bigint_init(&var->u.int_v->value, 0);
01934                 break;
01935         case tpc_nil:
01936                 assert(b_false);
01937         case tpc_string:
01938                 var = rdata_var_new(vc_string);
01939                 var->u.string_v = rdata_string_new();
01940                 var->u.string_v->value = "";
01941                 break;
01942         case tpc_resource:
01943                 var = rdata_var_new(vc_resource);
01944                 var->u.resource_v = rdata_resource_new();
01945                 var->u.resource_v->data = NULL;
01946                 break;
01947         }
01948 
01949         *rvar = var;
01950 }
01951 
01957 static void run_var_new_null_ref(run_t *run, rdata_var_t **rvar)
01958 {
01959         rdata_var_t *var;
01960 
01961         (void) run;
01962 
01963         /* Return null reference. */
01964         var = rdata_var_new(vc_ref);
01965         var->u.ref_v = rdata_ref_new();
01966 
01967         *rvar = var;
01968 }
01969 
01975 static void run_var_new_deleg(run_t *run, rdata_var_t **rvar)
01976 {
01977         rdata_var_t *var;
01978 
01979         (void) run;
01980 
01981         /* Return null reference. */
01982         var = rdata_var_new(vc_deleg);
01983         var->u.deleg_v = rdata_deleg_new();
01984 
01985         *rvar = var;
01986 }
01987 
01993 static void run_var_new_enum(run_t *run, tdata_enum_t *tenum,
01994     rdata_var_t **rvar)
01995 {
01996         rdata_var_t *var;
01997         list_node_t *embr_n;
01998         stree_embr_t *embr;
01999 
02000         (void) run;
02001 
02002         /* Get first member of enum which will serve as default value. */
02003         embr_n = list_first(&tenum->enum_d->members);
02004         assert(embr_n != NULL);
02005 
02006         embr = list_node_data(embr_n, stree_embr_t *);
02007 
02008         /* Return null reference. */
02009         var = rdata_var_new(vc_enum);
02010         var->u.enum_v = rdata_enum_new();
02011         var->u.enum_v->value = embr;
02012 
02013         *rvar = var;
02014 }
02015 
02021 run_thread_ar_t *run_thread_ar_new(void)
02022 {
02023         run_thread_ar_t *thread_ar;
02024 
02025         thread_ar = calloc(1, sizeof(run_thread_ar_t));
02026         if (thread_ar == NULL) {
02027                 printf("Memory allocation failed.\n");
02028                 exit(1);
02029         }
02030 
02031         return thread_ar;
02032 }
02033 
02038 run_proc_ar_t *run_proc_ar_new(void)
02039 {
02040         run_proc_ar_t *proc_ar;
02041 
02042         proc_ar = calloc(1, sizeof(run_proc_ar_t));
02043         if (proc_ar == NULL) {
02044                 printf("Memory allocation failed.\n");
02045                 exit(1);
02046         }
02047 
02048         return proc_ar;
02049 }
02050 
02055 void run_proc_ar_delete(run_proc_ar_t *proc_ar)
02056 {
02057         assert(proc_ar != NULL);
02058         free(proc_ar);
02059 }
02060 
02066 run_block_ar_t *run_block_ar_new(void)
02067 {
02068         run_block_ar_t *block_ar;
02069 
02070         block_ar = calloc(1, sizeof(run_block_ar_t));
02071         if (block_ar == NULL) {
02072                 printf("Memory allocation failed.\n");
02073                 exit(1);
02074         }
02075 
02076         return block_ar;
02077 }
02078 
02084 void run_block_ar_delete(run_block_ar_t *block_ar)
02085 {
02086         assert(block_ar != NULL);
02087         free(block_ar);
02088 }

Generated on Thu Jun 2 07:45:42 2011 for HelenOS/USB by  doxygen 1.4.7