Skip to content

Commit

Permalink
feat: new % (modulo) /= *= %= operators
Browse files Browse the repository at this point in the history
  • Loading branch information
fcoury committed Jul 5, 2024
1 parent a1979c6 commit 84c1d33
Show file tree
Hide file tree
Showing 6 changed files with 113 additions and 2 deletions.
1 change: 1 addition & 0 deletions src/interpreter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -526,6 +526,7 @@ impl Interpreter {
Operator::Multiply => Ok(Value::Int(left * right)),
Operator::Divide => Ok(Value::Int(left / right)),
Operator::Equals => Ok(Value::Bool(left == right)),
Operator::Modulo => Ok(Value::Int(left % right)),
},
_ => Err(Error::new_runtime(
"Binary operation on non-numeric values".to_string(),
Expand Down
78 changes: 77 additions & 1 deletion src/lexer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -56,8 +56,12 @@ pub enum TokenKind {
Minus,
Asterisk,
Slash,
Percent,
PlusEquals,
MinusEquals,
StarEquals,
SlashEquals,
PercentEquals,
Colon,
Dot,
DblDot,
Expand Down Expand Up @@ -178,7 +182,14 @@ impl Lexer {
self.create_token(TokenKind::Minus)
}
}
Some('*') => self.create_token(TokenKind::Asterisk),
Some('*') => {
if self.peek_char() == Some('=') {
self.read_char();
self.create_token(TokenKind::StarEquals)
} else {
self.create_token(TokenKind::Asterisk)
}
}
Some(':') => self.create_token(TokenKind::Colon),
Some('/') => {
if self.peek_char() == Some('/') {
Expand All @@ -199,10 +210,21 @@ impl Lexer {
self.read_char();
}
return self.next_token();
} else if self.peek_char() == Some('=') {
self.read_char();
self.create_token(TokenKind::SlashEquals)
} else {
return self.create_token(TokenKind::Slash);
}
}
Some('%') => {
if self.peek_char() == Some('=') {
self.read_char();
self.create_token(TokenKind::PercentEquals)
} else {
self.create_token(TokenKind::Percent)
}
}
Some('.') => {
let start = self.position;
if self.peek_char() == Some('.') {
Expand Down Expand Up @@ -1003,4 +1025,58 @@ mod tests {
assert_eq!(kind, expected);
}
}

#[test]
fn test_lex_times_equals() {
let code = "x *= 10;";
let mut lexer = Lexer::new(code);
let expected_tokens = vec![
TokenKind::Identifier("x".to_string()),
TokenKind::StarEquals,
TokenKind::Int(10),
TokenKind::Semicolon,
TokenKind::Eof,
];

for expected in expected_tokens {
let kind = lexer.next_token().kind;
assert_eq!(kind, expected);
}
}

#[test]
fn test_lex_divide_equals() {
let code = "x /= 10;";
let mut lexer = Lexer::new(code);
let expected_tokens = vec![
TokenKind::Identifier("x".to_string()),
TokenKind::SlashEquals,
TokenKind::Int(10),
TokenKind::Semicolon,
TokenKind::Eof,
];

for expected in expected_tokens {
let kind = lexer.next_token().kind;
assert_eq!(kind, expected);
}
}

#[test]
fn test_lex_mod_equals() {
let code = "x %= 10;";
let mut lexer = Lexer::new(code);
let expected_tokens = vec![
TokenKind::Identifier("x".to_string()),
TokenKind::PercentEquals,
TokenKind::Int(10),
TokenKind::Semicolon,
TokenKind::Eof,
];

for expected in expected_tokens {
let kind = lexer.next_token().kind;
assert_eq!(kind, expected);
}
}
}
10 changes: 9 additions & 1 deletion src/parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -286,6 +286,7 @@ pub enum Operator {
Multiply,
Divide,
Equals,
Modulo,
}

pub struct Parser {
Expand Down Expand Up @@ -828,10 +829,17 @@ impl Parser {

loop {
match self.current_token().kind {
TokenKind::PlusEquals | TokenKind::MinusEquals => {
TokenKind::PlusEquals
| TokenKind::MinusEquals
| TokenKind::StarEquals
| TokenKind::SlashEquals
| TokenKind::PercentEquals => {
let op = match self.current_token().kind {
TokenKind::PlusEquals => Operator::Plus,
TokenKind::MinusEquals => Operator::Minus,
TokenKind::StarEquals => Operator::Multiply,
TokenKind::SlashEquals => Operator::Divide,
TokenKind::PercentEquals => Operator::Modulo,
_ => unreachable!(),
};
self.advance();
Expand Down
20 changes: 20 additions & 0 deletions tests/scripts/opers.hk
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
let a = 1;
a += 8;
println(a);

a -= 3;
println(a);

a *= 2;
println(a);

a /= 2;
println(a);

a %= 2;
println(a);

a += 1;

a %= 2;
println(a);
Empty file added tests/scripts/opers.hk.err
Empty file.
6 changes: 6 additions & 0 deletions tests/scripts/opers.hk.out
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
9
6
12
6
0
1

0 comments on commit 84c1d33

Please sign in to comment.