diff --git a/frustration.rs b/frustration.rs index dd36c20..8b6190e 100644 --- a/frustration.rs +++ b/frustration.rs @@ -3,7 +3,7 @@ use std::io; use std::convert::TryInto; //const CORE_SIZE: usize = 65408 -const CORE_SIZE: usize = 192; +const CORE_SIZE: usize = 256; #[derive(Debug, Eq, PartialEq)] enum State { @@ -11,6 +11,13 @@ enum State { Interpreting } +#[derive(Debug)] +enum Post { + Nothing, + EatWord, + EatLine, +} + #[derive(Debug)] struct Core { ram: [u8; CORE_SIZE], @@ -18,6 +25,8 @@ struct Core { dp: u16, // newest link field, or 0 here: u16, // first unused byte state: State, + next_token: Option, + post: Post, dstack: [u16; 16], tds: usize, // post-incremented; exceeds top by one rstack: [u16; 16], @@ -47,12 +56,16 @@ struct TableEntry { immediate: bool } -const PRIMITIVES: [TableEntry; 14] = [ +const PRIMITIVES: [TableEntry; 18] = [ TableEntry {f: ret , name: None, immediate: false}, TableEntry {f: lit , name: None, immediate: false}, TableEntry {f: call , name: Some(ShortName {bytes: *b"cal", length: 4}), immediate: false}, + TableEntry {f: create_ , name: Some(ShortName {bytes: *b"cre", length: 6}), immediate: false}, + TableEntry {f: immediate,name: Some(ShortName {bytes: *b"imm", length: 9}), immediate: false}, + TableEntry {f: tick , name: Some(ShortName {bytes: *b"' ", length: 1}), immediate: false}, TableEntry {f: dot , name: Some(ShortName {bytes: *b". ", length: 1}), immediate: false}, TableEntry {f: dump , name: Some(ShortName {bytes: *b"dum", length: 4}), immediate: false}, + TableEntry {f: word , name: Some(ShortName {bytes: *b"wor", length: 4}), immediate: false}, TableEntry {f: comma_ , name: Some(ShortName {bytes: *b", ", length: 1}), immediate: false}, TableEntry {f: store , name: Some(ShortName {bytes: *b"! ", length: 1}), immediate: false}, TableEntry {f: load , name: Some(ShortName {bytes: *b"@ ", length: 1}), immediate: false}, @@ -67,6 +80,8 @@ const PRIMITIVES: [TableEntry; 14] = [ fn new_core() -> Core { let mut c = Core { ram: [0; CORE_SIZE], ip: 0, dp: 0, here: 2, state: State::Interpreting, + next_token: None, + post: Post::Nothing, dstack: [0; 16], tds: 0, rstack: [0; 16], trs: 0 }; init_dictionary(&mut c); @@ -84,6 +99,17 @@ fn create(c: &mut Core, name: ShortName) { c.here = (addr+6) as u16; } +fn create_(c: &mut Core) { + match &c.next_token { + Some(t) => { + let short_name = truncate_name(t); + create(c, short_name); + c.post = Post::EatWord; + } + _ => {} + } +} + fn find(c: &mut Core, name: ShortName) -> Option { let mut addr = c.dp as usize; while addr != 0 { @@ -127,6 +153,29 @@ fn is_immediate(c: &mut Core, addr: u16) -> bool { return (c.ram[(addr as usize) - 4] & 0x80) != 0; } +fn tick(c: &mut Core) { + match &c.next_token { + Some(t) => { + let name = t.to_string(); + let addr = find(c, truncate_name(&name)); + match addr { + Some(xt) => { + push(c, xt); + c.post = Post::EatWord; + } + None => { + println!(" ' cannot find {}", name); + c.post = Post::EatLine; + } + } + } + _ => { + println!(" ' needs an argument"); + c.post = Post::EatLine; + } + } +} + fn comma(c: &mut Core, val: u16) { let addr = c.here as usize; c.ram[addr..=addr+1].copy_from_slice(&val.to_le_bytes()); @@ -228,6 +277,16 @@ fn dump(c: &mut Core) { println!("{:?}", c); } +fn word(c: &mut Core) { + match &c.next_token { + Some(t) => { + println!("{}", t); + c.post = Post::EatWord; + } + _ => {} + } +} + // note: this is an inline primitive, not a dict entry fn lit(c: &mut Core) { let ip = c.ip as usize; @@ -271,33 +330,49 @@ fn rbracket(c: &mut Core) { fn outer(c: &mut Core, s: &str) { let ss = s.trim(); - let tokens = ss.split(" "); - for t in tokens { - match find(c, truncate_name(t)) { - Some(addr) => { - if c.state == State::Interpreting || is_immediate(c, addr) { - c.ip = addr; - inner(c); - } else { - comma(c, addr); - } - } - None => { - let val = t.parse::(); - match val { - Ok(n) => { - match c.state { - State::Interpreting => { push(c, n) } - State::Compiling => { - comma(c, 65534); // lit - comma(c, n); - } + let mut tokens = ss.split(" ").peekable(); + loop { + c.post = Post::Nothing; + match tokens.next() { + Some(t) => { + c.next_token = match tokens.peek() { + Some(t) => { Some(t.to_string()) } + None => { None } + }; + match find(c, truncate_name(t)) { + Some(addr) => { + if c.state == State::Interpreting || is_immediate(c, addr) { + to_r(c, c.ip); + c.ip = addr; + inner(c); + } else { + comma(c, addr); + } + } + None => { + let val = t.parse::(); + match val { + Ok(n) => { + match c.state { + State::Interpreting => { push(c, n) } + State::Compiling => { + comma(c, 65534); // lit + comma(c, n); + } + } + } + Err(_) => { if t != "" { println!("{}?", t) }} } } - Err(_) => { if t != "" { println!("{}?", t) }} } } + None => { break ; } } + match c.post { + Post::EatWord => { _ = tokens.next(); } + Post::EatLine => { break; } + Post::Nothing => { } + }; } } @@ -311,3 +386,7 @@ fn main() { } } } + +// create : ] create ] [ 65535 , +// create ; ] 65535 , [ ' [ , 65535 , immediate +// : dog 33 . ;