RSS Amplifier

Bit Maybe Wise · Mar 5, 2026

Tsonnet #32 - != done, but getting there

0
Sign in to vote or save

This page did not load. You can still read it on the original site — the toolbar below keeps your place in the directory.

Tsonnet gains a full set of binary operators

Welcome to the Tsonnet series!

If you’re not following along, check out how it all started in the first post of the series.

In the previous post, the equality operation was simplified:

Now, in order to complete the arithmetic tutorial, there’s a myriad of operations still left to be implemented. They are quite simple to add actually, so let’s do this ASAP!

a calculator sitting on top of a piece of paper
Photo by Joachim Schnürle on Unsplash

Operations everywhere!

Here are all the operations we are going to add to the lexer:

The parser changes are quite straightforward too:

I only had to introduce the new symbols we’d use for each operation.

The new AST variants:

The type checker changes are also straightforward:

What changes on evaluation?

The array concatenation was missing, so I added that:

The previous interpret_concat_op was renamed to be more specific: interpret_string_concat_op. A new function was added to handle the concatenation of arrays: interpret_array_concat_op.

We still don’t have one for objects, but we’ll get there eventually.

interpret_arith_op grew into a large matching function. It’s a lot of lines, but it’s easy to follow:

Most operations map directly to their OCaml equivalents. Equality we took care in the previous post. The exception is the comparison operators -- I had to abstract those under the Ast.Compare module:

Number comparisons work as you’d expect. Strings are compared by unicode codepoint order, which OCaml’s String.compare handles out of the box.

There’s also a new interpret_in_op that checks if a field is present in an object:

And the implementation:

We must pattern match on both String and Ident -- these are the two variants we use to define field names in objects, e.g. { a: 42 } or { "a": 42 }.

Verifying

New sample files:

Of course, I match each one with a cram test:

Conclusion

What looked like a mountain of work turned out to be quite mechanical -- once the scaffolding is in place, each new operator slotted in with minimal friction.

You can check the entire diff here.


Thanks for reading Bit Maybe Wise! If 'foo' in { foo: 1 } returns true for you too, subscribe.

Read on bitmaybewise.substack.com

Comments

Nothing yet. Say the first thing.

    Sign in to join the conversation.