Table of Contents
The Debugger
When an error, a break or break-into-play brings one of the editor's
threads into the debugger, the editor keeps the thread there, waiting,
and shows the Debugger dock, beside the Output and REPL docks, as Godot's
editor shows its Debugger: the condition, the restarts, the thread's
stack, and for a frame chosen, its variables, its form and a field that
evaluates a form in it. The editor's threads are its REPLs', the Script
screen's, which evaluates with Control+Shift+E, and a playing game's; in
the pyssel program, every thread's.
CL-USER> (defun half (n) (/ n 0))
HALF
CL-USER> (half 4)
The Debugger dock then shows, its first frame chosen:
arithmetic error DIVISION-BY-ZERO signalled
Operation was (/ 4 0).
[Condition of type DIVISION-BY-ZERO]
0: [ABORT] Return to the Editor REPL.
1: [ABORT] abort thread (#<THREAD tid=143225 "pyssel REPL Editor" RUNNING {1202D68D53}>)
0: (SB-KERNEL::INTEGER-/-INTEGER 4 0) SB-KERNEL::X = 4
1: (SB-INT:SIMPLE-EVAL-IN-LEXENV (HALF 4) #<NULL-LEXENV>) SB-KERNEL::Y = 0
2: (EVAL (HALF 4))
3: (PYSSEL/EDITOR::EVALUATE-REPL-INPUT "(half 4)")
HALF has no frame of its own here, its call to / being its last.
The dock
Each thread in the debugger has a tab of its own, named after the thread, the newest shown, and the dock comes to the front as one comes. A tab shows:
- The condition, its report and its type.
- The restarts, a button each, as SLY lists them: pressing one lets
the thread go on with it, as ABORT returns to the REPL the input came
from, and CONTINUE from a
break. A restart that asks for values, asuse-value, reads them from the thread's query stream, which has none to give: the dock says so, and the thread waits on. - The backtrace, from the frame that called
errororbreak, the first hundred frames, More frames listing the next hundred. Choosing a frame shows its variables, those the compiler kept where it is, each value a link that inspects it; a link to its form, which opens its file in the Script screen at the form, as a double click on the frame does; and a field that evaluates a form in the frame, its variables visible, read in its function's package, its values shown under it. Compiled with(debug 3), a function keeps every variable. - Abandon the Game, for a game's thread: the game is let go, as the editor's dialog for a game that does not stop lets it go, so another may play, its thread waiting on until the editor closes.
The thread answers the dock itself, since a frame's variables and its
lexical environment are its thread's: the dock hands it what to do, and it
hands back what it found. An error or a break in what it does, as in a
form evaluated in a frame, brings it into the debugger again, a level
deeper, whose ABORT returns to the level before.
What goes where
- The REPL: an error waits in the dock, and its ABORT, Return to the
Editor REPL., says
; Evaluation aborted.in the transcript. The REPL dock's Interrupt button breaks into an input that runs on, as SLY's C-c C-c does. - The Script screen: an error evaluating a form waits in the dock, and its ABORT abandons the evaluation. Compiling reports its errors as notes, as before.
- A game: an error that reaches the debugger on the game's threads,
as one in the engine's own drawing, or
break-into-play, waits in the dock, the game's frames stopped meanwhile. An error in a node's callback stops the node, as before. - The editor's own render thread cannot wait, the dock being drawn on
it: its error is said in the Output dock, and it goes on by the restart
that skips the rest of the frame's drawing, or else returns from a
break, or aborts. - SLY: while a debugger is installed for the whole Lisp, as SLY's
while it is connected, errors go there instead, as they did before,
unless the editor's settings say otherwise:
(setf (editor-settings-external-debugger settings) nil).
Closing the editor lets every thread waiting in its debugger go by the
ABORT restart it came with, an abandoned game's among them.
with-editor-debugger brings the errors of every thread of the Lisp
that has no debugger of its own to the editor's dock while its body
runs, as the pyssel program does while the editor it opens is open:
(let ((editor (pyssel/editor:edit "~/games/arena/")))
(pyssel/editor:with-editor-debugger (editor)
(pyssel:wait-for-stop (pyssel/editor:editor-engine editor))))
Inspecting
A value in the REPL, a frame's variable in the Debugger dock and a read-
only value in the Inspector dock are links that inspect them, as
inspect-value does from the REPL:
(pyssel/scene:call-in-tree
(pyssel/editor:editor-tree *editor*)
(lambda () (pyssel/editor:inspect-value *editor* (list 1 "two" :three))))
A node of the scene shown is selected, a playing game's node shown live,
and a resource shown with its properties, in the Inspector dock, as
before. Any other object shows there as its parts, as SLY's inspector
shows them, from object-parts: an instance's slots, a
list's or a vector's elements, a hash table's entries, a symbol's value
and function, and so on, the first 500, each value a link that inspects
it in turn. Back and Forward go through the objects shown, and the close
button shows the selected node again, as selecting a node does. A
playing game's objects, which the Inspector dock shows as the game's
thread printed them, it does not hold, and so does not inspect.
Thread rules
The Debugger dock is the editor's tree's, used on its thread. A thread in
the debugger waits on its own, doing what the dock asks of it, until a
restart is chosen; inspect-value is called on the editor's tree's
thread.
Getting started
The core
Drawing
Scenes
User interface
Games and the editor
- Playing a Game
- Projects
- The Editor
- The File System Dock
- The Script Screen
- The REPL
- The Debugger
- Lisp Text
- Code Services
- Project Manager
- Undo and Redo
- Exporting
The project