Skip to content

Commit

Permalink
V0.2.x (#28)
Browse files Browse the repository at this point in the history
  • Loading branch information
Yag000 authored Oct 13, 2023
2 parents d1afc30 + 34ce98a commit 2e91228
Show file tree
Hide file tree
Showing 16 changed files with 87 additions and 9 deletions.
2 changes: 1 addition & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "chimpanzee"
version = "0.2.2"
version = "0.2.3"
edition = "2021"
authors = ["Yago Iglesias <yagoiglesias7@gmail.com>"]
license = "MIT OR Apache-2.0"
Expand Down
1 change: 1 addition & 0 deletions docs/MONKEY.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ Integers support the following operators:
- `-`: subtraction
- `*`: multiplication
- `/`: division (integer division)
- `%`: modulo
- `==`: equality
- `!=`: inequality
- `<`: less than
Expand Down
2 changes: 1 addition & 1 deletion monkey_examples/filter.monkey
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,6 @@ let filter = fn (arr, f) {
};
let a = [1, 2, 3, 4, 5, 6, 7, 8, 9, 11, 100];
let is_even = fn (x) {
x / 2 * 2 == x
x % 2 == 0
};
filter(a, is_even);
2 changes: 2 additions & 0 deletions src/compiler/code.rs
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ pub enum Opcode {
NotEqual,
Or,
And,
Modulo,

// Prefix operators
Minus,
Expand Down Expand Up @@ -142,6 +143,7 @@ impl Display for Opcode {
Opcode::Or => "OpOr",
Opcode::And => "OpAnd",
Opcode::Minus => "OpMinus",
Opcode::Modulo => "OpModulo",
Opcode::Bang => "OpBang",
Opcode::JumpNotTruthy => "OpJumpNotTruthy",
Opcode::Jump => "OpJump",
Expand Down
10 changes: 10 additions & 0 deletions src/compiler/compiler_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,16 @@ pub mod tests {
Opcode::Pop.make(vec![]),
]),
},
CompilerTestCase {
input: "1 % 2".to_string(),
expected_constants: vec![Object::INTEGER(1), Object::INTEGER(2)],
expected_instructions: flatten_instructions(vec![
Opcode::Constant.make(vec![0]),
Opcode::Constant.make(vec![1]),
Opcode::Modulo.make(vec![]),
Opcode::Pop.make(vec![]),
]),
},
];

run_compiler(tests);
Expand Down
1 change: 1 addition & 0 deletions src/compiler/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -337,6 +337,7 @@ impl Compiler {
Token::NotEqual => self.emit(Opcode::NotEqual, vec![]),
Token::Or => self.emit(Opcode::Or, vec![]),
Token::And => self.emit(Opcode::And, vec![]),
Token::Modulo => self.emit(Opcode::Modulo, vec![]),
_ => return Err(format!("Unknown operator: {operator}")),
};
Ok(())
Expand Down
2 changes: 1 addition & 1 deletion src/compiler/test_utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ pub(crate) fn run_compiler(tests: Vec<CompilerTestCase>) {
let mut compiler = Compiler::new();

match compiler.compile(program) {
Ok(_) => {
Ok(()) => {
let bytecode = compiler.bytecode();
println!(
"want {}, got {}",
Expand Down
9 changes: 9 additions & 0 deletions src/lexer/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@ impl Lexer {
Token::Illegal("|".to_string())
}
}
'%' => Token::Modulo,
';' => Token::Semicolon,
'(' => Token::LParen,
')' => Token::RParen,
Expand Down Expand Up @@ -230,6 +231,7 @@ mod tests {
break;
continue;
42%13==20;
"#;

let mut lexer = Lexer::new(input);
Expand Down Expand Up @@ -361,6 +363,13 @@ mod tests {
Token::Continue,
Token::Semicolon,
//
Token::Int(String::from("42")),
Token::Modulo,
Token::Int(String::from("13")),
Token::Equal,
Token::Int(String::from("20")),
Token::Semicolon,
//
Token::Eof,
];

Expand Down
2 changes: 2 additions & 0 deletions src/lexer/token.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ pub enum Token {
NotEqual,
And,
Or,
Modulo,

// Delimiters
Comma,
Expand Down Expand Up @@ -92,6 +93,7 @@ impl Display for Token {
Token::While => write!(f, "while"),
Token::Break => write!(f, "break"),
Token::Continue => write!(f, "continue"),
Token::Modulo => write!(f, "%"),
}
}
}
5 changes: 3 additions & 2 deletions src/parser/ast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,8 @@ impl Expression {
| Token::LTE
| Token::GTE
| Token::And
| Token::Or => {
| Token::Or
| Token::Modulo => {
parser.next_token(); // TODO: Solve this.
// This is absolutely awful, I need to peek the next token
// only if a infix operator is found, I want to also
Expand Down Expand Up @@ -635,7 +636,7 @@ impl From<&Token> for Precedence {
Token::Equal | Token::NotEqual => Precedence::Equals,
Token::LT | Token::GT | Token::LTE | Token::GTE => Precedence::LessGreater,
Token::Plus | Token::Minus | Token::Or => Precedence::Sum,
Token::Slash | Token::Asterisk | Token::And => Precedence::Product,
Token::Slash | Token::Asterisk | Token::And | Token::Modulo => Precedence::Product,
Token::LParen => Precedence::Call,
Token::LSquare => Precedence::Index,
_ => Precedence::Lowest,
Expand Down
1 change: 1 addition & 0 deletions src/parser/parser_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,7 @@ mod tests {
("5 - 5;", "5", "-", "5"),
("5 * 5;", "5", "*", "5"),
("5 / 5;", "5", "/", "5"),
("5 % 5;", "5", "%", "5"),
("5 > 5;", "5", ">", "5"),
("5 >= 5;", "5", ">=", "5"),
("5 < 5;", "5", "<", "5"),
Expand Down
16 changes: 15 additions & 1 deletion src/vm/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,7 @@ impl VM {
| Opcode::Sub
| Opcode::Mul
| Opcode::Div
| Opcode::Modulo
| Opcode::Or
| Opcode::And => {
self.execute_binary_operation(op)?;
Expand Down Expand Up @@ -305,7 +306,20 @@ impl VM {
Opcode::Add => left + right,
Opcode::Sub => left - right,
Opcode::Mul => left * right,
Opcode::Div => left / right,
Opcode::Div => {
if right == 0 {
Err("Division by zero".to_string())?
} else {
left / right
}
}
Opcode::Modulo => {
if right == 0 {
Err("Division by zero".to_string())?
} else {
left % right
}
}
_ => unreachable!(),
};

Expand Down
11 changes: 11 additions & 0 deletions src/vm/test_utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,3 +37,14 @@ pub(crate) fn run_vm_tests(tests: Vec<VmTestCase>) {
check_constants(&vec![test.expected], &vec![got]);
}
}

#[allow(dead_code)]
pub(crate) fn run_vm_with_error_output(input: &str) -> Result<(), String> {
let program = parse(input);
let mut compiler = Compiler::new();
compiler.compile(program).unwrap();
let bytecode = compiler.bytecode();

let mut vm = VM::new(bytecode);
vm.run()
}
28 changes: 27 additions & 1 deletion src/vm/vm_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ mod tests {

use crate::{
object::Object,
vm::test_utils::{run_vm_tests, VmTestCase},
vm::test_utils::{run_vm_tests, run_vm_with_error_output, VmTestCase},
};

#[test]
Expand Down Expand Up @@ -67,10 +67,36 @@ mod tests {
input: "(5 + 10 * 2 + 15 / 3) * 2 + -10".to_string(),
expected: Object::INTEGER(50),
},
VmTestCase {
input: "5 % 5".to_string(),
expected: Object::INTEGER(0),
},
VmTestCase {
input: "5 % 1".to_string(),
expected: Object::INTEGER(0),
},
VmTestCase {
input: "5 % 2".to_string(),
expected: Object::INTEGER(1),
},
VmTestCase {
input: "4 % 5".to_string(),
expected: Object::INTEGER(4),
},
];
run_vm_tests(tests);
}

#[test]
fn test_division_by_zero() {
let tests = vec!["1 / 0", "1 % 0"];

for test in tests {
let result = run_vm_with_error_output(test);
assert!(result.is_err());
}
}

#[test]
fn test_boolean_logic() {
let tests = vec![
Expand Down
2 changes: 1 addition & 1 deletion tests/formatting_integrity.rs
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,7 @@ fn test_filter_integrity() {
iter(arr, []);
};
let a = [1, 2, 3, 4,5,6,7,8,9,11,100];
let is_even = fn(x) { (x/2)*2 == x };
let is_even = fn(x) { x % 2 == 0 };
filter(a, is_even);
"#;

Expand Down

0 comments on commit 2e91228

Please sign in to comment.