Contrasting interpreters: notes on porting jlox to Rust 01
Crafting Interpreters is really good. I’ve been working through it in Rust. Below are some notes from my campaign:
Consider jlox’s Expr
implementation:
abstract class Expr {
static class Binary {
Binary(Expr left, Token operator, Expr right) {
this.left = left;
this.operator = operator;
this.right = right;
}
final Expr left;
final Token operator;
final Expr right;
}
// ...
}
Implementing this in Rust (with static polymorphism) might look like this:
struct Binary<T, U> {
left: T,
operator: Token,
right: U,
}
impl<T, U> for Binary<T, U> {
pub fn new(left: T, operator: Token, right: U) -> Self {
Binary {
left,
operator,
right,
}
}
}
This differs from jlox’s implementation in a number of ways, notably: it is
generic over any type (T, U
) for left
and right
. Since Rust allows
bounds on generics, T
and U
can easily be restricted to
conform to an interface of our choosing later. In fact, trait bounds are
similar to how jlox gets around this problem in Java. To avoid having to modify
the implementation of each Expr
specialization, jlox uses the visitor
pattern; allowing an arbitrary number of new methods to be
implemented for each Expr
implementation.