use crate::{codegen_binary, 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::*;
codegen_binary!(self, left, right, oper, Add, ADD, Sub, SUB, Mul, MUL,
Div, DIV, Mod, MOD, Eq, EQ, Ne, NE, Gr, GR, Ge, GE, Ls, LS,
Le, LE, Or, OR, And, AND);
}
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;
}
}
_ => {}
}
}
}