bomlamaal 0.1.0

Bømlamål as a programming language.
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;
    }
}