parse: no good error messages, because the code sucks; eval: only branching, calling, and data segment left

This commit is contained in:
2017-05-28 16:41:38 -04:00
parent db19846539
commit 0709f2903e

View File

@@ -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);
} }