add modulo operator

This commit is contained in:
2024-10-14 12:53:22 -04:00
parent 9774b08227
commit e760e1fe92
3 changed files with 25 additions and 3 deletions

View File

@@ -90,6 +90,13 @@ impl<I: Iterator<Item = Result<ParseTree, ParseError>>> Executor<I> {
(Value::Float(x), Value::Float(y)) => Ok(Value::Float(x.powf(y))),
_ => Err(RuntimeError::NoOverloadForTypes),
},
ParseTree::Mod(x, y) => match (self.exec(*x, locals, in_function)?, self.exec(*y, locals, in_function)?) {
(Value::Int(x), Value::Int(y)) => Ok(Value::Int(x % y)),
(Value::Float(x), Value::Int(y)) => Ok(Value::Float(x % y as f64)),
(Value::Int(x), Value::Float(y)) => Ok(Value::Float(x as f64 % y)),
(Value::Float(x), Value::Float(y)) => Ok(Value::Float(x % y)),
_ => Err(RuntimeError::NoOverloadForTypes),
},
ParseTree::EqualTo(x, y) => match (self.exec(*x, locals, in_function)?, self.exec(*y, locals, in_function)?) {
(Value::Int(x), Value::Int(y)) => Ok(Value::Bool(x == y)),
(Value::Int(x), Value::Float(y)) => Ok(Value::Bool(x as f64 == y)),
@@ -257,3 +264,11 @@ impl<I: Iterator<Item = Result<ParseTree, ParseError>>> Iterator for Executor<I>
}
}
}
#[cfg(test)]
mod tests {
#[test]
fn recursion() {
let program = ": countdown i ?? <= i i 0 countdown - i 1";
}
}

View File

@@ -41,6 +41,7 @@ pub enum ParseTree {
Mul(Box<ParseTree>, Box<ParseTree>),
Div(Box<ParseTree>, Box<ParseTree>),
Exp(Box<ParseTree>, Box<ParseTree>),
Mod(Box<ParseTree>, Box<ParseTree>),
// Boolean Operations
EqualTo(Box<ParseTree>, Box<ParseTree>),
@@ -118,6 +119,10 @@ impl ParseTree {
Box::new(ParseTree::parse(tokens, globals, locals)?),
Box::new(ParseTree::parse(tokens, globals, locals)?)
)),
Op::Mod => Ok(ParseTree::Mod(
Box::new(ParseTree::parse(tokens, globals, locals)?),
Box::new(ParseTree::parse(tokens, globals, locals)?)
)),
Op::Equ | Op::LazyEqu | Op::GlobalEqu | Op::LazyGlobalEqu => {
let token = tokens.next()
.ok_or(ParseError::UnexpectedEndInput)?

View File

@@ -40,6 +40,7 @@ pub enum Op {
Div,
Exp,
Equ,
Mod,
LazyEqu,
GlobalEqu,
LazyGlobalEqu,
@@ -90,8 +91,9 @@ impl Token {
"+" => Ok(Token::Operator(Op::Add)),
"-" => Ok(Token::Operator(Op::Sub)),
"*" => Ok(Token::Operator(Op::Mul)),
"**" => Ok(Token::Operator(Op::Exp)),
"/" => Ok(Token::Operator(Op::Div)),
"**" => Ok(Token::Operator(Op::Exp)),
"%" => Ok(Token::Operator(Op::Mod)),
"=" => Ok(Token::Operator(Op::Equ)),
"." => Ok(Token::Operator(Op::LazyEqu)),
"=>" => Ok(Token::Operator(Op::GlobalEqu)),
@@ -170,8 +172,8 @@ impl<R: BufRead> std::iter::Iterator for Tokenizer<R> {
let mut input = String::new();
match self.reader.read_to_string(&mut input) {
Ok(0) => return None,
Err(e) => return Some(Err(TokenizeError::IO(e))),
Ok(0) => None,
Err(e) => Some(Err(TokenizeError::IO(e))),
_ => {
let re = regex::Regex::new(r#"[a-zA-Z0-9\.'_]+|[`~!@#\$%\^&\*\(\)\+-=\[\]\{\}\\|;:,<\.>/\?]+|("[^"]+")"#).expect("This wont fail promise :3");