Docs: Add in-depth guide to SSDL (Sketch DSL)
This commit is contained in:
@@ -41,6 +41,7 @@ This documentation suite provides comprehensive technical reference for the Manu
|
||||
| [State Lifecycle](guide_state_lifecycle.md) | Undo/redo via `HistoryManager` + `UISnapshot` (13 captured fields, 100-snapshot capacity, debounced change detection at render frame), reset flow (`_handle_reset_session` — clears 30+ fields, replaces project, preserves `active_project_path` per the 2026-06-08 regression fix), `App.__getattr__`/`__setattr__` state delegation to Controller, 8-thread io_pool with 11 lock-protected regions (per `IO_POOL_MAX_WORKERS = 8` in `src/io_pool.py:20`; bumped 4→8 in 4a338486 on 2026-06-06), hot-reload integration |
|
||||
| [Context Aggregation](guide_context_aggregation.md) | The `aggregate.py` (518-line) pipeline: 3 aggregation strategies (`auto`/`summarize`/`full`), 7 per-file view modes (`full`/`summary`/`skeleton`/`outline`/`masked`/`custom`/`none`), full `FileItem` schema (9 fields + `__post_init__` normalizer), `ContextPreset` schema and `ContextPresetManager`, Tier 3 worker variant (`build_tier3_context` with FuzzyAnchor re-resolution and focus-file handling), `force_full`/`auto_aggregate` short-circuits, output file numbering, cache strategy (static prefix + dynamic history) |
|
||||
| [ASCII Layout Map](guide_ascii_layout_map.md) | Structured text DSL reference: core conventions and vocabulary (lexicon of widgets, borders, separators), high-resolution zooming micro-sketches, grid-based alignment overlay, state multiplicity conditional annotations, and SSDL operational flow mappings. |
|
||||
| [SSDL (Sketch DSL)](guide_ssdl.md) | Spec/Sketch Description Language reference: visual topology design rules (6 computational shapes, control/data paths, repetitions), SSDL annotations and modifiers (state reads/writes, branches, terminators), and architectural defusing techniques (nil sentinels, generational handles, cache models). |
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -0,0 +1,191 @@
|
||||
# Guide to Spec/Sketch Description Language (SSDL)
|
||||
|
||||
This document provides a comprehensive technical guide and reference specification for the **Spec/Sketch Description Language (SSDL)**. SSDL is a text-side grammar used in the Manual Slop codebase to model **computational shapes**, trace data flows, analyze control-path branching, and document immediate-mode rendering graphs.
|
||||
|
||||
---
|
||||
|
||||
## 1. Context & Architectural Rationale
|
||||
|
||||
SSDL is heavily inspired by modern data-oriented design paradigms:
|
||||
1. ** Taxonomy of Computation Shapes** (Ryan Fleury, 2023) — mapping logic structures to visual topologies.
|
||||
2. **The Big OOPs: A 35-Year Mistake** (Casey Muratori, 2025) — prioritizing system data transformations over compile-time entity hierarchies.
|
||||
3. **Assuming as Much as Possible** (Andrew Reece, 2025) — reducing abstraction layers by exploiting specific access patterns.
|
||||
|
||||
### The Combinatoric Explosion
|
||||
Every conditional branch (`if`, `switch`, `try/except`) in a code path multiplies the number of potential execution routes. For example, a function containing 5 branches called from 10 different sites generates $2^5 \times 10 = 320$ effective codepaths. When state mutations are added, the permutations multiply, making comprehensive testing and reasoning impossible.
|
||||
|
||||
**SSDL is a design DSL built to combat this explosion.** By sketching the computational shapes of functions before writing code, developers can identify branch points, isolate state mutations, and apply architectural defusing techniques (such as nil sentinels and generational handles) to collapse complex branch graphs into flat, linear, easily testable paths.
|
||||
|
||||
---
|
||||
|
||||
## 2. SSDL Syntax Specification
|
||||
|
||||
SSDL uses a small, structured ASCII vocabulary to represent control flow, repetition, state interactions, and data propagation.
|
||||
|
||||
### 2.1 The 6 Computation Shapes (Primitives)
|
||||
|
||||
| Shape | SSDL Notation | Definition | Architectural Context |
|
||||
|---|---|---|---|
|
||||
| **Instruction** | `[I:name]` | A single unit of computation. | Reads, transforms, or writes data. No internal branching. |
|
||||
| **Codepath** | `->` | A sequential control flow. | A linear progression of instructions that terminates. |
|
||||
| **Wide Codepath** | `=>` | Parallel or branched control flow. | Represents concurrent operations, multi-column tables, or tabs. |
|
||||
| **Codecycle** | `o->` | A loop or repetitive path. | Iterations over arrays, dictionary scans, or frame render ticks. |
|
||||
| **Wide Codecycle** | `o=>` | Parallel repetitive loops. | Parallel processing threads or batch worker execution. |
|
||||
| **Codecycle Graph**| `Boxes + Arrows` | System-level network. | High-level graph showing data nodes and loop interactions. |
|
||||
|
||||
### 2.2 SSDL Modifiers and Annotations
|
||||
|
||||
Modifiers are applied to instructions to indicate state operations, termination conditions, or architectural invariants:
|
||||
|
||||
* `[T]` (Terminator): Marks the exit point of a path (e.g., `return`, `exit`, `break`).
|
||||
* `[B:condition]` (Branch): Marks a point where control flow forks (e.g., `if`, `else`, `match`).
|
||||
* `[M]` (Merge): Marks where multiple branch paths reconverge.
|
||||
* `[S:variable]` (State Mutation): Indicates that the instruction writes to persistent/mutable state.
|
||||
* `[Q:variable]` (State Query): Indicates that the instruction reads from persistent/mutable state.
|
||||
* `[N:sentinel]` (Nil Sentinel): Represents a guaranteed-safe fallback object that eliminates invalid pointer checks.
|
||||
* `───` (Data Path): Delimits data flow lines, as opposed to control-flow paths (`->`).
|
||||
* `[•]` (Defused Branch): Represents a conditional branch that has been refactored into a linear sequence.
|
||||
|
||||
---
|
||||
|
||||
## 3. Architectural Defusing Techniques in SSDL
|
||||
|
||||
The primary goal of SSDL during spec design is to **defuse branches**, collapsing N effective codepaths into 1.
|
||||
|
||||
### 3.1 Technique 1: The Nil Sentinel (Branch Elimination)
|
||||
|
||||
Null pointer checks (`if node is None:`) are a major source of branch multiplication. By introducing a self-referential nil sentinel node, we can eliminate null checks entirely.
|
||||
|
||||
#### Before (Branchy Null-Checking)
|
||||
Every traversal step requires a validation branch, resulting in $2^4 = 16$ effective codepaths:
|
||||
```
|
||||
[Q:root]
|
||||
│
|
||||
▼
|
||||
[B:root != 0?]
|
||||
├─ no ─────► [T:return 0]
|
||||
└─ yes
|
||||
│
|
||||
▼
|
||||
[I:ChildFromValue(root, 1)]
|
||||
│
|
||||
▼
|
||||
[B:n1 != 0?]
|
||||
├─ no ──► [T:return 0]
|
||||
└─ yes
|
||||
│
|
||||
▼
|
||||
[I:ChildFromValue(n1, 2)] ...
|
||||
```
|
||||
|
||||
#### After (Defused with Nil Sentinel `[N]`)
|
||||
A static `nil_node` is defined whose child pointers point to itself. Traversal becomes a straight line with **1 effective codepath**:
|
||||
```
|
||||
nil_node: [N] = { &nil_node, &nil_node, 0 }
|
||||
|
||||
[Q:root]
|
||||
│
|
||||
▼
|
||||
[I:ChildFromValue(root, 1)] -> [I:ChildFromValue(n1, 2)] -> [I:ChildFromValue(n2, 3)]
|
||||
│
|
||||
▼
|
||||
[T:return n3] (if not found, returns nil_node; caller safely queries it without checking)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 3.2 Technique 2: Generational Handles (Lifetime Defusing)
|
||||
|
||||
Checking if an allocated object has been freed or replaced typically introduces branch complexity. Generational handles defuse this by resolving queries through a validation check that returns a nil sentinel on mismatch.
|
||||
|
||||
```
|
||||
Main Path:
|
||||
[Q:entity_handle] ───► [I:ResolveHandle] ───► [B:Generation Matches?]
|
||||
├─ no ──► [I:return nil_sentinel] ──┐
|
||||
└─ yes ──► [I:return entity] │
|
||||
│ │
|
||||
▼ ▼
|
||||
[Q:entity.pos] [Q:nil.pos] (safe)
|
||||
│ │
|
||||
└────────► [M] ───┘
|
||||
│
|
||||
▼
|
||||
[I:DrawAtPosition]
|
||||
```
|
||||
The caller's rendering code remains a single straight-line path (`[I:DrawAtPosition]`), having outsourced the lifetime checks to the validation layer.
|
||||
|
||||
---
|
||||
|
||||
### 3.3 Technique 3: Immediate-Mode Cache Allocation
|
||||
|
||||
Retained-mode API resource management requires tracking allocation, deletion, and reload states (e.g. `is_loading`, `reloading_failed`). Immediate-mode caching defuses this by making resource fetching a synchronous key query that handles lazy loading in the background.
|
||||
|
||||
```
|
||||
RETAINED MODE (Branchy Lifecycle):
|
||||
[Q:resource] -> [B:is_allocated?]
|
||||
├─ no ──► [S:allocate] ──► [B:load_successful?]
|
||||
│ ├─ no ──► [T:draw_error]
|
||||
│ └─ yes ──► [T:draw_resource]
|
||||
└─ yes ──► [B:needs_reload?]
|
||||
├─ yes ──► [S:reallocate] ...
|
||||
└─ no ──► [T:draw_resource]
|
||||
|
||||
IMMEDIATE MODE (Defused Caching):
|
||||
[Q:resource_key] -> [I:FetchFromCache(key)] -> [I:DrawResource] -> [T]
|
||||
(cache loads in background if missing)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 4. Mapping SSDL to Python 3.11 ImGui
|
||||
|
||||
To enforce SSDL as a strict design contract, SSDL symbols correspond to specific Python code constructs in `src/gui_2.py`.
|
||||
|
||||
### 4.1 Basic SSDL-to-Code Transformations
|
||||
|
||||
| SSDL Code Pattern | Python Implementation |
|
||||
|---|---|
|
||||
| `[I:label]` | `imgui.text("Label")` |
|
||||
| `[S:app_var]` | `app.app_var = new_value` |
|
||||
| `[Q:app_var]` | `val = app.app_var` |
|
||||
| `[B:show_window] -> [I:panel]` | `if app.show_window: render_panel(app)` |
|
||||
| `o-> [I:row]` | `for item in items: render_row(item)` |
|
||||
| `=>` | `imgui.table_next_column()` or `imgui.same_line()` |
|
||||
| `[B:popup] => [B:choices]` | `if imgui.begin_popup_modal(...)[0]:` |
|
||||
|
||||
### 4.2 Comprehensive Code Mapping Example
|
||||
|
||||
This example demonstrates a complete ImGui popup modal implementation and its corresponding SSDL annotation.
|
||||
|
||||
#### Python Code
|
||||
```python
|
||||
def render_confirm_action_modal(app: App) -> None:
|
||||
"""Renders the confirm action popup modal.
|
||||
|
||||
SSDL: `[Q:show_confirm] -> [B:open_popup] -> [I:message] => [S:pending_action | B:cancel_button]`
|
||||
"""
|
||||
if app.show_confirm_modal:
|
||||
imgui.open_popup("Confirm Action")
|
||||
app.show_confirm_modal = False
|
||||
|
||||
if imgui.begin_popup_modal("Confirm Action", True, imgui.WindowFlags_.always_auto_resize)[0]:
|
||||
imgui.text("Are you sure you want to proceed?")
|
||||
|
||||
if imgui.button("Confirm", imgui.ImVec2(120, 0)):
|
||||
app.controller.execute_pending_action()
|
||||
imgui.close_current_popup()
|
||||
|
||||
imgui.same_line()
|
||||
if imgui.button("Cancel", imgui.ImVec2(120, 0)):
|
||||
imgui.close_current_popup()
|
||||
|
||||
imgui.end_popup()
|
||||
```
|
||||
|
||||
#### SSDL Trace Breakdown
|
||||
1. `[Q:show_confirm]`: The function checks `app.show_confirm_modal` state.
|
||||
2. `-> [B:open_popup]`: If true, it opens the modal dialog.
|
||||
3. `-> [I:message]`: Draws the warning text `"Are you sure you want to proceed?"`.
|
||||
4. `=>`: Branches horizontally to draw action options side-by-side.
|
||||
5. `[S:pending_action]`: Confirm button modifies state via controller.
|
||||
6. `[B:cancel_button]`: Cancel button closes the modal.
|
||||
Reference in New Issue
Block a user