use crate::bytecode::bytecode_generator;
use crate::frontend::{lexer, parser};
mod bytecode {
pub mod bytecode_interpreter;
pub mod bytecode_generator;
}
mod ast {
pub mod ast;
pub mod treewalk_interpreter;
}
mod frontend {
pub mod lexer;
pub mod parser;
}
pub fn interpret(source_code: &str) -> Result<String, String> {
let tokens = match lexer::lex(source_code) {
Ok(tokens) => tokens,
Err(lex_error) => return Err(String::from(lex_error)),
};
let ast = match parser::parse(tokens) {
Some(Ok(ast)) => ast,
Some(Err(parse_error)) => return Err(String::from(parse_error)),
None => return Err(String::from("")),
};
let bytecode = bytecode_generator::generate(&ast);
match bytecode::bytecode_interpreter::interpret(&bytecode) {
Ok(value) => Ok(format!("{}", value)),
Err(runtime_error) => Err(String::from(runtime_error))
}
}
#[cfg(test)]
mod tests {
use crate::interpret;
#[test]
fn test_interpret_div() {
let source = "(3 + 5 + 2 - 2) * 2 / 8";
assert_eq!(Ok("2".to_string()), interpret(source));
}
#[test]
fn test_div_zero() {
let source = "1 / 0";
assert_eq!(Err("Cannot divide by zero.\nNo result.\n".to_string()), interpret(source));
}
#[test]
fn test_double_exponentiate() {
let source = "2**3**2";
assert_eq!(Ok("512".to_string()), interpret(source));
}
}