use crate::{opcodes::OpCode, parser::{BinOp, Lit, AST}, vm::{Value, VM}}; pub struct Codegen { pub vm: VM } impl Codegen { pub fn new(text: String) -> Self { Codegen { vm: VM::new(Vec::new(), Vec::new(), Vec::new(), text.lines().map(|s| s.to_string()).collect()), } } pub fn visit(&mut self, ast: AST) { use crate::parser::ASTType::*; match ast.ast_type { Program(asts) => { for ast in asts { self.visit(ast); } } // REMOVE LATER Print(ref expr) => { self.visit_print(&ast, *expr.clone()); } Binary(left, oper, right) => { self.visit_binary(*left, oper, *right); } Lit(ref lit) => { self.visit_lit(&ast, lit.clone()); } _ => {} } } // REMOVE LATER pub fn visit_print(&mut self, ast: &AST, expr: AST) { self.visit(expr); self.vm.chunk.push(OpCode::PRINT.into()); if self.vm.lines.last().unwrap().0 != ast.end_line { self.vm.lines.push((ast.end_line, 1)); } else { self.vm.lines.last_mut().unwrap().1 += 1; } } pub fn visit_binary(&mut self, left: AST, oper: BinOp, right: AST) { use crate::parser::BinOp::*; match oper { Add => { self.visit(right); self.visit(left); self.vm.chunk.push(OpCode::ADD.into()); self.vm.lines.last_mut().unwrap().1 += 1; } Sub => { self.visit(right); self.visit(left); self.vm.chunk.push(OpCode::SUB.into()); self.vm.lines.last_mut().unwrap().1 += 1; } _ => { panic!("not implemented") } } } pub fn visit_lit(&mut self, ast: &AST, lit: Lit) { match lit { Lit::Num(value) => { self.vm.pool.push(Value::Num(value)); self.vm.chunk.push(OpCode::CONSTANT.into()); self.vm.chunk.push((self.vm.pool.len()-1) as u8); if self.vm.lines.len() == 0 || self.vm.lines.last().unwrap().0 != ast.end_line { self.vm.lines.push((ast.end_line, 2)); } else { self.vm.lines.last_mut().unwrap().1 += 2; } } Lit::Str(value) => { self.vm.pool.push(Value::Str(value.into())); self.vm.chunk.push(OpCode::CONSTANT.into()); self.vm.chunk.push((self.vm.pool.len()-1) as u8); if self.vm.lines.len() == 0 || self.vm.lines.last().unwrap().0 != ast.end_line { self.vm.lines.push((ast.end_line, 2)); } else { self.vm.lines.last_mut().unwrap().1 += 2; } } Lit::Bool(value) => { self.vm.pool.push(Value::Bool(value)); self.vm.chunk.push(OpCode::CONSTANT.into()); self.vm.chunk.push((self.vm.pool.len()-1) as u8); if self.vm.lines.len() == 0 || self.vm.lines.last().unwrap().0 != ast.end_line { self.vm.lines.push((ast.end_line, 2)); } else { self.vm.lines.last_mut().unwrap().1 += 2; } } _ => {} } } }