Add modulo

This commit is contained in:
Sofia 2020-07-07 15:06:10 +03:00
parent 6b87b51202
commit 1c7a9511ba
7 changed files with 58 additions and 3 deletions

View File

@ -1,3 +1,3 @@
let number = 100 * 5; let number = 123 % 5;
let text = "" + number / 2; let text = "" + number;
print(text); print(text);

View File

@ -18,6 +18,7 @@ pub enum ArithmeticOp {
Mult(VariableType, VariableType, VariableType), Mult(VariableType, VariableType, VariableType),
Pow(VariableType, VariableType, VariableType), Pow(VariableType, VariableType, VariableType),
Div(VariableType, VariableType, VariableType), Div(VariableType, VariableType, VariableType),
Mod(VariableType, VariableType, VariableType),
} }
pub struct Compiler { pub struct Compiler {
@ -35,6 +36,7 @@ impl Compiler {
ArithmeticOp::Mult(TypeI32, TypeI32, TypeI32), ArithmeticOp::Mult(TypeI32, TypeI32, TypeI32),
ArithmeticOp::Pow(TypeI32, TypeI32, TypeI32), ArithmeticOp::Pow(TypeI32, TypeI32, TypeI32),
ArithmeticOp::Div(TypeI32, TypeI32, TypeI32), ArithmeticOp::Div(TypeI32, TypeI32, TypeI32),
ArithmeticOp::Mod(TypeI32, TypeI32, TypeI32),
ArithmeticOp::Add(TypeString, TypeI32, TypeString), ArithmeticOp::Add(TypeString, TypeI32, TypeString),
ArithmeticOp::Add(TypeString, TypeString, TypeString), ArithmeticOp::Add(TypeString, TypeString, TypeString),
]; ];
@ -131,6 +133,7 @@ impl Compiler {
ArithmeticExpression::Mult(e1, e2) => (e1, e2), ArithmeticExpression::Mult(e1, e2) => (e1, e2),
ArithmeticExpression::Pow(e1, e2) => (e1, e2), ArithmeticExpression::Pow(e1, e2) => (e1, e2),
ArithmeticExpression::Div(e1, e2) => (e1, e2), ArithmeticExpression::Div(e1, e2) => (e1, e2),
ArithmeticExpression::Mod(e1, e2) => (e1, e2),
}; };
let type1 = self.handle_expression(exp1)?; let type1 = self.handle_expression(exp1)?;
let type2 = self.handle_expression(exp2)?; 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 { let (command, error) = match exp {
@ -197,6 +208,9 @@ impl Compiler {
ArithmeticExpression::Div(..) => { ArithmeticExpression::Div(..) => {
(Command::Div, ArithmeticOp::Div(type1, type2, TypeI32)) (Command::Div, ArithmeticOp::Div(type1, type2, TypeI32))
} }
ArithmeticExpression::Mod(..) => {
(Command::Mod, ArithmeticOp::Mod(type1, type2, TypeI32))
}
}; };
if let Some(t) = return_type { if let Some(t) = return_type {
self.list.push(command); self.list.push(command);

View File

@ -165,6 +165,9 @@ impl Display for CompilerError {
ArithmeticOp::Div(t1, t2, _) => { ArithmeticOp::Div(t1, t2, _) => {
format!("{} / {}", t1.to_string(), t2.to_string()) format!("{} / {}", t1.to_string(), t2.to_string())
} }
ArithmeticOp::Mod(t1, t2, _) => {
format!("{} % {}", t1.to_string(), t2.to_string())
}
}; };
format!("Invalid arithmetic operation: {}", text) format!("Invalid arithmetic operation: {}", text)
} }

View File

@ -85,6 +85,7 @@ impl Command {
Command::Mult => 12, Command::Mult => 12,
Command::Pow => 13, Command::Pow => 13,
Command::Div => 14, Command::Div => 14,
Command::Mod => 15,
} }
} }
@ -138,6 +139,7 @@ impl Command {
12 => Some(Command::Mult), 12 => Some(Command::Mult),
13 => Some(Command::Pow), 13 => Some(Command::Pow),
14 => Some(Command::Div), 14 => Some(Command::Div),
15 => Some(Command::Mod),
_ => None, _ => None,
} }
} }
@ -182,6 +184,7 @@ impl Command {
Command::Mult => (), Command::Mult => (),
Command::Pow => (), Command::Pow => (),
Command::Div => (), Command::Div => (),
Command::Mod => (),
} }
list list
} }

View File

@ -122,6 +122,7 @@ pub enum ArithmeticExpression {
Mult(Expression, Expression), Mult(Expression, Expression),
Div(Expression, Expression), Div(Expression, Expression),
Pow(Expression, Expression), Pow(Expression, Expression),
Mod(Expression, Expression),
} }
impl ArithmeticExpression { 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())
.or_else(|| parser.expect_static("*").get()); .or_else(|| parser.expect_static("*").get())
.or_else(|| parser.expect_static("%").get());
if sign.is_some() { if sign.is_some() {
list.push((exp, sign.clone())); list.push((exp, sign.clone()));
exp = Expression::parse(parser, false)?; exp = Expression::parse(parser, false)?;
@ -188,6 +190,17 @@ impl ArithmeticExpression {
list.insert(idx, (expr, sign2.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::Mod(exp.clone(), exp2.clone())),
);
list.insert(idx, (expr, sign2.clone()));
};
}
} }
} }

View File

@ -22,6 +22,7 @@ pub enum Command {
Mult, // Multiply last two items on stack Mult, // Multiply last two items on stack
Pow, // Take the power of last two items on stack Pow, // Take the power of last two items on stack
Div, // Divide last two items on stack Div, // Divide last two items on stack
Mod, // Take modulo of last two items on stack
} }
#[derive(Debug)] #[derive(Debug)]
@ -95,6 +96,16 @@ impl Value {
}, },
} }
} }
pub fn modu(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)] #[derive(Debug, Copy, Clone, PartialEq, Eq)]

View File

@ -205,6 +205,17 @@ impl VirtualMachine {
Err(RuntimePanic::AttemptedInvalidArithmeticOperation) 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)
}
}
} }
} }