A programming language whose source code falls down. You write it; gravity sorts it out. Whatever lands is the program.
A Liminal source file is a rectangle. Inside it: walls (#), wind
markers (> and <), pieces, and a
great deal of empty space.
Run it and the pieces fall. Each row drops in lockstep, one tick at a time, and stacks — a piece settles on a wall, on the floor, or on whatever came to rest beneath it. Nothing ghosts through. Letters pile into columns.
When everything has settled, the interpreter reads the grid from the bottom up. What you wrote
first lies lowest, so it runs first: source order survives by sinking. The whole settled grid
is the program, and every row shares one environment — a let low on
the grid is visible to a print above it. Only rows that begin with
let or print run; every other non-empty
row is inert data the grid holds for @[r, c] to read.
let x = 6 let y = 7 print x*y
| 0 | |||||||||
| 1 | |||||||||
| 2 | |||||||||
| 3 | |||||||||
| 4 | |||||||||
| 5 | |||||||||
| 6 |
Nothing below begins as code. Eight rows of letters scattered across their columns — each one drops straight down, and the floor assembles into a single statement. The arrangement looks like nothing; the landing reads as one line.
s
p u e
n o o
" t e
r t
t f i
o h "
i n| 0 | ||||||||||||||||||||||||
| 1 | ||||||||||||||||||||||||
| 2 | ||||||||||||||||||||||||
| 3 | ||||||||||||||||||||||||
| 4 | ||||||||||||||||||||||||
| 5 | ||||||||||||||||||||||||
| 6 | ||||||||||||||||||||||||
| 7 |
Gravity. Pieces fall. There is no opt-out.
Drift. <§drift=N §> gives a span N columns of horizontal
velocity per tick. The piece keeps falling; it just leans on the way down. Drift dies only when
a wall blocks the diagonal step while the drop straight down is still clear.
<§drift=-2 §>print "the whole line leans"
| 0 | |||||||||||||||||||||||||||||||||||||||||
| 1 | |||||||||||||||||||||||||||||||||||||||||
| 2 | |||||||||||||||||||||||||||||||||||||||||
| 3 | |||||||||||||||||||||||||||||||||||||||||
| 4 | |||||||||||||||||||||||||||||||||||||||||
| 5 | |||||||||||||||||||||||||||||||||||||||||
| 6 | |||||||||||||||||||||||||||||||||||||||||
| 7 | |||||||||||||||||||||||||||||||||||||||||
| 8 | |||||||||||||||||||||||||||||||||||||||||
| 9 |
Wind. A length-matched run of > (or
<) opens a field across the row. A piece crossing it catches one
tick of directional shove, then resumes its own affairs. Weather, briefly.
Walls. The # does not fall. It blocks pieces from
any direction, and the parser cannot see it. Scaffolding for a building the compiler never sees.
And @[r, c] evaluates to whatever character sits at row r,
column c once the dust settles. The grid is addressable; the program is its own data.
Liminal is not trying to replace anything. It is small on purpose and useless on purpose. Those are different things.
It is an argument, in working code, that source is a spatial artifact — that the column a character sits in is part of what it means, and execution order is a fact about geometry. Open the playground, drop a few statements, and watch them settle.