diff options
| author | user <user@clank> | 2026-08-14 23:53:53 +0200 |
|---|---|---|
| committer | user <user@clank> | 2026-08-14 23:53:53 +0200 |
| commit | e16834a81a7111a4d954369af7e42601e0190a7f (patch) | |
| tree | 1326d53e05cf7cbe1bb1fd898b82bd9b72e11bfb /src/expr.c | |
| parent | sl0ppty: the graphics stream gives the cursor back (diff) | |
| download | slosh-e16834a81a7111a4d954369af7e42601e0190a7f.tar.gz slosh-e16834a81a7111a4d954369af7e42601e0190a7f.tar.xz slosh-e16834a81a7111a4d954369af7e42601e0190a7f.zip | |
contrib: a shadertoy for shader expressions
You cannot see an expression by reading it. `(y % 2) * 40` is scanlines and
`(x > cols - 10) * 120` is a right margin, and neither is obvious until it is
on a screen -- so here is a screen. One HTML file, no build and no server:
open it and it works, offline, including from a checkout on a machine that
has never run sl0ppty.
It draws a fake pane with plausible contents, applies a chain of passes to
every cell, and prints the config line to paste. The mouse moves the cursor,
so `dist(x, y, curx, cury)` behaves the way it will in a pane rather than the
way it does at coordinates you imagined. Anything reading `t` animates. The
presets are every built-in written as an expression, which is the equivalence
the whole design rests on: `vignette` and `spotlight` are not special, they
are `dim` with an argument.
It also reports what each expression *reads* and whether that makes it
cacheable, because the dependency analysis is the interesting half of the
implementation and is otherwise invisible.
The hazard is that this is a second implementation of the language, in
another language, and it would disagree with the compiler quietly -- in the
third digit of a colour, on one preset, at one cursor position. So
tests/test_shadertoy.py lifts the evaluator straight out of the page (not a
copy of it, the page itself) and runs a few hundred expression/environment
pairs through both it and src/expr.c, including the corners: division by
zero, the ternary's untaken branch, `dist` counting a row double, and six
expressions that both sides must refuse. build/expr_eval is the real compiler
as a filter, which is what makes that comparison possible at all.
It found a bug on its first run, in the page: unary `-` and `!` did not
thread the environment through their closures, so `!x` threw instead of
evaluating. Which is the argument for the test, made better than I could have
made it.
Skipped with a message when node is missing -- a checker for a contrib toy is
not a reason the suite cannot run.
Diffstat (limited to 'src/expr.c')
0 files changed, 0 insertions, 0 deletions
