use crate::{lexer::Token, parser::AST, push_output, vm::Value};
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::parser::ASTType::*;
use crate::parser::BinOp::*;
use crate::parser::UnOp::*;
use crate::parser::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 += "\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 += "Break\n"; }
Continue => { output += "Continue\n"; }
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 += "\n";
output += &debug_ast(*expr, level+1);
}
Assign(name, expr) => {
output += &"| ".repeat(level);
output += "Assign ";
output += &name.name;
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;
}
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 ";
output += &name.name;
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(code: &Vec<u8>) -> String {
use crate::opcodes::OpCode::*;
let mut ip = 0;
let mut output = "".to_string();
while ip < code.len() {
match code[ip].into() {
CONSTANT => {
output += &ip.to_string();
output += " CONSTANT ";
ip += 1;
output += &code[ip].to_string();
output += "\n";
}
ADD => { output += &ip.to_string(); output += " ADD\n" }
SUB => { output += &ip.to_string(); output += " SUB\n" }
MUL => { output += &ip.to_string(); output += " MUL\n" }
DIV => { output += &ip.to_string(); output += " DIV\n" }
MOD => { output += &ip.to_string(); output += " MOD\n" }
BITAND => { output += &ip.to_string(); output += " BITAND\n" }
BITXOR => { output += &ip.to_string(); output += " BITXOR\n" }
BITOR => { output += &ip.to_string(); output += " BITOR\n" }
EQ => { output += &ip.to_string(); output += " EQ\n" }
NE => { output += &ip.to_string(); output += " NE\n" }
GR => { output += &ip.to_string(); output += " GR\n" }
GE => { output += &ip.to_string(); output += " GE\n" }
LS => { output += &ip.to_string(); output += " LS\n" }
LE => { output += &ip.to_string(); output += " LE\n" }
OR => { output += &ip.to_string(); output += " OR\n" }
AND => { output += &ip.to_string(); output += " AND\n" }
NOT => { output += &ip.to_string(); output += " NOT\n" }
NEG => { output += &ip.to_string(); output += " NEG\n" }
JMP => {
output += &ip.to_string();
output += " JMP ";
ip += 1;
let byte_one = (code[ip] as u16) << 8;
ip += 1;
let byte_two = code[ip] as u16;
output += &(byte_one | byte_two).to_string();
output += "\n";
}
IF_NE => {
output += &ip.to_string();
output += " IF_NE ";
ip += 1;
let byte_one = (code[ip] as u16) << 8;
ip += 1;
let byte_two = code[ip] as u16;
output += &(byte_one | byte_two).to_string();
output += "\n";
}
POP => { output += &ip.to_string(); output += " POP\n" }
PRINT => { output += &ip.to_string(); output += " PRINT\n" }
ERR => output += "ERR\n",
}
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
}