Interactive debugging behavior for a FROG IDE
FROG — Free Open Graphical Language
- 1. Overview
- 2. Document Role
- 3. Repository Navigation
- 4. Architectural Position and Dependencies
- 5. Ownership Boundary
- 6. Design Principles
- 7. Debug Session Model
- 8. Pause, Resume, and Abort
- 9. Breakpoints
- 10. Stepping Model
- 11. Nested-Scope Debugging
- 12. Execution Highlighting
- 13. Fault Handling During Debugging
- 14. Front Panel and Widget Debug Visibility
- 15. Relationship with Probes and Watches
- 16. IDE Requirements
- 17. Illustrative Debug Objects
- 18. Directory Navigation
- 19. Out of Scope
- 20. Summary
This document defines the interactive debugging behavior of a FROG IDE. It specifies how an IDE may pause, resume, inspect, and step through a live execution instance in a source-aligned way.
This document does not define execution semantics. Execution meaning remains defined by the validated executable graph and by the relevant language, library, and profile specifications. This document standardizes only the IDE-facing control meaning needed for:
- run-under-debug behavior,
- manual pause and resume,
- user-facing abort,
- breakpoints,
- single-step commands,
- fault-directed pause when supported,
- source-aligned debug inspection.
Language/
-> owns execution meaning and safe debug stops
IR/
-> owns execution-facing derivation and identity preservation posture
IDE/Observability.md
-> owns the observable projection consumed by tools
IDE/Debugging.md
-> owns interactive debug control meaning for the IDE
Interactive debugging is therefore a tooling-facing layer over already-defined execution meaning. It is not a replacement for the execution model, not a replacement for safe-boundary semantics, and not a runtime-internal scheduler specification.
This document is the debugging-focused document of the IDE/ family.
Its role is to define how a conforming IDE exposes interactive debug control over live execution that has already been made observable in source-aligned form.
This document should be read together with:
IDE/Readme.mdfor the overall IDE architecture,IDE/Observability.mdfor the live source-aligned observability layer,IDE/Probes.mdfor local inspection surfaces,IDE/Watch.mdfor persistent centralized inspection,IR/Execution IR.mdand related IR documents for execution-facing identity and attribution posture.
This document is intentionally modular. It defines debugging control meaning only. It does not absorb observability, probe ownership, watch ownership, IR ownership, or language ownership.
The most relevant repository files and directories for this document are:
IDE/
├── Readme.md
│ -> overall IDE architecture and document map
├── Observability.md
│ -> source-aligned execution observability consumed by debugging
├── Debugging.md
│ -> this document
├── Probes.md
│ -> local inspection tools used during execution and debugging
├── Watch.md
│ -> persistent centralized inspection model
└── Snippet.md
-> authoring-fragment transport, not debugger control
Upstream repository areas that matter for debugging are:
Expression/
├── Diagram.md
├── Front panel.md
├── Widget.md
└── Widget interaction.md
Language/
├── Readme.md
├── Control structures.md
└── State and cycles.md
IR/
├── Readme.md
├── Execution IR.md
├── Derivation rules.md
└── Lowering.md
Libraries/
└── ... primitive-local meaning used by execution
This navigation matters because debugging in FROG depends on a clean chain: source identity, validated meaning, execution-facing attribution, source-aligned observability, and finally debugger control.
This document belongs in IDE/ because it defines how interactive debugging is exposed to users and tools.
It does not belong to Language/ because it does not own execution meaning.
It does not belong to IR/ because it does not own execution-facing derivation or lowering.
This document depends on the following repository surfaces:
IDE/Readme.md— architectural ownership of tooling behavior in the IDE layer,IDE/Observability.md— source-aligned observability projection consumed by debugging,IDE/Probes.md— local inspection tools used together with debugging,IDE/Watch.md— persistent inspection tools used together with debugging,Expression/Diagram.md— canonical node, edge, and executable-graph representation,Expression/Front panel.md— front-panel source concepts used for source-aligned UI reflection,Expression/Widget.md— source-visible widget identities,Expression/Widget interaction.md— widget-related execution objects and explicit UI sequencing,Language/Control structures.md— normative control-structure execution semantics,Language/State and cycles.md— normative local-memory and cycle semantics,IR/Execution IR.md— execution-facing object identity and source attribution posture,IR/Derivation rules.md— correspondence rules from validated meaning to execution-facing representation.
Expression/ + Language/ + Libraries/ + Profiles/
|
v
IR/
|
v
IDE/Observability.md
/ | \
v v v
IDE/Debugging.md IDE/Probes.md IDE/Watch.md
This diagram is intentional. Debugging, probes, and watches are parallel IDE-side consumers of the observable execution world. Debugging does not own probes or watches.
If a conflict appears, the following ownership rules apply:
Expression/remains authoritative for source-visible representation and serialized identity,Language/remains authoritative for execution meaning, committed state, and safe debug-stop boundaries,Libraries/andProfiles/remain authoritative for primitive-local and capability-local executable meaning,IR/remains authoritative for execution-facing derivation and source-attributed execution objects,IDE/Observability.mdremains authoritative for the observable projection exposed to tools,IDE/Debugging.mdremains authoritative only for the user-facing and tool-facing debugging layer.
Expression/
owns what the user edits and what is serialized
Language/
owns what execution means and where a safe debug stop exists
IR/
owns execution-facing attribution and mapping posture
IDE/Observability.md
owns how live execution becomes observable in source-aligned form
IDE/Debugging.md
owns how the debugger controls and presents the already-defined execution
Debugging MUST be expressed in terms of source-visible concepts: nodes, edges, structures, regions, sub-FROG calls, local-memory observations, and widget-related execution objects when relevant. The user MUST NOT be required to reason about runtime-private artifacts.
FROG debugging MUST respect dataflow semantics. It MUST NOT assume an implicit sequential instruction stream. Debugging controls therefore operate over source-aligned observable execution activity.
A visible debugger stop MUST occur only at a language-valid safe debug stop. The debugger MUST NOT expose a partially committed source-level state as if it were stable. This document consumes that guarantee; it does not define it.
Different runtimes MAY implement debugging through different internal mechanisms. The source-level meaning exposed to the IDE MUST remain equivalent.
Interactive debugging in FROG depends on source-aligned observability. A debugger MAY control execution only to the extent that execution has already been projected into meaningful FROG objects.
Debugging SHOULD compose cleanly with probes and watches. A paused snapshot, step completion, breakpoint hit, or fault-directed pause MUST remain interpretable by probe and watch consumers without contradictory source state.
FROG defines a minimal interactive debugging core. Stronger debugging support levels MAY expose richer controls, additional breakpoint conditions, or deeper inspection capabilities, provided that the standardized meanings defined here remain preserved.
A debug session is the IDE-visible control context attached to one live execution instance. A debug session owns the active debugger configuration for that instance.
A debug session conceptually contains:
- the target
instance_id, - the current debug-session state,
- the current pause reason when paused,
- the active breakpoint set,
- the currently selected source-aligned object,
- the relevant execution context,
- the active step request if one exists.
A debug session MUST expose one of the following high-level states:
idle— no live execution instance is attached,starting— execution is being prepared under debug control,running— execution is progressing under an active debug session,paused— execution is suspended at a language-valid safe debug stop,completed— the instance finished normally,faulted— the instance terminated because of a fault without remaining paused,aborted— the instance terminated because of a user or external abort action.
When a debug session is paused, the primary pause reason SHOULD be available. Canonical pause reasons are:
manual_pause,breakpoint,step_complete,fault.
When paused, the debugger SHOULD identify one primary selected source-aligned object. That object MAY be:
- a node,
- an edge,
- a structure,
- a region,
- a sub-FROG call site,
- a widget-related execution object,
- another supported source-aligned execution object.
The selected object is a debugger-facing focus object. It does not replace the full execution context, which MUST remain available when needed to interpret:
- loop iteration identity,
- selected region identity,
- caller/callee nesting,
- repeated activations of the same source node.
A manual pause request asks the runtime to suspend execution at the next language-valid safe debug stop.
When the session becomes paused, the IDE-facing view MUST be interpretable as a pause-consistent snapshot. In particular, the debugger MUST be able to rely on the following:
- already-visible node completions are committed,
- already-visible edge values are committed,
- already-visible local-memory updates are committed,
- the visible structure and region context is coherent,
- the paused state corresponds to a coherent causal prefix.
A resume request restarts execution from the current paused state. Unless a step request is active, execution continues freely until one of the following occurs:
- a breakpoint is hit,
- a fault-directed pause occurs,
- the user pauses manually again,
- the instance completes normally,
- the instance is aborted.
A user-facing stop action terminates the live execution instance.
At the debugging level, that outcome MUST be represented consistently with the instance becoming aborted, unless a stronger implementation defines an explicitly different but equivalent user-stop presentation.
While paused, the IDE MAY expose:
- the selected source object,
- the current execution context,
- relevant committed values,
- relevant committed local-memory state,
- probe and watch views defined elsewhere.
All such inspection MUST remain consistent with the paused execution snapshot exposed to the IDE.
A breakpoint is a debugger-facing stop condition attached to a source-aligned execution object. When its condition is satisfied, execution MUST pause only at a corresponding language-valid safe debug stop.
Breakpoint triggering is evaluated in source-aligned terms. It MUST NOT require exposing runtime-private execution artifacts to the user.
The minimum interactive debugging baseline requires support for:
node_breakpoint
Additional standardized breakpoint kinds MAY include:
edge_breakpoint,structure_breakpoint,subfrog_breakpoint.
A node breakpoint is attached to one source node. The canonical baseline condition is:
on_start
Stronger implementations MAY additionally support:
on_ready,on_complete,on_fault.
An edge breakpoint is attached to one source edge. Its standardized meaning is:
- pause when a value becomes available on that edge in the relevant execution context.
A structure breakpoint is attached to one structure node. Its standardized meaning is:
- pause when that structure activation begins.
A sub-FROG breakpoint is attached to one subfrog call site.
Its standardized meaning is:
- pause when that call-site activation begins.
A breakpoint MAY be enabled or disabled without being removed. A disabled breakpoint MUST have no effect on execution.
If multiple breakpoint conditions are satisfied at the same safe debug stop, the runtime MAY report one primary breakpoint cause and additional matched breakpoints. The IDE MUST NOT present contradictory source state.
Single-stepping in FROG is defined over source-aligned observable execution, not over a linear instruction stream. A step request resumes execution in a constrained way until the first eligible safe debug stop for that request is reached.
An eligible safe debug stop is a language-valid safe debug stop that also satisfies the IDE-facing selection rule of the active step command. The step command defines the selection rule. The language defines where safe debug stops may exist.
step request issued by IDE
|
v
runtime continues execution
|
v
language-valid safe debug stops become reachable
|
v
first stop matching the step-selection rule
|
v
debug session pauses
The canonical step commands are:
step_into,step_over,step_out.
step_into resumes execution until the first eligible safe debug stop on the current causally reachable execution path.
When the current paused object represents a nested executable unit, step_into MAY stop inside that nested scope.
step_over treats the currently selected source-aligned executable unit as one debugger-facing unit.
It resumes execution until that currently selected unit has completed from the point of view of its immediate parent scope, then pauses at the first eligible safe debug stop in that parent scope.
step_out is valid only when the current paused location is inside a nested debug scope.
It resumes execution until the current nested scope has completed from the point of view of its immediate parent scope, then pauses at the first eligible safe debug stop in that parent scope.
When a step request succeeds normally, the resulting pause reason SHOULD be:
step_complete
If a breakpoint is hit before the intended step target is reached, the pause reason MAY be breakpoint.
If a fault-directed pause occurs, the pause reason MUST be fault.
FROG debugging is scope-aware. A paused location may belong to a nested source-aligned execution scope, including:
- a sub-FROG invocation scope,
- a selected structure region,
- a loop iteration context,
- another nested dynamic scope exposed by a stronger implementation.
The debugger SHOULD preserve that nesting explicitly in the visible execution context.
A subfrog node creates a nested source-aligned call scope for debugging purposes.
Therefore:
step_intoMAY enter the nested sub-FROG scope,step_overMUST treat the call as one caller-visible unit,step_outfrom inside the callee MUST return to the caller scope.
For a case structure:
- only the selected region belongs to the active dynamic path for that activation,
step_intoMAY stop at selected-region entry or at the first eligible stop inside it,step_overMUST execute the selected region as one structure activation and return to the parent scope,step_outfrom inside the selected region MUST continue until the structure activation completes and then return to the parent scope.
Loop debugging is iteration-aware. The same source node MAY therefore appear repeatedly under distinct iteration contexts. The IDE SHOULD preserve iteration identity while debugging.
When local-memory primitives are active inside nested scopes, the debugger MUST preserve the source meaning of local state for the current live execution instance. A paused view MUST NOT misrepresent stored state across iterations or nested activations.
A debugging-capable IDE SHOULD support execution highlighting. Execution highlighting is the source-level visual projection of live execution activity onto the diagram.
An IDE SHOULD be able to highlight at least:
- node execution start,
- node execution completion,
- edge value availability,
- structure entry,
- selected case regions,
- loop iteration progression.
Highlighting is descriptive, not prescriptive. It visualizes execution activity already made observable to the IDE. It MUST NOT alter execution meaning.
This specification does not require a particular animation model, color model, line style, or theme. Any rendering strategy is acceptable provided that the displayed meaning remains source-aligned and understandable.
If a fault occurs while debugging is active, the debug session SHOULD pause at the most relevant language-valid safe debug stop associated with that fault when the active implementation supports fault-directed pause.
The debug-session state MUST then become either:
pausedwith pause reasonfault, orfaultedif the implementation does not support fault-directed pause before termination.
When possible, the IDE SHOULD identify at least one primary source object related to the fault, such as:
- a node,
- a structure,
- a sub-FROG call site,
- a widget interaction node.
Fault-directed pause MUST still obey language-level safe debug-stop rules.
The debugger MUST NOT show a contradictory partial state merely because the pause reason is fault.
Widget participation in debugging occurs through the diagram-level execution objects already defined by source and consumed through the relevant primitive contracts, including:
widget_value,widget_reference,frog.ui.property_read,frog.ui.property_write,frog.ui.method_invoke.
A debugging-capable IDE MAY reflect debug state on the front panel when that reflection is source-meaningful. Examples include:
- showing the current widget value when relevant,
- showing that a property write has occurred,
- showing the result of a property read,
- showing explicit UI-effect sequencing progress.
However, the front panel remains a user-facing UI composition, not the authoritative executable graph. Pause locations and step targets therefore remain defined primarily in diagram terms.
Debugging is not identical to probes or watches, but it must compose with both. The architectural relation is:
live execution
|
v
source-aligned observability
|
+--> debugging control
+--> probes
\--> watches
Probes are local inspection objects attached to graph-meaningful surfaces. During debugging, probes SHOULD remain interpretable against the same paused snapshot and the same selected execution context as the debugger.
Watches are persistent centralized observation surfaces. During debugging, watches SHOULD remain attributable to meaningful source objects and SHOULD update consistently with pause, resume, step completion, and fault-directed pause.
This document does not define probe behavior or watch behavior in full. It defines only the compatibility requirements between debugger control and those inspection layers.
An IDE that claims support for FROG interactive debugging SHOULD provide at least:
- run under debug control,
- manual pause and resume,
- manual abort,
- execution highlighting,
node_breakpoint,step_into,step_over,step_out.
An IDE MAY additionally provide:
edge_breakpoint,structure_breakpoint,subfrog_breakpoint,- fault-directed pause with source localization,
- readiness-aware overlays when readiness is exposed,
- front-panel debug reflection,
- execution traces,
- probe integration as defined by
IDE/Probes.md, - watch integration as defined by
IDE/Watch.md.
User-interface design is not standardized here. Only the source-level meaning of the debugging controls is standardized here.
The examples below are illustrative only. They show possible debugger-facing representations. They are not a required transport format.
{
"kind": "node_breakpoint",
"enabled": true,
"target": {
"kind": "node",
"id": "add_1"
},
"condition": "on_start"
}{
"kind": "edge_breakpoint",
"enabled": true,
"target": {
"kind": "edge",
"id": "e_sum"
}
}{
"debug_state": "paused",
"pause_reason": "step_complete",
"instance_id": "run_42",
"selected_object": {
"kind": "node",
"id": "add_1"
},
"context": {
"subfrog_stack": [],
"structure_stack": [
{
"structure_id": "loop_1",
"region_id": "body",
"iteration": 3
}
]
}
}{
"debug_state": "paused",
"pause_reason": "fault",
"instance_id": "run_42",
"selected_object": {
"kind": "node",
"id": "write_gain"
},
"details": {
"fault_kind": "ui_write_failure"
}
}This document is easier to use when read together with the neighboring IDE documents:
IDE/
├── Readme.md
│ -> overall IDE ownership, components, and document map
├── Observability.md
│ -> source-aligned execution visibility consumed by tools
├── Debugging.md
│ -> this document; interactive debugger control
├── Probes.md
│ -> local inspection tools compatible with debugging
└── Watch.md
-> persistent inspection tools compatible with debugging
For readers following repository ownership boundaries, the main cross-layer path is:
Expression/
-> what source objects exist
Language/
-> what execution means
IR/
-> what execution-facing derivation preserves
IDE/Observability.md
-> how execution becomes visible back in source terms
IDE/Debugging.md
-> how the IDE controls that visible execution world
The following topics remain intentionally out of scope for this document:
- execution-model ownership,
- safe-debug-stop semantic ownership,
- probe behavior in full,
- watch behavior and watch expressions in full,
- conditional breakpoints,
- break-on-value-change semantics,
- break-on-fault filters,
- iteration-specific breakpoint expressions,
- reverse stepping,
- reverse execution,
- deterministic replay,
- distributed multi-runtime debug coordination,
- deep value-inspection protocols,
- performance profiling and timing analysis.
FROG interactive debugging defines the IDE-facing meaning of pause, resume, abort, breakpoints, and stepping for live executions of FROG programs. It preserves the dataflow nature of the language and avoids imposing a false sequential execution model.
This debugging layer provides the foundation for richer inspection tooling while preserving the architectural separation between:
- execution semantics,
- execution-facing attribution,
- observable execution projection,
- interactive debugger control,
- probe and watch consumption.
The practical reading is simple: debugging in FROG is source-aligned, dataflow-first, observability-dependent, and compatible with probes and watches without collapsing those concerns into one document.