debugger: setVariable #38

Closed
opened 2026-10-05 21:07:13 +00:00 by orion · 7 comments
Collaborator

Context

A write through the same places variables reads.

Source

Acceptance criteria

  • DAP setVariable for locals and fields
  • A session in tests/debug/

Dependencies

None known.

Moved from the planning lists of the docs; the design record stays the specification.

## Context A write through the same places `variables` reads. ## Source - [DEBUGGER.md section 20](https://git.torb.dev/torbscript/language/src/commit/393ef2608e4a60b8ff76d8b6b408951b822d887d/docs/design/DEBUGGER.md#L415) ## Acceptance criteria - [ ] DAP `setVariable` for locals and fields - [ ] A session in `tests/debug/` ## Dependencies None known. _Moved from the planning lists of the docs; the design record stays the specification._
Author
Collaborator

[loop:torbscript] intake: in scope (author orion, label loop). Implements DEBUGGER.md section 20 (DAP setVariable for locals and fields); the design record is the specification, no collision with CONCEPT "Open Questions". Touches the debugger and tests/debug/, seed impact to be confirmed in refine. next: refine (queued)

[loop:torbscript] intake: in scope (author orion, label loop). Implements DEBUGGER.md section 20 (DAP `setVariable` for locals and fields); the design record is the specification, no collision with CONCEPT "Open Questions". Touches the debugger and `tests/debug/`, seed impact to be confirmed in refine. next: refine (queued)
Author
Collaborator

[loop:torbscript] refine: still queued behind the intake order. next: waiting (ready buffer full: #4, #163, #164, #223 are ready) until 2026-10-10T04:00:00Z

[loop:torbscript] refine: still queued behind the intake order. next: waiting (ready buffer full: #4, #163, #164, #223 are ready) until 2026-10-10T04:00:00Z
Author
Collaborator

[loop:torbscript] claim refine by session:loop-torbscript-20261017 until 2026-10-17T00:10:30Z

[loop:torbscript] claim refine by session:loop-torbscript-20261017 until 2026-10-17T00:10:30Z
Author
Collaborator

[loop:torbscript] decided by the loop: scope, design and acceptance criteria for setVariable (implements DEBUGGER.md section 20, item "setVariable"; no owner question applies, all of it is internal technical design).

Goal. The adapter answers the DAP request setVariable for the scalar locals and scalar fields the variables request shows, and announces supportsSetVariable: true. VS Code then offers "Set Value" in the Variables view.

What is written (decided, why).

  • Only scalar leaves: integers (any width, range-checked), floats, Bool, Char. Why: section 6 guarantees that a binding in sight holds a value it owns, borrows or is empty, and the ownership pass releases by reference count. Writing a String, list, map, case or a whole record would need allocation and count updates inside a stopped program, which section 12 rules out for evaluate and which is exactly what the open item "snippet evaluator" is for. Everything else answers success: false with a message naming what can be set (Only numbers, Bool and Char can be set).
  • Places: a local (register slot, or the address a var parameter holds), a field of a record, tuple or shared type object below it (inline in the registers, or in the counted block at pointer + 16), an item of a fixed array. Items of List, Map and Set and fields of a case payload are refused for now (the read side finds them through the runtime's iterators, not through a stable address); not a split issue, the refusal message says so and a later issue can lift it if wanted.
  • Input text: the literal grammar of the breakpoint condition (compiler/src/debugger/refinements.trb, section 12): 42, -1, 2.5, 'a', true, false; the text must fit the target type (300 into an UInt8 is refused, a float into an integer is refused). No expressions, nothing runs.
  • Design: Value gains place: Int (the address of its first word, 0 where it is a temporary or unknown); sliceOf, layoutChildren and the boxed contents derive child places from it; Referenced.Locals(frame) resolves a name to a slot place, Referenced.Children(value) to a child by name. The store is Machine.store (one word) or KernelOperation.NarrowStore for narrow container elements, both existing: no new native, no runtime change. After a write the adapter re-reads the words of every live variablesReference from its place so a re-fetch of the parent and of sibling views shows the new value (DAP clients re-request after setVariable).
  • Sharing: a boxed record may be shared by several bindings (count > 1), a write through one shows through the others. Documented in docs/tooling/torb-debug.md, as in every native debugger. Immortal or static blocks (constant data) must not be written to: the implementer checks how const origin = Point 1, 2 is allocated and refuses the write where the block is not an ordinary counted heap block; if refusal is needed, that is covered by criterion 5.

Seed. Does not touch the seed: no syntax change, no new native, no driver flag, no std name looked up by string (Machine.store and NarrowStore exist already). One commit feat(debugger): set a scalar variable from the editor including the docs, or two (feat + docs); no seed refresh.

Acceptance criteria (replace those of the body).

  1. initialize answers supportsSetVariable: true; setVariable with variablesReference of Locals changes a scalar local (Int, Float64, Bool, Char, a narrow UInt8) and answers value, type, variablesReference of the new value (DAP SetVariableResponse).
  2. The same for a scalar field of a record, a tuple field, a field of a shared type object and an item of a fixed array, reached through a Children reference; also a var parameter (written through its address).
  3. After the write, variables of the parent and of the containing value shows the new value, and the continued program uses it (print output in .expected shows the changed number).
  4. Refused with success: false and a message, program untouched: a non-scalar target (String, list, map, case, whole record), a value out of range or of the wrong kind (300 into UInt8, 2.5 into Int, abc), an unknown name, a stale or unknown reference, a call while the program runs (as variables is answered only at a stop).
  5. Writing into constant data (const origin = Point 1, 2 as in tests/debug/breakpoint/main.trb) does not crash the adapter or the debuggee: either it works on an ordinary heap block or it is refused with a message; the session pins whichever it is.
  6. A session tests/debug/set-variable.dap with set-variable/main.trb, .expected regenerated with sh tools/debug.sh --update (checked by hand), covering 1 to 4 (gate of tier A, tools/debug.sh); tools/conformance.sh --vm under TORB_VM_DEBUGGED=1 stays as it is (no change without a debugger).
  7. Docs: DEBUGGER.md section 20 loses the item and a short subsection (section 12 or 10) states the rules above; docs/tooling/torb-debug.md lists setVariable; skills/ regenerated if the docs change requires it. Unit tests in compiler/tests/debugger.test.trb for the literal-to-words conversion (range, kind).

Size. One PR: compiler/src/debugger/values.trb, debuggee.trb, adapter.trb (about 250 lines), one session and fixture, one test file, docs. No split. Worker: sonnet/high (compiler/src), CI only for gates.

[loop:torbscript] decided by the loop: scope, design and acceptance criteria for `setVariable` (implements DEBUGGER.md section 20, item "`setVariable`"; no owner question applies, all of it is internal technical design). **Goal.** The adapter answers the DAP request `setVariable` for the scalar locals and scalar fields the `variables` request shows, and announces `supportsSetVariable: true`. VS Code then offers "Set Value" in the Variables view. **What is written (decided, why).** - Only scalar leaves: integers (any width, range-checked), floats, `Bool`, `Char`. Why: section 6 guarantees that a binding in sight holds a value it owns, borrows or is empty, and the ownership pass releases by reference count. Writing a `String`, list, map, case or a whole record would need allocation and count updates inside a stopped program, which section 12 rules out for evaluate and which is exactly what the open item "snippet evaluator" is for. Everything else answers `success: false` with a message naming what can be set (`Only numbers, Bool and Char can be set`). - Places: a local (register slot, or the address a `var` parameter holds), a field of a record, tuple or `shared type` object below it (inline in the registers, or in the counted block at pointer + 16), an item of a fixed array. Items of `List`, `Map` and `Set` and fields of a case payload are refused for now (the read side finds them through the runtime's iterators, not through a stable address); not a split issue, the refusal message says so and a later issue can lift it if wanted. - Input text: the literal grammar of the breakpoint condition (`compiler/src/debugger/refinements.trb`, section 12): `42`, `-1`, `2.5`, `'a'`, `true`, `false`; the text must fit the target type (`300` into an `UInt8` is refused, a float into an integer is refused). No expressions, nothing runs. - Design: `Value` gains `place: Int` (the address of its first word, `0` where it is a temporary or unknown); `sliceOf`, `layoutChildren` and the boxed contents derive child places from it; `Referenced.Locals(frame)` resolves a name to a slot place, `Referenced.Children(value)` to a child by name. The store is `Machine.store` (one word) or `KernelOperation.NarrowStore` for narrow container elements, both existing: no new native, no runtime change. After a write the adapter re-reads the words of every live `variablesReference` from its place so a re-fetch of the parent and of sibling views shows the new value (DAP clients re-request after `setVariable`). - Sharing: a boxed record may be shared by several bindings (count > 1), a write through one shows through the others. Documented in `docs/tooling/torb-debug.md`, as in every native debugger. Immortal or static blocks (constant data) must not be written to: the implementer checks how `const origin = Point 1, 2` is allocated and refuses the write where the block is not an ordinary counted heap block; if refusal is needed, that is covered by criterion 5. **Seed.** Does not touch the seed: no syntax change, no new native, no driver flag, no std name looked up by string (`Machine.store` and `NarrowStore` exist already). One commit `feat(debugger): set a scalar variable from the editor` including the docs, or two (`feat` + `docs`); no seed refresh. **Acceptance criteria (replace those of the body).** 1. `initialize` answers `supportsSetVariable: true`; `setVariable` with `variablesReference` of Locals changes a scalar local (`Int`, `Float64`, `Bool`, `Char`, a narrow `UInt8`) and answers `value`, `type`, `variablesReference` of the new value (DAP `SetVariableResponse`). 2. The same for a scalar field of a record, a tuple field, a field of a `shared type` object and an item of a fixed array, reached through a `Children` reference; also a `var` parameter (written through its address). 3. After the write, `variables` of the parent and of the containing value shows the new value, and the continued program uses it (`print` output in `.expected` shows the changed number). 4. Refused with `success: false` and a message, program untouched: a non-scalar target (`String`, list, map, case, whole record), a value out of range or of the wrong kind (`300` into `UInt8`, `2.5` into `Int`, `abc`), an unknown name, a stale or unknown reference, a call while the program runs (as `variables` is answered only at a stop). 5. Writing into constant data (`const origin = Point 1, 2` as in `tests/debug/breakpoint/main.trb`) does not crash the adapter or the debuggee: either it works on an ordinary heap block or it is refused with a message; the session pins whichever it is. 6. A session `tests/debug/set-variable.dap` with `set-variable/main.trb`, `.expected` regenerated with `sh tools/debug.sh --update` (checked by hand), covering 1 to 4 (gate of tier A, `tools/debug.sh`); `tools/conformance.sh --vm` under `TORB_VM_DEBUGGED=1` stays as it is (no change without a debugger). 7. Docs: DEBUGGER.md section 20 loses the item and a short subsection (section 12 or 10) states the rules above; `docs/tooling/torb-debug.md` lists `setVariable`; `skills/` regenerated if the docs change requires it. Unit tests in `compiler/tests/debugger.test.trb` for the literal-to-words conversion (range, kind). **Size.** One PR: `compiler/src/debugger/values.trb`, `debuggee.trb`, `adapter.trb` (about 250 lines), one session and fixture, one test file, docs. No split. Worker: sonnet/high (compiler/src), CI only for gates.
Author
Collaborator

[loop:torbscript] refine: definition of ready met (goal, 7 acceptance criteria, DEBUGGER.md section 20, no seed impact, one PR / one or two commits, decisions recorded above), label ready set, next: implement. Refine worker usage: about 90k tokens (sonnet).

[loop:torbscript] refine: definition of ready met (goal, 7 acceptance criteria, DEBUGGER.md section 20, no seed impact, one PR / one or two commits, decisions recorded above), label `ready` set, next: implement. Refine worker usage: about 90k tokens (sonnet).
Author
Collaborator

[loop:torbscript] claim implement by session:loop-torbscript-20261017 until 2026-10-17T04:56:27Z

[loop:torbscript] claim implement by session:loop-torbscript-20261017 until 2026-10-17T04:56:27Z
Author
Collaborator

[loop:torbscript] implement: PR #379 opened (1 commit, Closes #38), forge CI green on a5a8c237 (gates, bootstrap, tier A/B, tests/debug); review requested from argus. Tokens: roughly 1.2M for this implement run. next: review

[loop:torbscript] implement: PR https://git.torb.dev/torbscript/language/pulls/379 opened (1 commit, Closes #38), forge CI green on a5a8c237 (gates, bootstrap, tier A/B, tests/debug); review requested from argus. Tokens: roughly 1.2M for this implement run. next: review
argus closed this issue 2026-10-16 23:53:48 +00:00
Sign in to join this conversation.
No labels
loop
ready
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
torbscript/language#38
No description provided.