JMPL Devlog #3

A For Effort

July 13th 2025

Tags:

C

JMPL

Programming Language


Time for another weeks update on my set-theoretic programming language JMPL! As always, new features are added to the wiki, whenever they are ready, so keep an eye out. This week I've been working on a feature missing from last weeks update, as well as a few optimisations to the interpreter.

Additionally, I've been doing a lot of language design, asking questions like 'how purely set theoretical should JMPL be?'. To help answer this, I've been reading up on the syntax of SETL, the first, and possibly the only, set theoretic language. SETL is interesting as it is an imperative language whereas set theory is more declarative. If a set theoretic language combines set theory and a programming language, SETL is more on the programming language side. This is what JMPL is too, but I'm working on ideas to change that. Ideally, a set-theoretic language would follow all the axioms of set theory, with all values being constructed out of sets. This is far from optimal, but it is a good place to start. My current thoughts are to incoporate more designs from functional languages like Haskell but for now I'll settle with adding more imperative features to allow JMPL to emulate any task another language could.

What's changed?

The main addition to JMPL this week is for loops. For loops allow sets to be iterated through with a variable. This is not possible using while loops as it is for tuples as sets have no indexable values.

let S = {1, 2, 3, 4, 5}

let sum = 0

for x ∈ S do

    sum := sum + x

out sum // 15

The value created by the loop can be used in the loop condition or its body, but it is discarded outside of the loop. For loops can also take an optional predicate to filter out values in the set.

let S = {1, 2, 3, 4, 5}

let sum = 0

for x ∈ S | x < 3 do

    sum := sum + x

out sum // 6

This syntax uses a vertical pipe ('|') to mean 'where', an idea borrowed from set-builder notation. For more examples of its use, check out the maps example in the JMPL repository.

Another feature I added was what I'm calling the 'omission operation' because I forgot real languages call it the range operation.

out {1 ... 5} // {1, 2, 3, 4, 5}

out {1, 3 ... 9} // {1, 3, 5, 7, 9}

out (5 ... 1) // (5, 4, 3, 2, 1)

This operation uses an ellipsis to represent omitted values in order to construct a larger structure. It has the syntax (first, next ... last) where next is optional. This can be used to construct sets and tuples, with the order mattering for tuples. For now, it only accepts integer values.

In addition to this, I added a few improvements and optimisations to the interpreter backend. Most importantly, I increased the amount of constants that can be in a single scope from 255 to 65535 - a major improvement. I also attempted to use computed gotos to speed up the execution of the interpreter's VM, but I found this change to have negligable impacts, so that's on the backburner for now.

What's next?

With the features from last week and this week, v0.2.0 has been completed! Next week (and the start of v0.2.1), I will be working on set-builder notation, nondeterminate set member access, and quantification.

© 2025 Joel Luckett. All rights reserved.