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 /Makefile | |
| 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 'Makefile')
| -rw-r--r-- | Makefile | 11 |
1 files changed, 10 insertions, 1 deletions
@@ -71,6 +71,13 @@ EXPR_TEST := build/expr_test $(EXPR_TEST): tests/expr_test.c src/expr.c | build $(CC) $(CFLAGS) tests/expr_test.c src/expr.c -o $@ +# The real expression evaluator as a filter, so test_shadertoy.py can hold +# contrib/shadertoy.html's JavaScript to what the compiler actually does. +EXPR_EVAL := build/expr_eval + +$(EXPR_EVAL): tests/expr_eval.c src/expr.c | build + $(CC) $(CFLAGS) tests/expr_eval.c src/expr.c -o $@ + SHADER_TEST := build/shader_test $(SHADER_TEST): tests/shader_test.c src/shader.c src/screen.c src/json.c src/expr.c $(VT_LIB) | build @@ -93,13 +100,15 @@ build/exampleshader.so: contrib/shader-plugin/example.c src/shader_abi.h | build build/.pass-test_shader_plugin: build/testshader.so build/badshader.so \ build/exampleshader.so +build/.pass-test_shadertoy: $(EXPR_EVAL) contrib/shadertoy.html + build/.pass-%: tests/%.py tests/harness.py $(BIN) | build @cd tests && timeout 300 python3 $(notdir $<) > ../build/.log-$* 2>&1 \ || { echo "FAIL $(notdir $<)"; tail -25 ../build/.log-$*; exit 1; } @printf ' ok %-24s %s\n' "$(notdir $<)" "$$(grep -c '^ok' build/.log-$* 2>/dev/null || echo ?) checks" @touch $@ -test: $(BIN) $(TEST_BIN) $(KDL_TEST) $(SHADER_TEST) $(EXPR_TEST) ## unit + headless checks (fast) +test: $(BIN) $(TEST_BIN) $(KDL_TEST) $(SHADER_TEST) $(EXPR_TEST) $(EXPR_EVAL) ## unit + headless checks (fast) @./$(TEST_BIN) >/dev/null && ./$(KDL_TEST) >/dev/null && ./$(SHADER_TEST) >/dev/null \ && ./$(EXPR_TEST) >/dev/null \ && printf ' ok %-24s %s\n' "C unit tests" "4 binaries" |
