Skip to content

fix(dap): step-over treating TCO continuations as new calls#48

Merged
jig merged 1 commit into
developfrom
fix/dap-step-over
Apr 30, 2026
Merged

fix(dap): step-over treating TCO continuations as new calls#48
jig merged 1 commit into
developfrom
fix/dap-step-over

Conversation

@jig
Copy link
Copy Markdown
Owner

@jig jig commented Apr 30, 2026

Summary

Two bugs hit while smoke-testing the debugger from VSCode:

1) F10 acted like F11 (step-over entered every subform)

EVAL's TCO loop reuses the same Frame for do/let/if/fn-body and
re-enters the hook on the same Top() pointer. The PR2 step
controller paused whenever depth <= targetDepth, so it fired on
every TCO iteration — turning step-over into step-in.

Fix: snapshot the top frame at step time. Re-entries on that same
frame are TCO continuations and are skipped.

step-over: pause if Top() != stepFrame AND depth <= target
step-in:   pause if Top() != stepFrame
step-out:  pause if depth < target            (unaffected)

New regression test TestServer_StepOverSkipsTCOContinuation runs
(do 1 2 3 4) with stopOnEntry, sends one next, and asserts the
program terminates without pausing again.

2) VSCode reported "Configured debug type 'lisp' is not supported"

tools/vscode-lisp/package.json had activationEvents: ["onDebug", "onLanguage:lisp"]. onDebug activates after VSCode validates the
launch.json, which is too late. Switched to onDebugResolve:lisp and
onDebugDynamicConfigurations:lisp so the extension is up before
launch validation runs.

Re-package and re-install:

cd tools/vscode-lisp
npm run compile
npx @vscode/vsce package
code --install-extension vscode-lisp-0.1.0.vsix --force

Test plan

  • go build ./... and go build -tags lispdebug ./...
  • go test -tags lispdebug ./... — all green, including new regression
  • go vet ./... and go vet -tags lispdebug ./...
  • gofmt -l . clean
  • Manual: F5 in VSCode resolves debug type, breakpoint pauses,
    F10 steps over the form, F11 steps in. (Reviewer to verify.)

🤖 Generated with Claude Code

EVAL's TCO loop reuses the same Frame for `do`/`let`/`if`/fn-body and
re-enters the hook with the same `Top()` pointer. The previous step
controller looked only at depth, so step-over (`next`) paused on every
TCO iteration — making F10 behave indistinguishably from F11.

Snapshot the top-frame pointer at step time and treat re-entries on
that same frame as TCO continuations:

  - step-over pauses only when Top() != stepFrame and depth <= target
  - step-in   pauses only when Top() != stepFrame
  - step-out  unaffected (depth-only condition)

Also: vscode-lisp activationEvents needed `onDebugResolve:lisp` and
`onDebugDynamicConfigurations:lisp` to actually activate before VSCode
validates the launch.json — without them the user got
"Configured debug type 'lisp' is not supported".

New regression test: stepping over `(do 1 2 3 4)` with stopOnEntry now
runs the program to termination instead of pausing on every literal
subform.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
@jig jig merged commit 6d7479e into develop Apr 30, 2026
4 checks passed
@jig jig deleted the fix/dap-step-over branch April 30, 2026 19:58
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant