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