double eval(struct ast *a) { double v; if(!a) { // default value return 0.0; } switch(a->nodetype) { // constant number case 'K': v = ((struct numval *)a)->number; break; // name reference case 'N': v = ((struct symref *)a)->s->value; break; // assignment case '=': v = ((struct symasgn *)a)->s->value = eval(((struct symasgn *)a)->v); break; // expressions case '+': v = eval(a->l) + eval(a->r); break; case '-': v = eval(a->l) - eval(a->r); break; case '*': v = eval(a->l) * eval(a->r); break; case '/': v = eval(a->l) / eval(a->r); break; case '|': v = fabs(eval(a->l)); break; case 'M': v = -eval(a->l); break; // comparisons case '1': v = (eval(a->l) > eval(a->r))? 1 : 0; break; case '2': v = (eval(a->l) < eval(a->r))? 1 : 0; break; case '3': v = (eval(a->l) != eval(a->r))? 1 : 0; break; case '4': v = (eval(a->l) == eval(a->r))? 1 : 0; break; case '5': v = (eval(a->l) >= eval(a->r))? 1 : 0; break; case '6': v = (eval(a->l) <= eval(a->r))? 1 : 0; break; // if flow case 'I': if( eval( ((struct flow *)a)->cond) != 0) { if( ((struct flow *)a)->tl) { // else branch if exists v = eval( ((struct flow *)a)->tl); } else { v = 0.0; // default value } } else { if( ((struct flow *)a)->el) { // if branch if exists v = eval(((struct flow *)a)->el); } else { v = 0.0; // default value } } break; case 'W': // while flow v = 0.0; /* default value */ if( ((struct flow *)a)->tl) { while( eval(((struct flow *)a)->cond) != 0) { // loop v = eval(((struct flow *)a)->tl); } } break; // last value is the value returned // define user function case 'L': eval(a->l); v = eval(a->r); break; // call built-in function case 'F': v = callbuiltin((struct fncall *)a); break; // call user-defined function case 'C': v = calluser((struct ufncall *)a); break; // error default: printf("internal error: bad node %c\n", a->nodetype); } return v; }
double eval(struct pcdata *pp, struct ast *a) { double v; if(!a) { yyerror(pp, "internal error, null eval"); return 0.0; } switch(a->nodetype) { /* constant */ case 'K': v = ((struct numval *)a)->number; break; /* name reference */ case 'N': v = ((struct symref *)a)->s->value; break; /* assignment */ case '=': v = ((struct symasgn *)a)->s->value = eval(pp, ((struct symasgn *)a)->v); break; /* expressions */ case '+': v = eval(pp, a->l) + eval(pp, a->r); break; case '-': v = eval(pp, a->l) - eval(pp, a->r); break; case '*': v = eval(pp, a->l) * eval(pp, a->r); break; case '/': v = eval(pp, a->l) / eval(pp, a->r); break; case '|': v = fabs(eval(pp, a->l)); break; case 'M': v = -eval(pp, a->l); break; /* comparisons */ case '1': v = (eval(pp, a->l) > eval(pp, a->r))? 1 : 0; break; case '2': v = (eval(pp, a->l) < eval(pp, a->r))? 1 : 0; break; case '3': v = (eval(pp, a->l) != eval(pp, a->r))? 1 : 0; break; case '4': v = (eval(pp, a->l) == eval(pp, a->r))? 1 : 0; break; case '5': v = (eval(pp, a->l) >= eval(pp, a->r))? 1 : 0; break; case '6': v = (eval(pp, a->l) <= eval(pp, a->r))? 1 : 0; break; /* control flow */ /* null if/else/do expressions allowed in the grammar, so check for them */ case 'I': if( eval(pp, ((struct flow *)a)->cond) != 0) { if( ((struct flow *)a)->tl) { v = eval(pp, ((struct flow *)a)->tl); } else v = 0.0; /* a default value */ } else { if( ((struct flow *)a)->el) { v = eval(pp, ((struct flow *)a)->el); } else v = 0.0; /* a default value */ } break; case 'W': v = 0.0; /* a default value */ if( ((struct flow *)a)->tl) { while( eval(pp, ((struct flow *)a)->cond) != 0) v = eval(pp, ((struct flow *)a)->tl); } break; /* last value is value */ case 'L': eval(pp, a->l); v = eval(pp, a->r); break; case 'F': v = callbuiltin(pp, (struct fncall *)a); break; case 'C': v = calluser(pp, (struct ufncall *)a); break; default: printf("internal error: bad node %c\n", a->nodetype); } return v; }
double eval(struct ast *a) { double v; /* calculated value of this subtree */ if(NULL == a) { yyerror("internal error, null eval"); return 0.0; } switch(a->nodetype) { case 'K': v = ((struct numval *)a)->number; break; case 'N': v = ((struct symref *)a)->s->value; break; case '=': v = ((struct symasgn *)a)->s->value = eval( ((struct symasgn *)a)->v ); break; case '+': v = eval(a->l) + eval(a->r); break; case '-': v = eval(a->l) - eval(a->r); break; case '*': v = eval(a->l) * eval(a->r); break; case '/': v = eval(a->l) / eval(a->r); break; case '|': v = fabs(eval(a->l)); break; case 'M': v = -eval(a->l); break; case '1': v = (eval(a->l) > eval(a->r)) ? 1 : 0; break; case '2': v = (eval(a->l) < eval(a->r)) ? 1 : 0; break; case '3': v = (eval(a->l) != eval(a->r)) ? 1 : 0; break; case '4': v = (eval(a->l) == eval(a->r)) ? 1 : 0; break; case '5': v = (eval(a->l) >= eval(a->r)) ? 1 : 0; break; case '6': v = (eval(a->l) <= eval(a->r)) ? 1 : 0; break; /* control flow */ case 'I': if( eval( ((struct flow *)a)->cond) != 0) { if( ((struct flow *)a)->tl ) { v = eval( ((struct flow *)a)->tl ); } else v = 0.0; } else { if( ((struct flow *)a)->el ) { v = eval( ((struct flow *)a)->el ); } else v = 0.0; } break; case 'W': v = 0.0; if( ((struct flow *)a)->tl ) { while( eval(((struct flow *)a)->cond) != 0) v = eval(((struct flow *)a)->tl); } break; case 'L': eval(a->l); v = eval(a->r); break; case 'F': v = callbuiltin( (struct fncall *)a ); break; case 'C': v = calluser( (struct ufncall *)a ); break; default: printf("internal error: bad node %c\n", a->nodetype); } return v; }