Skip to content

Latest commit

 

History

History
1063 lines (819 loc) · 31.3 KB

File metadata and controls

1063 lines (819 loc) · 31.3 KB

FROG logo

FROG IDE Debugging

Interactive debugging behavior for a FROG IDE
FROG — Free Open Graphical Language


Contents


1. Overview

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.


2. Document Role

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.md for the overall IDE architecture,
  • IDE/Observability.md for the live source-aligned observability layer,
  • IDE/Probes.md for local inspection surfaces,
  • IDE/Watch.md for persistent centralized inspection,
  • IR/Execution IR.md and 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.


3. Repository Navigation

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.


4. Architectural Position and Dependencies

4.1 Repository position

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.

4.2 Dependencies

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.

4.3 Dependency diagram

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.


5. Ownership Boundary

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/ and Profiles/ remain authoritative for primitive-local and capability-local executable meaning,
  • IR/ remains authoritative for execution-facing derivation and source-attributed execution objects,
  • IDE/Observability.md remains authoritative for the observable projection exposed to tools,
  • IDE/Debugging.md remains 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

6. Design Principles

6.1 Source-level debugging

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.

6.2 Dataflow-first behavior

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.

6.3 Language-derived safe boundaries

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.

6.4 Runtime independence

Different runtimes MAY implement debugging through different internal mechanisms. The source-level meaning exposed to the IDE MUST remain equivalent.

6.5 Observability-first dependency

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.

6.6 Probe and watch compatibility

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.

6.7 Minimal but extensible

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.


7. Debug Session Model

7.1 Definition

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.

7.2 Debug-session states

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.

7.3 Pause reasons

When a debug session is paused, the primary pause reason SHOULD be available. Canonical pause reasons are:

  • manual_pause,
  • breakpoint,
  • step_complete,
  • fault.

7.4 Selected object and context

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.

8. Pause, Resume, and Abort

8.1 Manual pause

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.

8.2 Resume

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.

8.3 Abort

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.

8.4 Inspection during pause

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.


9. Breakpoints

9.1 General model

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.

9.2 Minimum interactive baseline

The minimum interactive debugging baseline requires support for:

  • node_breakpoint

9.3 Optional standardized breakpoint kinds

Additional standardized breakpoint kinds MAY include:

  • edge_breakpoint,
  • structure_breakpoint,
  • subfrog_breakpoint.

9.4 Node 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.

9.5 Edge breakpoint

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.

9.6 Structure breakpoint

A structure breakpoint is attached to one structure node. Its standardized meaning is:

  • pause when that structure activation begins.

9.7 Sub-FROG breakpoint

A sub-FROG breakpoint is attached to one subfrog call site. Its standardized meaning is:

  • pause when that call-site activation begins.

9.8 Enabled and disabled breakpoints

A breakpoint MAY be enabled or disabled without being removed. A disabled breakpoint MUST have no effect on execution.

9.9 Multiple simultaneous matches

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.


10. Stepping Model

10.1 General rule

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.

10.2 Eligible safe debug stop

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

10.3 Canonical step commands

The canonical step commands are:

  • step_into,
  • step_over,
  • step_out.

10.4 step_into

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.

10.5 step_over

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.

10.6 step_out

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.

10.7 Step completion

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.


11. Nested-Scope Debugging

11.1 General rule

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.

11.2 Sub-FROG scopes

A subfrog node creates a nested source-aligned call scope for debugging purposes. Therefore:

  • step_into MAY enter the nested sub-FROG scope,
  • step_over MUST treat the call as one caller-visible unit,
  • step_out from inside the callee MUST return to the caller scope.

11.3 Case structures

For a case structure:

  • only the selected region belongs to the active dynamic path for that activation,
  • step_into MAY stop at selected-region entry or at the first eligible stop inside it,
  • step_over MUST execute the selected region as one structure activation and return to the parent scope,
  • step_out from inside the selected region MUST continue until the structure activation completes and then return to the parent scope.

11.4 Loop structures

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.

11.5 Local memory inside nested scopes

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.


12. Execution Highlighting

12.1 General rule

A debugging-capable IDE SHOULD support execution highlighting. Execution highlighting is the source-level visual projection of live execution activity onto the diagram.

12.2 Highlightable objects

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.

12.3 Meaning of highlighting

Highlighting is descriptive, not prescriptive. It visualizes execution activity already made observable to the IDE. It MUST NOT alter execution meaning.

12.4 No mandatory rendering style

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.


13. Fault Handling During Debugging

13.1 General rule

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:

  • paused with pause reason fault, or
  • faulted if the implementation does not support fault-directed pause before termination.

13.2 Fault localization

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.

13.3 Consistency rule

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.


14. Front Panel and Widget Debug Visibility

14.1 Widget-related execution objects

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.

14.2 Front-panel reflection

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.


15. Relationship with Probes and Watches

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

15.1 Probes

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.

15.2 Watches

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.

15.3 Non-ownership rule

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.


16. IDE Requirements

16.1 Minimum interactive debugging baseline

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.

16.2 Optional standardized additions

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.


17. Illustrative Debug Objects

The examples below are illustrative only. They show possible debugger-facing representations. They are not a required transport format.

17.1 Node breakpoint

{
  "kind": "node_breakpoint",
  "enabled": true,
  "target": {
    "kind": "node",
    "id": "add_1"
  },
  "condition": "on_start"
}

17.2 Edge breakpoint

{
  "kind": "edge_breakpoint",
  "enabled": true,
  "target": {
    "kind": "edge",
    "id": "e_sum"
  }
}

17.3 Paused debug snapshot

{
  "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
      }
    ]
  }
}

17.4 Fault-directed pause

{
  "debug_state": "paused",
  "pause_reason": "fault",
  "instance_id": "run_42",
  "selected_object": {
    "kind": "node",
    "id": "write_gain"
  },
  "details": {
    "fault_kind": "ui_write_failure"
  }
}

18. Directory Navigation

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

19. Out of Scope

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.

20. Summary

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.