mirror of
https://gitlab.cs.washington.edu/fidelp/frustration.git
synced 2025-02-05 20:45:59 +01:00
stored-program computer
This commit is contained in:
parent
b864d77444
commit
70fcc8e9a9
1 changed files with 116 additions and 19 deletions
131
frustration.rs
131
frustration.rs
|
@ -1,24 +1,106 @@
|
|||
use std::cmp;
|
||||
use std::io;
|
||||
use std::convert::TryFrom;
|
||||
//use std::convert::TryFrom;
|
||||
use std::convert::TryInto;
|
||||
|
||||
//const CORE_SIZE: usize = 65280
|
||||
const CORE_SIZE: usize = 128;
|
||||
|
||||
#[derive(Debug)]
|
||||
struct Core {
|
||||
ram: [u8; CORE_SIZE],
|
||||
ip: usize,
|
||||
dstack: [u16; 64],
|
||||
tds: usize,
|
||||
rstack: [u16; 64],
|
||||
trs: usize
|
||||
enum State {
|
||||
Compiling,
|
||||
Interpreting
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct Core {
|
||||
ram: [u8; CORE_SIZE],
|
||||
ip: u16,
|
||||
dp: u16, // newest link field, or 0
|
||||
here: u16, // first unused byte
|
||||
state: State,
|
||||
dstack: [u16; 64],
|
||||
tds: usize, // post-incremented; exceeds top by one
|
||||
rstack: [u16; 64],
|
||||
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);
|
||||
return out;
|
||||
}
|
||||
|
||||
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}}
|
||||
];
|
||||
|
||||
fn new_core() -> Core {
|
||||
return Core { ram: [0; CORE_SIZE], ip: 0,
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
fn push(c: &mut Core, val: u16) {
|
||||
|
@ -42,12 +124,22 @@ fn from_r(c: &mut Core) -> u16 {
|
|||
}
|
||||
|
||||
fn call(c: &mut Core, val: u16) {
|
||||
to_r(c, u16::try_from(c.ip).unwrap()); // or panic
|
||||
c.ip = val as usize;
|
||||
to_r(c, c.ip);
|
||||
c.ip = val;
|
||||
}
|
||||
|
||||
fn ret(c: &mut Core) {
|
||||
c.ip = from_r(c) as usize;
|
||||
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;
|
||||
}
|
||||
|
||||
fn store(c: &mut Core) {
|
||||
|
@ -85,10 +177,6 @@ fn div(c: &mut Core) {
|
|||
push(c, v2 / v1);
|
||||
}
|
||||
|
||||
fn dot(c: &mut Core) {
|
||||
print!("{} ", pop(c));
|
||||
}
|
||||
|
||||
fn outer(c: &mut Core, s: &str) {
|
||||
let ss = s.trim();
|
||||
let tokens = ss.split(" ");
|
||||
|
@ -115,6 +203,15 @@ fn outer(c: &mut Core, s: &str) {
|
|||
"." => {
|
||||
dot(c);
|
||||
},
|
||||
"s" => {
|
||||
step(c);
|
||||
},
|
||||
"g" => {
|
||||
inner(c);
|
||||
},
|
||||
"dmp" => {
|
||||
println!("{:?}", c);
|
||||
},
|
||||
_ => {
|
||||
let val = t.parse::<u16>();
|
||||
match val {
|
||||
|
@ -137,5 +234,5 @@ fn main() {
|
|||
}
|
||||
//push(&mut c, 56); push(&mut c, 9); mul(&mut c); dot(&mut c);
|
||||
//let v = pop(&mut c); call(&mut c, v);
|
||||
println!("{:?}", c);
|
||||
//println!("{:?}", c);
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue