From 6b87b512028650759f53dde70982dc2ce3360384 Mon Sep 17 00:00:00 2001 From: teascade Date: Mon, 6 Jul 2020 12:42:38 +0300 Subject: [PATCH] Add pow and div arithmetic operators --- reid_src/test.reid | 4 ++-- src/compiler.rs | 30 +++++++++++++++++++++++++++++- src/errors.rs | 6 ++++++ src/file_io.rs | 6 ++++++ src/parser/parsed_reid.rs | 29 ++++++++++++++++++++++++++++- src/vm/compiled.rs | 24 +++++++++++++++++++++++- src/vm/mod.rs | 22 ++++++++++++++++++++++ 7 files changed, 116 insertions(+), 5 deletions(-) diff --git a/reid_src/test.reid b/reid_src/test.reid index 0e0285c..c9ba1f1 100644 --- a/reid_src/test.reid +++ b/reid_src/test.reid @@ -1,3 +1,3 @@ -let number = 2 * 5 * 2 - 10 + 5 * 7; -let text = "" + number; +let number = 100 * 5; +let text = "" + number / 2; print(text); \ No newline at end of file diff --git a/src/compiler.rs b/src/compiler.rs index f7bfe56..b1c0f47 100644 --- a/src/compiler.rs +++ b/src/compiler.rs @@ -16,6 +16,8 @@ pub enum ArithmeticOp { Add(VariableType, VariableType, VariableType), Subtract(VariableType, VariableType, VariableType), Mult(VariableType, VariableType, VariableType), + Pow(VariableType, VariableType, VariableType), + Div(VariableType, VariableType, VariableType), } pub struct Compiler { @@ -31,6 +33,8 @@ impl Compiler { ArithmeticOp::Add(TypeI32, TypeI32, TypeI32), ArithmeticOp::Subtract(TypeI32, TypeI32, TypeI32), ArithmeticOp::Mult(TypeI32, TypeI32, TypeI32), + ArithmeticOp::Pow(TypeI32, TypeI32, TypeI32), + ArithmeticOp::Div(TypeI32, TypeI32, TypeI32), ArithmeticOp::Add(TypeString, TypeI32, TypeString), ArithmeticOp::Add(TypeString, TypeString, TypeString), ]; @@ -125,6 +129,8 @@ impl Compiler { ArithmeticExpression::Add(e1, e2) => (e1, e2), ArithmeticExpression::Subtract(e1, e2) => (e1, e2), ArithmeticExpression::Mult(e1, e2) => (e1, e2), + ArithmeticExpression::Pow(e1, e2) => (e1, e2), + ArithmeticExpression::Div(e1, e2) => (e1, e2), }; let type1 = self.handle_expression(exp1)?; let type2 = self.handle_expression(exp2)?; @@ -156,6 +162,22 @@ impl Compiler { } } } + ArithmeticOp::Div(t1, t2, t3) => { + if let ArithmeticExpression::Div(..) = exp { + if (t1 == &type1 && t2 == &type2) || (t2 == &type1 && t1 == &type2) { + return_type = Some(t3); + break; + } + } + } + ArithmeticOp::Pow(t1, t2, t3) => { + if let ArithmeticExpression::Pow(..) = exp { + if (t1 == &type1 && t2 == &type2) || (t2 == &type1 && t1 == &type2) { + return_type = Some(t3); + break; + } + } + } } } let (command, error) = match exp { @@ -167,7 +189,13 @@ impl Compiler { ArithmeticOp::Subtract(type1, type2, TypeI32), ), ArithmeticExpression::Mult(..) => { - (Command::Mult, ArithmeticOp::Subtract(type1, type2, TypeI32)) + (Command::Mult, ArithmeticOp::Mult(type1, type2, TypeI32)) + } + ArithmeticExpression::Pow(..) => { + (Command::Pow, ArithmeticOp::Pow(type1, type2, TypeI32)) + } + ArithmeticExpression::Div(..) => { + (Command::Div, ArithmeticOp::Div(type1, type2, TypeI32)) } }; if let Some(t) = return_type { diff --git a/src/errors.rs b/src/errors.rs index f400659..ee6afdc 100644 --- a/src/errors.rs +++ b/src/errors.rs @@ -159,6 +159,12 @@ impl Display for CompilerError { ArithmeticOp::Mult(t1, t2, _) => { format!("{} * {}", t1.to_string(), t2.to_string()) } + ArithmeticOp::Pow(t1, t2, _) => { + format!("{} ** {}", t1.to_string(), t2.to_string()) + } + ArithmeticOp::Div(t1, t2, _) => { + format!("{} / {}", t1.to_string(), t2.to_string()) + } }; format!("Invalid arithmetic operation: {}", text) } diff --git a/src/file_io.rs b/src/file_io.rs index cc3ff91..21fdeed 100644 --- a/src/file_io.rs +++ b/src/file_io.rs @@ -83,6 +83,8 @@ impl Command { Command::Add => 10, Command::Subtract => 11, Command::Mult => 12, + Command::Pow => 13, + Command::Div => 14, } } @@ -134,6 +136,8 @@ impl Command { 10 => Some(Command::Add), 11 => Some(Command::Subtract), 12 => Some(Command::Mult), + 13 => Some(Command::Pow), + 14 => Some(Command::Div), _ => None, } } @@ -176,6 +180,8 @@ impl Command { Command::Add => (), Command::Subtract => (), Command::Mult => (), + Command::Pow => (), + Command::Div => (), } list } diff --git a/src/parser/parsed_reid.rs b/src/parser/parsed_reid.rs index 65077a0..f6ff25e 100644 --- a/src/parser/parsed_reid.rs +++ b/src/parser/parsed_reid.rs @@ -120,6 +120,8 @@ pub enum ArithmeticExpression { Add(Expression, Expression), Subtract(Expression, Expression), Mult(Expression, Expression), + Div(Expression, Expression), + Pow(Expression, Expression), } impl ArithmeticExpression { @@ -134,6 +136,8 @@ impl ArithmeticExpression { .expect_static("+") .get() .or_else(|| parser.expect_static("-").get()) + .or_else(|| 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())); @@ -146,11 +150,33 @@ impl ArithmeticExpression { return Err(SyntaxError::Fatal); } - // Replace all (expr, "*"), (expr, any) => ((mult_expr, any) + // Replace all (expr, "*/**//"), (expr, any) => ((mult/pow/div_expr, any) let clone = list.clone(); let iter = clone.iter().enumerate().rev(); for (idx, (exp, sign)) in iter { if let Some(sign) = sign { + if sign == "**" { + if let Some((exp2, sign2)) = list.clone().get(idx + 1) { + list.remove(idx + 1); + list.remove(idx); + let expr = Expression::ArithmeticExpression( + parser.pos(), + Box::new(ArithmeticExpression::Pow(exp.clone(), exp2.clone())), + ); + list.insert(idx, (expr, sign2.clone())); + }; + } + if sign == "/" { + if let Some((exp2, sign2)) = list.clone().get(idx + 1) { + list.remove(idx + 1); + list.remove(idx); + let expr = Expression::ArithmeticExpression( + parser.pos(), + Box::new(ArithmeticExpression::Div(exp.clone(), exp2.clone())), + ); + list.insert(idx, (expr, sign2.clone())); + }; + } if sign == "*" { if let Some((exp2, sign2)) = list.clone().get(idx + 1) { list.remove(idx + 1); @@ -165,6 +191,7 @@ impl ArithmeticExpression { } } + // Replace all (expr, "+/-"), (expr, any) => ((add/sub_expr, any)) let mut ret = Err(SyntaxError::Fatal); while list.len() > 1 { let (exp2, sign2) = list.remove(1); diff --git a/src/vm/compiled.rs b/src/vm/compiled.rs index 8ec85d7..b2e1fd5 100644 --- a/src/vm/compiled.rs +++ b/src/vm/compiled.rs @@ -19,7 +19,9 @@ pub enum Command { 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 + Mult, // Multiply last two items on stack + Pow, // Take the power of last two items on stack + Div, // Divide last two items on stack } #[derive(Debug)] @@ -73,6 +75,26 @@ impl Value { }, } } + + pub fn pow(self, other: Value) -> Option { + match self { + Value::StringVal(_) => None, + Value::I32Val(val) => match other { + Value::I32Val(val2) => Some(Value::I32Val(val.pow(val2 as u32))), + _ => None, + }, + } + } + + pub fn div(self, other: Value) -> Option { + 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)] diff --git a/src/vm/mod.rs b/src/vm/mod.rs index 3b76270..de76e38 100644 --- a/src/vm/mod.rs +++ b/src/vm/mod.rs @@ -183,6 +183,28 @@ impl VirtualMachine { Err(RuntimePanic::AttemptedInvalidArithmeticOperation) } } + Command::Pow => { + let val1 = self.pop_stack()?; + let val2 = self.pop_stack()?; + let res = val2.pow(val1); + if let Some(res) = res { + self.push_stack(res)?; + Ok(()) + } else { + Err(RuntimePanic::AttemptedInvalidArithmeticOperation) + } + } + Command::Div => { + let val1 = self.pop_stack()?; + let val2 = self.pop_stack()?; + let res = val2.div(val1); + if let Some(res) = res { + self.push_stack(res)?; + Ok(()) + } else { + Err(RuntimePanic::AttemptedInvalidArithmeticOperation) + } + } } }