diff options
| author | user <user@clank> | 2026-08-16 16:16:19 +0200 |
|---|---|---|
| committer | user <user@clank> | 2026-08-16 16:16:19 +0200 |
| commit | a540b74dd3bb04d33a69219487cb2db32f2022f1 (patch) | |
| tree | 4e21d8c3cf739c0f9cd2e91983e23fd4e796cb63 /src/expr.c | |
| parent | sl0ppty: sin and cos (diff) | |
| download | slosh-a540b74dd3bb04d33a69219487cb2db32f2022f1.tar.gz slosh-a540b74dd3bb04d33a69219487cb2db32f2022f1.tar.xz slosh-a540b74dd3bb04d33a69219487cb2db32f2022f1.zip | |
sl0ppty: PI is 180
Angles here are degrees, and pi in an angle language is not a number -- it is a
half turn. So `PI` is 180, `TAU` is 360, and a formula written the radian way
ports across as written:
sin(TAU * x / cols) one cycle over the pane's width
sin(TAU * p * 3 / perim) three lobes fitted exactly to a border
PI / 2 a quarter turn
PI / 6 thirty degrees, exactly
That last line is the argument. A numeric pi would be 3 in this language, and
`3.14159 / 6` in integers is 0 -- so radians cannot express a sixth of a turn
here at all, while degrees give it as a whole number. The pun is not a
compromise; it is the more precise reading of the two.
Which is why there is no `deg2rad` or `rad2deg` beside them, and asking for one
says `unknown function`. There is one angle unit. A conversion could only lose
the angle (`deg2rad(90)` is 1, and `sin(1)` is nearly nothing) or invent a second
scale for the language to disagree with itself about.
Spelled-out numbers rather than variables: they read no environment, carry no
dependency, and fold into the program like the literals they are. The browser
preview learned the same two, from the same table.
Verified: 12 cases in `tests/expr_test.c`, including that `deg2rad` and
`rad2deg` are refused; the cross-check agrees with the compiler on 700
evaluations, now including `sin(TAU * x / cols)` and friends.
Two smaller things ride along, both from the repl. `PI`/`TAU` tab-complete, and
its drift test grew a third table to check -- it already caught `sin`/`cos`
missing before I did. And it now checks the script *parses* before starting a
pane that runs it: I broke the indentation of one line here, and the failure
arrived as `IndexError: list index out of range` from a pane that died before
its prompt, which is a long way from "line 212".
Diffstat (limited to 'src/expr.c')
| -rw-r--r-- | src/expr.c | 27 |
1 files changed, 27 insertions, 0 deletions
@@ -27,6 +27,28 @@ enum { enum { V_X, V_Y, V_COLS, V_ROWS, V_CURX, V_CURY, V_CURSOR, V_FOCUSED, V_T, V_SINCE }; +/* Angles are counted in degrees here (see `isin`), and pi is not a number in an + * angle language -- it is a half turn. So `PI` is 180 and `TAU` is 360, and a + * formula written the radian way ports across unchanged: `sin(TAU * x / cols)` is + * one cycle across the pane, `PI / 2` is a quarter turn, `PI / 6` is thirty + * degrees. It is also *more* exact than radians can be in integers, where + * 3.14159 / 6 is 0 and the common fractions of a turn are whole degrees. + * + * Which is why there is no `deg2rad` or `rad2deg` beside them. There is one angle + * unit and these are two of its landmarks; a conversion would have to either lose + * the angle (`deg2rad(90)` is 1, and `sin(1)` is nearly nothing) or invent a + * second scale for the language to disagree with itself about. + * + * Spelled-out numbers rather than variables: they read no environment, carry no + * dependency, and fold into the program like the literals they are. */ +static const struct { + const char *name; + int32_t value; +} CONSTS[] = { + {"PI", 180}, /* a half turn */ + {"TAU", 360}, /* ...and a whole one */ +}; + static const struct { const char *name; int slot; @@ -219,6 +241,11 @@ static void parse_primary(parser_t *ps, expr_prog_t *pr) { return; } + for (size_t i = 0; i < sizeof CONSTS / sizeof *CONSTS; i++) { + if (strcmp(CONSTS[i].name, name) != 0) continue; + emit(ps, pr, OP_PUSH, CONSTS[i].value); + return; + } for (size_t i = 0; i < sizeof VARS / sizeof *VARS; i++) { if (strcmp(VARS[i].name, name) != 0) continue; pr->deps |= VARS[i].dep; |
