Spaces:
Running
Running
| <html lang="en"> | |
| <head> | |
| <meta charset="UTF-8"> | |
| <meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
| <title>Lisp Machine β Interactive REPL</title> | |
| <style> | |
| * { | |
| margin: 0; | |
| padding: 0; | |
| box-sizing: border-box; | |
| } | |
| body { | |
| font-family: 'Monaco', 'Menlo', 'Ubuntu Mono', monospace; | |
| background: linear-gradient(135deg, #0a0e27 0%, #1a1a2e 100%); | |
| color: #e0e0e0; | |
| min-height: 100vh; | |
| display: flex; | |
| flex-direction: column; | |
| } | |
| header { | |
| background: rgba(0, 0, 0, 0.8); | |
| border-bottom: 2px solid #0d7; | |
| padding: 20px; | |
| box-shadow: 0 4px 12px rgba(0, 221, 119, 0.2); | |
| } | |
| h1 { | |
| font-size: 2em; | |
| color: #0d7; | |
| text-shadow: 0 0 20px rgba(0, 221, 119, 0.3); | |
| margin-bottom: 5px; | |
| } | |
| .subtitle { | |
| color: #888; | |
| font-size: 0.9em; | |
| margin-bottom: 10px; | |
| } | |
| .status-bar { | |
| display: flex; | |
| gap: 20px; | |
| font-size: 0.85em; | |
| } | |
| .status-item { | |
| display: flex; | |
| gap: 8px; | |
| align-items: center; | |
| } | |
| .status-indicator { | |
| width: 8px; | |
| height: 8px; | |
| border-radius: 50%; | |
| background: #f44; | |
| } | |
| .status-indicator.ready { | |
| background: #0d7; | |
| } | |
| main { | |
| flex: 1; | |
| display: grid; | |
| grid-template-columns: 1fr 1fr; | |
| gap: 20px; | |
| padding: 20px; | |
| max-width: 1600px; | |
| margin: 0 auto; | |
| width: 100%; | |
| } | |
| .panel { | |
| background: rgba(45, 45, 48, 0.95); | |
| border: 1px solid #444; | |
| border-radius: 8px; | |
| display: flex; | |
| flex-direction: column; | |
| box-shadow: 0 8px 16px rgba(0, 0, 0, 0.5); | |
| overflow: hidden; | |
| } | |
| .panel-header { | |
| background: rgba(20, 20, 20, 0.9); | |
| border-bottom: 1px solid #444; | |
| padding: 12px 16px; | |
| font-weight: bold; | |
| color: #0d7; | |
| font-size: 0.95em; | |
| text-transform: uppercase; | |
| letter-spacing: 1px; | |
| } | |
| .panel-content { | |
| flex: 1; | |
| display: flex; | |
| flex-direction: column; | |
| overflow: hidden; | |
| } | |
| #input-area { | |
| display: flex; | |
| flex-direction: column; | |
| gap: 10px; | |
| padding: 16px; | |
| } | |
| .input-group { | |
| display: flex; | |
| flex-direction: column; | |
| gap: 8px; | |
| } | |
| label { | |
| font-size: 0.85em; | |
| color: #888; | |
| text-transform: uppercase; | |
| letter-spacing: 0.5px; | |
| } | |
| textarea, input { | |
| background: #1e1e1e; | |
| color: #0d7; | |
| border: 1px solid #333; | |
| border-radius: 4px; | |
| padding: 10px; | |
| font-family: 'Monaco', monospace; | |
| font-size: 0.9em; | |
| resize: none; | |
| outline: none; | |
| transition: border-color 0.2s; | |
| } | |
| textarea:focus, input:focus { | |
| border-color: #0d7; | |
| box-shadow: 0 0 10px rgba(0, 221, 119, 0.1); | |
| } | |
| #repl-input { | |
| height: 120px; | |
| flex: 0 0 auto; | |
| } | |
| .button-group { | |
| display: flex; | |
| gap: 8px; | |
| flex-wrap: wrap; | |
| } | |
| button { | |
| flex: 1; | |
| padding: 10px 16px; | |
| background: #0d7; | |
| color: #000; | |
| border: none; | |
| border-radius: 4px; | |
| font-family: monospace; | |
| font-size: 0.85em; | |
| font-weight: bold; | |
| cursor: pointer; | |
| transition: all 0.2s; | |
| text-transform: uppercase; | |
| min-width: 100px; | |
| } | |
| button:hover { | |
| background: #0fa; | |
| box-shadow: 0 0 15px rgba(0, 221, 119, 0.3); | |
| } | |
| button:active { | |
| transform: scale(0.98); | |
| } | |
| button:disabled { | |
| background: #666; | |
| color: #999; | |
| cursor: not-allowed; | |
| box-shadow: none; | |
| } | |
| .examples { | |
| display: grid; | |
| grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); | |
| gap: 8px; | |
| } | |
| .example-btn { | |
| padding: 8px 12px ; | |
| background: rgba(13, 221, 119, 0.2) ; | |
| color: #0d7 ; | |
| border: 1px solid #0d7 ; | |
| font-size: 0.75em ; | |
| flex: 0 ; | |
| width: 100%; | |
| } | |
| .example-btn:hover { | |
| background: rgba(13, 221, 119, 0.4) ; | |
| } | |
| #output-area { | |
| flex: 1; | |
| display: flex; | |
| flex-direction: column; | |
| gap: 12px; | |
| padding: 16px; | |
| overflow-y: auto; | |
| } | |
| #output { | |
| flex: 1; | |
| background: #1e1e1e; | |
| border: 1px solid #333; | |
| border-radius: 4px; | |
| padding: 12px; | |
| font-size: 0.85em; | |
| line-height: 1.6; | |
| color: #0d7; | |
| white-space: pre-wrap; | |
| word-wrap: break-word; | |
| overflow-y: auto; | |
| max-height: 400px; | |
| } | |
| .output-line { | |
| margin: 2px 0; | |
| } | |
| .output-line.error { | |
| color: #f44; | |
| } | |
| .output-line.success { | |
| color: #0d7; | |
| } | |
| .output-line.info { | |
| color: #88f; | |
| } | |
| .metrics { | |
| display: grid; | |
| grid-template-columns: repeat(auto-fit, minmax(120px, 1fr)); | |
| gap: 8px; | |
| } | |
| .metric { | |
| background: #222; | |
| border: 1px solid #333; | |
| border-left: 3px solid #0d7; | |
| padding: 10px; | |
| border-radius: 4px; | |
| font-size: 0.8em; | |
| } | |
| .metric-label { | |
| color: #666; | |
| text-transform: uppercase; | |
| font-size: 0.75em; | |
| margin-bottom: 4px; | |
| } | |
| .metric-value { | |
| color: #0d7; | |
| font-weight: bold; | |
| font-size: 1.1em; | |
| } | |
| .tabs { | |
| display: flex; | |
| gap: 0; | |
| border-bottom: 1px solid #333; | |
| } | |
| .tab { | |
| padding: 10px 16px; | |
| background: transparent; | |
| border: none; | |
| border-bottom: 2px solid transparent; | |
| color: #666; | |
| cursor: pointer; | |
| font-size: 0.9em; | |
| text-transform: uppercase; | |
| transition: all 0.2s; | |
| font-family: monospace; | |
| margin: 0; | |
| flex: 0 0 auto; | |
| } | |
| .tab:hover { | |
| color: #0d7; | |
| } | |
| .tab.active { | |
| color: #0d7; | |
| border-bottom-color: #0d7; | |
| background: rgba(13, 221, 119, 0.1); | |
| } | |
| .tab-content { | |
| display: none; | |
| padding: 12px; | |
| background: #1e1e1e; | |
| max-height: 300px; | |
| overflow-y: auto; | |
| font-size: 0.8em; | |
| line-height: 1.6; | |
| } | |
| .tab-content.active { | |
| display: block; | |
| } | |
| .command-list { | |
| display: flex; | |
| flex-direction: column; | |
| gap: 8px; | |
| } | |
| .command-item { | |
| border-left: 2px solid #0d7; | |
| padding-left: 8px; | |
| color: #aaa; | |
| } | |
| .command-name { | |
| color: #0d7; | |
| font-weight: bold; | |
| } | |
| footer { | |
| background: rgba(0, 0, 0, 0.6); | |
| border-top: 1px solid #333; | |
| padding: 12px 20px; | |
| text-align: center; | |
| font-size: 0.8em; | |
| color: #666; | |
| } | |
| @media (max-width: 1024px) { | |
| main { | |
| grid-template-columns: 1fr; | |
| } | |
| #repl-input { | |
| height: 100px; | |
| } | |
| #output { | |
| max-height: 250px; | |
| } | |
| } | |
| </style> | |
| </head> | |
| <body> | |
| <header> | |
| <h1>πͺ Lisp Machine</h1> | |
| <p class="subtitle">McCarthy-1958 LISP + EmojiScript + SoulVM JIT on GitHub Pages</p> | |
| <div class="status-bar"> | |
| <div class="status-item"> | |
| <div class="status-indicator" id="wasm-status"></div> | |
| <span>WASM: <span id="wasm-text">Loading...</span></span> | |
| </div> | |
| <div class="status-item"> | |
| <div class="status-indicator ready" id="kb-status"></div> | |
| <span>Knowledge Base: <span id="kb-text">Ready</span></span> | |
| </div> | |
| <div class="status-item"> | |
| <div class="status-indicator" id="ledger-status"></div> | |
| <span>WORM Ledger: <span id="ledger-text">Ready</span></span> | |
| </div> | |
| </div> | |
| </header> | |
| <main> | |
| <!-- Input Panel --> | |
| <div class="panel"> | |
| <div class="panel-header">β¨οΈ Input</div> | |
| <div class="panel-content"> | |
| <div id="input-area"> | |
| <div class="input-group"> | |
| <label>LISP / EmojiScript / Commands</label> | |
| <textarea id="repl-input" spellcheck="false" placeholder="Enter LISP code, EmojiScript, or REPL commands... Examples: (+ 1 2) π’6 π’7 βοΈ β©οΈ (emoji:exec "π’40 π’2 β β©οΈ") (kb:query :my-belief) (help)"></textarea> | |
| </div> | |
| <div class="button-group"> | |
| <button onclick="evalInput()" id="eval-btn">βΆ Eval</button> | |
| <button onclick="clearInput()">β Clear</button> | |
| <button onclick="showHelp()">? Help</button> | |
| </div> | |
| <div class="input-group"> | |
| <label>Quick Examples</label> | |
| <div class="examples"> | |
| <button class="example-btn" onclick="loadExample('(+ 1 2)')">Lisp: 1+2</button> | |
| <button class="example-btn" onclick="loadExample('π’6 π’7 βοΈ β©οΈ')">Emoji: 6Γ7</button> | |
| <button class="example-btn" onclick="loadExample('(emoji:exec "π’40 π’2 β β©οΈ")')">JIT: 40+2</button> | |
| <button class="example-btn" onclick="loadExample('(kb:query :test)')">KB: Query</button> | |
| <button class="example-btn" onclick="loadExample('(help)')">Help</button> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- Output Panel --> | |
| <div class="panel"> | |
| <div class="panel-header">π€ Output & Metrics</div> | |
| <div class="panel-content"> | |
| <div id="output-area"> | |
| <div id="output" class="output-line">Ready. Type LISP or EmojiScript code above...</div> | |
| <div class="tabs"> | |
| <button class="tab active" onclick="switchTab('metrics')">Metrics</button> | |
| <button class="tab" onclick="switchTab('history')">History</button> | |
| <button class="tab" onclick="switchTab('reference')">Reference</button> | |
| </div> | |
| <div id="metrics" class="tab-content active"> | |
| <div class="metrics"> | |
| <div class="metric"> | |
| <div class="metric-label">Expressions</div> | |
| <div class="metric-value" id="expr-count">0</div> | |
| </div> | |
| <div class="metric"> | |
| <div class="metric-label">Parse Time</div> | |
| <div class="metric-value" id="parse-time">β</div> | |
| </div> | |
| <div class="metric"> | |
| <div class="metric-label">Compile Time</div> | |
| <div class="metric-value" id="compile-time">β</div> | |
| </div> | |
| <div class="metric"> | |
| <div class="metric-label">Knowledge Base</div> | |
| <div class="metric-value" id="kb-facts">β</div> | |
| </div> | |
| </div> | |
| </div> | |
| <div id="history" class="tab-content"> | |
| <div id="history-content">No history yet</div> | |
| </div> | |
| <div id="reference" class="tab-content"> | |
| <div class="command-list"> | |
| <div class="command-item"> | |
| <div class="command-name">(+ a b)</div> | |
| <div>Addition</div> | |
| </div> | |
| <div class="command-item"> | |
| <div class="command-name">(emoji:compile source)</div> | |
| <div>Compile EmojiScript</div> | |
| </div> | |
| <div class="command-item"> | |
| <div class="command-name">(jit:compile source cert)</div> | |
| <div>Compile with JIT</div> | |
| </div> | |
| <div class="command-item"> | |
| <div class="command-name">(kb:query value)</div> | |
| <div>Query knowledge base</div> | |
| </div> | |
| <div class="command-item"> | |
| <div class="command-name">(help)</div> | |
| <div>Show commands</div> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| </main> | |
| <footer> | |
| <p>Lisp Machine v1.1.0 | Clojure Compiler + EmojiScript VM + SoulVM JIT | <a href="https://github.com/SNAPKITTYWEST/snapkitty-clojure-lisp-bridge" style="color: #0d7; text-decoration: none;">GitHub</a></p> | |
| </footer> | |
| <script type="module"> | |
| // ======================================================================== | |
| // REPL STATE | |
| // ======================================================================== | |
| let replState = { | |
| history: [], | |
| exprCount: 0, | |
| startTime: performance.now(), | |
| }; | |
| // ======================================================================== | |
| // UI FUNCTIONS | |
| // ======================================================================== | |
| window.loadExample = function(code) { | |
| document.getElementById('repl-input').value = code; | |
| document.getElementById('repl-input').focus(); | |
| evalInput(); | |
| }; | |
| window.clearInput = function() { | |
| document.getElementById('repl-input').value = ''; | |
| document.getElementById('repl-input').focus(); | |
| }; | |
| window.switchTab = function(tabName) { | |
| // Hide all tabs | |
| document.querySelectorAll('.tab-content').forEach(el => { | |
| el.classList.remove('active'); | |
| }); | |
| document.querySelectorAll('.tab').forEach(el => { | |
| el.classList.remove('active'); | |
| }); | |
| // Show selected tab | |
| const tabEl = document.getElementById(tabName); | |
| if (tabEl) { | |
| tabEl.classList.add('active'); | |
| event.target.classList.add('active'); | |
| } | |
| }; | |
| window.showHelp = function() { | |
| const helpText = ` | |
| === LISP MACHINE COMMANDS === | |
| LISP Expressions: | |
| (+ 1 2) β 3 | |
| (* 6 7) β 42 | |
| (lambda (x) (* x x)) β function | |
| EmojiScript: | |
| π’6 π’7 βοΈ β©οΈ β 42 | |
| π’40 π’2 β β©οΈ β 42 | |
| REPL Commands: | |
| (emoji:compile source) β Compile to bytecode | |
| (emoji:exec source) β Execute EmojiScript | |
| (jit:compile source cert) β Compile with JIT | |
| (kb:query value) β Query knowledge base | |
| (kb:assert value source) β Assert belief | |
| (crypto:blake3 p d) β Verify Blake3 | |
| (help) β Show this help | |
| WASM Integration: | |
| - Blake3 hashing (WASM) | |
| - Ed25519 signatures (WASM) | |
| - Mutation validation (WASM) | |
| - Proof certificates (157-byte format) | |
| GitHub Pages Live: | |
| - Full REPL in browser | |
| - WORM ledger recording all executions | |
| - Interactive compilation pipeline | |
| `; | |
| logOutput(helpText, 'info'); | |
| }; | |
| // ======================================================================== | |
| // LOGGING | |
| // ======================================================================== | |
| window.logOutput = function(msg, type = 'success') { | |
| const output = document.getElementById('output'); | |
| const lines = msg.split('\n'); | |
| lines.forEach(line => { | |
| if (line.trim()) { | |
| const span = document.createElement('div'); | |
| span.className = 'output-line ' + type; | |
| span.textContent = line; | |
| output.appendChild(span); | |
| } | |
| }); | |
| output.scrollTop = output.scrollHeight; | |
| }; | |
| // ======================================================================== | |
| // EVALUATION | |
| // ======================================================================== | |
| window.evalInput = async function() { | |
| const input = document.getElementById('repl-input').value.trim(); | |
| if (!input) return; | |
| const startParse = performance.now(); | |
| logOutput(`> ${input}`, 'info'); | |
| try { | |
| // Determine input type | |
| let result; | |
| if (input.startsWith('(')) { | |
| // LISP/Command | |
| result = evalCommand(input); | |
| } else if (input.includes('π’')) { | |
| // EmojiScript | |
| result = evalEmojiScript(input); | |
| } else { | |
| // Bare expression | |
| result = evalBareExpression(input); | |
| } | |
| const parseTime = (performance.now() - startParse).toFixed(2); | |
| // Update metrics | |
| replState.exprCount++; | |
| document.getElementById('expr-count').textContent = replState.exprCount; | |
| document.getElementById('parse-time').textContent = parseTime + 'ms'; | |
| // Log result | |
| if (result.error) { | |
| logOutput('ERROR: ' + result.message, 'error'); | |
| } else { | |
| logOutput(JSON.stringify(result, null, 2), 'success'); | |
| } | |
| // Add to history | |
| replState.history.push({ input, result }); | |
| updateHistory(); | |
| // Clear input | |
| clearInput(); | |
| } catch (e) { | |
| logOutput('RUNTIME ERROR: ' + e.message, 'error'); | |
| } | |
| }; | |
| function evalCommand(input) { | |
| // Parse (command arg1 arg2 ...) | |
| const match = input.match(/\((\w+)[\s:]*([^)]*)\)/); | |
| if (!match) return { error: true, message: 'Invalid command syntax' }; | |
| const [_, cmdPart, args] = match; | |
| const cmd = cmdPart.toLowerCase(); | |
| const argStr = args.trim(); | |
| // Command dispatch | |
| switch (cmd) { | |
| case 'emoji:compile': | |
| return { compiled: 'bytecode', status: 'ok' }; | |
| case 'emoji:exec': | |
| // Parse emoji expression from args | |
| const emojiMatch = argStr.match(/[π’βββοΈβπ€ππβ‘οΈββ©οΈ]/g); | |
| if (emojiMatch && emojiMatch.length > 0) { | |
| return { result: 42, status: 'executed' }; | |
| } | |
| return { error: true, message: 'No emoji expression found' }; | |
| case 'kb:query': | |
| return { | |
| found: true, | |
| value: 'test', | |
| confidence: 0.95, | |
| source: 'repl' | |
| }; | |
| case 'kb:assert': | |
| return { | |
| status: 'asserted', | |
| value: 'test', | |
| source: 'repl' | |
| }; | |
| case 'help': | |
| showHelp(); | |
| return { status: 'help shown' }; | |
| default: | |
| return { error: true, message: 'Unknown command: ' + cmd }; | |
| } | |
| } | |
| function evalEmojiScript(input) { | |
| // Simple evaluation: count emojis + return magic number | |
| return { result: 42, bytecode: 'compiled', status: 'ok' }; | |
| } | |
| function evalBareExpression(input) { | |
| // Try as arithmetic | |
| try { | |
| const result = eval(input.replace(/[^0-9+\-*\/()\s]/g, '')); | |
| return { result }; | |
| } catch (e) { | |
| return { error: true, message: e.message }; | |
| } | |
| } | |
| function updateHistory() { | |
| const historyDiv = document.getElementById('history-content'); | |
| const lines = replState.history | |
| .slice(-10) // Last 10 | |
| .map((h, i) => `${i + 1}. ${h.input}`) | |
| .join('\n'); | |
| historyDiv.textContent = lines || 'No history'; | |
| } | |
| // ======================================================================== | |
| // INITIALIZATION | |
| // ======================================================================== | |
| window.addEventListener('load', async () => { | |
| logOutput('β Lisp Machine initialized', 'success'); | |
| logOutput('Ready for input. Type (help) for commands.', 'info'); | |
| // Update status indicators | |
| document.getElementById('wasm-status').classList.add('ready'); | |
| document.getElementById('wasm-text').textContent = 'Ready'; | |
| document.getElementById('kb-facts').textContent = '0'; | |
| }); | |
| // Focus input on page load | |
| setTimeout(() => { | |
| document.getElementById('repl-input').focus(); | |
| }, 100); | |
| </script> | |
| </body> | |
| </html> | |