dreamstack/IMPLEMENTATION_PLAN.md

270 lines
12 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# DreamStack Implementation Plan
Build a working prototype of the DreamStack vision — a new UI framework with compile-time reactivity, algebraic effects, constraint layout, and physics animation. The strategy is to **bootstrap pragmatically**: use Rust for the compiler/runtime core, target WASM + DOM, and prove each pillar with working demos before unifying them.
---
## Phase 0 — Foundation (Weeks 13)
**Goal:** A working compiler that turns DreamStack syntax into executable WASM + JS glue.
### Compiler Pipeline (Rust)
#### [NEW] `compiler/crates/ds-parser/`
- Hand-written recursive descent parser for DreamStack syntax
- Produces an AST of `view`, `let`, `when`, `match`, `effect`, `on`, `stream`, `layout` constructs
- Homoiconic representation: AST nodes are also the runtime data structure (tagged vectors/maps)
#### [NEW] `compiler/crates/ds-analyzer/`
- **Signal graph extraction:** Static analysis pass that identifies signals, derived values, and their dependencies → builds a DAG
- **Effect collection:** Catalogs all `perform` sites and their expected effect signatures
- **Type inference:** Hindley-Milner base with structural typing; dependent types deferred to Phase 4
#### [NEW] `compiler/crates/ds-codegen/`
- Emits **Rust → WASM** for:
- Signal graph runtime (push-based notification)
- Constraint solver (Cassowary algorithm)
- Spring physics engine
- Emits **JS glue** for DOM bindings — surgical `textContent`, `setAttribute`, `insertBefore`, `removeChild` calls (no VDOM)
- Output format: single `.wasm` + single `.js` module
#### [NEW] `compiler/crates/ds-cli/`
- `dreamstack build <file.ds>` → produces `.wasm` + `.js` + `.html`
- `dreamstack dev <file.ds>` → dev server with file watching + hot-reload
- `dreamstack check <file.ds>` → type check + signal graph validation
### Deliverable
A counter app (`examples/counter.ds`) compiles and runs in the browser with reactive signal updates, no VDOM.
---
## Phase 1 — Reactive Core (Weeks 46)
**Goal:** Fine-grained reactivity with compile-time dependency tracking, proving the "no re-render" model.
### Signal Runtime (Rust → WASM)
#### [NEW] `runtime/crates/ds-signals/`
- `Signal<T>` — mutable source, notifies dependents on write
- `Derived<T>` — computed from signals, lazy + cached, auto-invalidated
- `Effect` — runs side-effect when dependencies change (for DOM updates only — user-facing effects use algebraic effects)
- Batching: multiple signal writes in one tick coalesce into a single propagation pass
- Topological sort of the DAG ensures glitch-free propagation (no intermediate states visible)
### DOM Binding Layer (JS)
#### [NEW] `runtime/js/dom-bindings.js`
- Minimal JS layer (~3KB) that the codegen targets
- Functions: `bindText(nodeId, signalId)`, `bindAttr(nodeId, attr, signalId)`, `bindVisible(nodeId, signalId)`, `mountChildren(parentId, listSignalId, templateFn)`
- Each binding registers itself as an effect on the signal graph
- No framework runtime — just a bag of DOM mutation functions
### Benchmark Suite
#### [NEW] `bench/`
- Signal propagation: 1K / 10K / 100K signals, measure update latency
- DOM updates: compare against Solid.js, Svelte 5, vanilla JS
- Target: <1ms for 1K signal cascade, <16ms for 10K
### Deliverable
A TodoMVC app (`examples/todomvc.ds`) with add/remove/toggle/filter all reactive, no VDOM, benchmarked against Solid.js.
---
## Phase 2 — Effect System & Streams (Weeks 710)
**Goal:** Algebraic effects for side-effects, stream primitives for temporal data.
### Algebraic Effects (Rust → WASM)
#### [NEW] `runtime/crates/ds-effects/`
- Effect declarations: `effect fetchUser(id: UserId): Result<User, ApiError>`
- `perform` keyword: suspends the current continuation, delegates to the nearest handler
- `handle ... with` blocks: install effect handlers at any level of the component tree
- Continuation-based: handlers receive a `resume` function to continue execution
- Built-in effects: `Http`, `Time`, `Random`, `Storage`, `Console`
### Stream Engine
#### [NEW] `runtime/crates/ds-streams/`
- `Stream<T>` push-based async sequence
- Core operators: `map`, `filter`, `flatmap`, `merge`, `combine`, `debounce`, `throttle`, `distinct`, `take`, `skip`, `scan`
- `stream from <event>` creates a stream from DOM events
- Streams integrate with the signal graph: a stream's latest value is a signal
- Backpressure: drop or buffer strategies, configurable per stream
### Deliverable
A search-with-autocomplete app (`examples/search.ds`) using `debounce`, `flatmap` over an HTTP effect, with the effect handler swappable for testing.
---
## Phase 3 — Layout & Animation (Weeks 1114)
**Goal:** Constraint-based layout engine and physics-based animation, both running in WASM.
### Constraint Solver
#### [NEW] `runtime/crates/ds-layout/`
- Implement the **Cassowary** simplex-based constraint solving algorithm in Rust
- Constraint types: `eq`, `gte`, `lte`, `clamp`, `ratio`
- Reactive integration: constraints reference signals solver re-runs when inputs change
- Output: absolute `(x, y, width, height)` for each element, applied directly to DOM via `transform: translate()` (avoids reflow)
- Performance target: solve 500 constraints in <2ms
### Spring Physics
#### [NEW] `runtime/crates/ds-springs/`
- `Spring { value, velocity, target, stiffness, damping, mass }`
- RK4 integrator, fixed timestep (1/120s), interpolated for display
- `spring.target = x` triggers animation to new target (interruptible by default)
- Springs are signals anything that reads `spring.value` auto-updates
- Gesture integration: direct-manipulation by setting `spring.target` to pointer position
### Animation Scheduler
#### [NEW] `runtime/js/raf-scheduler.js`
- Drives springs via `requestAnimationFrame`
- When no springs are active, scheduler sleeps (zero CPU when idle)
- Coordinates with signal graph: spring value changes go through normal propagation
### Deliverable
A draggable panel layout (`examples/dashboard.ds`) with resizable sidebar (constraints) and spring-animated panel transitions.
---
## Phase 4 — Type System (Weeks 1518)
**Goal:** Dependent types for UI correctness guarantees.
### Type Checker
#### [NEW] `compiler/crates/ds-types/`
- **Base:** Hindley-Milner with let-generalization, structural records
- **Refinement types:** `type PositiveInt = { n: Int | n > 0 }` checked at compile time where possible, runtime where not
- **Signal-aware types:** `Signal<T>` is a first-class type; the compiler tracks which values are reactive
- **Effect types:** functions declare which effects they may perform compiler verifies all effects are handled
- **UI types:** `View` type ensures only valid UI expressions appear in `view` blocks
### Error Messages
- Inspired by Elm: suggest fixes, show the specific constraint that failed, include code context
- Signal graph visualization in error output for dependency-related errors
### Deliverable
The compiler catches: unhandled effects, type mismatches in signal derivations, invalid UI expressions all with helpful error messages.
---
## Phase 5 — Live Editor (Weeks 1924)
**Goal:** Bidirectional structural editing the killer feature.
### Incremental Compiler
#### [NEW] `compiler/crates/ds-incremental/`
- Tracks which AST nodes changed between edits
- Re-analyzes only affected signal subgraph
- Re-generates only changed DOM bindings
- Target: <50ms from keystroke to live update
### Editor Integration
#### [NEW] `editor/`
- Web-based editor (Monaco or CodeMirror 6 with custom language mode)
- Split pane: code live preview
- **Code Preview:** incremental compile on every keystroke
- **Preview Code:** click an element in preview highlights source; drag to reorder AST rewrite code updates
- State preservation: signals retain their current values across edits
### Visual Inspector
- Overlay on the live preview showing signal dependencies, constraint wires, spring states
- Click a DOM element see its signal bindings, constraint relationships, effect dependencies
### Deliverable
A working playground at `dreamstack.dev` where users can write DreamStack code and see live results with bidirectional editing.
---
## Phase 6 — Production Readiness (Weeks 2530)
**Goal:** SSR, ecosystem tooling, documentation, and real-world validation.
### Server-Side Rendering
- Compile DreamStack to static HTML + hydration script
- Streaming SSR: emit HTML as constraint solver resolves layout
- Effect handlers for server context (no DOM, no springs)
### Package System
- `dreamstack add <package>` package registry for reusable views and effect handlers
- Standard library: common UI patterns (buttons, inputs, lists, modals, toasts)
- Interop: import/export with JavaScript modules
### Documentation & Examples
- Language reference
- Tutorial: "Build a real app in 30 minutes"
- Cookbook: common patterns (forms, routing, data fetching, auth)
- Migration guide: "Coming from React" / "Coming from Svelte"
---
## Implementation Language Choices
| Component | Language | Rationale |
|---|---|---|
| Parser, Analyzer, Codegen, Type Checker | **Rust** | Performance, WASM target, memory safety without GC |
| Signal Runtime, Constraint Solver, Springs | **Rust → WASM** | Must run at 60fps, no GC pauses |
| DOM Bindings, RAF Scheduler | **JavaScript** | Must interact with browser APIs directly |
| CLI | **Rust** (clap) | Fast startup, single binary distribution |
| Editor | **TypeScript** | CodeMirror/Monaco ecosystem, web-native |
| Dev Server | **Rust** (axum) | Fast file watching, WebSocket HMR |
---
## Key Technical Risks
| Risk | Mitigation |
|---|---|
| Compile-time signal analysis is undecidable in general | Restrict to analyzable patterns; fall back to runtime tracking for dynamic cases |
| Cassowary solver is O(n²) worst case | Incremental solving; partition independent constraint groups |
| WASM JS boundary overhead for DOM updates | Batch mutations; use `FinalizationRegistry` for memory management |
| Algebraic effects require delimited continuations | Use CPS transform in codegen; or one-shot continuations via WASM stack switching (Stage 3 proposal) |
| Homoiconic representation vs performance | Two representations: rich AST for editor, optimized IR for runtime |
---
## Verification Plan
Since this is a greenfield language/framework, verification is demo-driven:
### Phase 01: Reactive Core
```bash
# Build the compiler and run the counter example
cargo build --release -p ds-cli
./target/release/dreamstack build examples/counter.ds
# Serve and verify in browser
./target/release/dreamstack dev examples/counter.ds
# Run signal propagation benchmarks
cargo bench -p ds-signals
```
### Phase 2: Effects & Streams
```bash
# Run effect system unit tests
cargo test -p ds-effects
# Run the search example with mock handler (automated test)
./target/release/dreamstack test examples/search.ds
```
### Phase 3: Layout & Animation
```bash
# Constraint solver correctness tests
cargo test -p ds-layout
# Visual regression: screenshot comparison of dashboard example
./target/release/dreamstack screenshot examples/dashboard.ds --compare snapshots/
```
### Phase 5: Live Editor
- **Manual verification:** Open the playground, type code, verify preview updates <50ms
- **Bidirectional test:** Drag an element in preview, verify code updates correspondingly
> [!IMPORTANT]
> The user should weigh in on which phase to prioritize first. The plan assumes linear progression, but Phases 13 could be parallelized if multiple contributors are involved. Phase 4 (dependent types) is the highest-risk and could be deferred to a v2.