si_set_finalizer is CL-world function and returns 0 values. That means
in particular, that env->nvalues is changed.
In this situation, when new binding was introduced, we could lose our
nvalues, what lead to invalid multiple-value-bind (next commit will
contain a regression test).
We use unprotected version. If interrupts cause problems with it, we
may need to wrap it in disable_interrupts. Threading code uses
ecl_set_finalizer_unprotected without such wrapping though, so I
believe that should be safe.
Fixes#233.
These two function are the same.
Here is my understanding: FEprogram_error_noreturn was introduced with
the noreturn function attribute in commit 7d9fb8bb because
FEprogram_error did not have this attribute. However, FEprogram_error
got the noreturn function attribute in commit 790d466c. Now there is
no reason to have both of these.
This removes FEprogram_error_noreturn and changes all calls to it
with calls to FEprogram_error instead.
This is for signalling an error about binding a constant variable.
This makes the error messages originally in commits 745686, c9e732
and 4e3283 more precise.
Commit 745686 prevents LET from binding constant variables, but this
sometimes caused a problem during "make check". The problem would
only happen sometimes, depending on the order in which the tests were
run. cmp.0026.defconstant-warn defines a constant variable named
FOO and cmp.0015.setf-expander binds FOO using LET. Now rename the
constant variable FOO to +FOO+.
"make check" runs fine
PROGV was allowed to bind constants in the C-compiler and the bytecode
compiler and interpreter, but the behavior would differ between them:
> (defun foo ()
(flet ((memq (item list) (member item list :test #'eq)))
(progv (list :test) (list :test-not)
(memq 'bar '(bar baz quux)))))
FOO
> (foo)
(BAZ QUUX)
> (compile 'foo)
FOO
> (foo)
(BAR BAZ QUUX)
CLHS says the behavior is undefined when attempting to bind or assign
constant variables (CLHS 3.1.2.1.1.3 and the entry for defconstant).
The C-compiler and bytecode compiler and interpreter give errors when
attempting to bind or assign constant variables in lambda expressions,
LET, SETQ and various other binding/assignment forms. So the behavior
above in PROGV is inconsistent.
Now give an error when attempting to bind a constant variable in PROGV
in the C-compiler and the bytecode compiler and interpreter.
M-V-B was allowed to lexically and dynamically bind constants in the
bytecode compiler and interpreter:
> (multiple-value-bind (pi rem) (truncate pi) pi)
3
CLHS says the behavior is undefined when attempting to bind or assign
constant variables (CLHS 3.1.2.1.1.3 and the entry for defconstant).
The C-compiler gives errors for these sorts of things, and the bytecode
compiler and interpreter gives errors when attempting to bind or assign
constant variables in lambda expressions, LET, SETQ and various other
binding/assignment forms. So the behavior above in M-V-B is
inconsistent with the C-compiler and other parts of the bytecode
compiler and interpreter.
Now give an error when attempting to bind a constant variable in M-V-B
in the bytecode compiler and interpreter.
LET/LET* were allowed to lexically and dynamically bind constants in
the bytecode compiler and interpreter:
> (let ((pi 3)) pi)
3
> (progn (defconstant +c+ 'foo) (let ((+c+ 'bar)) +c+))
BAR
> (flet ((hello () (format t "hi")))
(let ((t nil))
(declare (special t))
; Oops, now this returns a string
(hello)))
"hi"
Plus plenty of other ways to wreak havoc on unsuspecting code.
CLHS says the behavior is undefined when attempting to bind or assign
constant variables (CLHS 3.1.2.1.1.3 and the entry for defconstant).
(Well, CLHS 3.4.1 explicitly says that constant variables cannot be
used for variables in lambda lists.)
The C-compiler gives errors for these sorts of things, and the bytecode
compiler and interpreter gives errors when attempting to bind or assign
constant variables in lambda expressions, SETQ and various other forms.
So the behavior above in LET is inconsistent with both the C-compiler
and other parts of the bytecode compiler and interpreter.
Now give an error when attempting to bind a constant variable in
LET/LET* in the bytecode compiler and interpreter.
This also changes the behavior of PROG/PROG* and DESTRUCTURING-BIND so
that they give errors when attempting to bind constants as well.