Refusing every defconst was right about the class and wrong about most of the instances. A constant the checker consumed - (defconst rows (/ h c)), which decides grid's type before anything else resolves - is in the shape of the program and no store can reach it. A constant that is only ever read at run time is just bytes in memory. sand's colors is the second kind, and tuning a colour table live is exactly the thing you would want a dev loop for. So a dev build emits every defconst as a mutable global rather than a constant. LLVM can then no longer fold a read of it and a module can store into it, and a changed one is published at the frame boundary the same way a new function body is. Release builds emit constant and get all the folding back. Tast.global.gfolded records which kind it is, because nothing downstream of the checker can tell: env.consts holds exactly the constants the folding pass consumed, and membership is the question "is this value in the program's shape?". The session keys its refusal on that, with a message that says what the constant is used for rather than just that it changed. Verified against a running sand: sim/colors is accepted, sim/rows is refused and says why.
Description
Languages
OCaml
67.2%
Emacs Lisp
15.2%
C
10.4%
HTML
2.9%
Standard ML
2.8%
Other
1.5%