/******************************************************************************** * * File: eval.gen * The evaluation engine for the calculator * Programmer: Leonidas Fegaras, UTA * Date: 1/10/03 * ********************************************************************************/ abstract class Eval { static double error ( String msg, Ast x ) { System.out.println("*** Evaluation Error: " + msg + " " + x); return 0; } /* evaluate an expression e using a symbol table st */ static double eval ( Ast e, SymbolTable st ) { if (e instanceof Number) return (double) ((Number) e).value(); else if (e instanceof Real) return ((Real) e).value(); else if (e instanceof Astring) return error("Strings are not permitted",e); else if (e instanceof Variable) { Ast s = st.lookup(((Variable) e).value()); if (s == null) return error("Undefined variable",e); else if (s instanceof Real) return ((Real) s).value(); else return error("Name is not a variable",e); } else #case e | call_exp(`fnc,...args) => { double res; Ast s = st.lookup(((Variable) fnc).value()); if (s == null) return error("Undefined function",fnc); #case s | fnc_def(`body,...params) => { Arguments arguments = #[]; #for arg in args do arguments = arguments.append(new Real(eval(arg,st))); #end; if (params.length() != arguments.length()) return error("Wrong number of arguments",e); st.begin_scope(); /* extend the environment by binding parameters to arguments */ #for param in params do st.insert(((Variable) param).value(),arguments.head()); arguments = arguments.tail(); #end; /* evaluate the body under the new environment */ res = eval(body,st); /* remove the functions' parameters from the current environment */ st.end_scope(); return res; } | _ => return error("Name has not been defined as a function",fnc); #end; } | if_exp(`e1,`e2,`e3) /* if-then-else expression needs lazy evaluation */ => if (eval(e1,st) > 0) return eval(e2,st); else return eval(e3,st); | not(`u) => if (eval(u,st) > 0) return 0.0; else return 1.0; | `f(`e1,`e2) => { double left = eval(e1,st); double right = eval(e2,st); #case new Variable(f) | plus_exp => return left + right; | minus_exp => return left - right; | times_exp => return left * right; | div_exp => return left / right; | and_exp => return ((left>0) && (right>0)) ? 1 : 0; | or_exp => return ((left>0) || (right>0)) ? 1 : 0; | eq_exp => return (left == right) ? 1 : 0; | ne_exp => return (left != right) ? 1 : 0; | gt_exp => return (left > right) ? 1 : 0; | lt_exp => return (left < right) ? 1 : 0; | ge_exp => return (left >= right) ? 1 : 0; | le_exp => return (left <= right) ? 1 : 0; #end; } | _ => return error("Unrecognized expression",e); #end; return 0.0; } static SymbolTable symbol_table = new SymbolTable(); public static double evaluate ( Ast e ) { return eval(e,symbol_table); } /* assign value to the variable name */ public static void assign ( String name, double value ) { symbol_table.insert(name,new Real(value)); } /* define a new function */ public static void define ( String name, Arguments parameters, Ast body ) { symbol_table.insert(name,#); } }