Welcome to the Tsonnet series!
In the previous post, we added arithmetic operations:
The interpret_bin_op function was a bit ugly, plus we had a catch-all case on the pattern matching raising an exception for non-numeric expr.
Let's get going and wrap numerical types into a Number type — just like JSON.
The lexer does not need to change. The parser only needs to wrap INT and FLOAT in a Number:
The print function needs to match the Number too — it is getting annoying, but let's roll with it for now and sort it out next.
The interpret_bin_op is where the bulk of the changes are:
Now, I know what you're thinking — "That's a lot of pattern matching!" and yeah, it's not the prettiest code I've ever written. But here's why it's actually pretty cool:
We've isolated arithmetic operations into **interpret_bin_op** and got rid of the exception handling for non-numerical values
The pattern matching makes the code explicit (even if verbose)
Most importantly, we're following the single-responsibility principle — our numeric operations are now completely separate from other binary operations
This refactoring might seem like a lot of work for little gain, but trust me, it'll pay off when we start adding other binary operations like string concatenation. We can now pattern-match BinOp without touching our numeric operation logic at all. Clean separation of concerns!
In the next post, we'll tackle improving our JSON output presentation. But for now, pour yourself a drink and admire those clean-type boundaries we just created!