use crate::{
ast::{LhsAssignType, 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::Lit::*;
use crate::ast::UnOp::*;
let mut output = "".to_string();
match ast.kind {
Program(asts) => {
output += &"| ".repeat(level);
output += "Program";
for ast in asts {
output += "\n";
output += &debug_ast(ast, level + 1);
}
}
Function(name, params, block) => {
output += &"| ".repeat(level);
output += "Function";
output += &(" ".to_string() + &name.name);
for param in params {
output += &(" ".to_string() + ¶m.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(lhs, expr) => {
output += &"| ".repeat(level);
output += "Assign ";
match lhs.kind {
LhsAssignType::Ident(name) => {
output += &name;
}
LhsAssignType::Subscript(name, index) => {
output += "\n";
output += &"| ".repeat(level + 1);
output += "Subscript\n";
output += &debug_ast(*name, level + 2);
output += "\n";
output += &debug_ast(*index, level + 2);
}
}
output += &format!(" {:?}", ast.extensions);
output += "\n";
output += &debug_ast(*expr, level + 1);
}
Anonymous(params, block) => {
output += &"| ".repeat(level);
output += "Anonymous ";
for param in params {
output += &(" ".to_string() + ¶m.name);
}
output += "\n";
output += &debug_ast(*block, 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 += " LOAD ";
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";
}
REF => {
output += &vm.ip.to_string();
output += " ";
output += &vm.find_line().to_string();
output += " REF ";
vm.ip += 1;
output += &vm.units[vm.unit_ptr].code[vm.ip].to_string();
output += "\n";
}
ASN => {
output += &vm.ip.to_string();
output += " ";
output += &vm.find_line().to_string();
output += " ASN ";
vm.ip += 1;
output += &vm.units[vm.unit_ptr].code[vm.ip].to_string();
output += "\n";
}
ASNARR => {
output += &vm.ip.to_string();
output += " ";
output += &vm.find_line().to_string();
output += " ASNARR";
output += "\n";
}
DECL => {
output += &vm.ip.to_string();
output += " ";
output += &vm.find_line().to_string();
output += " DECL";
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
}