Every function in the Cantor language takes exactly one natural number as its argument. Real programs, however, often need to pass two or more values at once — think addition, which needs both anDocumentation Index
Fetch the complete documentation index at: https://mintlify.com/felipenugo/cantor-interpreter/llms.txt
Use this file to discover all available pages before exploring further.
x and a y. The solution is Georg Cantor’s pairing function: a mathematical bijection that encodes any two natural numbers into a single natural number, losslessly. The Cantor Interpreter relies on this encoding everywhere: from the CLI’s input pipeline all the way down to how built-ins like add and mul unpack their arguments at runtime.
What is Cantor pairing?
Cantor’s pairing functionπ: ℕ × ℕ → ℕ is a bijection — a perfect one-to-one mapping from pairs of natural numbers to natural numbers. Every pair (x, y) maps to a unique natural number, and every natural number maps back to exactly one pair. No information is lost, and no two distinct pairs share the same encoding.
The formula is:
(x + y) is called the diagonal of the pair. The function counts along successive diagonals of the ℕ × ℕ grid: the diagonal where x + y = 0 contains only (0, 0), the diagonal where x + y = 1 contains (1, 0) and (0, 1), and so on. Within each diagonal, pairs are ordered by increasing y.
Python implementation
The pairing helpers live insrc/cantor_stdlib.py and are the foundation every other stdlib function builds on.
Encoding: pi
Decoding: unpi
w from z using an integer square root, then computing the offset within that diagonal to separate x from y. Both operations use only integer arithmetic, so there is no floating-point rounding risk.
Round-trip example (from the test suite):
List encoding
Two numbers can be encoded withpi, but programs often need to pass three or more values (for example, a triple (a, b, c)). The interpreter handles this by folding the list right-to-left, nesting pairs:
pi_from_list
pi(3, 2) = ((3+2)(3+2+1))/2 + 2 = (5 × 6)/2 + 2 = 15 + 2 = 17pi(1, 17) = ((1+17)(1+17+1))/2 + 17 = (18 × 19)/2 + 17 = 171 + 17 = 188
unpi_list
unpi_list mirrors pi_from_list: it repeatedly splits off the head and recurses into the tail, stopping when the expected number of elements have been extracted. You must supply the correct count — if num_elements does not match what was originally encoded, the decoded values will be meaningless.
CLI input encoding
When you run a Cantor program from the command line and provide whitespace-separated numbers on stdin, the interpreter encodes them into a single natural number before calling the program’smain function.
parse_input_text
encode_input_text
encode_input_text is the single entry point the CLI uses. It parses the raw text into a list of integers with parse_input_text, then folds them into one number with pi_from_list.
Empty input — an empty string or only whitespace — encodes to
0. This is because pi_from_list([]) returns 0 by convention, and many Cantor programs treat 0 as a neutral or base value.Stdlib function summary
pi(x, y)
Encode two naturals as one:
((x+y)(x+y+1))/2 + y.unpi(z)
Decode one natural back to a pair
(x, y) using integer square root.pi_from_list(numbers)
Right-fold a list of naturals into one number by nesting
pi calls.unpi_list(z, n)
Recover a list of
n naturals from a single encoded value.parse_input_text(text)
Split a whitespace-separated string into a validated list of naturals.
encode_input_text(text)
Parse and encode stdin text into a single Cantor number for the interpreter.
How pairing enables n-ary functions
Becauseπ is a bijection, any function f(x, y) can be reimplemented as f'(z) where z = π(x, y). The function body simply calls unpi(z) to recover (x, y). This is exactly what every arithmetic built-in does:
pair combinator in the language itself is what constructs encoded pairs at the language level:
pair id k_1 applied to n yields π(n, 1), which can then be passed to add to compute n + 1.
Worked example: suma.cantor with input 3 2
The program tests/programs/phase1-core/suma.cantor is a single line:
"3 2" goes through these steps:
Step 1 — Encode the input.
17 is passed to main.
Step 2 — Execute add(17).
3, 2 → π → 17 → unπ → 3, 2 → add → 5 demonstrates the full encoding lifecycle in one minimal program.
Further reading
Built-in Functions
Reference for all seven built-ins (
k_1, id, add, mul, diff, fst, snd) that consume encoded pairs.Language Reference
How
pair, comp, compair, mu, and primrec wire functions together using the pairing model.