use crate::{ast::AST, lexer::Token, push_codegen, push_output, vm::{Value, VM}}; pub fn debug_token_array(tokens: Vec) -> 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"; } 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) -> String { let mut output = "".to_string(); for value in stack.iter().rev() { output += &format!("{:?}", value); output += "\n"; } output }