package typelang;
import static typelang.AST.*;
import static typelang.Heap.*;
import static typelang.Value.*;
import java.util.List;
import java.util.ArrayList;
import java.io.File;
import java.io.IOException;
import typelang.Env.*;
public class Evaluator implements Visitor
Printer.Formatter ts = new Printer.Formatter();
Env
Heap heap = new Heap16Bit(); //New for reflang
Value valueOf(Program p) {
return (Value) p.accept(this, initEnv);
}
@Override
public Value visit(AddExp e, Env
List
int result = 0;
for(Exp exp: operands) {
NumVal intermediate = (NumVal) exp.accept(this, env); // Dynamic type-checking
result += intermediate.v(); //Semantics of AddExp in terms of the target language.
}
return new NumVal(result);
}
@Override
public Value visit(UnitExp e, Env
return new UnitVal();
}
@Override
public Value visit(NumExp e, Env
return new NumVal(e.v());
}
@Override
public Value visit(StrExp e, Env
return new StringVal(e.v());
}
@Override
public Value visit(BoolExp e, Env
return new BoolVal(e.v());
}
@Override
public Value visit(DivExp e, Env
List
NumVal lVal = (NumVal) operands.get(0).accept(this, env);
double result = lVal.v();
for(int i=1; i
List
double result = 1;
for(Exp exp: operands) {
NumVal intermediate = (NumVal) exp.accept(this, env); // Dynamic type-checking
result *= intermediate.v(); //Semantics of MultExp.
}
return new NumVal(result);
}
@Override
public Value visit(Program p, Env
try {
for(DefineDecl d: p.decls())
d.accept(this, initEnv);
return (Value) p.e().accept(this, initEnv);
} catch (ClassCastException e) {
return new DynamicError(e.getMessage());
}
}
@Override
public Value visit(SubExp e, Env
List
NumVal lVal = (NumVal) operands.get(0).accept(this, env);
double result = lVal.v();
for(int i=1; i
// Previously, all variables had value 42. New semantics.
return env.get(e.name());
}
@Override
public Value visit(LetExp e, Env
List
List
List
for(Exp exp : value_exps)
values.add((Value)exp.accept(this, env));
Env
for (int index = 0; index < names.size(); index++)
new_env = new ExtendEnv
return (Value) e.body().accept(this, new_env);
}
@Override
public Value visit(DefineDecl e, Env
String name = e.name();
Exp value_exp = e.value_exp();
Value value = (Value) value_exp.accept(this, env);
((GlobalEnv
return new Value.UnitVal();
}
@Override
public Value visit(LambdaExp e, Env
return new Value.FunVal(env, e.formals(), e.body());
}
@Override
public Value visit(CallExp e, Env
Object result = e.operator().accept(this, env);
if(!(result instanceof Value.FunVal))
return new Value.DynamicError(“Operator not a function in call ” + ts.visit(e, null));
Value.FunVal operator = (Value.FunVal) result; //Dynamic checking
List
// Call-by-value semantics
List
for(Exp exp : operands)
actuals.add((Value)exp.accept(this, env));
List
if (formals.size()!=actuals.size())
return new Value.DynamicError(“Argument mismatch in call ” + ts.visit(e, null));
Env
for (int index = 0; index < formals.size(); index++)
fun_env = new ExtendEnv
return (Value) operator.body().accept(this, fun_env);
}
@Override
public Value visit(IfExp e, Env
Object result = e.conditional().accept(this, env);
if(!(result instanceof Value.BoolVal))
return new Value.DynamicError(“Condition not a boolean in expression ” + ts.visit(e, null));
Value.BoolVal condition = (Value.BoolVal) result; //Dynamic checking
if(condition.v())
return (Value) e.then_exp().accept(this, env);
else return (Value) e.else_exp().accept(this, env);
}
@Override
public Value visit(LessExp e, Env
Value.NumVal first = (Value.NumVal) e.first_exp().accept(this, env);
Value.NumVal second = (Value.NumVal) e.second_exp().accept(this, env);
return new Value.BoolVal(first.v() < second.v());
}
@Override
public Value visit(EqualExp e, Env
Value.NumVal first = (Value.NumVal) e.first_exp().accept(this, env);
Value.NumVal second = (Value.NumVal) e.second_exp().accept(this, env);
return new Value.BoolVal(first.v() == second.v());
}
@Override
public Value visit(GreaterExp e, Env
Value.NumVal first = (Value.NumVal) e.first_exp().accept(this, env);
Value.NumVal second = (Value.NumVal) e.second_exp().accept(this, env);
return new Value.BoolVal(first.v() > second.v());
}
@Override
public Value visit(CarExp e, Env
Value.PairVal pair = (Value.PairVal) e.arg().accept(this, env);
return pair.fst();
}
@Override
public Value visit(CdrExp e, Env
Value.PairVal pair = (Value.PairVal) e.arg().accept(this, env);
return pair.snd();
}
@Override
public Value visit(ConsExp e, Env
Value first = (Value) e.fst().accept(this, env);
Value second = (Value) e.snd().accept(this, env);
return new Value.PairVal(first, second);
}
@Override
public Value visit(ListExp e, Env
List
int length = elemExps.size();
if(length == 0)
return new Value.Null();
//Order of evaluation: left to right e.g. (list (+ 3 4) (+ 5 4))
Value[] elems = new Value[length];
for(int i=0; i
result = new PairVal(elems[i], result);
return result;
}
@Override
public Value visit(NullExp e, Env
Value val = (Value) e.arg().accept(this, env);
return new BoolVal(val instanceof Value.Null);
}
@Override
public Value visit(LetrecExp e, Env
List
List
List
for(Exp exp : fun_exps)
funs.add((Value.FunVal)exp.accept(this, env));
Env
return (Value) e.body().accept(this, new_env);
}
@Override
public Value visit(RefExp e, Env
Exp value_exp = e.value_exp();
Value value = (Value) value_exp.accept(this, env);
return heap.ref(value);
}
@Override
public Value visit(DerefExp e, Env
Exp loc_exp = e.loc_exp();
Value.RefVal loc = (Value.RefVal) loc_exp.accept(this, env);
return heap.deref(loc);
}
@Override
public Value visit(AssignExp e, Env
Exp rhs = e.rhs_exp();
Exp lhs = e.lhs_exp();
//Note the order of evaluation below.
Value rhs_val = (Value) rhs.accept(this, env);
Value.RefVal loc = (Value.RefVal) lhs.accept(this, env);
Value assign_val = heap.setref(loc, rhs_val);
return assign_val;
}
@Override
public Value visit(FreeExp e, Env
Exp value_exp = e.value_exp();
Value.RefVal loc = (Value.RefVal) value_exp.accept(this, env);
heap.free(loc);
return new Value.UnitVal();
}
public Value visit(EvalExp e, Env
StringVal programText = (StringVal) e.code().accept(this, env);
Program p = _reader.parse(programText.v());
return (Value) p.accept(this, env);
}
public Value visit(ReadExp e, Env
StringVal fileName = (StringVal) e.file().accept(this, env);
try {
String text = Reader.readFile(“” + System.getProperty(“user.dir”) + File.separator + fileName.v());
return new StringVal(text);
} catch (IOException ex) {
return new DynamicError(ex.getMessage());
}
}
private Env
GlobalEnv
/* Procedure: (read
List
formals.add(“file”);
Exp body = new AST.ReadExp(new VarExp(“file”));
Value.FunVal readFun = new Value.FunVal(initEnv, formals, body);
initEnv.extend(“read”, readFun);
/* Procedure: (require
formals = new ArrayList<>();
formals.add(“file”);
body = new EvalExp(new AST.ReadExp(new VarExp(“file”)));
Value.FunVal requireFun = new Value.FunVal(initEnv, formals, body);
initEnv.extend(“require”, requireFun);
/* Add new built-in procedures here */
return initEnv;
}
Reader _reader;
public Evaluator(Reader reader) {
_reader = reader;
}
}