enzotar
9d01f1b702
feat: component event callbacks + function prop forwarding
...
- ComponentUse wraps Assign/MethodCall/Block props as arrow functions
- Component prop wrapper preserves function props (typeof check)
- Event handler fallthrough calls function-type identifiers
- New: examples/callback-demo.ds with Button onClick callbacks
- All existing examples build successfully
2026-02-26 16:51:58 -08:00
enzotar
cbd6dfc7a6
feat: dynamic lists (push/remove/pop) + TodoMVC demo
...
- MethodCall AST node: obj.method(args) parsing
- Array push: items.push(x) → immutable spread+append
- Array remove: items.remove(idx) → filter by index
- Array pop: items.pop() → slice(0, -1)
- Fix: loop vars (todo, _idx) emitted without .value via is_local_var()
- Fix: _idx added to each loop scope for index-based event handlers
- New: examples/todomvc.ds — add, remove, clear all, fully reactive
2026-02-26 16:46:06 -08:00
enzotar
a7af39e900
fix: when/else parentNode null guard for slot context + match parser boundaries + showcase demo
...
- When/else inside slots: anchor parentNode is null during initial effect
Fixed with named effect function + requestAnimationFrame retry
- Match parser now terminates on ] } else tokens (works inside containers)
- Updated Progress/Badge components
- Added examples/showcase.ds: 5-section demo exercising all features
2026-02-26 16:34:45 -08:00
enzotar
5425d7768c
feat: dev server improvements - recursive watching, auto-open browser
...
- Recursive file watching: catches imported file changes from registry/
- Auto-detect project root: walks up to find registry/ or examples/ dir
- Auto-open browser on startup (xdg-open/open/cmd)
- Verified HMR live reload: 0ms recompile on file save
2026-02-26 16:19:33 -08:00
enzotar
76bb1bb3a2
feat: slot/children composition for components
...
- AST: added Expr::Slot variant
- Parser: 'slot' keyword renders children, [...] bracket children after ComponentUse
- Codegen: DS_{name}(props, __children) factory pattern
- Type checker: Slot => Type::View
- Updated Card component with slot for children
- Added examples/slot-demo.ds
2026-02-26 16:14:35 -08:00
enzotar
bb65e10f5c
feat: when/else conditional branching
...
- AST: When(cond, body) -> When(cond, body, Option<else_body>)
- Parser: optional 'else -> expr' after when body
- Codegen: reactive DOM swap with anchor comments
- Signal graph + type checker updated for 3-arg When
- Component prop signal wrapping: .value compatible accessors
- Added examples/when-else-demo.ds
2026-02-26 16:03:29 -08:00
enzotar
55dc24eecc
fix: component prop signal wrapping + import demo
...
- emit_component_decl now wraps props in signal-like accessors
- Props use { get value() { return props.X; } } pattern
- Missing props default to empty string instead of null
- Added examples/import-demo.ds demonstrating 3-component import
- Zero console errors when rendering imported Card, Badge, Button
2026-02-26 15:46:55 -08:00
enzotar
8a318e380e
fix: integer division + streaming restart
...
Codegen: BinOp::Div now emits Math.trunc(l / r)
- Clock displays 0:1:30 instead of 0.016:1.5:30
- Affects both emit_expr and predicate_to_js
Lexer: removed duplicate 'in' keyword mapping
- InKw at line 312 is canonical, removed old In at line 338
Examples: added project-tracker.ds (each loops + cards)
2026-02-26 15:22:54 -08:00
enzotar
008f164ae7
feat: each loop, dreamstack init, expanded registry
...
Language:
- each item in list -> template (reactive list rendering)
- each/in tokens in lexer, Expr::Each in AST
- Reactive forEach codegen with scope push/pop
- Container trailing props: column [...] { variant: card }
CLI:
- dreamstack init [name] - scaffold new project
- Generates app.ds, components/, dreamstack.json
- 4 starter components (button, card, badge, input)
Registry expanded to 11 components:
- NEW: progress, alert, separator, toggle, avatar
- All embedded via include_str!
CSS: progress bar, avatar, separator, alert variants,
toggle switch, stat values (230+ lines design system)
Examples:
- each-demo.ds: list rendering demo
- dashboard.ds: glassmorphism cards with container variant
2026-02-26 14:42:00 -08:00
enzotar
a290bc1891
feat: container variant props, 11-component registry, rich dashboard
...
Parser:
- column/row/stack now parse trailing { props } after ]
- Enables: column [...] { variant: "card" }
Codegen:
- Container props dispatch: variant, class, click, style, layout
- variant_to_css() maps (tag, variant) → CSS class
- variant_map_js() for dynamic variants via inline JS map
- 230+ lines design system CSS (button/badge/card/dialog/toast/
progress/alert/separator/toggle/avatar/stat)
Registry (11 components):
- button, input, card, badge, dialog, toast
- NEW: progress, alert, separator, toggle, avatar
- All embedded via include_str! for offline use
Examples:
- showcase.ds: component gallery with variant prop
- dashboard.ds: admin dashboard with glassmorphism cards
2026-02-26 13:58:33 -08:00
enzotar
7805b94704
feat: component registry with styled variants, dreamstack add/convert CLI, and showcase
...
- Phase 1: Component parser + codegen (emit_component_decl, emit_component_use, emit_match)
- Phase 2: 6 registry components (button, input, card, badge, dialog, toast)
- Phase 3: dreamstack add CLI with dependency resolution and --list/--all
- Phase 4: dreamstack convert TSX→DS transpiler with --shadcn GitHub fetch
- Phase 5: 120+ lines variant CSS (buttons, badges, cards, dialog, toast, input)
- New example: showcase.ds demonstrating all component styles
2026-02-26 13:27:49 -08:00
enzotar
61c26acfa7
improve: dependent types review — cycle detection, precision, error quality
...
- Fix ast_to_pred_expr silent Value fallback → opaque Call prevents false positives
- check_refinement now handles BoolLit/StringLit with human-readable display
- Integer equality/inequality uses exact i64 via try_resolve_ints (no f64 loss)
- Type::Refined handled in unwrap_reactive + new unwrap_refined() utility
- Type alias cycle detection via type_expr_references in Pass 0
- 9 new tests: predicate display, evaluate_static (int/compound/eq_precision),
unwrap_refined, refined type display, cycle detection, readable violations
127 workspace tests pass (25 in ds-types), 0 failures
2026-02-26 11:21:43 -08:00
enzotar
9ef28bb53a
feat: dependent types — refinement types, type aliases, type annotations
...
- Lexer: added 'type' and 'where' keywords
- AST: TypeExpr::Refined, Declaration::TypeAlias, LetDecl.type_annotation
- Parser: parse_type_alias_decl, parse_type_expr (Named, Generic, where)
- Type system: Type::Refined, Predicate/PredicateExpr with evaluate_static()
- Errors: RefinementViolation, TypeAliasCycle (Elm-style messages)
- Checker: type alias registry, resolve_type_expr, ast_to_predicate,
static refinement checking for literal values
- Codegen: Phase 1b runtime guards, predicate_to_js helper
Syntax: type PositiveInt = Int where value > 0
let count: PositiveInt = 5 -- static check passes
let count: PositiveInt = -1 -- compile error
118 tests pass (16 in ds-types, 5 new for refinements)
2026-02-26 11:09:33 -08:00
enzotar
5dcbbdca86
docs: add STREAM_COMPOSITION.md — full API reference and protocol spec
2026-02-26 10:12:29 -08:00
enzotar
a8235c48b3
feat: stream composition API — select, schema, relay filtering
...
1. Receiver-side `select` clause:
- `stream from "url" { select: field1, field2 }`
- Parser, AST, codegen all updated
- Emits: `_connectStream(url, ["field1","field2"])`
- Client-side _csFilter strips unwanted fields
2. Schema announcement (0x32):
- Sources send output schema on connect
- Lists registered signal names and mode
3. Relay schema cache:
- ChannelState stores schema from 0x32
- Forwarded to late-joining receivers
4. Relay-side subscribe filter (0x33):
- Receivers send wanted fields after connecting
- Relay strips unwanted JSON keys from 0x30/0x31
frames before forwarding — saves bandwidth
Protocol: SchemaAnnounce=0x32, SubscribeFilter=0x33
54 tests pass, all crates build clean.
2026-02-26 10:07:47 -08:00
enzotar
b5d813b9af
feat: chained signal composition — 3→1→final + mood mixing
...
Add compose-metrics.ds (Layer 1): receives counter+clock+stats,
derives uptime/events/status, re-streams on /peer/metrics. This app
is BOTH a receiver and a source.
Add compose-master.ds (Layer 2): receives chained metrics from
Layer 1 + mood direct from Layer 0. Demonstrates multi-layer
signal composition with independent stream mixing.
Verified: Uptime: 51s, Total Events: 9 flowing through the full
three-layer chain to the master dashboard.
2026-02-26 09:51:36 -08:00
enzotar
442a2db65e
fix: use explicit /peer/counter channel for streaming-counter
...
The 'default' relay channel accumulated stale Source connections from
previous sessions, causing frame delivery issues to Receivers on
/stream/default. Moving counter to an explicit /peer/counter channel
(matching clock, stats, mood pattern) fixes the composition dashboard.
All 4 streams now show live data: Count: 3, Doubled: 6.
2026-02-26 09:45:07 -08:00
enzotar
8775860fdd
feat: 4-app signal composition demo with explicit outputs
...
Add 3 new streaming apps with explicit output declarations:
- streaming-clock.ds: output hours, minutes, seconds (tick private)
- streaming-stats.ds: output total, average, max (sum private)
- streaming-mood.ds: output mood, energy, color (clicks private)
Add compose-dashboard.ds that receives all 4 streams via unique
relay channels (/stream/default, /stream/clock, /stream/stats,
/stream/mood) into a single dashboard view.
Each app demonstrates selective signal registration — only declared
outputs are streamed, internal state remains private.
2026-02-26 09:04:22 -08:00
enzotar
627ee44275
feat: explicit signal output API for stream declarations
...
Add 'output: field1, field2' syntax to stream declarations to control
which signals are exposed over the relay. Only listed signals are
registered in _signalRegistry (and thus streamed). Omitting output
streams all signals (backwards-compatible).
Also strips internal sync metadata (_pid, _v) from receiver state
so composition consumers only see clean signal values.
Parser: parse comma-separated idents after 'output:' key
AST: Vec<String> output field on StreamDecl
Codegen: conditional _registerSignal, delete _pid/_v on receive
Example: stream counter on 'ws://...' { mode: signal, output: count, doubled }
2026-02-26 08:56:32 -08:00
enzotar
b0e7de3b2e
fix: signal composition — stream derived signals, fix identity check, correct relay routing
...
- Register derived signals in _signalRegistry so _streamSync includes them
- Auto-sync all signals (source + derived) after flush() recomputes effects
- Fix Object.assign identity check: create new object so signal setter detects changes
- Change _connectStream receiver path from /signal/main to /stream/default
- Initialize stream state with {} instead of null to prevent crashes
- Emit StreamFrom bindings directly without double-wrapping in signal()
Verified: static build shows Count: 9, Doubled: 18 on composition page.
HMR interference with WebSocket connections is a separate issue.
2026-02-25 23:55:05 -08:00
enzotar
e5ff612197
feat: per-signal version counters for conflict resolution
...
- _signalVersions: monotonic counter per signal, incremented on each local mutation
- Diffs include _v: {name: version} for version comparison
- _applyRemoteDiff only applies if remote version >= local version
- Prevents stale overwrites when both devices edit simultaneously
- onopen snapshot includes version map for late-joiner consistency
2026-02-25 21:58:14 -08:00
enzotar
0290ed464a
fix: streaming polish — bind diff, state snapshot, dead code cleanup
...
- bind: input handler now emits _streamDiff so typed text syncs
- Peers broadcast full state snapshot on WS open (late joiners sync)
- Removed dead _handleRemoteInput 0x31 case (old source/receiver model)
- Preserved scroll (0x50), pointer, and key handlers
2026-02-25 21:55:49 -08:00
enzotar
8c9f5e8bfb
fix: add _streamDiff to push/pop/reverse built-ins
...
Array-mutating built-in functions now emit DS._streamDiff() for
streaming sync. Previously only signal assignments emitted diffs.
2026-02-25 21:47:50 -08:00
enzotar
a943d2e2e9
feat: peer mode relay + self-echo filtering for true bidirectional sync
...
- Added /peer/{name} route to relay: all clients are equal peers
- handle_peer: binary broadcast to all other peers, catchup for late joiners
- Simplified runtime: single /peer/ WS replaces dual source+receiver
- _peerId: random 8-char ID prevents self-echo from broadcast
- _pid in each diff JSON, filtered in _applyRemoteDiff
2026-02-25 21:37:17 -08:00
enzotar
5f09886c3c
fix: bidirectional streaming sync — phone→laptop now works
...
- Fix URL routing: /source/default and /stream/default paths
- _streamDiff sends via both source WS and receiver WS (INPUT flag)
- Source rebroadcasts 0x31 diffs from receivers to all other receivers
- Echo loop guard prevents infinite rebroadcast
2026-02-25 21:11:12 -08:00
enzotar
69c7ff1e22
feat: bidirectional signal streaming sync
...
- _signalRegistry: maps signal names → signal objects
- _registerSignal: called after each DS.signal() declaration
- _applyRemoteDiff: JSON diff → update local signals + flush
- _initStreamReceiver: parallel receiver WS for incoming diffs
- Echo loop guard: _applyingRemoteDiff prevents re-broadcasting
- 0x31 handler in _handleRemoteInput for signal diff frames
Changes sync both directions: laptop → phone, phone → laptop.
2026-02-25 21:00:57 -08:00
enzotar
0369bf831f
feat: todo app demo — streamable, showcases v2 builtins
...
Push, len, for-in with index, array access, if/then/else in elements,
string interpolation, input binding, streaming enabled.
40 lines of .ds code. Run: dreamstack stream examples/todo.ds
2026-02-25 20:51:01 -08:00
enzotar
55ec9353ae
feat: v2 codegen hardening — scoped local variables
...
Replace flat HashSet<String> local_vars with Vec<HashSet<String>> scope
stack. For-in loops push/pop scopes for loop variables. Nested loops
no longer clobber outer loop variable visibility.
Methods: push_scope(), pop_scope(), is_local_var()
110 tests, 0 failures.
2026-02-25 20:39:41 -08:00
enzotar
6368b798cf
feat: v2 module system — import/export with multi-file compilation
...
Syntax:
import { Counter, shared_count } from "./shared"
export let shared_count = 0
export component Counter = ...
Implementation:
- Lexer: Import, Export keywords
- AST: ImportDecl(names, source), Export(name, inner_decl)
- Parser: parse_import_decl, parse_export_decl
- CLI: resolve_imports() — recursive file resolution, dedup, inline
Resolves relative paths, adds .ds extension, handles transitive imports.
110 tests, 0 failures.
2026-02-25 20:36:18 -08:00
enzotar
26d6c4f17a
feat: v2 built-in functions — 90+ native functions
...
Array: len, push, pop, filter, map, concat, contains, reverse, slice,
indexOf, find, some, every, flat, sort (mutating ops re-trigger signal)
Math: abs, min, max, floor, ceil, round, random, sqrt, pow, sin, cos,
tan, atan2, clamp, lerp
String: split, join, trim, upper, lower, replace, starts_with, ends_with,
char_at, substring
Conversion: int, float, string, bool
Console: log, debug, warn
Timer: delay
Also adds ExprStatement support for top-level expressions (log, push, etc).
110 tests, 0 failures.
2026-02-25 20:30:08 -08:00
enzotar
2aa2c7ad8e
feat: step sequencer demo — reactive pads, playhead, BPM
...
Step sequencer: 4 instruments × 8 steps, timer-driven playhead,
toggleable pads, BPM controls with streaming. 75 lines of .ds code.
Parser fixes:
- UI elements checked before LParen (button (if ...) is element, not call)
- Element args support parenthesized expressions: button (if cond ...)
- StringInterp recognized as valid string start in parse_primary/parse_element
Codegen fixes:
- emit_expr checks local_vars: loop var i emits 'i' not 'i.value'
- Array index mutations re-trigger signal: pads.value = [...pads.value]
110 tests, 0 failures.
2026-02-25 19:33:12 -08:00
enzotar
2d07b1652a
feat: v2 phase 1 — array access, timer, string interpolation
...
Array access: Expr::Index in AST, [expr] postfix parsing, codegen for
reads (grid.value[i.value]) and writes (event handler assignments with
root signal extraction for stream diff broadcasting).
Timer: 'every N -> expr' declaration. Every keyword in lexer. EveryDecl
in AST. parse_every_decl in parser. setInterval codegen with DS.flush.
String interpolation: already committed separately.
Type checker: handles Expr::Index (infers array element type).
110 tests, 0 failures.
2026-02-25 19:20:20 -08:00
enzotar
70ca55b1af
docs: add USE_CASES.md — vision, revenue paths, and demo roadmap
...
5 fundamental UI redesigns: ambient UI, time-travel interfaces,
signal mixing, zero-install apps, physics-native interaction.
5 revenue applications: relay-as-a-service, live education,
collaborative design, IoT dashboards, live commerce.
Demo prioritization: step sequencer → physics playground →
whiteboard → session replay → multi-surface dashboard.
2026-02-25 18:58:12 -08:00
enzotar
cde84ae270
feat: production hardening — relay v1.0.0, receiver protocol completeness
...
Relay v1.0.0:
- Max receivers per channel (default: 64) with rejection counting
- Max channels limit (default: 256) with over-limit rejection
- Channel GC: periodic scan removes idle channels after grace period (30s)
- Source reconnection: cache preserved on disconnect, new input channels
- Stats: peak_receivers, total_connections, rejected_connections, uptime
- ChannelState::is_idle(), grace_period_expired() for lifecycle mgmt
- StateCache::clear(), has_state() for cache introspection
- Banner shows config: max receivers, max channels, grace period
- 54 tests (+8 new: channel_max_limit, idle detection, grace period, cache ops)
Receiver (_connectStream):
- Complete frame type handling: SignalSync (full replace), SignalDiff (merge),
Pixels/Keyframe (emit stream_frame), DeltaPixels (XOR + RLE decode),
Ping (keepalive), StreamEnd (emit stream_end)
- RLE decoder for delta pixel frames
- Exponential backoff reconnect (1s → capped at 10s)
- Connection stats: frames, bytes, reconnects
- Event emissions: stream_frame, stream_end for app-level handling
105 tests, 0 failures across workspace
2026-02-25 18:30:40 -08:00
enzotar
392e478351
feat: WebRTC transport — peer-to-peer data channels with auto-fallback
...
Relay:
- /signal/{channel} path for SDP/ICE exchange via WebSocket
- handle_signaling broadcasts text messages between signaling peers
- signaling_tx broadcast channel in ChannelState
- 46 ds-stream tests (+2 signaling path tests)
JS Runtime:
- _initWebRTC(signalingUrl, streamUrl, mode) with RTCPeerConnection
- Unordered DataChannel (ordered:false, maxRetransmits:0) for low latency
- Auto-fallback: WebSocket starts immediately, WebRTC upgrades in ≤5s
- Data channel override of _streamSend for transparent binary protocol
Parser/AST:
- StreamTransport enum (WebSocket, WebRTC)
- transport field in StreamDecl
- Parses: stream x on url { mode: signal, transport: webrtc }
Codegen:
- WebRTC: emits DS._initWebRTC(sigUrl, streamUrl, mode)
- WebSocket: emits DS._initStream(url, mode) (unchanged)
97 tests, 0 failures
2026-02-25 15:02:31 -08:00
enzotar
e2570b5df4
feat(examples): add streaming-physics.ds, mark all roadmap items complete
...
- streaming-physics.ds: physics scene streaming via named /source/physics channel
- Updated BITSTREAM_INTEGRATION.md: Phase B/C items marked ✅
- 95 tests, 0 failures across workspace
2026-02-25 14:53:12 -08:00
enzotar
0ed76513a6
feat(relay): multi-source routing — /source/{name} and /stream/{name}
...
- ChannelState: per-channel broadcast, input mpsc, cache
- RelayState: HashMap<String, Arc<RwLock<ChannelState>>>
- parse_path: /source/{n}, /stream/{n}, legacy / fallback
- Per-channel stats logging with channel name prefix
- Backward compatible: plain /source and /stream use 'default' channel
- 44 ds-stream tests, 95 total workspace (0 failures)
2026-02-25 14:50:39 -08:00
enzotar
2b2b4ffaec
feat(wasm): add ds-stream-wasm crate — browser codec via WebAssembly
...
- 18KB WASM binary with wasm-bindgen exports
- Header encode/decode, RLE compression, XOR delta
- Message builders for signal diff/sync and input events
- 7 native tests, all passing
- Total workspace: 89 tests, 0 failures
2026-02-25 14:45:51 -08:00
enzotar
7f795eac6a
docs: add compiler-native streaming syntax to language reference
...
- Added streaming (source/receiver) to status table
- Documented 'stream' declaration, 'stream from' expression
- Streaming modes table (signal/delta/pixel)
- CLI 'dreamstack stream' usage
2026-02-25 14:37:16 -08:00
enzotar
be811662bf
feat(examples): add streaming .ds examples — compiler-native streaming
...
- streaming-counter.ds: reactive counter with 'stream counter on ws://...'
- streaming-receiver.ds: remote receiver with 'stream from ws://...'
- E2E verified: compiles to streaming JS, connects to relay, sends signal diffs
2026-02-25 14:34:41 -08:00
enzotar
2fec039a28
docs: add Next Steps roadmap (Phases A-C) to integration spec
2026-02-25 13:31:06 -08:00
enzotar
439a775dec
feat(compiler): complete bitstream integration — all 9 changes
...
- AST: StreamDecl, StreamMode, Declaration::Stream, StreamFrom struct variant
- Lexer: Pixel, Delta, Signals keywords
- Parser: parse_stream_decl with mode block, fixed TokenKind::On match
- Signal graph: streamable flag, SignalManifest, Declaration::Stream detection
- Checker: StreamFrom { source, .. } pattern
- Codegen: DS._initStream(), DS._connectStream(), DS._streamDiff() hooks
- Runtime JS: full streaming layer with binary protocol encoding
- Layout: to_bytes/from_bytes on LayoutRect
82 tests pass (5 new: 3 parser stream + 2 analyzer streamable)
2026-02-25 13:26:59 -08:00
enzotar
980ac5c9b3
docs: mark all integration spec changes as implemented, update test counts
2026-02-25 13:25:38 -08:00
enzotar
d86818ca6a
feat(compiler): full bitstream integration across 7 pipeline stages
...
AST: StreamDecl, StreamMode, Expr::StreamFrom { source, mode }
Lexer: Pixel, Delta, Signals keywords
Parser: parse_stream_decl() with mode parsing, StreamFrom expression
Signal Graph: streamable flag on SignalNode, auto-detect stream decls
Type Checker: StreamFrom returns Type::Stream
Codegen: emit_stream_init phase, StreamFrom → DS.streamConnect(),
streaming runtime JS (WebSocket relay, binary protocol, signal frames,
remote input handler, auto-reconnect)
CLI: 'dreamstack stream' command — compile+serve with streaming enabled,
auto-inject stream declaration for the first view
All 77 workspace tests pass, 0 failures.
2026-02-25 13:13:21 -08:00
enzotar
968d62d0bb
feat(demos): sync protocol with Rust codec, add touch/gamepad support
...
- RLE format: 2-byte LE count (matches Rust rle_encode/rle_decode)
- Delta frames: FLAG_COMPRESSED flag set correctly
- Signal sync: FLAG_KEYFRAME flag + periodic sync every ~5s for late-join
- Source: handle touch, gamepad axis/button, resize inputs from receiver
- Receiver: touch event capture for mobile, ping frame handling
- Protocol constants: added FRAME_PING, INPUT_TOUCH, INPUT_GAMEPAD_*
2026-02-25 11:06:42 -08:00
enzotar
69f39746af
feat(ds-stream): RLE compression, input events, keyframe caching
...
- protocol.rs: TouchEvent, GamepadAxisEvent, GamepadButtonEvent, ResizeEvent
with encode/decode and roundtrip tests
- codec.rs: rle_encode/rle_decode for delta frame compression (333x on
unchanged frames), signal_sync_frame/signal_diff_frame builders,
touch/gamepad/stream_end convenience builders
- relay.rs: StateCache for late-joining receivers (keyframe + signal sync +
accumulated diffs), periodic keepalive pings, stats logging every 30s,
diff accumulator with cap at 1000
- BITSTREAM_INTEGRATION.md: compiler integration spec for another agent
- Tests: 17 → 38 (all passing)
2026-02-25 11:04:05 -08:00
enzotar
ea64617569
feat: physics language integration — scene container with Rapier2D WASM
...
- Add scene container to AST, lexer, parser, analyzer, and codegen
- Add circle/rect/line as UI elements for physics body declaration
- Compile scene {} to canvas + async WASM init + Rapier2D PhysicsWorld
- Reactive gravity via DS.effect() — bodies wake on gravity change
- Mouse drag interaction with impulse-based body movement
- Compile-time hex color parsing for body colors
- Fix is_signal_ref matching numeric literals (700.value bug)
- Fix body variable uniqueness (next_node_id per body)
- Fix gravity signal detection (check AST Ident before emit_expr)
- Add physics.ds example with 5 bodies + 4 gravity control buttons
- Update DREAMSTACK.md and IMPLEMENTATION_PLAN.md with Phase 10-11
- 39 tests pass across all crates, 22KB output
2026-02-25 10:58:43 -08:00
enzotar
d7961cdc98
feat: universal bitstream streaming — any input → any output
...
New crate: engine/ds-stream/
- Binary protocol: 16-byte header, typed frame/input enums
- Frame types: Pixels, Delta, Audio, Signal, Neural (0x01-0x43)
- Input types: Pointer, Key, Scroll, Gamepad, MIDI, BCI (0x01-0x90)
- WebSocket relay server (tokio + tungstenite)
- Source → receivers: frame broadcast
- Receivers → source: input routing
- Codec: encode/decode, XOR delta compression, RLE, convenience builders
- 17 unit tests, all passing
Streaming modes (stream-source.html):
1. Pixel mode: raw RGBA framebuffer (~28 MB/s)
2. Delta mode: XOR + RLE compression (~1-9 MB/s, 70-95% savings)
3. Signal mode: compact JSON signal diffs (~2 KB/s, 12000x reduction)
4. Neural mode: procedural SDF pixel generator (concept demo)
5. Audio channel: spring velocity→frequency synthesis
6. Multi-receiver: broadcast to all connected clients
Thin receiver client (stream-receiver.html, ~300 lines):
- Zero framework, zero build step
- Renders any incoming bitstream mode
- Local signal-diff renderer for signal mode
- AudioContext playback for audio frames
- Full input capture: click/drag, keyboard, scroll
- Per-channel bitstream bus visualization
DREAMSTACK.md: Phase 7 section with protocol spec
2026-02-25 10:29:44 -08:00
enzotar
a35d44bd59
feat: two-way binding, form props, and async resources
...
Phase 8 features:
- bind prop: two-way signal <-> input sync
- placeholder, value, style, disabled props
- DS.resource() for reactive async data fetching
- DS.fetchJSON() convenience wrapper
- Props-only element parsing: input { bind: x }
- examples/form.ds: contact form with validation
Fixed: double .value.value bug in bind codegen.
2026-02-25 08:08:37 -08:00
enzotar
33ed843abb
docs: add router to DREAMSTACK.md features and comparison
2026-02-25 07:54:43 -08:00