diff options
| author | Brian Cully <bjc@spork.org> | 2025-08-23 10:22:11 -0400 |
|---|---|---|
| committer | Brian Cully <bjc@spork.org> | 2025-08-23 11:36:31 -0400 |
| commit | 5b8962e35836cf7ccbfdbca312f6b0eb9269e2a6 (patch) | |
| tree | e537f04279c4b1ef27f7040c25beff2551c8bf84 /src/lib.rs | |
| parent | 12c06171b3f94696e852c3910c116f56cbfc5b64 (diff) | |
| download | automathon-5b8962e35836cf7ccbfdbca312f6b0eb9269e2a6.tar.gz automathon-5b8962e35836cf7ccbfdbca312f6b0eb9269e2a6.zip | |
show wordlist in html on compile
Diffstat (limited to 'src/lib.rs')
| -rwxr-xr-x | src/lib.rs | 106 |
1 files changed, 63 insertions, 43 deletions
@@ -1,4 +1,4 @@ -use log::{Level, debug, info}; +use log::{Level, debug, error, info}; use console_log; use wasm_bindgen::prelude::*; @@ -10,75 +10,95 @@ pub struct ExportedInstructionPointer { pub offset: usize, } +// wasm can't wrap Vec<Vec<String>>, so we need a custom type +// - 23-aug-2025 #[wasm_bindgen] pub struct ExportedByteCode(Vec<String>); +impl ExportedByteCode { + pub fn from_bc(bc: &forth::interp::ByteCode) -> Self { + fn tr(op: &forth::interp::OpCode) -> String { + use forth::interp::OpCode::*; + let s = match op { + If(t, None) => format!("If({}, none)", t), + If(t, Some(f)) => format!("If({}, {})", t, f), + TIf(t, None) => format!("TIf({}, none)", t), + TIf(t, Some(f)) => format!("TIf({}, {})", t, f), + other => format!("{:?}", other), + }; + s.to_string() + } + + ExportedByteCode(bc.iter().map(tr).collect()) + } +} + #[wasm_bindgen] impl ExportedByteCode { pub fn len(&self) -> usize { self.0.len() } - pub fn at(&self, index: usize) -> String { - self.0[index].clone() + pub fn at(&self, offset: usize) -> String { + self.0[offset].clone() } } #[wasm_bindgen] -pub fn compile(text: &str) { - info!("compiling code: `{}`", text); - let mut p = forth::parser::Parser::new(&text); - p.parse().expect("couldn't parse text"); - debug!("wordlist: {:?}", &p.wordlist); - let interp = forth::interp::Interp::new(p.wordlist); - debug!("interp: {:?}", interp); -} - -#[wasm_bindgen] -pub fn tick() { - info!("executing single instruction"); +pub struct ExportedInterp { + i: Option<forth::interp::Interp>, } #[wasm_bindgen] -pub fn ip() -> ExportedInstructionPointer { - ExportedInstructionPointer { - word: 0, - offset: 0, +impl ExportedInterp { + fn new() -> Self { + Self { i: None } } -} -#[wasm_bindgen] -pub fn wordlist() -> Vec<ExportedByteCode> { - vec![ - ExportedByteCode(vec!["NOP".to_string(), "2".to_string(), "DUP".to_string()]), - ] -} + pub fn compile(&mut self, text: &str) -> bool { + let mut p = forth::parser::Parser::new(&text); + if let Err(e) = p.parse() { + 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 + } -#[wasm_bindgen] -pub struct ExportedInterp { - i: forth::interp::Interp, -} + pub fn tick(&mut self) { + info!("executing single instruction"); + } -#[wasm_bindgen] -impl ExportedInterp { - fn from_interp(i: forth::interp::Interp) -> Self { - Self { i } + pub fn run(&mut self) { + info!("running to completion"); } - pub fn foo(&self) { - info!("in interp::foo: {:?}", self.i.wordlist); + pub fn wordlist(&self) -> Vec<ExportedByteCode> { + let Some(interp) = self.i.as_ref() else { + return vec![] + }; + + info!("wordlist: ‘{:?}’", interp.wordlist); + interp.wordlist.iter().map(|bc| ExportedByteCode::from_bc(bc)).collect() } -} -#[wasm_bindgen] -pub fn interp() -> ExportedInterp { - let i = forth::interp::Interp::new(forth::interp::WordList(vec![])); - ExportedInterp::from_interp(i) + pub fn ip(&self) -> ExportedInstructionPointer { + let Some(interp) = self.i.as_ref() else { + return ExportedInstructionPointer { word: 0, offset: 0 } + }; + + ExportedInstructionPointer { + word: interp.ip.word, + offset: interp.ip.offset, + } + } } #[wasm_bindgen] -pub fn run() { - info!("running to completion"); +pub fn make_interp() -> ExportedInterp { + ExportedInterp::new() } #[wasm_bindgen(start)] |
