After loading emacs25 -nw (or just emacs, doesn't matter) and telling him to start slime (M-x slime), this is what i get.
The function SWANK/BACKEND::MAKE-AUTO-FLUSH-THREAD is undefined.
[Condition of type UNDEFINED-FUNCTION]
Restarts:
0: [CONTINUE] Retry calling SWANK/BACKEND::MAKE-AUTO-FLUSH-THREAD.
1: [USE-VALUE] Call specified function.
2: [RETURN-VALUE] Return specified values.
3: [RETURN-NOTHING] Return zero values.
4: [*ABORT] Return to SLIME's top level.
5: [ABORT] abort thread (#<THREAD "worker" RUNNING {1006CCF143}>)
Backtrace:
0: ("undefined function" #<SWANK/GRAY::SLIME-OUTPUT-STREAM
{10072A4F33}>)
--more--
However, if I the just press 3, it seems to work out and start what I want. I'd like to know what's going on tho, since it is a good idea in general.
Since you are using sbcl I find the following configuration works for me:
(setq inferior-lisp-program "/usr/bin/sbcl")
(load (expand-file-name "~/quicklisp/slime-helper.el"))
you wil need to install quicklisp and set sbcl as inferior-lisp.
follow Astray_BI's Blog
Related
According to this question, I can customize the variable *DEBUGGER-HOOK* so that it falls back to toplevel (in REPL) instead of the debugger. I've added this line to my ~/.sbclrc and it's all fine when I start sbcl from command line.
(setf *debugger-hook* #'(lambda (c h) (declare (ignore h)) (print c) (abort)))
But, the above doesn't work for Emacs SLIME. Whenever I compile/load a file (C-c C-k), it still invokes the debugger (with options like abort calculation, restart, enter new value etc.). How can I ask SLIME to just print the error message and throw me back to toplevel? Yea, it's with SBCL and the same ~/.sbclrc as before. Looks like SLIME doesn't respect a user's setting of *DEBUGGER-HOOK*.
As per http://common-lisp.net/project/slime/doc/html/Other-configurables.html setting SWANK:*GLOBAL-DEBUGGER* to nil in ~/.swank.lisp file should force SLIME to not replace *DEBUGGER-HOOK* to SWANK:SWANK-DEBUGGER-HOOK (which shows list of restarts etc.), but it somehow doesn't work for me, i.e. SWANK:*GLOBAL-DEBUGGER* is nil but anyway *DEBUGGER-HOOK* is replaced by SLIME. Maybe you'll be more lucky.
As a workaround I can propose to set *DEBUGGER-HOOK* to whatever you want in the slime-repl buffer manually, which is worked for me.
I'm in search for a better technique for doing it. My general struggle is with the fact that debugger enters either too late or too early to be able to catch the value of the variables.
What I tried first:
(loop for i from 0 to 10 do
(break))
When debugger enter on break, I can't access i :( So it's a wasted effort. I've tried e option of debugger (eval in frame), but SLIME generally just bugs out, and I have to reconnect to SWANK. v or t don't help, because the variable just "isn't there".
What I ended up doing:
(loop for i from 0 to 10 do
(signal i))
This is stupid, but works, because it puts i on the stack of the frame I can examine in debugger. But this is just... well, it's hackish in the worst sense of the word. Isn't there some way to "watch" a variable, or have a more meaningful way to put a breakpoint, such that I can see more variables around the place the breakpoint is entered?
Your first snippet works just fine for me with CCL (default optimize settings), Emacs 24, and a recently pulled Slime:
Break
[Condition of type SIMPLE-CONDITION]
Restarts:
0: [CONTINUE] Return from BREAK.
1: [RETRY] Retry SLIME REPL evaluation request.
2: [*ABORT] Return to SLIME's top level.
3: [ABORT-BREAK] Reset this thread
4: [ABORT] Kill this thread
Backtrace:
0: (#<Anonymous Function #x186F9B7E>)
Locals:
I = 0
1: (CCL::CHEAP-EVAL (LOOP FOR I FROM 0 TO 10 DO (BREAK)))
⋮
sldb-eval-in-frame works fine for me, too. Maybe you should try a different Lisp implementation or a different version of Slime.
Also, note that different optimize settings might be important here, and some implementations give better debugging results for interpreted code (if an interpreter is available, that is). Try something like (declaim (optimize (debug 3) (speed 0) (space 0))).
I'm using SLIME to debug my Common Lisp function. Inside the function, I've made it artificially signal an error (trying to "debug"—perhaps I should be stepping) like so:
(define-condition unknown-zone (error)
((text :initarg :text :reader text)))
(defun parse-mime-date (date)
(let ((last-space (position #\Space date :from-end t)))
(let ((date-time (net.telent.date:parse-time (subseq date 0 last-space)))
(zone (subseq date (1+ last-space))))
(unless (or (char= (elt zone 0) #\+)
(char= (elt zone 0) #\-))
(error 'unknown-zone :text (format nil "Unknown timezone: ~a" zone)))
(let ((hours (parse-integer (subseq zone 0 3)))
(minutes (parse-integer
(concatenate 'string
(list (elt zone 0))
(subseq zone 3)))))
(error 'unknown-zone :text "LOL")
(let ((adjusted-date-time (- date-time (* 60 (+ minutes (* 60 hours))))))
(format t "date-time: ~a; zone: ~a~%" date-time zone)
(format t "adjusted: ~a" (net.telent.date:universal-time-to-http-date adjusted-date-time)))))))
I'm trying to work around what appears to be a deficiency in net.telent.date:parse-time (it seems to botch up timezone handling, though I'm not 100% yet).
The "LOL" unknown-zone error is of course the artificial breakpoint.
When it hits this part of the function, SLDB faithfully opens up with the backtrace:
Bad type argument:
NS-MAIL2ZD::UNKNOWN-ZONE
[Condition of type SIMPLE-TYPE-ERROR]
Restarts:
0: [RETRY] Retry SLIME REPL evaluation request.
1: [*ABORT] Return to SLIME's top level.
2: [REMOVE-FD-HANDLER] Remove #<SB-IMPL::HANDLER INPUT on descriptor 7: #<CLOSURE (LABELS SWANK-BACKEND::RUN :IN SWANK-BACKEND:ADD-FD-HANDLER) {10030AD9FB}>>
3: [ABORT] Exit debugger, returning to top level.
Backtrace:
0: (MAKE-CONDITION NS-MAIL2ZD::UNKNOWN-ZONE :TEXT "LOL")
1: (ERROR NS-MAIL2ZD::UNKNOWN-ZONE :TEXT "LOL")
2: (NS-MAIL2ZD:PARSE-MIME-DATE "Wed, 14 Mar 2012 06:59:36 +1100")
3: (SB-INT:SIMPLE-EVAL-IN-LEXENV (NS-MAIL2ZD:PARSE-MIME-DATE *LOL*) #<NULL-LEXENV>)
4: (EVAL (NS-MAIL2ZD:PARSE-MIME-DATE *LOL*))
--more--
Then I page down to the frame:
Backtrace:
0: (MAKE-CONDITION NS-MAIL2ZD::UNKNOWN-ZONE :TEXT "LOL")
1: (ERROR NS-MAIL2ZD::UNKNOWN-ZONE :TEXT "LOL")
Locals:
SB-KERNEL::ARGUMENTS = (:TEXT "LOL")
SB-KERNEL::DATUM = NS-MAIL2ZD::UNKNOWN-ZONE
2: (NS-MAIL2ZD:PARSE-MIME-DATE "Wed, 14 Mar 2012 06:59:36 +1100")
Now I hit e to invoke sldb-eval-in-frame and type last-space, as that should be available where the error was signaled.
It seems this isn't how it's meant (?) to work:
The variable LAST-SPACE is unbound.
[Condition of type UNBOUND-VARIABLE]
Restarts:
0: [ABORT] Return to sldb level 1.
1: [RETRY] Retry SLIME REPL evaluation request.
2: [*ABORT] Return to SLIME's top level.
3: [REMOVE-FD-HANDLER] Remove #<SB-IMPL::HANDLER INPUT on descriptor 7: #<CLOSURE (LABELS SWANK-BACKEND::RUN :IN SWANK-BACKEND:ADD-FD-HANDLER) {10030AD9FB}>>
4: [ABORT] Exit debugger, returning to top level.
Backtrace:
0: ((LAMBDA (#:G1144)) #<unavailable argument>)
--more--
Is there a way to do what I want? Am I over-complicating matters?
Thanks!
Addendum: I've tried using (break) (this seems a tad more canonical), but I still can't see let-bound variables with e. :<
There is another option to debug a Lisp function: use an interpreter if available. Most implementations can switch between interpreted and compiled code. You could run all code compiled, but the function you want to debug could be running interpreted. In the extreme case you could even break into a stepper for the interpreted function (if available).
Note that it makes sense to define a default optimization setting based on your requirements.
don't set safety very low globally. Do that only in code sections where this is useful.
don't set speed very high globally. Do that only in code sections where this is useful.
keep debug information, use a setting of 2. Depending on the implementation a high debug setting may shut down tail call optimization (TCO) - which can be undesirable for execution and desirable for debugging.
I would propose different settings for:
development: safe + debug friendly
deployment: safe
optimization of numeric code, locally for speed
By default you should use a setting that is useful for interactive use:
speed 1-2. speed is somewhat important
safety 2-3. safety is very important. all operations are checked at runtime
debug 2-3. debug information is kept and the operations should be interruptible by a debugger.
space 1. The size of the code is not important.
compilation-speed 1. The speed of the compilation process is not so important.
The range is from 0 to 3. No number defaults to 3. 3 is higher.
Depending on the implementation there might be additional optimization settings and also some variables to configure the compiler.
In speed-critical sections you can set speed higher than safety and debug. But be aware that in some cases this changes the semantics of the code execution (error detection, overflows, ...) and that missing runtime checks may make it possible that your code corrupts the Lisp heap.
In some delivery situations it also may be useful to to have a very low debug setting. But if your Lisp compiler is set to high speed optimizations and low debug, debugging the code by looking at the backtrace of the stack may get much harder.
Try using the complete name of the symbol (i.e. package::symbol-name) instead of just the symbol name (i.e. symbol-name). In the current case, maybe net.telent.date::last-space.
Also make sure that you compiled with debugging support set to maximum (for instance, try placing a (declaim (optimize debug)) before your function and recompile the file - C-c C-k).
Checking that the code you're trying to debug has enough debug information: in the sldb window, put the cursor on the relevant line in the backtrace and press t - this should expand the frame and show values for all the locals. Pressing t again collapses the local frame information. If there is not enough debug information, you won't see the local variables, but some made up names (such as SB-DEBUG:ARG-0 under SBCL). Inside the sldb window, if you press Enter with the cursor on a value, it will expand that value into an inspector window (useful if the value is a long list which is shown truncated).
Also, SLIME debugging support seems to vary with the implementation. The advice above works on SBCL under Linux, YMMV under different implementations.
The variable seems to be optimized away. From the SBCL Manual:
The value of a variable may be unavailable for these reasons:
The value of the debug optimization quality may have omitted debug
information needed to determine whether the variable is available.
Unless a variable is an argument, its value will only be available
when debug is at least
The compiler did lifetime analysis and
determined that the value was no longer needed, even though its scope
had not been exited. Lifetime analysis is inhibited when the debug
optimization quality is
The variable’s name is an uninterned
symbol (gensym). To save space, the compiler only dumps debug
information about uninterned variables when the debug optimization
quality is
The frame’s location is unknown (see Section 5.3.5 [Unknown Locations and Interrupts], page 31) because the debugger was entered
due to an interrupt or unexpected hardware error. Under these
conditions the values of arguments will be available, but might be
incorrect. This is the exception mentioned above.
The variable (or
the code referencing it) was optimized out of existence. Variables
with no reads are always optimized away. The degree to which the
compiler deletes variables will depend on the value of the
compilation-speed optimization quality, but most source-level
optimizations are done under all compilation policies.
The variable is never set and its definition looks like (LET ((var1 var2)) ...) In this case, var1 is substituted with var2.
The variable is never set and is referenced exactly once. In this case, the reference is substituted with the variable initial value
You can see all available local variables with t.
If you add a reference to your variable after your error conditions, probably you'll be able to get its value in the corresponding debug frame.
I have installed LispBox on Windows and it's running great. I do however have some trouble with debugging code : when I try and compile code and it contains an error such as a syntax error, the error message output (printed below) is not very useful.
Serious errors encountered during compilation of
"d:/Jervis/Documents/Programming/LISP/hw1.lisp"
[Condition of type SIMPLE-ERROR]
0: (CCL::%COMPILE-FILE "d:/Jervis/Documents/Programming/LISP/hw1.lisp" "d:/Jervis/Documents/Programming/LISP/hw1.wx64fsl" T NIL T T NIL T :DEFER NIL #<BACKEND WIN64 #x21001C6FCD> :DEFAULT NIL 0)
1: (COMPILE-FILE #P"d:/Jervis/Documents/Programming/LISP/hw1.lisp" :OUTPUT-FILE #P"d:/Jervis/Documents/Programming/LISP/hw1.wx64fsl" :VERBOSE T :PRINT NIL :LOAD NIL :FEATURES NIL :TARGET :WIN64 :SAVE-LOC..
2: (SWANK-BACKEND:CALL-WITH-COMPILATION-HOOKS #<CCL:COMPILED-LEXICAL-CLOSURE (:INTERNAL SWANK-BACKEND:SWANK-COMPILE-FILE) #x2100C2730F>)
3: ((:INTERNAL SWANK:COMPILE-FILE-FOR-EMACS))
Does anyone know how to get the line number of the code that is causing the compilation errors?
I have tried to follow the advice here of opening the Compiler Input buffer but that did not work. (The buffer was unavailable, and thus couldn't be opened).
Any Ideas?
A clarification first: the *Compiler Input* buffer you mention has nothing to do with Common Lisp and Slime, it is about errors that Emacs encountered when compiling Emacs Lisp (its internal lisp, quite different from CL).
As for your problem (determining a file name/line number to narrow down the problem): when I enter a broken piece of code in a file (say test.lisp):
(defun fact (n)
(if (= 0 n)
1
!(* n (facto (1- n)))))
, then try to send it to CCL via Slime by pressing C-c C-k in the test.lisp buffer, I get an error and a list of restarts (below the list of restarts there's also a backtrace similar to what you got). Select restart 0 by pressing 0, then 'n' to not load the broken compiled file into CCL. The buffer with the error should be replaced with a buffer named *slime-compilation*, which in my case contains:
cd d:/tmp/lispbox-0.7/
2 compiler notes:
test.lisp:2:5:
warning: Extra arguments in (IF (= 0 N) 1 ! (* N (FACTO (1- N)))) don't match lambda list (CCL::TEST CCL:TRUE &OPTIONAL CCL:FALSE).
style-warning: Unused lexical variable N
Compilation failed.
, which looks like it's what you wanted.
My hand-installed Linux CL setup doesn't need selecting the 0 restart and there's also a slime setting to avoid the 'load fasl file anyway (y/n)' prompt, so the experience can get better with some customization.
I'm debugging my (Common) Lisp code in Slime tied to clisp.
When the debugger generates the Backtrace it's my understanting that I can hit 'v' on a frame to take me to the source.
However, when I do this on the any frame I get:
frame-source-location not implemented
Is this expected, am I missing anything?
Edit1: In addition every single frame has "No Locals", is this to be expected too?
Edit2: In fact, the whole backtrace output is pretty unintelligible. I'm new to Lisp, so I wasn't initially sure if this was expected or not - but I'm attaching a screenshot, hopefully someone can confirm for me if this looks 'normal':
Edit3 I'm guessing this is related
Since posting the question I have found this link which seems to indicate the Slime and clisp integration is not quite working as it should be.
So, in the meantime I have installed Steel Bank Common Lisp (sbcl), as easy as (on Ubuntu/Debian)
sudo apt-get install sbcl
and configured Slime to use that instead of clisp:
Snippet of my .emacs file:
;;; Lisp (SLIME) interaction
;;(setq inferior-lisp-program "clisp")
(setq inferior-lisp-program "sbcl")
This results in more pleasant debug output: