Monorepo for Aesthetic.Computer aesthetic.computer
4
fork

Configure Feed

Select the types of activity you want to include in your feed.

at main 229 lines 6.0 kB view raw view rendered
1# KidLisp Live Parameter Editing 2 3## 🎯 Goal 4Enable live editing of KidLisp variables (like framerate, line coordinates, colors) while the program is running, without restarting from frame 0. 5 6## 💡 Concept 7When you change a `def` value in the editor while the code is playing, update only that variable in the running instance instead of reloading the entire program. 8 9## 🎬 User Experience 10 11### Before (Current) 12```lisp 13(def speed 5) 14(def color "red") 15(line 0 0 100 100) 16``` 17- User edits `speed 5``speed 10` 18- Presses Enter/Play 19- **Program restarts from frame 0** (frameCount resets, all state lost) 20 21### After (Proposed) 22```lisp 23(def speed 5) 24(def color "red") 25(line 0 0 100 100) 26``` 27- User edits `speed 5``speed 10` 28- **Variable updates live**, program keeps running 29- Frame count continues, timing state preserved 30- Only the changed variable updates 31 32## 🔧 Implementation Strategy 33 34### Phase 1: Variable Hot-Swapping (Simplest) 35 36Detect when only `def` statements have changed: 37 38```javascript 39// In kidlisp.mjs 40updateVariable(name, value) { 41 // Update the variable without restarting 42 this.globalDef[name] = value; 43 // Keep frameCount, timing state, etc. 44} 45 46// In kidlisp.com or boot.mjs 47function handleCodeUpdate(newCode, oldCode) { 48 const changedDefs = detectChangedDefs(newCode, oldCode); 49 50 if (changedDefs.length > 0 && onlyDefsChanged(newCode, oldCode)) { 51 // Hot-swap the variables 52 changedDefs.forEach(({ name, value }) => { 53 kidlispInstance.updateVariable(name, value); 54 }); 55 // Don't reload, keep running! 56 } else { 57 // Structure changed, do full reload 58 kidlispInstance.reload(newCode); 59 } 60} 61``` 62 63### Phase 2: Smart Diff Detection 64 65Compare AST to detect what changed: 66 67```javascript 68function detectChanges(oldAST, newAST) { 69 return { 70 defsChanged: [...], // Variable definitions that changed 71 codeChanged: false, // Whether non-def code changed 72 timingChanged: false, // Whether timing expressions changed 73 }; 74} 75``` 76 77### Phase 3: Partial Recompilation (Advanced) 78 79For more complex changes: 80- Changed `def` → hot-swap variable 81- Changed function body → recompile function, keep state 82- Changed timing expression → update timing map, keep counters 83- Changed drawing code → reparse that section 84 85## 📊 What to Preserve 86 87### Must Keep Running 88- `frameCount` - Current frame number 89- `lastSecondExecutions` - Timing state for `1s...`, `2s...` etc 90- `sequenceCounters` - Sequence state for timing 91- `onceExecuted` - Track of `once` blocks 92- Embedded layer buffers 93- `bakes` - Baked background layers 94 95### Can Update 96- `globalDef` - Variables defined with `(def ...)` 97- Parsed AST if code structure changed 98- Function definitions (`later` functions) 99 100## 🎨 UI Considerations 101 102### Visual Feedback 103``` 104🔴 PLAYING (Frame 234) ← Show it's running 105✏️ Variable 'speed' updated (5 → 10) ← Confirm change 106``` 107 108### Keyboard Shortcuts 109- `Cmd+Enter` - Smart reload (hot-swap if possible, full reload if needed) 110- `Cmd+Shift+Enter` - Force full reload (restart from frame 0) 111 112## 🏗️ Architecture 113 114### kidlisp.mjs Changes 115```javascript 116class KidLisp { 117 // New method 118 hotUpdateVariable(name, value) { 119 this.globalDef[name] = value; 120 // Invalidate any cached evaluations that use this variable 121 this.invalidateVariableCache(name); 122 } 123 124 // New method 125 canHotUpdate(newSource) { 126 const newAST = this.parse(newSource); 127 const diff = this.diffAST(this.ast, newAST); 128 return diff.onlyDefsChanged; 129 } 130 131 // Enhanced reload 132 reload(newSource, options = {}) { 133 if (options.preserveState && this.canHotUpdate(newSource)) { 134 // Hot update path 135 this.hotUpdate(newSource); 136 } else { 137 // Full reload path (current behavior) 138 this.fullReload(newSource); 139 } 140 } 141} 142``` 143 144### boot.mjs Changes 145```javascript 146// Enhance existing kidlisp-reload handler 147if (event.data?.type === "kidlisp-reload") { 148 const code = event.data.code; 149 const preserveState = event.data.preserveState !== false; 150 151 window.acSEND({ 152 type: "piece-reload", 153 content: { 154 source: code, 155 preserveState: preserveState // NEW 156 } 157 }); 158} 159``` 160 161### kidlisp.com Changes 162```javascript 163// Add option to preserve state 164function sendCode(preserveState = true) { 165 previewIframe.contentWindow.postMessage({ 166 type: 'kidlisp-reload', 167 code: editor.getValue(), 168 preserveState: preserveState // NEW 169 }, aestheticUrl); 170} 171 172// Keyboard shortcuts 173editor.addCommand(monaco.KeyMod.CtrlCmd | monaco.KeyCode.Enter, () => { 174 sendCode(true); // Smart reload 175}); 176 177editor.addCommand(monaco.KeyMod.CtrlCmd | monaco.KeyMod.Shift | monaco.KeyCode.Enter, () => { 178 sendCode(false); // Force full reload 179}); 180``` 181 182## 🧪 Test Cases 183 184### Should Hot-Update 185```lisp 186; Change value 187(def speed 5) (def speed 10) 188 189; Change color 190(def color "red") (def color "blue") 191 192; Change multiple defs 193(def x 10) 194(def y 20) 195``` 196 197### Should Full-Reload 198```lisp 199; Add new code 200(line 0 0 100 100) (line 0 0 100 100) (circle 50 50 25) 201 202; Change timing 203(1s (ink red)) (2s (ink red)) 204 205; Change structure 206(repeat 5 i (box i)) (repeat 10 i (box i)) 207``` 208 209## 🚀 Benefits 210 2111. **Faster iteration** - Tweak values without losing animation progress 2122. **Better debugging** - See parameter effects immediately 2133. **Live performance** - Adjust values during live coding performances 2144. **Teaching tool** - Show immediate cause/effect of parameter changes 215 216## 📝 Notes 217 218- Start simple: only hot-swap `def` changes 219- Can expand to timing expressions, function bodies later 220- Keep full reload as fallback for complex changes 221- Consider auto-detection vs manual mode selection 222 223## 🎯 Success Criteria 224 225- ✅ Can change `(def speed 5)` to `(def speed 10)` while running 226- ✅ Frame count continues from current value 227- ✅ Timing state (1s..., 2s...) preserved 228- ✅ Visual feedback shows what was updated 229- ✅ Fallback to full reload for structural changes