Interpreter Project: Evaluating Expressions

Published on May 11, 2018

This is it... the guts of the interpreter are essentially done. The rest of the Lox language features will be adding to, refining and improving the existing code. Or so I believe. I can't imaging there is any other large piece of code to be added still though.

The current code can be seen here.

Overblown Calculator

It is satisfying to finally see some computation being done by the interpreter, even though it is essentially a calculator. It doesn't handle statements yet, so you can't declare a variable. Even if you could there is no environment to store the variable and its value.

There isn't much to say about the implementation. I stuck pretty close to the code in the tutorial.

I did add code to handle the comma and ternary operators that I added in the last sections challenge. The comma re-used the Ringo::Binary AST node class, so processing that amounted to adding another case statement to the visit_binary method.

visit_binary(binary)
  left = evaluate(binary.left)
  right = evaluate(binary.right)

  case binary.operator.type
  when :plus
    ...
  when :minus
    ...
  when :comma
    return right
  end
end

The comma operator evaluates each expression, one at a time, and throws away the results until it reaches the last expression on the right. That expression result is returned. Since the left and right expressions are evaluated at the top of the method all I had to do is return the right result.

The ternary operator was also easy enough to implement.

def visit_conditional(conditional)
  expr = evaluate(conditional.expression)

  return evaluate(conditional.then_branch) if is_truthy?(expr)
  return evaluate(conditional.else_branch)
end

First evaluate the first expression, that part before the ?. Then check if the result of that evaluation is true. If so evaluate the then_branch, otherwise evaluate the else_branch.

Moving Forward

The next section is about adding statements. That should add some keyword processing and the ability to create and reference variables. That also means maintaining an environment for the running code.