1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
use crate::{Code, Instructions, Object};
use tonic_parser::{Statement, Expression, Op};

#[derive(Debug)]
pub struct Compiler {
    instructions: Instructions,
    constants: Vec<Object>,
}

impl Compiler {
    
    pub fn new() -> Self {
        Self {
            instructions: Vec::new(),
            constants: Vec::new()
        }
    }

    pub fn instructions(&self) -> Vec<Code> {
        self.instructions.clone()
    }

    pub fn compile(&mut self, statement: Statement) {
        match statement {
            Statement::Expression { expression } => {
                self.expression(expression)
            },
            _ => todo!()
        }
    }

    pub fn expression(&mut self, expression: Expression) {
        match expression {
            Expression::Infix(left, op, right) => {
                self.expression(*left);
                self.expression(*right);

                match op {
                    Op::Add => self.emit(Code::Add),
                    _ => todo!()
                };
            },
            Expression::Number(n) => {
                let position = self.constant(Object::Number(n));

                self.emit(Code::Constant(position));
            },
            _ => todo!()
        }
    }

    fn constant(&mut self, object: Object) -> usize {
        self.constants.push(object);
        self.constants.len() - 1
    }

    fn emit(&mut self, code: Code) -> usize {
        self.instructions.push(code);
        self.instructions.len() - 1
    }
}

#[derive(Debug)]
pub struct Bytecode {
    pub instructions: Instructions,
    pub constants: Vec<Object>,
}

impl From<Compiler> for Bytecode {
    fn from(c: Compiler) -> Self {
        Self { instructions: c.instructions, constants: c.constants }
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use tonic_parser::{Lexer, Parser};

    #[test]
    fn infixes() {
        assert_eq!(compile("1 + 1;"), vec![
            Code::Constant(0),
            Code::Constant(1),
            Code::Add,
        ]);
    }

    fn compile(source: &str) -> Vec<Code> {
        let program = parse(source);
        let mut compiler = Compiler::new();

        for statement in program {
            compiler.compile(statement);
        }

        compiler.instructions().clone()
    }

    fn parse(source: &str) -> Vec<Statement> {
        let lexer = Lexer::new(source);
        let mut parser = Parser::new(lexer);

        parser.read();
        parser.read();

        parser.parse()
    }
}