diff --git a/examples/factorial b/examples/factorial new file mode 100644 index 0000000..d4609d1 --- /dev/null +++ b/examples/factorial @@ -0,0 +1,20 @@ +ENTRY 22 +LOAD -3 +CONST 2 +LT +BRF 10 +CONST 1 +RET +LOAD -3 +LOAD -3 +CONST 1 +SUB +CALL 0 1 +MULT +RET +CONST 12 +CALL 0 1 +IPRINT +CONST 10 +PRINT +HALT diff --git a/src/main.rs b/src/main.rs index c817533..06d9dee 100644 --- a/src/main.rs +++ b/src/main.rs @@ -2,14 +2,45 @@ use std::fs::File; use std::io; use std::io::Read; use std::env; +use std::collections::HashMap; -const EXEC: [(i32, (&'static str, i32)); 1] = [ - (0, ("add", 0)) +const EXEC_RPR: [(&'static str, i32); 28] = [ + ("entry", 1), + ("add", 0), + ("sub", 0), + ("mult", 0), + ("div", 0), + ("mod", 0), + ("lt", 0), + ("eq", 0), + ("gt", 0), + ("br", 1), + ("brt", 1), + ("brf", 1), + ("const", 1), + ("load", 1), + ("gload", 1), + ("store", 1), + ("gstore", 1), + ("print", 0), + ("pop", 0), + ("halt", 0), + ("leq", 0), + ("geq", 0), + ("call", 2), + ("ret", 0), + ("iprint", 0), + ("fetch", 0), + ("inc", 0), + ("dec", 0) ]; -struct Exec { - arguments: i32, - name: String +fn build_opcodes() -> HashMap<&'static str, (i64, i32)> { + let mut opcodes = HashMap::new(); + for (i, elem) in EXEC_RPR.iter().enumerate() { + opcodes.insert((*elem).0, (i as i64, (*elem).1)); + } + return opcodes; } fn usage(pname: String) { @@ -23,14 +54,41 @@ fn get_contents(fname: String) -> Result { Ok(contents) } -fn parse(contents: String) -> Vec { - return vec![]; +fn parse(contents: String, opcodes: HashMap<&'static str, (i64, i32)>) -> Vec { + let mut code = Vec::new(); + 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()[..]; + match opcodes.get(opcode) { + Some(v) => { + code.push(v.0); + if args.len() as i32 != v.1 { + panic!("Expected {} arguments for opcode {}, but got {}!", v.1, opcode, args.len()); + } + for elem in args { + match elem.parse::() { + 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 } -fn exec(instructions: Vec) { +fn exec(instructions: Vec) { + for elem in instructions { + println!("{}", elem); + } } fn main() { + let opcodes = build_opcodes(); + let args: Vec<_> = env::args().collect(); if args.len() != 2 { @@ -49,7 +107,7 @@ fn main() { } }; - let parsed = parse(contents); + let parsed = parse(contents, opcodes); let execd = exec(parsed); }