block([expop], ...) raises a Lisp error and block([fpprec], ...) leaks the inner working precision
A block local with no initial value binds the variable to its own symbol. For an option variable that value is never valid, and the variable's assign hook is skipped, so derived internal state is neither set on entry nor restored on exit.
block([expop], expand((x+1)^3));
/* => Maxima encountered a Lisp error: The value $EXPOP is not of type REAL */
h(p) := block([fpprec : p], bfloat(1/3))$
block([], h(40), bfloat(1/3));
/* => 3.333333333333333b-1 correct */
block([fpprec], h(40), bfloat(1/3));
/* => 3.333333333333333333333333333333333333333b-1 WRONG */
bfloat(1/3);
/* => 3.333333333333333b-1 */
The two blocks differ only by the harmless-looking bare local fpprec, yet the second computes at 40 digits: h's inner block([fpprec:40], ...) set the internal precision through the assign hook, and restoring the outer binding never put it back.
Expected result: block([fpprec], ...) must behave like block([], ...) as far as the surrounding state goes, and block([expop], ...) must give a Maxima-level error (or bind expop to its current value) rather than a raw SBCL type error.
Detected by Claude.
I would think that calling the assign hook is the right thing to do. That way any constraints imposed on an ordinary assignment are also imposed on temporary assignments generated by
block. For the cases at hand (fpprecandexpop), that will makeblock([expop], ...)andblock([fpprec], ...)trigger errors -- I think that's right.