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() {
|
fn main() {
|
||||||
|
|
||||||
let code = r#"
|
let code = r#"
|
||||||
a = 54 * 3;
|
let a = 5 * 3;
|
||||||
b = 5;
|
let b = 5;
|
||||||
print("{}", a + b);
|
(a + b * 3) / 5;
|
||||||
"#;
|
"#;
|
||||||
|
|
||||||
let mut lexer = Lexer::new(code);
|
let mut lexer = Lexer::new(code);
|
||||||
@ -16,8 +16,12 @@ fn main() {
|
|||||||
println!("Tokens: \n{}\n", tokens);
|
println!("Tokens: \n{}\n", tokens);
|
||||||
|
|
||||||
let mut parser = Parser::new(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 lexer;
|
||||||
pub mod ast;
|
pub mod ast;
|
||||||
pub mod parser;
|
pub mod parser;
|
||||||
|
pub mod interpreter;
|
||||||
|
|
||||||
pub use lexer::Lexer;
|
pub use lexer::Lexer;
|
||||||
pub use parser::Parser;
|
pub use parser::Parser;
|
||||||
|
pub use interpreter::Interpreter;
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user