enzotar
f4e5ace37c
feat: *= /= operators + 6 new array methods
...
New assignment operators (full pipeline: lexer → parser → analyzer → codegen):
- *= (MulAssign): count *= 2
- /= (DivAssign): count /= 2
New array methods in event handler (all flush signal + stream diff):
- .clear() → items = []
- .insert(i, v) → splice at index
- .sort() → immutable sort
- .reverse() → immutable reverse
- .filter(fn) → filter in place
- .map(fn) → map in place
New example: language-features.ds (65KB)
- Tests all assignment ops (+=, -=, *=, /=)
- Tests array methods (push, pop, sort, reverse, clear)
- Tests match expressions
- Tests comparison operators
- Tests derived signals (let doubled = count * 2)
- Browser-verified: zero console errors
All 11 examples pass.
2026-02-26 20:29:35 -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
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
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
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
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
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
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
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
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
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
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
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
adff40d47f
feat: hash-based router + keyed list reconciliation
...
Phase 7 features:
- route "/path" -> body declarations with hash-based routing
- navigate "/path" built-in function
- DS.route signal tracks current hash path
- DS.matchRoute() with :param pattern matching
- DS.keyedList() for keyed DOM reconciliation
- Route-aware mounting: views + routes compose
- examples/router.ds: 3-page app (home/about/counter)
- State persists across route changes (10818 bytes)
2026-02-25 07:54:00 -08:00
enzotar
ca45c688df
feat: for-in list rendering + component system
...
Phase 6 features:
- ForIn reactive list rendering: for item in items -> body
- Optional index binding: for item, idx in items -> body
- Component declarations: component Name(props) = body
- Component instantiation: ComponentUse { name, props }
Added across 5 crates:
- ds-parser: For/In/Component tokens, ForIn/ComponentDecl AST nodes
- ds-codegen: reactive list effect, component function emission
- ds-types: ForIn/ComponentUse type inference
- local_vars tracking for non-reactive for-in loop vars
Includes examples/list.ds showcasing for-in + when + signals.
2026-02-25 01:33:28 -08:00
enzotar
a634152318
feat: DreamStack compiler foundation — Phase 0/1
...
Complete compiler pipeline from .ds source to reactive browser apps:
- ds-parser: lexer (string interpolation, operators, keywords) + recursive
descent parser with operator precedence + full AST types
- ds-analyzer: signal graph extraction (source/derived classification),
topological sort for glitch-free propagation, DOM binding analysis
- ds-codegen: JavaScript emitter with embedded reactive runtime (~3KB
signal/derived/effect system) and dark-theme CSS design system
- ds-cli: build (compile to HTML+JS), dev (live server), check (analyze)
Verified working: source signals, derived signals, event handlers,
conditional rendering (when), 12 unit tests passing, 6.8KB output.
2026-02-25 00:03:06 -08:00