exec: hello world works, factorial almost works

This commit is contained in:
2017-06-04 22:42:18 -04:00
parent 6e5fdbc8a4
commit be1a75c1ca

View File

@@ -4,9 +4,9 @@ use std::env;
use std::fs::File; use std::fs::File;
use std::io; use std::io;
use std::io::Read; use std::io::Read;
use std::process;
const EXEC_RPR: [(&'static str, i32); 28] = [ const EXEC_RPR: [(&'static str, i32); 27] = [
("entry", 1),
("add", 0), ("add", 0),
("sub", 0), ("sub", 0),
("mult", 0), ("mult", 0),
@@ -100,86 +100,84 @@ fn binop<F>(stack: &mut Vec<i64>, fun: F) where F: Fn(i64, i64) -> i64 {
/* Casting abound. You have been warned. */ /* Casting abound. You have been warned. */
fn exec(instructions: Vec<i64>, _ip: usize) -> i64 { fn exec(instructions: Vec<i64>, _ip: usize) -> i64 {
let mut stack: Vec<i64> = Vec::new(); let mut stack: Vec<i64> = Vec::new();
let mut data: Vec<i64> = Vec::new(); let mut data: Vec<i64> = vec![0; 1024];
let ilen = instructions.len(); let ilen = instructions.len();
let mut ip: usize = _ip; let mut ip: usize = _ip;
let mut fp: usize = 0; let mut fp: usize = 0;
while ip < ilen { while ip < ilen {
match instructions[ip] {
/* ENT */ 0 => (),
/* ADD */ 1 => binop(&mut stack, |x, y| x + y),
/* SUB */ 2 => binop(&mut stack, |x, y| x - y),
/* MUL */ 3 => binop(&mut stack, |x, y| x * y),
/* DIV */ 4 => binop(&mut stack, |x, y| x / y),
/* MOD */ 5 => binop(&mut stack, |x, y| x % y),
/* LT */ 6 => binop(&mut stack, |x, y| (x < y) as i64),
/* EQ */ 7 => binop(&mut stack, |x, y| (x == y) as i64),
/* GT */ 8 => binop(&mut stack, |x, y| (x > y) as i64),
/* BR */ 9 => {
ip = instructions[ip+1] as usize;
},
/* BRT */ 10 => {
ip += 1; ip += 1;
match instructions[ip-1] {
/* ADD */ 0 => binop(&mut stack, |x, y| x + y),
/* SUB */ 1 => binop(&mut stack, |x, y| x - y),
/* MUL */ 2 => binop(&mut stack, |x, y| x * y),
/* DIV */ 3 => binop(&mut stack, |x, y| x / y),
/* MOD */ 4 => binop(&mut stack, |x, y| x % y),
/* LT */ 5 => binop(&mut stack, |x, y| (x < y) as i64),
/* EQ */ 6 => binop(&mut stack, |x, y| (x == y) as i64),
/* GT */ 7 => binop(&mut stack, |x, y| (x > y) as i64),
/* BR */ 8 => ip = instructions[ip+1] as usize,
/* BRT */ 9 => {
let addr = instructions[ip]; let addr = instructions[ip];
if let Some(x) = stack.pop() { if let Some(x) = stack.pop() {
if x != 0 { ip = addr as usize; } if x != 0 { ip = addr as usize; }
else { ip += 1; }
} }
}, },
/* BRF */ 11 => { /* BRF */ 10 => {
ip += 1;
let addr = instructions[ip]; let addr = instructions[ip];
if let Some(x) = stack.pop() { if let Some(x) = stack.pop() {
if x == 0 { ip = addr as usize; } if x == 0 { ip = addr as usize; }
else { ip += 1; }
} }
}, },
/* CST */ 12 => { /* CST */ 11 => {
stack.push(instructions[ip]);
ip += 1; ip += 1;
stack.push(instructions[ip])
}, },
/* LD */ 13 => { /* LD */ 12 => {
stack.push(instructions[ip+fp]);
ip += 1; ip += 1;
stack.push(instructions[ip+fp])
}, },
/* GLD */ 14 => { /* GLD */ 13 => {
ip += 1;
stack.push(data[instructions[ip] as usize]); stack.push(data[instructions[ip] as usize]);
},
/* ST */ 15 => {
ip += 1; ip += 1;
},
/* ST */ 14 => {
if let Some(x) = stack.pop() { if let Some(x) = stack.pop() {
stack[fp+instructions[ip] as usize] = x; stack[fp+instructions[ip] as usize] = x;
} }
},
/* GST */ 16 => {
ip += 1; ip += 1;
},
/* GST */ 15 => {
if let Some(x) = stack.pop() { if let Some(x) = stack.pop() {
data[instructions[ip] as usize] = x; data[instructions[ip] as usize] = x;
} }
ip += 1;
}, },
/* PRN */ 17 => { /* PRN */ 16 => {
if let Some(x) = stack.last() { if let Some(x) = stack.last() {
if let Some(x) = char::from_digit(*x as u32, 10) { if let Some(x) = char::from_u32(*x as u32) {
print!("{}", x); print!("{}", x);
} }
} }
}, },
/* POP */ 18 => { /* POP */ 17 => {
stack.pop(); stack.pop();
(); ();
} }
/* HLT */ 19 => break, /* HLT */ 18 => return 0,
/* LEQ */ 20 => binop(&mut stack, |x, y| (x <= y) as i64), /* LEQ */ 19 => binop(&mut stack, |x, y| (x <= y) as i64),
/* GEQ */ 21 => binop(&mut stack, |x, y| (x >= y) as i64), /* GEQ */ 20 => binop(&mut stack, |x, y| (x >= y) as i64),
/* CAL */ 22 => { /* CAL */ 21 => {
let addr = instructions[ip+1]; let addr = instructions[ip];
let nargs = instructions[ip+2]; let nargs = instructions[ip+1];
stack.push(nargs); stack.push(nargs);
stack.push(fp as i64); stack.push(fp as i64);
stack.push((ip+2) as i64); stack.push((ip+1) as i64);
fp = stack.len() as usize; fp = stack.len() as usize;
ip = addr as usize; ip = addr as usize;
}, },
/* RET */ 23 => { /* RET */ 22 => {
if let Some(addr) = stack.pop() { if let Some(addr) = stack.pop() {
let mut nargs = 0; let mut nargs = 0;
stack.truncate(addr as usize); stack.truncate(addr as usize);
@@ -197,25 +195,24 @@ fn exec(instructions: Vec<i64>, _ip: usize) -> i64 {
stack.push(addr); stack.push(addr);
} }
}, },
/* IPR */ 24 => { /* IPR */ 23 => {
if let Some(x) = stack.last() { if let Some(x) = stack.last() {
print!("{}", x); print!("{}", x);
}; };
}, },
/* FET */ 25 => (), /* FET */ 24 => (),
/* INC */ 26 => { /* INC */ 25 => {
if let Some(x) = stack.pop() { if let Some(x) = stack.pop() {
stack.push(x+1); stack.push(x+1);
} }
}, },
/* DEC */ 27 => { /* DEC */ 26 => {
if let Some(x) = stack.pop() { if let Some(x) = stack.pop() {
stack.push(x-1); stack.push(x-1);
} }
}, },
/* IMP */ x => panic!("Unknown instruction {}!", x) /* IMP */ x => panic!("Unknown instruction {}!", x)
} }
ip += 1;
} }
return *stack.first().unwrap_or(&0); return *stack.first().unwrap_or(&0);
} }
@@ -243,5 +240,5 @@ fn main() {
let (parsed, ip) = parse(contents, opcodes); let (parsed, ip) = parse(contents, opcodes);
println!("{}", exec(parsed, ip)); process::exit(exec(parsed, ip) as i32);
} }