We have not yet discussed how to use visitors to implement methods that take arguments in addition to the receiver (visitor host). We can illustrate this use of visitors by extending our previous example to include variables in the type ArithExpr. To accommodate variables, our composite hierarchy must include an additional concrete variant:
class Var extends ArithExpr {
String name;
Var(String n) {
name = n;
}
public String toString() {
return name;
}
int apply(Visitor v) {
return v.forVar(this);
}
}
Then the visitor interface for ArithExprs with variables has the form:
interface Visitor {
int forConst(Const c);
int forSum(Sum c);
int forNeg(Neg n);
int forVar(Var v);
}
The concrete visitor class that implements expression evaluation is:
class EvalVisitor implements Visitor {
Env env; // an environment for looking up variables
EvalVisitor(Env e) { env = e; }
public int forConst(Const c) { return c.getValue(); }
public int forSum(Sum s) {
return (s.getLeft().apply(this)).getValue()) +
(s.getRight().apply(this)).getValue());
}
public int forNeg(Neg n) {
return -(p.getArg());
}
int forVar(Var v) { return env.lookup(v.name); }
}
The environment env, which was an explicit parameter of the
eval method in our method-based implementation for
evaluation, is now a field of the visitor. As before, it is directly
used only for evaluating instances of Var, but now we
don't need to explicitly pass the environment through method argument
lists.
Since we are programming in a functional style, the forConst method only needs to return its argument as the result, rather than allocating a copy. The forSum and forNeg methods are straightforward, evaluating their subexpressions first and applying the appropriate arithmetic operation to the results.
The forVar method looks up the value of the variable in the current environment. The environment is passed in when an EvalVisitor is created, and is presumably given bindings for the existing variables beforehand.
Finger Exercise
Finish the visitor-based implementation of expression evaluation,
including the definition of the
Environment class, by yourself. Can you think of other
operations on expressions that the visitor pattern might helper you
implement?