use std::collections::HashMap;
use super::ast::{Node, NodeType};
use super::parser::Parser;
use super::types::Type;
use super::value::Value;
pub struct Interpreter {
parser: Parser,
symbol_table: HashMap<String, Box<Value>>,
}
impl Interpreter {
pub fn new(parser: Parser) -> Self {
Self {
parser: parser,
symbol_table: HashMap::new(),
}
}
pub fn visit<'a>(&'a mut self, node: &Box<Node>) -> Option<Box<Value>> {
let mut r = None;
if *node.get_node_type() == NodeType::BinOP {
r = self.visit_bin_op(node);
}
if *node.get_node_type() == NodeType::UnaryOP {
r = self.visit_unary_op(node);
}
if *node.get_node_type() == NodeType::VariableOP {
r = self.visit_variable(node);
}
if *node.get_node_type() == NodeType::CompoundOP {
self.visit_compound_op(node);
}
if *node.get_node_type() == NodeType::AssignOP {
r = self.visit_assign(node);
}
if *node.get_node_type() == NodeType::NumOP {
r = self.visit_num(node);
}
return r;
}
pub fn visit_bin_op(&mut self, node: &Box<Node>) -> Option<Box<Value>> {
let mut value = Box::new(Value::NONE);
let _type = *node.get_token().get_type();
if _type == Type::PLUS {
value = Box::new(Value::INTEGER(
self.visit(node.get_left()).expect("Error").get_integer()
+ self.visit(node.get_right()).expect("Error").get_integer(),
));
}
if _type == Type::MINUS {
value = Box::new(Value::INTEGER(
self.visit(&node.get_left()).expect("Error").get_integer()
- self.visit(node.get_right()).expect("Error").get_integer(),
));
}
if _type == Type::PLUS {
value = Box::new(Value::INTEGER(
self.visit(&node.get_left()).expect("Error").get_integer()
+ self.visit(&node.get_right()).expect("Error").get_integer(),
));
}
if _type == Type::MULTIPLY {
value = Box::new(Value::INTEGER(
self.visit(&node.get_left()).expect("Error").get_integer()
* self.visit(&node.get_right()).expect("Error").get_integer(),
));
}
if _type == Type::DIVIDE {
value = Box::new(Value::INTEGER(
self.visit(&node.get_left()).expect("Error").get_integer()
/ self.visit(&node.get_right()).expect("Error").get_integer(),
));
}
return Some(value);
}
pub fn visit_unary_op(&mut self, node: &Box<Node>) -> Option<Box<Value>> {
let mut value = Box::new(Value::NONE);
let _type = *node.get_token().get_type();
if _type == Type::PLUS {
value = Box::new(Value::INTEGER(
self.visit(node.get_mid()).expect("Error").get_integer(),
));
}
if _type == Type::MINUS {
value = Box::new(Value::INTEGER(
-self.visit(node.get_mid()).expect("Error").get_integer(),
));
}
return Some(value);
}
pub fn visit_num<'a>(&'a self, node: &'a Box<Node>) -> Option<Box<Value>> {
return Some(node.get_token().get_value().clone());
}
pub fn visit_compound_op(&mut self, node: &Box<Node>) -> Option<Box<Value>> {
for node in node.get_children().iter() {
self.visit(node);
}
return None;
}
pub fn visit_assign(&mut self, node: &Box<Node>) -> Option<Box<Value>> {
let var_name = node.get_left().get_token().get_value().get_string();
let value = self.visit(node.get_right()).expect("Error");
self.symbol_table.insert(var_name.to_string(), value);
return None;
}
pub fn visit_variable(&mut self, node: &Box<Node>) -> Option<Box<Value>> {
let var_name = node.get_token().get_value().get_string();
match self.symbol_table.get(var_name) {
Some(value) => Some(value.clone()),
None => panic!("Undefined variable"),
}
}
pub fn interpret(&mut self) -> Option<Box<Value>> {
let tree = self.parser.parse();
let value = self.visit(&tree);
for (key, val) in self.symbol_table.iter() {
println!("{} is {:?}", key, val);
}
return value;
}
}