Tsonnet #27 - Consistency, consistency, consistency
The one where I reorganize function parameters and feel weirdly accomplished.
Welcome to the Tsonnet series!
If you’re not following the series so far, you can check out how it all started in the first post of the series.
In the previous post, I added comprehensive testing for object interpretation to prevent reference leaks:
This will be short and sweet post, so let’s get to it.
When I first wrote the type checking function, I made an innocent mistake by having the environment parameter in a different order in the translate function compared to the interpreter. It’s not a big deal, but consistency is important!
Yeah, I know what you’re thinking: “Is this really worth a whole post?”. We can argue that this is not a big deal, and in theory, it isn’t, but in practice it’s much more comfortable to work in a codebase where you get used to the pattern, and even better when they are replicated across multiple modules and functions. It just feels natural! Our brains just stop fighting the code.
Consistency, consistency, consistency!
Speaking of patterns -- this parameter ordering change is actually a small step toward a bigger goal. Eventually, I want to enforce better type checking in-between compiler phases: parsing -> scope validation -> type checking -> interpretation. As of now, we work with the same AST across multiple phases, but it would be nice to have intermediate representations between each step. This could help removing duplicated checks already present, and making invalid states unrepresentable.
But that’s a story for another day. Before doing such big refactoring, there’s something even more mundane that helps moving towards this goal: extracting error messages.
lib/error.ml:
See what I mean with the shared operation messages?! Those invalid_binary_op and invalid_unary_op strings appear in both the type checker and interpreter -- operations that should really only happen once, in a single compilation phase.
Now I can replace the hard-coded error messages everywhere:
Conclusion
That’s all for today! Nothing revolutionary, but these little improvements are making the codebase easier to navigate.
Now let me write down the ideas for a future refactoring.
The entire diff can be seen here.




