Add simple and very rough interpreter
- Implemented an interpreter that - Only works with int64 values - Executes maths expressions - Declares and assigns variables in global table - Can use variables in expressions - Debug prints expression only statements - Can NOT use, or declare functions
This commit is contained in:
parent
6bd58a4ecb
commit
623fa71355
@ -4,9 +4,9 @@ use plang2_lib::*;
|
||||
fn main() {
|
||||
|
||||
let code = r#"
|
||||
a = 54 * 3;
|
||||
b = 5;
|
||||
print("{}", a + b);
|
||||
let a = 5 * 3;
|
||||
let b = 5;
|
||||
(a + b * 3) / 5;
|
||||
"#;
|
||||
|
||||
let mut lexer = Lexer::new(code);
|
||||
@ -16,8 +16,12 @@ fn main() {
|
||||
println!("Tokens: \n{}\n", tokens);
|
||||
|
||||
let mut parser = Parser::new(tokens);
|
||||
let expr = parser.parse().unwrap();
|
||||
let prog = parser.parse().unwrap();
|
||||
|
||||
println!("{:#?}", expr);
|
||||
println!("{:#?}\n\n", prog);
|
||||
|
||||
let mut interpreter = Interpreter::new(prog);
|
||||
|
||||
interpreter.run();
|
||||
|
||||
}
|
||||
|
||||
93
plang2_lib/src/interpreter.rs
Normal file
93
plang2_lib/src/interpreter.rs
Normal file
@ -0,0 +1,93 @@
|
||||
use std::collections::HashMap;
|
||||
|
||||
use crate::{ast::{Statement, Expr}, token::Literal};
|
||||
|
||||
pub struct Interpreter {
|
||||
prog: Vec<Statement>,
|
||||
|
||||
// TODO: Those varibales are global only, so this will have to change with functions. Also Literal is reused as variable type
|
||||
variables: HashMap<String, Literal>,
|
||||
|
||||
// Print expression statements to stdout
|
||||
debug: bool,
|
||||
}
|
||||
|
||||
impl Interpreter {
|
||||
pub fn new(prog: Vec<Statement>) -> Self {
|
||||
let variables = Default::default();
|
||||
Self { prog, variables, debug: true }
|
||||
}
|
||||
|
||||
pub fn run(&mut self) {
|
||||
|
||||
for idx in 0..self.prog.len() {
|
||||
self.execute_stmt(idx);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
pub fn execute_stmt(&mut self, idx: usize) {
|
||||
|
||||
// TODO: The clone here is not optimal
|
||||
match self.prog[idx].clone() {
|
||||
Statement::Expr(expr) => {
|
||||
let expr_result = self.execute_expr(expr.clone());
|
||||
if self.debug {
|
||||
println!("{:?}", expr_result);
|
||||
}
|
||||
}
|
||||
Statement::LetBinding(var_name, expr) => {
|
||||
let rhs = self.execute_expr(expr);
|
||||
self.variables.insert(var_name, rhs);
|
||||
}
|
||||
Statement::Assignment(var_name, expr) => {
|
||||
let rhs = self.execute_expr(expr);
|
||||
*self.variables.get_mut(&var_name).expect("Assigning variable before declaration") = rhs;
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
fn execute_expr(&mut self, expr: Expr) -> Literal {
|
||||
match expr {
|
||||
Expr::Literal(lit) => lit,
|
||||
Expr::Variable(name) => self.variables.get(&name).expect("Using variable before declaration").clone(),
|
||||
Expr::FnCall(_) => todo!(),
|
||||
Expr::BinOp(bot, lhs, rhs) => {
|
||||
|
||||
let lhs = match self.execute_expr(*lhs) {
|
||||
Literal::Int64(val) => val,
|
||||
_ => panic!("Binary operators for non i64 not yet implemented")
|
||||
};
|
||||
let rhs = match self.execute_expr(*rhs) {
|
||||
Literal::Int64(val) => val,
|
||||
_ => panic!("Binary operators for non i64 not yet implemented")
|
||||
};
|
||||
|
||||
let res = match bot {
|
||||
crate::ast::BinOpType::Add => lhs + rhs,
|
||||
crate::ast::BinOpType::Sub => lhs - rhs,
|
||||
crate::ast::BinOpType::Mul => lhs * rhs,
|
||||
crate::ast::BinOpType::Div => lhs / rhs,
|
||||
crate::ast::BinOpType::Mod => lhs % rhs,
|
||||
};
|
||||
|
||||
Literal::Int64(res)
|
||||
}
|
||||
Expr::UnOp(uot, expr) => {
|
||||
match uot {
|
||||
crate::ast::UnOpType::Neg => {
|
||||
let mut res = self.execute_expr(*expr);
|
||||
match &mut res {
|
||||
Literal::Boolean(_) => panic!("Can't negate bool"),
|
||||
Literal::Int64(val) => *val *= -1,
|
||||
Literal::String(_) => panic!("Can't negate string"),
|
||||
};
|
||||
|
||||
res
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@ -2,6 +2,8 @@ pub mod token;
|
||||
pub mod lexer;
|
||||
pub mod ast;
|
||||
pub mod parser;
|
||||
pub mod interpreter;
|
||||
|
||||
pub use lexer::Lexer;
|
||||
pub use parser::Parser;
|
||||
pub use interpreter::Interpreter;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user