frustration/frustration.rs

239 lines
5.4 KiB
Rust
Raw Normal View History

2022-03-24 08:01:51 +01:00
use std::cmp;
2022-03-22 04:45:42 +01:00
use std::io;
2022-03-24 08:01:51 +01:00
//use std::convert::TryFrom;
use std::convert::TryInto;
2022-03-22 04:45:42 +01:00
//const CORE_SIZE: usize = 65280
2022-03-22 04:45:42 +01:00
const CORE_SIZE: usize = 128;
2022-03-24 08:01:51 +01:00
#[derive(Debug)]
enum State {
Compiling,
Interpreting
}
2022-03-22 04:45:42 +01:00
#[derive(Debug)]
struct Core {
ram: [u8; CORE_SIZE],
2022-03-24 08:01:51 +01:00
ip: u16,
dp: u16, // newest link field, or 0
here: u16, // first unused byte
state: State,
2022-03-22 04:45:42 +01:00
dstack: [u16; 64],
2022-03-24 08:01:51 +01:00
tds: usize, // post-incremented; exceeds top by one
2022-03-22 04:45:42 +01:00
rstack: [u16; 64],
2022-03-24 08:01:51 +01:00
trs: usize, // post-incremented; exceeds top by one
}
type Primitive = fn(&mut Core);
struct ShortName {
bytes: [u8; 3],
length: u8
}
fn truncate_name(name: &str) -> ShortName {
let name_bytes = name.as_bytes();
let mut out = ShortName {
bytes: [32, 32, 32],
length: std::cmp::min(3, name_bytes.len()) as u8 };
out.bytes[0..out.length as usize].copy_from_slice(&name_bytes[0..out.length as usize]);
2022-03-24 08:01:51 +01:00
return out;
2022-03-22 04:45:42 +01:00
}
2022-03-24 08:01:51 +01:00
struct TableEntry {
f: Primitive,
name: ShortName
}
const PRIMITIVES: [TableEntry; 8] = [
TableEntry {f: ret , name: ShortName {bytes: ['r' as u8, 'e' as u8, 't' as u8], length: 1}},
TableEntry {f: dot , name: ShortName {bytes: ['.' as u8, 32, 32], length: 1}},
TableEntry {f: store, name: ShortName {bytes: ['!' as u8, 32, 32], length: 1}},
TableEntry {f: load , name: ShortName {bytes: ['@' as u8, 32, 32], length: 1}},
TableEntry {f: add , name: ShortName {bytes: ['+' as u8, 32, 32], length: 1}},
TableEntry {f: sub , name: ShortName {bytes: ['-' as u8, 32, 32], length: 1}},
TableEntry {f: mul , name: ShortName {bytes: ['*' as u8, 32, 32], length: 1}},
TableEntry {f: div , name: ShortName {bytes: ['/' as u8, 32, 32], length: 1}}
];
2022-03-22 04:45:42 +01:00
fn new_core() -> Core {
2022-03-24 08:01:51 +01:00
let mut c = Core {
ram: [0; CORE_SIZE], ip: 0, dp: 0, here: 2, state: State::Interpreting,
dstack: [0; 64], tds: 0,
rstack: [0; 64], trs: 0 };
init_dictionary(&mut c);
return c;
}
fn create(c: &mut Core, name: ShortName) {
let addr: usize = c.here as usize;
c.ram[addr+0..=addr+1].copy_from_slice(&c.dp.to_le_bytes());
c.dp = addr as u16;
c.ram[addr+2] = name.length;
c.ram[addr+3..=addr+5].copy_from_slice(&name.bytes);
c.here = (addr+6) as u16;
}
fn init_dictionary(c: &mut Core) {
let mut opcode = 65535;
for p in PRIMITIVES {
create(c, p.name);
comma(c, opcode);
opcode -= 1;
}
}
fn step(c: &mut Core) {
let ip = c.ip as usize;
let opcode = u16::from_le_bytes(c.ram[ip..=ip+1].try_into().unwrap());
c.ip += 2;
let primitive_index = (65535 - opcode) as usize;
if primitive_index < PRIMITIVES.len() {
(PRIMITIVES[primitive_index].f)(c);
} else {
call(c, opcode);
}
}
fn inner(c: &mut Core) {
c.ip = 0;
while c.ip != 2 {
step(c);
}
2022-03-22 04:45:42 +01:00
}
fn push(c: &mut Core, val: u16) {
c.dstack[c.tds] = val;
c.tds += 1;
}
fn pop(c: &mut Core) -> u16 {
c.tds -= 1;
return c.dstack[c.tds];
}
fn to_r(c: &mut Core, val: u16) {
c.rstack[c.trs] = val;
c.trs += 1;
}
fn from_r(c: &mut Core) -> u16 {
c.trs -= 1;
return c.rstack[c.trs];
}
fn call(c: &mut Core, val: u16) {
2022-03-24 08:01:51 +01:00
to_r(c, c.ip);
c.ip = val;
2022-03-22 04:45:42 +01:00
}
fn ret(c: &mut Core) {
2022-03-24 08:01:51 +01:00
c.ip = from_r(c);
}
fn dot(c: &mut Core) {
print!("{} ", pop(c));
}
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());
c.here += 2;
2022-03-22 04:45:42 +01:00
}
fn store(c: &mut Core) {
let addr = pop(c) as usize;
2022-03-22 04:45:42 +01:00
let val = pop(c);
c.ram[addr..=addr+1].copy_from_slice(&val.to_le_bytes());
2022-03-22 04:45:42 +01:00
}
fn load(c: &mut Core) {
let addr = pop(c) as usize;
push(c, u16::from_le_bytes(c.ram[addr..=addr+1].try_into().unwrap()));
2022-03-22 04:45:42 +01:00
}
fn add(c: &mut Core) {
let v1 = pop(c);
let v2 = pop(c);
push(c, v1 + v2);
}
fn sub(c: &mut Core) {
let v1 = pop(c);
let v2 = pop(c);
push(c, v2 - v1);
}
fn mul(c: &mut Core) {
let v1 = pop(c);
let v2 = pop(c);
push(c, v1 * v2);
}
fn div(c: &mut Core) {
let v1 = pop(c);
let v2 = pop(c);
push(c, v2 / v1);
}
2022-03-23 05:13:17 +01:00
fn outer(c: &mut Core, s: &str) {
2022-03-22 04:45:42 +01:00
let ss = s.trim();
let tokens = ss.split(" ");
for t in tokens {
match t {
"+" => {
add(c);
},
"-" => {
sub(c);
},
"*" => {
mul(c);
},
"/" => {
div(c);
},
"@" => {
load(c);
},
"!" => {
store(c);
},
"." => {
dot(c);
},
2022-03-24 08:01:51 +01:00
"s" => {
step(c);
},
"g" => {
inner(c);
},
"dmp" => {
println!("{:?}", c);
},
2022-03-22 04:45:42 +01:00
_ => {
let val = t.parse::<u16>();
match val {
Ok(n) => { push(c, n) }
Err(_) => { if t != "" { println!("{}?", t) }}
}
}
}
}
}
fn main() {
let mut c = new_core();
loop {
let mut buf = String::new();
match io::stdin().read_line(&mut buf) {
2022-03-23 05:13:17 +01:00
Ok(_) => { outer(&mut c, &buf); println!(" ok");}
Err(_) => { break; }
2022-03-22 04:45:42 +01:00
}
}
//push(&mut c, 56); push(&mut c, 9); mul(&mut c); dot(&mut c);
//let v = pop(&mut c); call(&mut c, v);
2022-03-24 08:01:51 +01:00
//println!("{:?}", c);
2022-03-22 04:45:42 +01:00
}