parse: no good error messages, because the code sucks; eval: only branching, calling, and data segment left
This commit is contained in:
79
src/main.rs
79
src/main.rs
@@ -1,8 +1,9 @@
|
|||||||
|
use std::char;
|
||||||
|
use std::collections::HashMap;
|
||||||
|
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::env;
|
|
||||||
use std::collections::HashMap;
|
|
||||||
|
|
||||||
const EXEC_RPR: [(&'static str, i32); 28] = [
|
const EXEC_RPR: [(&'static str, i32); 28] = [
|
||||||
("entry", 1),
|
("entry", 1),
|
||||||
@@ -61,44 +62,37 @@ fn parse(contents: String, opcodes: HashMap<&'static str, (i64, i32)>) -> Vec<i6
|
|||||||
let tmp = line.split(" ").map(String::from).collect::<Vec<String>>();
|
let tmp = line.split(" ").map(String::from).collect::<Vec<String>>();
|
||||||
let (op, args) = tmp.split_first().expect("malformatted line!");
|
let (op, args) = tmp.split_first().expect("malformatted line!");
|
||||||
let opcode: &str = &op.to_lowercase()[..];
|
let opcode: &str = &op.to_lowercase()[..];
|
||||||
match opcodes.get(opcode) {
|
if let Some(v) = opcodes.get(opcode) {
|
||||||
Some(v) => {
|
code.push(v.0);
|
||||||
code.push(v.0);
|
if args.len() as i32 != v.1 {
|
||||||
if args.len() as i32 != v.1 {
|
panic!("Expected {} arguments for opcode {}, but got {}!", v.1, opcode, args.len());
|
||||||
panic!("Expected {} arguments for opcode {}, but got {}!", v.1, opcode, args.len());
|
}
|
||||||
}
|
for elem in args {
|
||||||
for elem in args {
|
if let Ok(v) = elem.parse::<i64>() {
|
||||||
match elem.parse::<i64>() {
|
code.push(v);
|
||||||
Ok(v) => code.push(v),
|
|
||||||
_ => panic!("Could not parse argument {} to instruction {} as number!", elem, opcode)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
None => panic!("Do not know opcode {}!", opcode)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return code
|
return code
|
||||||
}
|
}
|
||||||
|
|
||||||
fn binop<F>(stack: &mut Vec<i64>, fun: F) where F: Fn(i64, i64) -> i64 {
|
fn binop<F>(stack: &mut Vec<i64>, fun: F) where F: Fn(i64, i64) -> i64 {
|
||||||
let x = stack.pop();
|
if let Some(x) = stack.pop() {
|
||||||
let y = stack.pop();
|
if let Some(y) = stack.pop() {
|
||||||
match x {
|
stack.push(fun(x, y));
|
||||||
Some(x) =>
|
return;
|
||||||
match y {
|
}
|
||||||
Some(y) => stack.push(fun(x, y)),
|
|
||||||
_ => panic!("pop needs at least two elements on the stack")
|
|
||||||
},
|
|
||||||
_ => panic!("pop needs at least two elements on the stack")
|
|
||||||
}
|
}
|
||||||
|
panic!("pop needs at least two elements on the stack");
|
||||||
}
|
}
|
||||||
|
|
||||||
fn exec(instructions: Vec<i64>) -> i64 {
|
fn exec(instructions: Vec<i64>) -> i64 {
|
||||||
let mut stack: Vec<i64> = Vec::new();
|
let mut stack: Vec<i64> = Vec::new();
|
||||||
|
let mut data: Vec<i64> = Vec::new();
|
||||||
let ilen = instructions.len();
|
let ilen = instructions.len();
|
||||||
let mut ip = 0;
|
let mut ip = 0;
|
||||||
while ip < ilen {
|
while ip < ilen {
|
||||||
ip += 1; /* TMP */
|
|
||||||
match instructions[ip] {
|
match instructions[ip] {
|
||||||
/* ENT */ 0 => (),
|
/* ENT */ 0 => (),
|
||||||
/* ADD */ 1 => binop(&mut stack, |x, y| x + y),
|
/* ADD */ 1 => binop(&mut stack, |x, y| x + y),
|
||||||
@@ -112,24 +106,49 @@ fn exec(instructions: Vec<i64>) -> i64 {
|
|||||||
/* BR */ 9 => (),
|
/* BR */ 9 => (),
|
||||||
/* BRT */ 10 => (),
|
/* BRT */ 10 => (),
|
||||||
/* BRF */ 11 => (),
|
/* BRF */ 11 => (),
|
||||||
/* CST */ 12 => (),
|
/* CST */ 12 => {
|
||||||
|
ip += 1;
|
||||||
|
stack.push(instructions[ip])
|
||||||
|
},
|
||||||
/* LD */ 13 => (),
|
/* LD */ 13 => (),
|
||||||
/* GLD */ 14 => (),
|
/* GLD */ 14 => (),
|
||||||
/* ST */ 15 => (),
|
/* ST */ 15 => (),
|
||||||
/* GST */ 16 => (),
|
/* GST */ 16 => (),
|
||||||
/* PRN */ 17 => (),
|
/* PRN */ 17 => {
|
||||||
/* POP */ 18 => (),
|
if let Some(x) = stack.last() {
|
||||||
|
if let Some(x) = char::from_digit(*x as u32, 10) {
|
||||||
|
print!("{}", x);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
/* POP */ 18 => {
|
||||||
|
stack.pop();
|
||||||
|
();
|
||||||
|
}
|
||||||
/* HLT */ 19 => break,
|
/* HLT */ 19 => break,
|
||||||
/* LEQ */ 20 => binop(&mut stack, |x, y| (x <= y) as i64),
|
/* LEQ */ 20 => binop(&mut stack, |x, y| (x <= y) as i64),
|
||||||
/* GEQ */ 21 => binop(&mut stack, |x, y| (x >= y) as i64),
|
/* GEQ */ 21 => binop(&mut stack, |x, y| (x >= y) as i64),
|
||||||
/* CAL */ 22 => (),
|
/* CAL */ 22 => (),
|
||||||
/* RET */ 23 => (),
|
/* RET */ 23 => (),
|
||||||
/* IPR */ 24 => (),
|
/* IPR */ 24 => {
|
||||||
|
if let Some(x) = stack.last() {
|
||||||
|
print!("{}", x);
|
||||||
|
};
|
||||||
|
},
|
||||||
/* FET */ 25 => (),
|
/* FET */ 25 => (),
|
||||||
/* INC */ 26 => (),
|
/* INC */ 26 => {
|
||||||
/* DEC */ 27 => (),
|
if let Some(x) = stack.pop() {
|
||||||
|
stack.push(x+1);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
/* DEC */ 27 => {
|
||||||
|
if let Some(x) = stack.pop() {
|
||||||
|
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);
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user