use crate::{ast::AST, lexer::Token, push_codegen, push_output, vm::{Value, VM}};
pub fn debug_token_array(tokens: Vec<Token>) -> String {
let mut output = "".to_string();
for token in tokens {
output += &token.token_type.to_string();
output += "\n";
}
output[..output.len()-1].to_string()
}
pub fn debug_ast(ast: AST, level: usize) -> String {
use crate::ast::ASTType::*;
use crate::ast::BinOp::*;
use crate::ast::UnOp::*;
use crate::ast::Lit::*;
let mut output = "".to_string();
match ast.ast_type {
Program(asts) => {
output += &"| ".repeat(level);
output += "Program";
for ast in asts {
output += "\n";
output += &debug_ast(ast, level+1);
}
}
Function(name, args, block) => {
output += &"| ".repeat(level);
output += "Function";
output += &(" ".to_string() + &name.name);
for arg in args {
output += &(" ".to_string() + &arg.name);
}
output += &format!(" {:?}", ast.extensions);
output += "\n";
output += &debug_ast(*block, level+1);
}
Return(expr) => {
output += &"| ".repeat(level);
output += "Return";
if let Some(expr) = *expr {
output += "\n";
output += &debug_ast(expr, level+1);
}
}
Loop(block) => {
output += &"| ".repeat(level);
output += "Loop";
output += "\n";
output += &debug_ast(*block, level+1);
}
While(condition, block) => {
output += &"| ".repeat(level);
output += "While";
output += "\n";
output += &debug_ast(*condition, level+1);
output += "\n";
output += &debug_ast(*block, level+1);
}
For(expr1, expr2, expr3, block) => {
output += &"| ".repeat(level);
output += "For";
if let Some(expr1) = *expr1 {
output += "\n";
output += &debug_ast(expr1, level+1);
}
if let Some(expr2) = *expr2 {
output += "\n";
output += &debug_ast(expr2, level+1);
}
if let Some(expr3) = *expr3 {
output += "\n";
output += &debug_ast(expr3, level+1);
}
output += "\n";
output += &debug_ast(*block, level+1);
}
Break => {
output += &"| ".repeat(level);
output += "Break";
}
Continue => {
output += &"| ".repeat(level);
output += "Continue";
}
If(condition, block, else_expr) => {
output += &"| ".repeat(level);
output += "If\n";
output += &debug_ast(*condition, level+1);
output += "\n";
output += &debug_ast(*block, level+1);
if let Some(else_expr) = *else_expr {
output += "\n";
output += &"| ".repeat(level);
output += "Else";
output += "\n";
output += &debug_ast(else_expr, level+1);
}
}
Block(asts) => {
output += &"| ".repeat(level);
output += "Block";
for ast in asts {
output += "\n";
output += &debug_ast(ast, level+1);
}
}
Expr(expr) => {
output += &"| ".repeat(level);
output += "Expr\n";
output += &debug_ast(*expr, level+1);
}
// REMOVE LATER
Print(expr) => {
output += &"| ".repeat(level);
output += "Print\n";
output += &debug_ast(*expr, level+1);
}
Decl(name, expr) => {
output += &"| ".repeat(level);
output += "Decl ";
output += &name.name;
output += &format!(" {:?}", ast.extensions);
output += "\n";
output += &debug_ast(*expr, level+1);
}
Assign(name, expr) => {
output += &"| ".repeat(level);
output += "Assign ";
output += &name.name;
output += &format!(" {:?}", ast.extensions);
output += "\n";
output += &debug_ast(*expr, level+1);
}
Ternary(condition, true_expr, false_expr) => {
output += &"| ".repeat(level);
output += "Ternary\n";
output += &debug_ast(*condition, level+1);
output += "\n";
output += &debug_ast(*true_expr, level+1);
output += "\n";
output += &debug_ast(*false_expr, level+1);
}
Subscript(array, index) => {
output += &"| ".repeat(level);
output += "Subscript\n";
output += &debug_ast(*array, level+1);
output += "\n";
output += &debug_ast(*index, level+1);
}
Binary(left, oper, right) => {
output += &"| ".repeat(level);
output += "Binary ";
push_output!(oper, output,
Add, Sub, Mul, Div, Mod, BitAnd, BitXor, BitOr,
Eq, Ne, Gr, Ge, Ls, Le, Or, And);
output += "\n";
output += &debug_ast(*left, level+1);
output += "\n";
output += &debug_ast(*right, level+1);
}
Unary(oper, right) => {
output += &"| ".repeat(level);
output += "Unary ";
push_output!(oper, output,
Not, Neg);
output += "\n";
output += &debug_ast(*right, level+1);
}
Lit(lit) => {
output += &"| ".repeat(level);
output += "Lit ";
match lit {
Ident(name) => {
output += &name;
output += &format!(" {:?}", ast.extensions);
}
Str(value) => {
output += &value;
}
Num(value) => {
output += &value.to_string();
}
Bool(value) => {
output += &value.to_string();
}
Array(value) => {
for value in value {
output += "\n";
output += &debug_ast(value, level+1);
}
}
}
}
Call(name, args) => {
output += &"| ".repeat(level);
output += "Call\n";
output += &debug_ast(*name, level+1);
for arg in args {
output += "\n";
output += &debug_ast(arg, level+1);
}
}
Member(left, right) => {
output += &"| ".repeat(level);
output += "Member\n";
output += &debug_ast(*left, level+1);
output += "\n";
output += &debug_ast(*right, level+1);
}
}
output
}
pub fn debug_bytecode(vm: &VM) -> String {
use crate::opcodes::OpCode::*;
//let mut ip = 0;
let mut output = "".to_string();
let mut vm = vm.clone();
while vm.ip < vm.units[vm.unit_ptr].code.len() {
// remove PRINT later
push_codegen!(vm.units[vm.unit_ptr].code[vm.ip].into(), vm, output, ADD, SUB, MUL, DIV, MOD, BITAND,
BITXOR, BITOR, EQ, NE, GR, GE, LS, LE, OR, AND, NOT, NEG,
PRINT, ERR);
match vm.units[vm.unit_ptr].code[vm.ip].into() {
LOAD => {
output += &vm.ip.to_string();
output += " ";
output += &vm.find_line().to_string();
output += " CONSTANT ";
vm.ip += 1;
output += &vm.units[vm.unit_ptr].code[vm.ip].to_string();
output += "\n";
}
VAR => {
output += &vm.ip.to_string();
output += " ";
output += &vm.find_line().to_string();
output += " VAR ";
vm.ip += 1;
output += &vm.units[vm.unit_ptr].code[vm.ip].to_string();
output += "\n";
}
ASSIGN => {
output += &vm.ip.to_string();
output += " ";
output += &vm.find_line().to_string();
output += " ASSIGN ";
vm.ip += 1;
output += &vm.units[vm.unit_ptr].code[vm.ip].to_string();
output += "\n";
}
JMP => {
output += &vm.ip.to_string();
output += " ";
output += &vm.find_line().to_string();
output += " JMP ";
vm.ip += 1;
let byte_one = (vm.units[vm.unit_ptr].code[vm.ip] as u16) << 8;
vm.ip += 1;
let byte_two = vm.units[vm.unit_ptr].code[vm.ip] as u16;
output += &(byte_one | byte_two).to_string();
output += "\n";
}
JMP_UP => {
output += &vm.ip.to_string();
output += " ";
output += &vm.find_line().to_string();
output += " JMP_UP ";
vm.ip += 1;
let byte_one = (vm.units[vm.unit_ptr].code[vm.ip] as u16) << 8;
vm.ip += 1;
let byte_two = vm.units[vm.unit_ptr].code[vm.ip] as u16;
output += &(byte_one | byte_two).to_string();
output += "\n";
}
JNE => {
output += &vm.ip.to_string();
output += " ";
output += &vm.find_line().to_string();
output += " JNE ";
vm.ip += 1;
let byte_one = (vm.units[vm.unit_ptr].code[vm.ip] as u16) << 8;
vm.ip += 1;
let byte_two = vm.units[vm.unit_ptr].code[vm.ip] as u16;
output += &(byte_one | byte_two).to_string();
output += "\n";
}
CALL => {
output += &vm.ip.to_string();
output += " ";
output += &vm.find_line().to_string();
output += " CALL ";
vm.ip += 1;
output += &(vm.units[vm.unit_ptr].code[vm.ip]).to_string();
output += "\n";
}
RET => {
output += &vm.ip.to_string();
output += " ";
output += &vm.find_line().to_string();
output += " RET";
output += "\n";
}
LIST => {
output += &vm.ip.to_string();
output += " ";
output += &vm.find_line().to_string();
output += " LIST ";
vm.ip += 1;
output += &(vm.units[vm.unit_ptr].code[vm.ip]).to_string();
output += "\n";
}
SCR => {
output += &vm.ip.to_string();
output += " ";
output += &vm.find_line().to_string();
output += " SCR";
output += "\n";
}
POP => {
output += &vm.ip.to_string();
output += " ";
output += &vm.find_line().to_string();
output += " POP ";
vm.ip += 1;
output += &vm.units[vm.unit_ptr].code[vm.ip].to_string();
output += "\n";
}
_ => {}
}
vm.ip += 1;
}
output
}
pub fn debug_stack(stack: &Vec<Value>) -> String {
let mut output = "".to_string();
for value in stack.iter().rev() {
output += &format!("{:?}", value);
output += "\n";
}
output
}