There was in fact something wrong with every iteration of the comments
over the past 20 years. NS was right to want to make the XEP not
appear - XEPs are just the trampolines and showing them would make the
function appear twice. However, what actually inhibits the XEPs
appearance is always annotating tail-recursive *local calls* as tail,
even when it's non-returning, since XEPs local call the actual
function.
I think people got confused because of these two facets - there's the
XEP, as well as the main function. The XEP should always tail-call the
main function because we don't want it to show up in the backtrace
unless there's an actual error happening within the XEP (think
optional processing problems etc).
Also remove ALLOW-NON-RETURNING-TAIL-CALL. Not only is the function it
was originally written for gone, but it was inherently bogus: It
achieved function frame disappearance by making all non-returning
calls tail calls, even when they aren't in tail position. If the
intention is just to make the function not appear in the backtrace,
the debugger already has a facility to do that. Functions that just
call error do not need TCO per se, because, well, they aren't going to
consume more stack frames and don't need to be fast. Create a macro
helper to express the intent more clearly. We also avoid scanning
every single node in the component during tail annotation.
Also, some non-trivial functions were wrongly annotated with
ALLOW-NON-RETURNING-TAIL-CALL, hiding potentially useful local
variables. So, don't make those error wrappers.
The following categories of tests are not expected behaviors,
or would be "nice to have but can't" in the interpreter:
- explicitly unsafe code to explore edge cases
- inlining, use of compiler-macros
- non-consing (especially dx allocation)
A few places that appeared to assume that EVAL meant "compile"
are changed to call COMPILE.
The test driver will cons :INTERPRETER onto *FEATURES* around
each test file when actually interpreting, so that tests can
use :SKIPPED-ON instead of testing SB-EXT:*EVALUATOR-MODE*.
After this, an almost-fully-passing run of tests is possible
in the new interpreter; not nearly so in sb-eval though.
This was potentially called by each use of a destructuring-bind,
and the theory was that it was cheaper than passing keyword arguments.
This is no longer true, and it's not worth having another random
error-signaling function just to convert positional to keyword args
in at most two places.
Incidentally, the declaration in 'fndb' without SB!KERNEL:: was bogus.
Mostly resembling the patch mailed to the group, with changes
per review: a rename or two plus lots more commentary.
The tests in lambda-list have been upgraded to test their
inputs two ways: using the AST matcher (a predicate that just
returns T/NIL), and a function that parses without pre-testing
for validity and which signals TYPE-ERROR at any point.
As this seems to be a point of confusion, we'll issue a style-warning
if it looks like a constant default form in &OPTIONAL / &KEY won't match
the destructuring pattern for which it provides the default.
- &OPTIONAL with no variables when unparsing a ds-lambda-list matters.
Otherwise the lambda list (A &OPTIONAL ((&OPTIONAL))) - which is merely "weird"
turns into (A &OPTIONAL (())) which is not only weird, but illegal,
because () is another spelling for NIL, and NIL is a constant.
The former lambda list takes 1 or 2 arguments. The 2nd argument, if supplied,
must be NIL, because it binds to a lambda that accepts zero things.
- Add DS-LAMBDA-LIST-SYMBOLS which extracts all bound symbols.
Also use :ACCEPT, not :CONTEXT, to check if dotted tail is allowed;
and prefer LOGTEST to LOGBITP except for testing whether the
current state is in a set of states. No behavior change.
And return one fewer value from PARSE-LAMBDA-LIST since &MORE
can not co-occur with &REST; and unparse macro lambda lists
losslessly by distinguishing &BODY from &REST.
Several tests were passing implicitly compiled lambdas, for lack of
a quote, which was a no-op at the explicit COMPILE, and one can imagine
that in some scenario the effect would not be precisely the same,
although in every case here it was in fact the same.
It was done at once before all other bindings were processed, while it
should be just after the binding to which supplied-p is related is
bound.
Fixes lp#721135.
Add an interpreting EVAL, for cases where the compiler is
unsuitable due to e.g. compilation overhead.
* The old EVAL is still the default. To use the new one,
(SETF SB-EXT:*EVALUATOR-MODE* :INTERPRET).
Making the interpreter the default might be the purer
choice, since there's a standard way of ensuring that code
is compiled, and no standard way of ensuring that it's
not. On the other hand, there are practical reasons for
keeping the compiler as the default. The interpreter is very
slow, doesn't have proper debugger support (either for
backtraces or inspecting frames), and it doesn't have
stepper support.
* The interpreter doesn't treat THE or type declarations for
lexical variables as assertions. The regression tests that
assume otherwise have been disabled when running in
interpreted mode. The intepreter will however type-check the
proclaimed types of specials.
* Order of &AUX vs. &KEY/&REST in destructuring
lambda lists, check for multiple &optional, etc.
* Resignal errors from macroexpansion before converting
to COMPILED-PROGRAM-ERROR so that user code that
wants to handle them can.