Add arithmeticexpression
This commit is contained in:
		
							parent
							
								
									ec32e55357
								
							
						
					
					
						commit
						00619f09fd
					
				| @ -1,2 +1,3 @@ | ||||
| let gotus = "Hello, world!"; | ||||
| print(gotus); | ||||
| let number = 2 + 5 * 2 + 5 + 1 * 10 + 1; | ||||
| let text = "" + number; | ||||
| print(text); | ||||
| @ -3,23 +3,42 @@ use std::collections::HashMap; | ||||
| use std::num::ParseIntError; | ||||
| 
 | ||||
| use super::errors::CompilerError; | ||||
| use super::parser::{Expression, LiteralPattern, ParsedReid, Pattern, Statement}; | ||||
| use super::parser::{ | ||||
|     ArithmeticExpression, Expression, LiteralPattern, ParsedReid, Pattern, Statement, | ||||
| }; | ||||
| use super::vm::VariableType::*; | ||||
| use super::vm::{Command, CompiledReid, FuncID, FunctionSignature, HeapID, Position, VariableType}; | ||||
| 
 | ||||
| pub type Variable = (HeapID, VariableType); | ||||
| 
 | ||||
| #[derive(Debug, Clone)] | ||||
| pub enum ArithmeticOp { | ||||
|     Add(VariableType, VariableType, VariableType), | ||||
|     Subtract(VariableType, VariableType, VariableType), | ||||
|     Mult(VariableType, VariableType, VariableType), | ||||
| } | ||||
| 
 | ||||
| pub struct Compiler { | ||||
|     parsed: ParsedReid, | ||||
|     root_scope: Scope, | ||||
|     list: Vec<Command>, | ||||
|     possible_arit_possib: Vec<ArithmeticOp>, | ||||
| } | ||||
| 
 | ||||
| impl Compiler { | ||||
|     pub fn from(parsed: ParsedReid) -> Compiler { | ||||
|         let list = vec![ | ||||
|             ArithmeticOp::Add(TypeI32, TypeI32, TypeI32), | ||||
|             ArithmeticOp::Subtract(TypeI32, TypeI32, TypeI32), | ||||
|             ArithmeticOp::Mult(TypeI32, TypeI32, TypeI32), | ||||
|             ArithmeticOp::Add(TypeString, TypeI32, TypeString), | ||||
|             ArithmeticOp::Add(TypeString, TypeString, TypeString), | ||||
|         ]; | ||||
|         Compiler { | ||||
|             parsed, | ||||
|             root_scope: Scope::default(), | ||||
|             list: Vec::new(), | ||||
|             possible_arit_possib: list, | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
| @ -76,6 +95,9 @@ impl Compiler { | ||||
|                     Err(CompilerError::FunctionNotFound(pos, name, arguments)) | ||||
|                 } | ||||
|             } | ||||
|             Expression::ArithmeticExpression(pos, val) => { | ||||
|                 self.handle_arithmetic_expression(pos, *val) | ||||
|             } | ||||
|             Expression::ValueRef(_, val) => match val { | ||||
|                 Pattern::IdentPattern(pos, ident) => { | ||||
|                     if let Some(var) = self.root_scope.get(ident.clone()) { | ||||
| @ -94,6 +116,77 @@ impl Compiler { | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     fn handle_arithmetic_expression( | ||||
|         &mut self, | ||||
|         pos: Position, | ||||
|         exp: ArithmeticExpression, | ||||
|     ) -> Result<Option<VariableType>, CompilerError> { | ||||
|         let (exp1, exp2) = match exp.clone() { | ||||
|             ArithmeticExpression::Add(e1, e2) => (e1, e2), | ||||
|             ArithmeticExpression::Subtract(e1, e2) => (e1, e2), | ||||
|             ArithmeticExpression::Mult(e1, e2) => (e1, e2), | ||||
|         }; | ||||
|         let type1 = self.handle_expression(exp1)?; | ||||
|         let type2 = self.handle_expression(exp2)?; | ||||
|         if let (Some(type1), Some(type2)) = (type1, type2) { | ||||
|             let mut return_type = None; | ||||
|             for op in &self.possible_arit_possib { | ||||
|                 match op { | ||||
|                     ArithmeticOp::Add(t1, t2, t3) => { | ||||
|                         if let ArithmeticExpression::Add(..) = exp { | ||||
|                             if (t1 == &type1 && t2 == &type2) || (t2 == &type1 && t1 == &type2) { | ||||
|                                 return_type = Some(t3); | ||||
|                                 break; | ||||
|                             } | ||||
|                         } | ||||
|                     } | ||||
|                     ArithmeticOp::Subtract(t1, t2, t3) => { | ||||
|                         if let ArithmeticExpression::Subtract(..) = exp { | ||||
|                             if (t1 == &type1 && t2 == &type2) || (t2 == &type1 && t1 == &type2) { | ||||
|                                 return_type = Some(t3); | ||||
|                                 break; | ||||
|                             } | ||||
|                         } | ||||
|                     } | ||||
|                     ArithmeticOp::Mult(t1, t2, t3) => { | ||||
|                         if let ArithmeticExpression::Mult(..) = exp { | ||||
|                             if (t1 == &type1 && t2 == &type2) || (t2 == &type1 && t1 == &type2) { | ||||
|                                 return_type = Some(t3); | ||||
|                                 break; | ||||
|                             } | ||||
|                         } | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
|             let (command, error) = match exp { | ||||
|                 ArithmeticExpression::Add(..) => { | ||||
|                     (Command::Add, ArithmeticOp::Add(type1, type2, TypeI32)) | ||||
|                 } | ||||
|                 ArithmeticExpression::Subtract(..) => ( | ||||
|                     Command::Subtract, | ||||
|                     ArithmeticOp::Subtract(type1, type2, TypeI32), | ||||
|                 ), | ||||
|                 ArithmeticExpression::Mult(..) => { | ||||
|                     (Command::Mult, ArithmeticOp::Subtract(type1, type2, TypeI32)) | ||||
|                 } | ||||
|             }; | ||||
|             if let Some(t) = return_type { | ||||
|                 self.list.push(command); | ||||
|                 Ok(Some(*t)) | ||||
|             } else { | ||||
|                 Err(CompilerError::ArithmeticExpressionFailed( | ||||
|                     pos, | ||||
|                     Box::new(CompilerError::InvalidArithmeticOperation(error)), | ||||
|                 )) | ||||
|             } | ||||
|         } else { | ||||
|             Err(CompilerError::ArithmeticExpressionFailed( | ||||
|                 pos, | ||||
|                 Box::new(CompilerError::CanNotAssignVoidType), | ||||
|             )) | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     fn handle_statement( | ||||
|         &mut self, | ||||
|         statement: Statement, | ||||
|  | ||||
| @ -5,6 +5,9 @@ use std::io; | ||||
| #[cfg(feature = "compiler")] | ||||
| use std::num::ParseIntError; | ||||
| 
 | ||||
| #[cfg(feature = "compiler")] | ||||
| use super::compiler::ArithmeticOp; | ||||
| 
 | ||||
| #[cfg(feature = "compiler")] | ||||
| use super::vm::Position; | ||||
| use super::vm::VariableType; | ||||
| @ -113,6 +116,8 @@ pub enum CompilerError { | ||||
|     CanNotAssignVoidType, | ||||
|     FunctionNotFound(Position, String, Vec<VariableType>), | ||||
|     ParseIntError(ParseIntError), | ||||
|     ArithmeticExpressionFailed(Position, Box<CompilerError>), | ||||
|     InvalidArithmeticOperation(ArithmeticOp), | ||||
| } | ||||
| 
 | ||||
| #[cfg(feature = "compiler")] | ||||
| @ -140,6 +145,23 @@ impl Display for CompilerError { | ||||
|                 pos | ||||
|             ), | ||||
|             CompilerError::ParseIntError(err) => format!("Failed to parse integer value: {}", err), | ||||
|             CompilerError::ArithmeticExpressionFailed(pos, err) => { | ||||
|                 format!("Arithmetic expression failed at {}:\n  {}", pos, err) | ||||
|             } | ||||
|             CompilerError::InvalidArithmeticOperation(op) => { | ||||
|                 let text = match op { | ||||
|                     ArithmeticOp::Add(t1, t2, _) => { | ||||
|                         format!("{} + {}", t1.to_string(), t2.to_string()) | ||||
|                     } | ||||
|                     ArithmeticOp::Subtract(t1, t2, _) => { | ||||
|                         format!("{} - {}", t1.to_string(), t2.to_string()) | ||||
|                     } | ||||
|                     ArithmeticOp::Mult(t1, t2, _) => { | ||||
|                         format!("{} * {}", t1.to_string(), t2.to_string()) | ||||
|                     } | ||||
|                 }; | ||||
|                 format!("Invalid arithmetic operation: {}", text) | ||||
|             } | ||||
|         }; | ||||
|         write!(f, "{}", text) | ||||
|     } | ||||
| @ -175,4 +197,5 @@ pub enum RuntimePanic { | ||||
|     ValueNotInitialized, | ||||
|     InvalidTypeAssign, | ||||
|     InvalidFuncAddress, | ||||
|     AttemptedInvalidArithmeticOperation, | ||||
| } | ||||
|  | ||||
| @ -80,6 +80,9 @@ impl Command { | ||||
|             Command::StringLit(..) => 7, | ||||
|             Command::I32Lit(..) => 8, | ||||
|             Command::FunctionCall(..) => 9, | ||||
|             Command::Add => 10, | ||||
|             Command::Subtract => 11, | ||||
|             Command::Mult => 12, | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
| @ -128,6 +131,9 @@ impl Command { | ||||
|                 let funcid = u16::from_be_bytes([*iter.next()?, *iter.next()?]); | ||||
|                 Some(Command::FunctionCall(funcid)) | ||||
|             } | ||||
|             10 => Some(Command::Add), | ||||
|             11 => Some(Command::Subtract), | ||||
|             12 => Some(Command::Mult), | ||||
|             _ => None, | ||||
|         } | ||||
|     } | ||||
| @ -167,6 +173,9 @@ impl Command { | ||||
|                 let funcid = funcid.to_be_bytes(); | ||||
|                 list.append(&mut vec![funcid[0], funcid[1]]); | ||||
|             } | ||||
|             Command::Add => (), | ||||
|             Command::Subtract => (), | ||||
|             Command::Mult => (), | ||||
|         } | ||||
|         list | ||||
|     } | ||||
|  | ||||
| @ -22,7 +22,7 @@ impl Statement { | ||||
|             parser | ||||
|                 .expect_static("=") | ||||
|                 .get_or(SyntaxError::ExpectedToken(pos, '='))?; | ||||
|             match Expression::parse(parser) { | ||||
|             match Expression::parse(parser, true) { | ||||
|                 Ok(expr) => { | ||||
|                     parser | ||||
|                         .expect_static(";") | ||||
| @ -32,7 +32,7 @@ impl Statement { | ||||
|                 Err(err) => Err(SyntaxError::ExpectedExpression(pos, Some(Box::new(err)))), | ||||
|             } | ||||
|         } else { | ||||
|             match Expression::parse(parser) { | ||||
|             match Expression::parse(parser, true) { | ||||
|                 Ok(expr) => { | ||||
|                     let statement = Statement::ExprStatement(pos, expr); | ||||
|                     parser | ||||
| @ -50,14 +50,15 @@ impl Statement { | ||||
| pub enum Expression { | ||||
|     BlockExpr(Position, Vec<Statement>), | ||||
|     FunctionCall(Position, Ident, Vec<Expression>), | ||||
|     ArithmeticExpression(Position, Box<ArithmeticExpression>), | ||||
|     ValueRef(Position, Pattern), | ||||
| } | ||||
| 
 | ||||
| impl Expression { | ||||
|     pub fn parse(parser: &mut Parser) -> Result<Expression, SyntaxError> { | ||||
|     pub fn parse(parser: &mut Parser, allow_arithmetic: bool) -> Result<Expression, SyntaxError> { | ||||
|         let begin_pos = parser.pos(); | ||||
| 
 | ||||
|         if parser.expect_static("{").get().is_some() { | ||||
|         let first = if parser.expect_static("{").get().is_some() { | ||||
|             let mut statement_list = Vec::new(); | ||||
|             while { | ||||
|                 match Statement::parse(parser) { | ||||
| @ -78,7 +79,7 @@ impl Expression { | ||||
|             let name = texts.get(0).unwrap(); | ||||
|             let mut arg_list = Vec::new(); | ||||
|             while { | ||||
|                 match Expression::parse(parser) { | ||||
|                 match Expression::parse(parser, true) { | ||||
|                     Ok(exp) => { | ||||
|                         arg_list.push(exp); | ||||
|                         parser.expect_static(",").get().is_some() | ||||
| @ -100,10 +101,103 @@ impl Expression { | ||||
|             Ok(Expression::ValueRef(begin_pos, pattern)) | ||||
|         } else { | ||||
|             Err(SyntaxError::ExpectedExpression(begin_pos, None)) | ||||
|         }?; | ||||
| 
 | ||||
|         if allow_arithmetic { | ||||
|             if let Ok(exp) = ArithmeticExpression::parse(first.clone(), parser) { | ||||
|                 Ok(Expression::ArithmeticExpression(begin_pos, Box::new(exp))) | ||||
|             } else { | ||||
|                 Ok(first) | ||||
|             } | ||||
|         } else { | ||||
|             Ok(first) | ||||
|         } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| #[derive(Debug, Clone)] | ||||
| pub enum ArithmeticExpression { | ||||
|     Add(Expression, Expression), | ||||
|     Subtract(Expression, Expression), | ||||
|     Mult(Expression, Expression), | ||||
| } | ||||
| 
 | ||||
| impl ArithmeticExpression { | ||||
|     fn parse( | ||||
|         first_exp: Expression, | ||||
|         parser: &mut Parser, | ||||
|     ) -> Result<ArithmeticExpression, SyntaxError> { | ||||
|         let mut list = Vec::new(); | ||||
|         let mut exp = first_exp; | ||||
|         while { | ||||
|             let sign = parser | ||||
|                 .expect_static("+") | ||||
|                 .get() | ||||
|                 .or_else(|| parser.expect_static("-").get()) | ||||
|                 .or_else(|| parser.expect_static("*").get()); | ||||
|             if sign.is_some() { | ||||
|                 list.push((exp, sign.clone())); | ||||
|                 exp = Expression::parse(parser, false)?; | ||||
|             } | ||||
|             sign.is_some() | ||||
|         } {} | ||||
|         list.push((exp, None)); | ||||
|         if list.len() == 1 { | ||||
|             return Err(SyntaxError::Fatal); | ||||
|         } | ||||
| 
 | ||||
|         // Replace all (expr, "*"), (expr, any) => ((mult_expr, any)
 | ||||
|         let clone = list.clone(); | ||||
|         let iter = clone.iter().enumerate().rev(); | ||||
|         let mut previous: Option<(Expression, Option<String>)> = None; | ||||
|         for (idx, (exp, sign)) in iter { | ||||
|             if let Some(sign) = sign { | ||||
|                 if sign == "*" { | ||||
|                     if let Some((exp2, sign2)) = previous { | ||||
|                         list.remove(idx + 1); | ||||
|                         list.remove(idx); | ||||
|                         let expr = Expression::ArithmeticExpression( | ||||
|                             parser.pos(), | ||||
|                             Box::new(ArithmeticExpression::Mult(exp.clone(), exp2.clone())), | ||||
|                         ); | ||||
|                         list.insert(idx, (expr, sign2.clone())); | ||||
|                     }; | ||||
|                 } | ||||
|             } | ||||
|             previous = Some((exp.clone(), sign.clone())); | ||||
|         } | ||||
| 
 | ||||
|         let mut ret = Err(SyntaxError::Fatal); | ||||
|         while list.len() > 1 { | ||||
|             let (exp2, sign2) = list.remove(1); | ||||
|             let (exp1, sign1) = list.remove(0); | ||||
|             let expr = if let Some(sign1) = sign1 { | ||||
|                 match &*sign1 { | ||||
|                     "+" => Some(Box::new(ArithmeticExpression::Add(exp1, exp2))), | ||||
|                     "-" => Some(Box::new(ArithmeticExpression::Subtract(exp1, exp2))), | ||||
|                     _ => None, | ||||
|                 } | ||||
|             } else { | ||||
|                 return Err(SyntaxError::ExpectedExpression(parser.pos(), None)); | ||||
|             }; | ||||
|             if let Some(expr) = expr { | ||||
|                 list.insert( | ||||
|                     0, | ||||
|                     (Expression::ArithmeticExpression(parser.pos(), expr), sign2), | ||||
|                 ); | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         if let Some(first) = list.get(0) { | ||||
|             if let Expression::ArithmeticExpression(_, expr) = &first.0 { | ||||
|                 ret = Ok(*expr.clone()); | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         ret | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| #[derive(Debug, Clone)] | ||||
| pub enum Pattern { | ||||
|     IdentPattern(Position, Ident), | ||||
|  | ||||
| @ -1,6 +1,8 @@ | ||||
| use std::fmt; | ||||
| use std::fmt::Display; | ||||
| 
 | ||||
| use std::ops::{Add, Sub}; | ||||
| 
 | ||||
| pub type FuncID = u16; | ||||
| pub type HeapID = u16; | ||||
| pub type RegID = u8; | ||||
| @ -17,6 +19,9 @@ pub enum Command { | ||||
|     StringLit(String),                        // Bring String Literal to Stack
 | ||||
|     I32Lit(i32),                              // Bring i32 Literal to Stack
 | ||||
|     FunctionCall(FuncID),                     // Call Function at FuncID
 | ||||
|     Add,                                      // Add last two items on stack
 | ||||
|     Subtract,                                 // Subtract last two items on stack
 | ||||
|     Mult,                                     // Subtract last two items on stack
 | ||||
| } | ||||
| 
 | ||||
| #[derive(Debug)] | ||||
| @ -37,6 +42,39 @@ impl Value { | ||||
|             Value::I32Val(_) => VariableType::TypeI32, | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     pub fn add(self, other: Value) -> Option<Value> { | ||||
|         match self { | ||||
|             Value::StringVal(string) => match other { | ||||
|                 Value::StringVal(string2) => Some(Value::StringVal(string + &string2)), | ||||
|                 Value::I32Val(val) => Some(Value::StringVal(string + &val.to_string())), | ||||
|             }, | ||||
|             Value::I32Val(val) => match other { | ||||
|                 Value::StringVal(string) => Some(Value::StringVal(val.to_string() + &string)), | ||||
|                 Value::I32Val(val2) => Some(Value::I32Val(val + val2)), | ||||
|             }, | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     pub fn sub(self, other: Value) -> Option<Value> { | ||||
|         match self { | ||||
|             Value::StringVal(_) => None, | ||||
|             Value::I32Val(val) => match other { | ||||
|                 Value::I32Val(val2) => Some(Value::I32Val(val - val2)), | ||||
|                 _ => None, | ||||
|             }, | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     pub fn mul(self, other: Value) -> Option<Value> { | ||||
|         match self { | ||||
|             Value::StringVal(_) => None, | ||||
|             Value::I32Val(val) => match other { | ||||
|                 Value::I32Val(val2) => Some(Value::I32Val(val * val2)), | ||||
|                 _ => None, | ||||
|             }, | ||||
|         } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| #[derive(Debug, Copy, Clone, PartialEq, Eq)] | ||||
|  | ||||
| @ -73,38 +73,29 @@ impl VirtualMachine { | ||||
|         match command { | ||||
|             Command::InitializeVariable(heapid, vtype) => { | ||||
|                 self.heap.insert(heapid, AllocatedVar(vtype, None)); | ||||
|                 //dbg!("Initialized new variable to heap", &self.heap);
 | ||||
|                 Ok(()) | ||||
|             } | ||||
|             Command::BeginScope => { | ||||
|                 self.registry_stack.push(self.registry.clone()); | ||||
|                 self.registry = Default::default(); | ||||
|                 //dbg!("Begun new scope");
 | ||||
|                 Ok(()) | ||||
|             } | ||||
|             Command::EndScope => { | ||||
|                 if let Some(reg) = self.registry_stack.pop() { | ||||
|                     self.registry = reg; | ||||
|                     //dbg!("Scope ended");
 | ||||
|                     Ok(()) | ||||
|                 } else { | ||||
|                     Err(RuntimePanic::ScopeStackUnderflow) | ||||
|                 } | ||||
|             } | ||||
|             Command::Pop(regid) => { | ||||
|                 if let Some(val) = self.stack.pop() { | ||||
|                     self.registry[regid as usize] = Some(val); | ||||
|                     //dbg!("Registry popped", regid, &self.stack, &self.registry);
 | ||||
|                     Ok(()) | ||||
|                 } else { | ||||
|                     Err(RuntimePanic::StackUnderflow) | ||||
|                 } | ||||
|                 self.registry[regid as usize] = Some(self.pop_stack()?); | ||||
|                 Ok(()) | ||||
|             } | ||||
|             Command::Push(regid) => { | ||||
|                 if let Some(reg) = &self.registry[regid as usize] { | ||||
|                     if self.stack.len() < usize::MAX { | ||||
|                         self.stack.push(reg.clone()); | ||||
|                         //dbg!("Registry pushed", regid, &self.stack);
 | ||||
|                         Ok(()) | ||||
|                     } else { | ||||
|                         Err(RuntimePanic::StackOverflow) | ||||
| @ -117,7 +108,6 @@ impl VirtualMachine { | ||||
|                 if let Some(reg) = &self.registry[regid as usize] { | ||||
|                     if let Some(var) = self.heap.get_mut(&heapid) { | ||||
|                         var.try_set(Some(reg.clone()))?; | ||||
|                         //dbg!("Variable assigned", heapid, regid, &self.heap);
 | ||||
|                         Ok(()) | ||||
|                     } else { | ||||
|                         Err(RuntimePanic::InvalidHeapAddress) | ||||
| @ -130,7 +120,6 @@ impl VirtualMachine { | ||||
|                 if let Some(var) = self.heap.get(&heapid) { | ||||
|                     if let Some(val) = &var.1 { | ||||
|                         self.registry[regid as usize] = Some(val.clone()); | ||||
|                         //dbg!("Variable pushed to registry", heapid, regid, &self.registry);
 | ||||
|                         Ok(()) | ||||
|                     } else { | ||||
|                         Err(RuntimePanic::ValueNotInitialized) | ||||
| @ -139,23 +128,8 @@ impl VirtualMachine { | ||||
|                     Err(RuntimePanic::InvalidHeapAddress) | ||||
|                 } | ||||
|             } | ||||
|             Command::StringLit(string) => { | ||||
|                 if self.stack.len() < usize::MAX { | ||||
|                     self.stack.push(Value::StringVal(string)); | ||||
|                     //dbg!("String literal added to stack", string, &self.stack);
 | ||||
|                     Ok(()) | ||||
|                 } else { | ||||
|                     Err(RuntimePanic::StackOverflow) | ||||
|                 } | ||||
|             } | ||||
|             Command::I32Lit(val) => { | ||||
|                 if self.stack.len() < usize::MAX { | ||||
|                     self.stack.push(Value::I32Val(val)); | ||||
|                     Ok(()) | ||||
|                 } else { | ||||
|                     Err(RuntimePanic::StackOverflow) | ||||
|                 } | ||||
|             } | ||||
|             Command::StringLit(string) => self.push_stack(Value::StringVal(string)), | ||||
|             Command::I32Lit(val) => self.push_stack(Value::I32Val(val)), | ||||
|             Command::FunctionCall(funcid) => { | ||||
|                 if self.functions.len() <= funcid as usize { | ||||
|                     Err(RuntimePanic::InvalidFuncAddress) | ||||
| @ -176,6 +150,56 @@ impl VirtualMachine { | ||||
|                     Ok(()) | ||||
|                 } | ||||
|             } | ||||
|             Command::Add => { | ||||
|                 let val1 = self.pop_stack()?; | ||||
|                 let val2 = self.pop_stack()?; | ||||
|                 let res = val2.add(val1); | ||||
|                 if let Some(res) = res { | ||||
|                     self.push_stack(res); | ||||
|                     Ok(()) | ||||
|                 } else { | ||||
|                     Err(RuntimePanic::AttemptedInvalidArithmeticOperation) | ||||
|                 } | ||||
|             } | ||||
|             Command::Subtract => { | ||||
|                 let val1 = self.pop_stack()?; | ||||
|                 let val2 = self.pop_stack()?; | ||||
|                 let res = val2.sub(val1); | ||||
|                 if let Some(res) = res { | ||||
|                     self.push_stack(res); | ||||
|                     Ok(()) | ||||
|                 } else { | ||||
|                     Err(RuntimePanic::AttemptedInvalidArithmeticOperation) | ||||
|                 } | ||||
|             } | ||||
|             Command::Mult => { | ||||
|                 let val1 = self.pop_stack()?; | ||||
|                 let val2 = self.pop_stack()?; | ||||
|                 let res = val2.mul(val1); | ||||
|                 if let Some(res) = res { | ||||
|                     self.push_stack(res); | ||||
|                     Ok(()) | ||||
|                 } else { | ||||
|                     Err(RuntimePanic::AttemptedInvalidArithmeticOperation) | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     fn pop_stack(&mut self) -> Result<Value, RuntimePanic> { | ||||
|         if let Some(val) = self.stack.pop() { | ||||
|             Ok(val) | ||||
|         } else { | ||||
|             Err(RuntimePanic::StackUnderflow) | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     fn push_stack(&mut self, val: Value) -> Result<(), RuntimePanic> { | ||||
|         if self.stack.len() < usize::MAX { | ||||
|             self.stack.push(val); | ||||
|             Ok(()) | ||||
|         } else { | ||||
|             Err(RuntimePanic::StackOverflow) | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user