diff options
Diffstat (limited to 'forth/foreforthfourth/index.html')
-rw-r--r-- | forth/foreforthfourth/index.html | 381 |
1 files changed, 381 insertions, 0 deletions
diff --git a/forth/foreforthfourth/index.html b/forth/foreforthfourth/index.html new file mode 100644 index 0000000..a4400f3 --- /dev/null +++ b/forth/foreforthfourth/index.html @@ -0,0 +1,381 @@ +<!DOCTYPE html> +<html lang="en"> +<head> + <meta charset="UTF-8"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> + <title>4-Stack Forth</title> + <style> + body { + font-family: 'Courier New', monospace; + margin: 0; + padding: 10px; + background-color: #000; + color: #fff; + min-height: 100vh; + display: flex; + flex-direction: column; + } + + .container { + max-width: 100%; + flex: 1; + display: flex; + flex-direction: column; + } + + h1 { + font-size: 18px; + margin: 0 0 10px 0; + text-align: center; + } + + .help { + background-color: #111; + border: 1px solid #333; + padding: 10px; + margin-bottom: 10px; + font-size: 12px; + line-height: 1.3; + } + + .help h2 { + margin: 0 0 5px 0; + font-size: 13px; + } + + .help p { + margin: 0; + } + + .stacks-container { + display: grid; + grid-template-columns: repeat(4, 1fr); + gap: 8px; + margin-bottom: 10px; + flex: 1; + min-height: 200px; + } + + .stack { + border: 2px solid; + padding: 8px; + display: flex; + flex-direction: column; + background-color: #111; + position: relative; + transition: all 0.3s ease; + } + + .stack.focused { + border-width: 4px; + box-shadow: 0 0 15px rgba(255, 255, 255, 0.3); + transform: scale(1.02); + } + + .stack-1 { border-color: #ff6b6b; } + .stack-2 { border-color: #4ecdc4; } + .stack-3 { border-color: #45b7d1; } + .stack-4 { border-color: #f9ca24; } + + .stack h3 { + margin: 0 0 8px 0; + text-align: center; + font-size: 12px; + color: #fff; + } + + .stack-items { + flex: 1; + display: flex; + flex-direction: column-reverse; + gap: 2px; + align-items: stretch; + } + + .stack-item { + background-color: #222; + padding: 4px 6px; + text-align: center; + border: 1px solid #555; + font-size: 12px; + word-break: break-all; + } + + .input-section { + margin-bottom: 10px; + } + + .input-container { + display: flex; + gap: 5px; + margin-bottom: 8px; + } + + #forth-input { + flex: 1; + padding: 8px; + font-family: 'Courier New', monospace; + font-size: 14px; + border: 1px solid #555; + background-color: #111; + color: #fff; + } + + #forth-input:focus { + outline: none; + border-color: #fff; + } + + button { + padding: 8px 12px; + font-family: 'Courier New', monospace; + font-size: 12px; + border: 1px solid #fff; + background-color: #000; + color: #fff; + cursor: pointer; + } + + button:hover, button:active { + background-color: #fff; + color: #000; + } + + .output { + background-color: #111; + border: 1px solid #555; + padding: 8px; + height: 300px; + overflow-y: auto; + font-family: 'Courier New', monospace; + font-size: 12px; + line-height: 1.3; + } + + /* Semantic section styling */ + section { + margin-bottom: 10px; + } + + section h2 { + margin: 0 0 8px 0; + font-size: 14px; + color: #fff; + } + + .output-section h2 { + margin-bottom: 5px; + } + + .error { + color: #fff; + } + + .success { + color: #fff; + } + + /* Screen reader only content */ + .sr-only { + position: absolute; + width: 1px; + height: 1px; + padding: 0; + margin: -1px; + overflow: hidden; + clip: rect(0, 0, 0, 0); + white-space: nowrap; + border: 0; + } + + /* Mobile optimizations */ + @media (max-width: 768px) { + body { padding: 5px; } + + h1 { font-size: 16px; } + + .help { + font-size: 11px; + padding: 8px; + } + + .help h2 { + font-size: 12px; + } + + .stacks-container { + gap: 4px; + min-height: 150px; + } + + .stack { + padding: 6px; + } + + .stack h3 { + font-size: 11px; + margin-bottom: 6px; + } + + .stack-item { + font-size: 11px; + padding: 3px 4px; + } + + #forth-input { + font-size: 16px; /* Prevents zoom on iOS */ + padding: 6px; + } + + button { + font-size: 11px; + padding: 6px 10px; + } + + .output { + height: 80px; + font-size: 11px; + padding: 6px; + } + } + + @media (max-width: 480px) { + .stacks-container { + grid-template-columns: repeat(2, 1fr); + grid-template-rows: repeat(2, 1fr); + } + + .input-container { + flex-direction: column; + } + + button { + width: 100%; + } + } + </style> +</head> +<body> + <header> + <h1>4-Stack Forth</h1> + </header> + + <main class="container"> + <section class="help" aria-label="Quick help"> + <h2>Quick Help</h2> + <p>Type <strong>help</strong> to see all available words with documentation and stack effects. Add a word to the stack like <code>s" dup"</code> and then run <code>doc</code> to see documentation for that word.</p> + <p><strong>Stack Focus:</strong> Use <code>focus.red</code>, <code>focus.teal</code>, <code>focus.blue</code>, or <code>focus.yellow</code> (or <code>focus.1</code>, <code>focus.2</code>, <code>focus.3</code>, <code>focus.4</code>) to switch which stack operations target. Currently focused: <span id="current-focus">Red (1)</span></p> + </section> + + <section class="stacks-container" aria-label="Data stacks"> + <h2 class="sr-only">Data Stacks</h2> + <div class="stack stack-1" role="region" aria-label="Stack 1 (Red)" id="stack-1"> + <h3>Stack 1 (Red)</h3> + <div class="stack-items" id="stack-1-items" aria-live="polite"></div> + </div> + <div class="stack stack-2" role="region" aria-label="Stack 2 (Teal)" id="stack-2"> + <h3>Stack 2 (Teal)</h3> + <div class="stack-items" id="stack-2-items" aria-live="polite"></div> + </div> + <div class="stack stack-3" role="region" aria-label="Stack 3 (Blue)" id="stack-3"> + <h3>Stack 3 (Blue)</h3> + <div class="stack-items" id="stack-3-items" aria-live="polite"></div> + </div> + <div class="stack stack-4" role="region" aria-label="Stack 4 (Yellow)" id="stack-4"> + <h3>Stack 4 (Yellow)</h3> + <div class="stack-items" id="stack-4-items" aria-live="polite"></div> + </div> + </section> + + <section class="input-section" aria-label="Command input"> + <h2 class="sr-only">Command Input</h2> + <div class="input-container"> + <label for="forth-input" class="sr-only">Forth command input</label> + <input type="text" id="forth-input" placeholder="Enter Forth commands here..." aria-describedby="input-help" /> + <button type="button" onclick="executeForth()" aria-label="Execute command">Run</button> + <button type="button" onclick="clearAll()" aria-label="Clear all stacks">Clear</button> + </div> + <div id="input-help" class="sr-only">Press Enter to execute commands</div> + </section> + + <section class="output-section" aria-label="Command output"> + <h2 class="sr-only">Output</h2> + <div class="output" id="output" role="log" aria-live="polite" aria-label="Forth interpreter output"></div> + </section> + </main> + + <script src="forth.js"></script> + <script> + let forthState = ForthInterpreter.createInitialState(); + + + + // Update visual display + const updateDisplay = () => { + // Update stacks + forthState.stacks.forEach((stack, index) => { + const container = document.getElementById(`stack-${index + 1}-items`); + container.innerHTML = ''; + stack.forEach(item => { + const div = document.createElement('div'); + div.className = 'stack-item'; + div.textContent = item.toString(); + container.appendChild(div); + }); + }); + + // Update focus indicator + document.querySelectorAll('.stack').forEach((stack, index) => { + if (index === forthState.focusedStack) { + stack.classList.add('focused'); + } else { + stack.classList.remove('focused'); + } + }); + + // Update focus text + const focusNames = ['Red (1)', 'Teal (2)', 'Blue (3)', 'Yellow (4)']; + document.getElementById('current-focus').textContent = focusNames[forthState.focusedStack]; + + // Update output + const outputElement = document.getElementById('output'); + outputElement.innerHTML = forthState.output + .slice(-100) // Show last 100 messages for better help display + .map(msg => { + const className = msg.startsWith('Error:') ? 'error' : 'success'; + return `<div class="${className}">${msg}</div>`; + }) + .join(''); + outputElement.scrollTop = outputElement.scrollHeight; + }; + + // Execute Forth commands + const executeForth = () => { + const input = document.getElementById('forth-input'); + const command = input.value.trim(); + + if (command) { + forthState = ForthInterpreter.parseAndExecute(forthState, command); + updateDisplay(); + input.value = ''; + } + }; + + // Clear all stacks + const clearAll = () => { + forthState = ForthInterpreter.createInitialState(); + updateDisplay(); + }; + + // Handle Enter key in input + document.getElementById('forth-input').addEventListener('keypress', (e) => { + if (e.key === 'Enter') { + executeForth(); + } + }); + + // Initialize display + updateDisplay(); + </script> +</body> +</html> \ No newline at end of file |