From 365312b14723503424a601a49827c191af82ad7a Mon Sep 17 00:00:00 2001 From: Brian Cully Date: Sat, 23 Aug 2025 13:40:37 -0400 Subject: begginnenblinken --- index.html | 47 +++++++++++++++++++++++++++++----------------- main.css | 52 +++++++++++++++++++++++++++++++++++++++++++++++---- main.mjs | 63 ++++++++++++++++++++++++++++++++++++++------------------------ src/lib.rs | 6 +----- 4 files changed, 118 insertions(+), 50 deletions(-) diff --git a/index.html b/index.html index 7e2d4c6..8b96298 100644 --- a/index.html +++ b/index.html @@ -7,7 +7,11 @@

automathon

- - - - -
- stack -
    -
    -
    - call stack -
      -
      -
      - word list -
      -
      +drop + +
      +
      +
      + + + +
      +
      + word list +
      +
      +
      + stack +
        +
        +
        + call stack +
          +
          +
          +
          + +
          no canvas! diff --git a/main.css b/main.css index 7a032cc..960db69 100644 --- a/main.css +++ b/main.css @@ -1,10 +1,50 @@ -canvas { - border: 1px solid greenyellow; +html { + box-sizing: border-box; +} +*, *::before, *::after { + box-sizing: inherit; } -textarea { - width: 25em; +#editor { + display: grid; + grid-template-columns: repeat(2, 1fr); + grid-gap: 1em; +} + +#code { + position: relative; + grid-row: 1; +} + +#code textarea { + width: 100%; height: 25ex; + margin-top: 1ex; + padding: 1em; +} + +#compile { + position: absolute; + right: 0; +} + +#state-container { + grid-row: 1; +} + +#state { + display: grid; + grid-template-columns: repeat(2, 1fr); +} + +#state .controls { + grid-row: 1; + grid-column: 1 / span 2; +} + +#state .wordlist { + grid-row: 2; + grid-column: 1 / span 2; } #wordlist .ip { @@ -28,3 +68,7 @@ x-op { padding: 5px; border: 1px solid grey; } + +canvas { + border: 1px solid greenyellow; +} diff --git a/main.mjs b/main.mjs index f8c9267..dcd2ec7 100644 --- a/main.mjs +++ b/main.mjs @@ -15,9 +15,7 @@ function wordlistElts(wordlist) { } function selectorForIP(word, offset) { - const sel = `#wordlist x-bytecode[x-index='${word}'] x-op[x-index='${offset}']`; - console.debug('using sel', sel); - return sel; + return `#wordlist x-bytecode[x-index='${word}'] x-op[x-index='${offset}']`; } function initWordlist() { @@ -34,10 +32,8 @@ function renderStack(interp) { } interp.stack().reverse() .forEach(datum => { - console.debug('creating elt for', datum); const elt = document.createElement('li'); elt.textContent = datum; - console.debug('elt', elt); e.appendChild(elt); return elt; }); @@ -51,16 +47,29 @@ function renderCallStack(interp) { } interp.callstack().reverse() .forEach(datum => { - console.debug('creating elt for', datum); const elt = document.createElement('li'); elt.textContent = `${datum.word}@${datum.offset}`; - console.debug('elt', elt); e.appendChild(elt); return elt; }); }); } +function tick(interp) { + if (!interp.tick()) { + interp.reset_ip(); + } + + const { word, offset } = interp.ip(); + document.querySelectorAll('#wordlist .ip').forEach(e => e.classList.remove('ip')); + const sel = selectorForIP(word, offset); + document.querySelectorAll(sel).forEach(e => { + e.classList.add('ip'); + }); + renderStack(interp); + renderCallStack(interp); +} + async function loaded() { console.debug('running init'); const mod = await init(); @@ -75,7 +84,6 @@ async function loaded() { console.debug('removing child', wordlistContainer.lastChild) wordlistContainer.removeChild(wordlistContainer.lastChild); } - console.debug('container has firstchild', wordlistContainer.firstChild) // always add a newline until i decide what to do with the parser. const text = document.querySelector('textarea').value + '\n'; @@ -87,25 +95,13 @@ async function loaded() { const wordlist = wordlistElts(interp.wordlist()); wordlist.forEach(elt => wordlistContainer.appendChild(elt)); initWordlist(); + renderStack(interp); + renderCallStack(interp); } }; document.querySelector('#tick').onclick = e => { console.debug('tick clicked', e); - if (!interp.tick()) { - interp.reset_ip(); - } - console.info('callstack', interp.callstack()); - console.info('stack', interp.stack()); - - const { word, offset } = interp.ip(); - console.info('ip', word, offset); - document.querySelectorAll('#wordlist .ip').forEach(e => e.classList.remove('ip')); - const sel = selectorForIP(word, offset); - document.querySelectorAll(sel).forEach(e => { - e.classList.add('ip'); - }); - renderStack(interp); - renderCallStack(interp); + tick(interp); }; document.querySelector('#bench').onclick = e => { console.debug('bench clicked', e); @@ -115,9 +111,28 @@ async function loaded() { tickCount += interp.run(); } const end = performance.now(); - console.info(`run took ${end-start} ms for ${tickCount} ticks (${(end-start)/tickCount * 1000000} µs/tick).`); + console.info(`run took ${end-start} ms for ${tickCount} ticks (${(end-start)/tickCount * 1_000_000} ns/tick).`); console.info('result', interp.stack()); }; + + let blinkenRun = false; + document.querySelector('#blinken').onclick = e => { + console.debug('blinken clicked', e); + blinkenRun = !blinkenRun; + if (blinkenRun) { + e.target.textContent = 'haltenblinken'; + } else { + e.target.textContent = 'blinken'; + } + const frameRate = 6; + const onTimeout = _ => { + if (blinkenRun) { + tick(interp); + setTimeout(onTimeout, 1_000 / frameRate); + } + } + setTimeout(onTimeout); + } window.interp = interp; } diff --git a/src/lib.rs b/src/lib.rs index f3c9a89..850070a 100755 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,4 +1,4 @@ -use log::{Level, debug, error, info}; +use log::{Level, error, info}; use console_log; use wasm_bindgen::prelude::*; @@ -67,7 +67,6 @@ impl ExportedInterp { error!("couldn't parse program text: {:?}", e); return false } - debug!("wordlist: {:?}", &p.wordlist); let interp = forth::interp::Interp::new(p.wordlist); let _ = self.i.insert(interp); true @@ -77,7 +76,6 @@ impl ExportedInterp { let Some(interp) = &mut self.i else { return Err("no interpreter".to_string()) }; - info!("executing single instruction"); interp.tick().or_else(|err| Err(format!("runtime error: {:?}", err))) } @@ -104,7 +102,6 @@ impl ExportedInterp { return vec![] }; - info!("wordlist: ‘{:?}’", interp.wordlist); interp.wordlist.iter().map(|bc| ExportedByteCode::from_bc(bc)).collect() } @@ -112,7 +109,6 @@ impl ExportedInterp { let Some(interp) = &self.i else { return vec![] }; - info!("callstack: ‘{:?}’", interp.callstack); interp.callstack.0.iter() .map(|ip| ip.into()) .collect() -- cgit v1.3