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; } }
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 ; }