From 6e5fdbc8a46131da418591ba1bd4ae55ef011d6a Mon Sep 17 00:00:00 2001 From: hellerve Date: Sun, 4 Jun 2017 15:27:29 -0400 Subject: [PATCH] exec: implemented; still doesnt work --- src/main.rs | 97 ++++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 82 insertions(+), 15 deletions(-) diff --git a/src/main.rs b/src/main.rs index f5b3d3c..9e83062 100644 --- a/src/main.rs +++ b/src/main.rs @@ -55,13 +55,23 @@ fn get_contents(fname: String) -> Result { Ok(contents) } -fn parse(contents: String, opcodes: HashMap<&'static str, (i64, i32)>) -> Vec { +fn parse(contents: String, opcodes: HashMap<&'static str, (i64, i32)>) -> (Vec, usize) { let mut code = Vec::new(); + let mut ip = 0; for line in contents.split("\n") { if line.is_empty() { continue } let tmp = line.split(" ").map(String::from).collect::>(); let (op, args) = tmp.split_first().expect("malformatted line!"); let opcode: &str = &op.to_lowercase()[..]; + + // Special case: ENTRY + if opcode == "entry" { + if let Ok(_ip) = args[0].parse::() { + ip = _ip; + } + continue; + } + if let Some(v) = opcodes.get(opcode) { code.push(v.0); if args.len() as i32 != v.1 { @@ -74,7 +84,7 @@ fn parse(contents: String, opcodes: HashMap<&'static str, (i64, i32)>) -> Vec(stack: &mut Vec, fun: F) where F: Fn(i64, i64) -> i64 { @@ -87,11 +97,13 @@ fn binop(stack: &mut Vec, fun: F) where F: Fn(i64, i64) -> i64 { panic!("pop needs at least two elements on the stack"); } -fn exec(instructions: Vec) -> i64 { +/* Casting abound. You have been warned. */ +fn exec(instructions: Vec, _ip: usize) -> i64 { let mut stack: Vec = Vec::new(); let mut data: Vec = Vec::new(); let ilen = instructions.len(); - let mut ip = 0; + let mut ip: usize = _ip; + let mut fp: usize = 0; while ip < ilen { match instructions[ip] { /* ENT */ 0 => (), @@ -103,17 +115,47 @@ fn exec(instructions: Vec) -> i64 { /* 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 => (), - /* BRT */ 10 => (), - /* BRF */ 11 => (), + /* BR */ 9 => { + ip = instructions[ip+1] as usize; + }, + /* BRT */ 10 => { + ip += 1; + let addr = instructions[ip]; + if let Some(x) = stack.pop() { + if x != 0 { ip = addr as usize; } + } + }, + /* BRF */ 11 => { + ip += 1; + let addr = instructions[ip]; + if let Some(x) = stack.pop() { + if x == 0 { ip = addr as usize; } + } + }, /* CST */ 12 => { ip += 1; stack.push(instructions[ip]) }, - /* LD */ 13 => (), - /* GLD */ 14 => (), - /* ST */ 15 => (), - /* GST */ 16 => (), + /* LD */ 13 => { + ip += 1; + stack.push(instructions[ip+fp]) + }, + /* GLD */ 14 => { + ip += 1; + stack.push(data[instructions[ip] as usize]); + }, + /* ST */ 15 => { + ip += 1; + if let Some(x) = stack.pop() { + stack[fp+instructions[ip] as usize] = x; + } + }, + /* GST */ 16 => { + ip += 1; + if let Some(x) = stack.pop() { + data[instructions[ip] as usize] = x; + } + }, /* PRN */ 17 => { if let Some(x) = stack.last() { if let Some(x) = char::from_digit(*x as u32, 10) { @@ -128,8 +170,33 @@ fn exec(instructions: Vec) -> i64 { /* HLT */ 19 => break, /* LEQ */ 20 => binop(&mut stack, |x, y| (x <= y) as i64), /* GEQ */ 21 => binop(&mut stack, |x, y| (x >= y) as i64), - /* CAL */ 22 => (), - /* RET */ 23 => (), + /* CAL */ 22 => { + let addr = instructions[ip+1]; + let nargs = instructions[ip+2]; + stack.push(nargs); + stack.push(fp as i64); + stack.push((ip+2) as i64); + fp = stack.len() as usize; + ip = addr as usize; + }, + /* RET */ 23 => { + if let Some(addr) = stack.pop() { + let mut nargs = 0; + stack.truncate(addr as usize); + if let Some(_ip) = stack.pop() { + ip = _ip as usize; + } + if let Some(_fp) = stack.pop() { + fp = _fp as usize; + } + if let Some(_nargs) = stack.pop() { + nargs = _nargs; + } + let stl = stack.len(); + stack.truncate(stl-nargs as usize); + stack.push(addr); + } + }, /* IPR */ 24 => { if let Some(x) = stack.last() { print!("{}", x); @@ -174,7 +241,7 @@ fn main() { } }; - let parsed = parse(contents, opcodes); + let (parsed, ip) = parse(contents, opcodes); - println!("{}", exec(parsed)); + println!("{}", exec(parsed, ip)); }