exec: hello world works, factorial almost works
This commit is contained in:
89
src/main.rs
89
src/main.rs
@@ -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);
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user