From 1c7a9511ba4e6ddafd8437f0ef6d9303dc55da49 Mon Sep 17 00:00:00 2001 From: teascade Date: Tue, 7 Jul 2020 15:06:10 +0300 Subject: [PATCH] Add modulo --- reid_src/test.reid | 4 ++-- src/compiler.rs | 14 ++++++++++++++ src/errors.rs | 3 +++ src/file_io.rs | 3 +++ src/parser/parsed_reid.rs | 15 ++++++++++++++- src/vm/compiled.rs | 11 +++++++++++ src/vm/mod.rs | 11 +++++++++++ 7 files changed, 58 insertions(+), 3 deletions(-) diff --git a/reid_src/test.reid b/reid_src/test.reid index c9ba1f1..1c7baea 100644 --- a/reid_src/test.reid +++ b/reid_src/test.reid @@ -1,3 +1,3 @@ -let number = 100 * 5; -let text = "" + number / 2; +let number = 123 % 5; +let text = "" + number; print(text); \ No newline at end of file diff --git a/src/compiler.rs b/src/compiler.rs index b1c0f47..3b19560 100644 --- a/src/compiler.rs +++ b/src/compiler.rs @@ -18,6 +18,7 @@ pub enum ArithmeticOp { Mult(VariableType, VariableType, VariableType), Pow(VariableType, VariableType, VariableType), Div(VariableType, VariableType, VariableType), + Mod(VariableType, VariableType, VariableType), } pub struct Compiler { @@ -35,6 +36,7 @@ impl Compiler { ArithmeticOp::Mult(TypeI32, TypeI32, TypeI32), ArithmeticOp::Pow(TypeI32, TypeI32, TypeI32), ArithmeticOp::Div(TypeI32, TypeI32, TypeI32), + ArithmeticOp::Mod(TypeI32, TypeI32, TypeI32), ArithmeticOp::Add(TypeString, TypeI32, TypeString), ArithmeticOp::Add(TypeString, TypeString, TypeString), ]; @@ -131,6 +133,7 @@ impl Compiler { ArithmeticExpression::Mult(e1, e2) => (e1, e2), ArithmeticExpression::Pow(e1, e2) => (e1, e2), ArithmeticExpression::Div(e1, e2) => (e1, e2), + ArithmeticExpression::Mod(e1, e2) => (e1, e2), }; let type1 = self.handle_expression(exp1)?; let type2 = self.handle_expression(exp2)?; @@ -178,6 +181,14 @@ impl Compiler { } } } + ArithmeticOp::Mod(t1, t2, t3) => { + if let ArithmeticExpression::Mod(..) = exp { + if (t1 == &type1 && t2 == &type2) || (t2 == &type1 && t1 == &type2) { + return_type = Some(t3); + break; + } + } + } } } let (command, error) = match exp { @@ -197,6 +208,9 @@ impl Compiler { ArithmeticExpression::Div(..) => { (Command::Div, ArithmeticOp::Div(type1, type2, TypeI32)) } + ArithmeticExpression::Mod(..) => { + (Command::Mod, ArithmeticOp::Mod(type1, type2, TypeI32)) + } }; if let Some(t) = return_type { self.list.push(command); diff --git a/src/errors.rs b/src/errors.rs index ee6afdc..31dd7d4 100644 --- a/src/errors.rs +++ b/src/errors.rs @@ -165,6 +165,9 @@ impl Display for CompilerError { ArithmeticOp::Div(t1, t2, _) => { format!("{} / {}", t1.to_string(), t2.to_string()) } + ArithmeticOp::Mod(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 21fdeed..148e2d2 100644 --- a/src/file_io.rs +++ b/src/file_io.rs @@ -85,6 +85,7 @@ impl Command { Command::Mult => 12, Command::Pow => 13, Command::Div => 14, + Command::Mod => 15, } } @@ -138,6 +139,7 @@ impl Command { 12 => Some(Command::Mult), 13 => Some(Command::Pow), 14 => Some(Command::Div), + 15 => Some(Command::Mod), _ => None, } } @@ -182,6 +184,7 @@ impl Command { Command::Mult => (), Command::Pow => (), Command::Div => (), + Command::Mod => (), } list } diff --git a/src/parser/parsed_reid.rs b/src/parser/parsed_reid.rs index f6ff25e..f3a6eda 100644 --- a/src/parser/parsed_reid.rs +++ b/src/parser/parsed_reid.rs @@ -122,6 +122,7 @@ pub enum ArithmeticExpression { Mult(Expression, Expression), Div(Expression, Expression), Pow(Expression, Expression), + Mod(Expression, Expression), } impl ArithmeticExpression { @@ -138,7 +139,8 @@ impl ArithmeticExpression { .or_else(|| parser.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()) + .or_else(|| parser.expect_static("%").get()); if sign.is_some() { list.push((exp, sign.clone())); exp = Expression::parse(parser, false)?; @@ -188,6 +190,17 @@ impl ArithmeticExpression { 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::Mod(exp.clone(), exp2.clone())), + ); + list.insert(idx, (expr, sign2.clone())); + }; + } } } diff --git a/src/vm/compiled.rs b/src/vm/compiled.rs index b2e1fd5..49fefd7 100644 --- a/src/vm/compiled.rs +++ b/src/vm/compiled.rs @@ -22,6 +22,7 @@ pub enum Command { Mult, // Multiply last two items on stack Pow, // Take the power of last two items on stack Div, // Divide last two items on stack + Mod, // Take modulo of last two items on stack } #[derive(Debug)] @@ -95,6 +96,16 @@ impl Value { }, } } + + pub fn modu(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 de76e38..c85ec99 100644 --- a/src/vm/mod.rs +++ b/src/vm/mod.rs @@ -205,6 +205,17 @@ impl VirtualMachine { Err(RuntimePanic::AttemptedInvalidArithmeticOperation) } } + Command::Mod => { + let val1 = self.pop_stack()?; + let val2 = self.pop_stack()?; + let res = val2.modu(val1); + if let Some(res) = res { + self.push_stack(res)?; + Ok(()) + } else { + Err(RuntimePanic::AttemptedInvalidArithmeticOperation) + } + } } }