CS 214: Programming Languages
Spring 2009

Home|Syllabus|Schedule
<<|>>|ANTLR API|CITkit API|PolyD API|EasyMock API

Returning a String?
Interpreters, Iteration 14

Why Is the Result of Interpretation a String?

Because it was the easiest thing to return at the time.

HobbesInterpreter#interpret(ExpressionTIR) presently returns a String. One of the upcoming user stories will be to recursively evaluate operator expressions like 1 + 2 + 3. If the result of 1 + 2 is a String, how do you add "3" and new IntegerETIR(3)?

Sure, it can be done, but you already have code that adds IntegerETIRs. Wouldn't it be easier if 1 + 2 returned another IntegerETIR.

Yes, it would!

Chase the Compiler Errors

I'm not sure it matters if you change some computation code first or if you change tests instead. There's one really dramatic change that you'll be forced to deal with, so I'm suggesting that you start there:

Have HobbesInterpreter implement ExpressionTIRVisitor<ExpressionTIR> instead of ExpressionTIRVisitor<String>.

This will trigger a lot of incompatible-return-type errors since the methods implemented for that interface should now have a return type of ExpressionTIR.

Eclipse's Quick Fix will fix each problem for you, but you'll have to use it on each error. I find a copy-and-paste solution much easier. (Put the new return type into the clipboard.)

Fix these errors. Ignore any new errors.

You should have errors for interpreting integers, strings, and operator expressions. These errors are due to the computations themselves since they're computing Strings.

So consider, if your interpreter gets an IntegerETIR, what should it return? If it gets a StringETIR? Base cases are supposed to be this easy!

Fix the visitIntegerETIR() and visitStringETIR() methods.

So what about interpreting an OperatorETIR? Its visit method defers the computation to an OperatorAlgorithm, the compute() method of an OperatorAlgorithm (to be specific).

Change OperatorAlgorithm#compute(ExpressionTIR,ExpressionTIR) appropriately.

More errors!

The errors now revolve around the mock-object test in HobbesInterpreterTest and all of the OperatorAlgorithm subclasses.

It turns out that the OperatorAlgorithm subclasses are easier to fix for the compiler.

Change the return type of the compute(ExpressionTIR,ExpressionTIR) methods.

This does not end you work on these classes, and you'll be tempted to change more return types in them. Don't!

Instead, turn to the mock-object test. The complaint is that the expected return type from applying an operator algorithm has changed. Instead of some random String there, you need an ExpressionTIR. Yes, you could use some real ExpressionTIR object, but why start now? That test is already using mock objects, so what's one more!

In shouldInterpretOperatorExpression(), create a new local variable named result set to be a mock ExpressionTIR. Use that in the returned value from evaluating the operator algorithm and in the assertion.

Chasing Unit-Test Failures

I have one test passing! (It's the unit test using mock objects. Hmmmmm...)

Red bar.

Start with HobbesInterpreterTest since this will establish a pattern.

Look at the two failures from HobbesInterpreterTest. Why do they fail?

Keep in mind that assertEquals(Object,Object) takes any two Objects. It doesn't mind that the expected value is a String and the computed value is an ExpressionTIR. So all of the Strings in the assertions have to be changed to ExpressionTIRs.

Fix the assertions in HobbesInterpreterTest. Red bar (but green for HobbesInterpreterTest).

The operator algorithms are a bit more tricky. (They always are.) The problem is that the PolyD multiple-dispatch library is doing some type checking at runtime. And the remaining String return types are being detected when you run the tests.

The error message is a bit dense, so read it over to make sense of it.

Pick one of the operator algorithms.

Change the remaining String return types as appropriate. Change computations, too. Red bar.

Now you'll get failures (not errors) for the operator algorithm you're working on. Fix the assertions the same way you fixed the assertions in HobbesInterpreterTest.

Repeat for the other operator algorithms (one at a time).

Green bar!

Actually, everything is green.

Run your unit and acceptance tests. Green!