Exemplo n.º 1
0
VAL_LOC_T eval_dispatch(
    struct AstNode *node,
    struct Runtime *rt,
    struct SymMap *sym_map,
    struct AstLocMap *alm)
{
    /* It is possible that the debugger flag will change during evaluation. */
    bool debug_begin_called = false;

    VAL_LOC_T begin = rt->stack.top;

#if LOG_LEVEL <= LLVL_TRACE
    char *node_string = ast_serialize(node);
    LOG_TRACE("eval_impl BEGIN(%s)", node_string);
    mem_free(node_string);
#endif

    if (rt->debug) {
        dbg_call_begin(&rt->debugger, node);
        debug_begin_called = true;
    }

    switch (node->type) {
    case AST_SYMBOL:
        eval_symbol(node, rt, sym_map, alm);
        break;

    case AST_SPECIAL:
        eval_special(node, rt, sym_map, alm);
        break;

    case AST_FUNCTION_CALL:
        eval_func_call(node, rt, sym_map, alm);
        break;

    case AST_LITERAL_COMPOUND:
        eval_literal_compound(node, rt, sym_map, alm);
        break;

    case AST_LITERAL_ATOMIC:
        eval_literal_atomic(node, rt, sym_map, alm);
        break;
    }

    if (err_state()) {

        VAL_LOC_T ret_val = -1;
        if (debug_begin_called) {
            dbg_call_end(&rt->debugger, rt, ret_val, true);
        }

        err_push_src("EVAL", alm_try_get(alm, node), "Failed evaluating expression");
        LOG_TRACE("eval_impl END(error)");
        return ret_val;

    } else {

        if (debug_begin_called) {
            dbg_call_end(&rt->debugger, rt, begin, false);
        }

        LOG_TRACE("eval_impl END(result=%td)", begin);
        return begin;
    }
}
Exemplo n.º 2
0
FUNC bool duel_eval(tnode *n,tvalue *v)
{
   tvalue u,tmp ;
   bool ok=FALSE ;
   tnode *prev_loc ;

   if(!n) return FALSE ;
   prev_loc=duel_set_eval_loc(n);        /* set current eval node, save prev */
   if(n->eval.level==0) n->eval.level=1 ; /* indicate node is 'active' */

   switch(n->node_kind) {
      case NK_CONST: /* return a 'value' node made of this constant */
         if(n->eval.level==1) {
            n->eval.level=2 ;
            *v=n->cnst ;
            ok=TRUE ;
         }
      break ;
      case NK_NAME:
         if(n->eval.level==1) {
            n->eval.level=2 ;
            duel_eval_name(n->name,v);
            ok=TRUE ;
         }
      break ;
      case NK_OP:
         switch(n->op_kind) {
          case OPK_SUNARY:              /* special unary ops */
             if(n->op=='#') {
                 int count=0 ;
                 if(n->eval.level==1) {
                     while(duel_eval(n->kids[0],&u)) 
		       if(count++ == 0) duel_set_symb_val(v,"#/(%s ...)",&u,0);
		     if(count == 0) duel_set_symb_val(v,"#/(empty)",0,0);
                     v->val_kind=VK_RVALUE ;
                     v->ctype=ctype_int ;
                     v->u.rval_int=count ;
                     n->eval.level=2 ;
                     ok=TRUE ;
                 }
             }
             else 
             if(n->op==OP_AND) {
                 if(n->eval.level==1) { int result=1 ;
                     while(duel_eval(n->kids[0],v)) {
                         if(!duel_mk_logical(v,"&&/x")) {
                             stop_eval(n->kids[0]);
                             result=0 ;
                             break ;
                         }
                     }
                     v->val_kind=VK_RVALUE ;
                     v->ctype=ctype_int ;
                     v->u.rval_int=result ;
                     sprintf(v->symb_val,"%d",result);
                     n->eval.level=2 ;
                     ok=TRUE ;
                 }
             }
             else 
             if(n->op==OP_OR) {
                 if(n->eval.level==1) { int result=0 ;
                     while(duel_eval(n->kids[0],v)) {
                         if(duel_mk_logical(v,"||/x")) {
                             stop_eval(n->kids[0]);
                             result=1 ;
                             break ;
                         }
                     }
                     v->val_kind=VK_RVALUE ;
                     v->ctype=ctype_int ;
                     v->u.rval_int=result ;
                     sprintf(v->symb_val,"%d",result);
                     n->eval.level=2 ;
                     ok=TRUE ;
                 }
             }
             else 
             if(n->op==OP_SIZ) {
                 if(n->eval.level==1) {
		     char *tname=n->kids[0]->ctype->name ;
                     duel_assert(n->kids[0]->node_kind==NK_CTYPE);
                     v->val_kind=VK_RVALUE ;
                     v->ctype=ctype_size_t ;
                     v->u.rval_size_t=n->kids[0]->ctype->size ;
                     n->eval.level=2 ; 
		     if(tname==NULL || *tname=='\0') tname="T" ; /* cheating */
		     sprintf(v->symb_val,"sizeof(%s)",tname);
                     ok=TRUE ;
                 }
             }
             else duel_assert(0);
          break ;
          case OPK_UNARY:
            if(!duel_eval(n->kids[0],v)) break ;
            duel_apply_unary_op(n->op,v);
            ok=TRUE ;
          break ;
          case OPK_POST_UNARY:
            if(!duel_eval(n->kids[0],v)) break ;
            duel_apply_post_unary_op(n->op,v);
            ok=TRUE ;
          break ;
          case OPK_BIN:    /* a+b, compute and hold a, iterate on b, redo a */
             while(n->eval.level==2 || duel_eval(n->kids[0],&n->eval.v1)) {
                n->eval.level=2 ;  /* left side active op in vals[0] */
                while(duel_eval(n->kids[1],&u)) {
                  tmp= n->eval.v1 ;  /* copy left val, it is destoryed*/
                  ok=duel_apply_bin_op(n->op,&tmp,&u,v);
                  if(ok) goto done;
                }
                n->eval.level=1 ;   /*left side val no longer valid, re-eval*/
             }
          break ;
          case OPK_SBIN:   /* a,b etc, special ops */
             ok=duel_eval_sbin(n,v) ;
          break ;
          case OPK_TRI: 
             ok=duel_eval_tri(n,v) ;
          break ;
          case OPK_QUAD: 
             ok=duel_eval_quad(n,v) ;
          break ;
          case OPK_CAST:
             duel_assert(n->kids[0]->node_kind==NK_CTYPE);
             if(!duel_eval(n->kids[1],v)) break ;
             duel_do_cast(n->kids[0]->ctype,v);
             ok=TRUE ;
          break ;
          case OPK_ASSIGN: 
             duel_gen_error("modified assignment is not supported yet",0);
          case OPK_FUNC: 
             ok=eval_func_call(n,v) ;
          break ;
          default: duel_assert(0);
         }
      break ;
      default: duel_assert(0);
   }
done:
   if(!ok) n->eval.level=0 ;  /* no other val available */
   duel_set_eval_loc(prev_loc);
   return ok ;
}