use std::fs; use std::env; use std::fmt; use std::usize; use std::collections::HashMap; mod eval; struct Program { data: Vec, pc: usize, vars: HashMap } impl Program { fn from_string(program: String) -> Program { let mut op_list: Vec = Vec::new(); for opcode in program.split("\n").collect::>() { let new_op = opcode.to_owned(); // new_op = new_op.replace("\n", ""); if new_op.len() != 0 { op_list.push(new_op.to_owned()); } } return Program{ data: op_list, pc: 0, vars: HashMap::new() }; } fn args_or_vars(&self, arguments: &str) -> String { let mut builder = String::from(""); let argument_vec: Vec = arguments.chars().collect(); for index in 0..argument_vec.len() { let current_char = argument_vec[index]; let str_to_push: String; if index > 0 { if argument_vec[index-1] == '$' { continue; } } if current_char == '$' { let variable = argument_vec[index+1]; let key = self.vars.get(&variable); match key { Some(value) => str_to_push = value.to_string(), None => panic!("NotFoundError: Variable {} has not been defined", variable) } } else { str_to_push = current_char.to_string(); } builder.push_str(&str_to_push); } builder } fn add_var(&mut self, arguments: &str) { let argument_vec: Vec = arguments.chars().collect(); let name = argument_vec[0]; let value = argument_vec[1..].into_iter().collect::(); self.vars.insert(name, value); } fn parse(&mut self, instruction: &String) { let opcode = instruction.chars().collect::>()[0]; let arguments = &instruction[1..]; match opcode { 'p' => println!("{}", self.args_or_vars(arguments)), 'a' => println!("{}", eval::do_math(self.args_or_vars(arguments), '+')), 's' => println!("{}", eval::do_math(self.args_or_vars(arguments), '-')), 'm' => println!("{}", eval::do_math(self.args_or_vars(arguments), '*')), 'd' => println!("{}", eval::do_math(self.args_or_vars(arguments), '/')), 'l' => self.add_var(arguments), _ => panic!("SyntaxError: No such opcode: {}", self.pc) } } fn run(&mut self) { println!("{}", self); while self.pc < self.data.len() { let instruction = self.data[self.pc].to_owned(); self.parse(&instruction); self.pc = self.pc + 1; } } } impl fmt::Display for Program { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "Program ({:?})", self.data) } } fn main() { let args: Vec = env::args().collect(); if args.len() == 1 { panic!("You must provide a filename!"); } let filename = &args[1]; let contents = fs::read_to_string(filename).expect("Something went wrong reading the file"); let mut prog = Program::from_string(contents); prog.run(); }