debug: implement printers for bytecode instructions and runtime values

This commit is contained in:
2026-05-17 15:34:53 +01:00
parent 58b4bb2c51
commit f629b05672
2 changed files with 366 additions and 54 deletions
+310 -9
View File
@@ -2,6 +2,8 @@
#include "ast/ast.h" #include "ast/ast.h"
#include "parse/token.h" #include "parse/token.h"
#include "runtime/opcode.h"
#include "script-block.h"
#include <fx/string.h> #include <fx/string.h>
#include <fx/term/print.h> #include <fx/term/print.h>
@@ -82,15 +84,6 @@ extern void print_lex_token(struct lex_token *tok)
void print_ast_node(struct ast_node *node) void print_ast_node(struct ast_node *node)
{ {
struct ast_iterator it = {0};
ast_node_iterate(node, &it);
while (1) {
node = ast_iterator_peek(&it);
if (!node) {
break;
}
for (unsigned long i = 0; i < node->n_it.e_depth; i++) { for (unsigned long i = 0; i < node->n_it.e_depth; i++) {
fx_puts(" "); fx_puts(" ");
} }
@@ -143,7 +136,315 @@ void print_ast_node(struct ast_node *node)
} }
fx_printf("[reset]\n"); fx_printf("[reset]\n");
}
void print_ast_node_recursive(struct ast_node *node)
{
struct ast_iterator it = {0};
ast_iterator_enqueue(&it, node);
while (1) {
node = ast_iterator_peek(&it);
if (!node) {
break;
}
print_ast_node(node);
ast_iterator_dequeue(&it); ast_iterator_dequeue(&it);
} }
} }
void print_scriptblock(bshell_scriptblock *block, size_t depth)
{
bshell_instruction *instr = NULL;
size_t nr_instr = 0;
bshell_scriptblock_get_text(block, &instr, &nr_instr);
for (size_t i = 0; i < nr_instr; i++) {
size_t offset = i * sizeof *instr;
for (size_t ii = 0; ii < depth; ii++) {
fputs("| ", stdout);
}
printf("%04zx: ", offset);
print_instruction(offset, instr[i], block, depth);
}
}
void print_instruction(
size_t offset,
bshell_instruction instr,
bshell_scriptblock *container,
size_t depth)
{
enum bshell_opcode opcode = 0;
uint32_t arg = 0;
fx_value *pool_value = NULL;
bshell_instruction_decode(instr, &opcode, &arg);
fx_printf("%08x [blue]", instr);
switch (opcode) {
case OPCODE_LDC_INT:
fx_printf("ldc.int [yellow]#0x%02x", arg);
break;
case OPCODE_LDC_STR:
pool_value = bshell_scriptblock_get_pool_value(
container,
arg,
FX_TYPE_STRING);
if (!pool_value) {
pool_value = bshell_scriptblock_get_pool_value(
container,
arg,
FX_TYPE_CSTR);
}
fx_printf("ldc.str [cyan]@0x%02x ", arg);
if (pool_value) {
fx_printf(
"[reset][[[green]%s[reset]]",
fx_value_get_cstr(pool_value));
} else {
fx_printf("[red]<INVALID>[reset]");
}
break;
case OPCODE_LDGLOBAL:
fx_printf("ldglobal [cyan]@0x%02x", arg);
break;
case OPCODE_LDBLOCK:
pool_value = bshell_scriptblock_get_pool_value(
container,
arg,
BSHELL_TYPE_SCRIPTBLOCK);
fx_printf("ldblock [cyan]@0x%02x ", arg);
if (pool_value) {
fx_printf("[reset][[[magenta]vvv[reset]]\n");
print_scriptblock(
fx_value_get_object(pool_value),
depth + 1);
} else {
fx_printf("[red]<INVALID>[reset]");
}
break;
case OPCODE_LDLOCAL:
pool_value = bshell_scriptblock_get_pool_value(
container,
arg,
FX_TYPE_STRING);
if (!pool_value) {
pool_value = bshell_scriptblock_get_pool_value(
container,
arg,
FX_TYPE_CSTR);
}
fx_printf("ldlocal [cyan]@0x%02x ", arg);
if (pool_value) {
fx_printf(
"[reset][[[green]%s[reset]]",
fx_value_get_cstr(pool_value));
} else {
fx_printf("[red]<INVALID>");
}
break;
case OPCODE_LDENV:
fx_printf("ldenv [cyan]@0x%02x", arg);
break;
case OPCODE_LDSTATIC:
fx_printf("ldstatic [cyan]@0x%02x", arg);
break;
case OPCODE_LDARG:
fx_printf("ldarg [cyan]@0x%02x", arg);
break;
case OPCODE_LDPROP:
fx_printf("ldprop [cyan]@0x%02x", arg);
break;
case OPCODE_LDELEM:
fx_printf("ldelem [cyan]@0x%02x", arg);
break;
case OPCODE_LDELEM_C:
fx_printf("ldelem.c [cyan]@0x%02x", arg);
break;
case OPCODE_STLOCAL:
pool_value = bshell_scriptblock_get_pool_value(
container,
arg,
FX_TYPE_STRING);
if (!pool_value) {
pool_value = bshell_scriptblock_get_pool_value(
container,
arg,
FX_TYPE_CSTR);
}
fx_printf("stlocal [cyan]@0x%02x ", arg);
if (pool_value) {
fx_printf("[%s]", fx_value_get_cstr(pool_value));
fx_printf(
"[reset][[[green]%s[reset]]",
fx_value_get_cstr(pool_value));
} else {
fx_printf("<INVALID>");
}
break;
case OPCODE_STPROP:
fx_printf("stprop [cyan]@0x%02x", arg);
break;
case OPCODE_STELEM:
fx_printf("stelem [cyan]@0x%02x", arg);
break;
case OPCODE_LDCMD:
fx_printf("ldcmd [yellow]#0x%02x", arg);
break;
case OPCODE_PEXEC:
fx_printf("pexec [yellow]#0x%02x", arg);
break;
case OPCODE_CALL:
fx_printf("call");
break;
case OPCODE_MK_STR:
fx_printf("mk.str [yellow]#0x%02x", arg);
break;
case OPCODE_MK_ARRAY:
fx_printf("mk.array [yellow]#0x%02x", arg);
break;
case OPCODE_MK_HTAB:
fx_printf("mk.htab [yellow]#0x%02x", arg);
break;
case OPCODE_POP:
fx_printf("pop");
break;
case OPCODE_ADD:
fx_printf("add");
break;
case OPCODE_SUB:
fx_printf("sub");
break;
case OPCODE_MUL:
fx_printf("mul");
break;
case OPCODE_DIV:
fx_printf("div");
break;
case OPCODE_ADD_IP:
fx_printf("add.ip");
break;
case OPCODE_MOD:
fx_printf("mod");
break;
case OPCODE_INC:
fx_printf("inc");
break;
case OPCODE_DEC:
fx_printf("dec");
break;
case OPCODE_SHL:
fx_printf("shl");
break;
case OPCODE_SHR:
fx_printf("shr");
break;
case OPCODE_BAND:
fx_printf("band");
break;
case OPCODE_BOR:
fx_printf("bor");
break;
case OPCODE_BXOR:
fx_printf("bxor");
break;
case OPCODE_BNOT:
fx_printf("bnot");
break;
case OPCODE_CMP_NULL:
fx_printf("cmp.null");
break;
case OPCODE_CMP_EQ:
fx_printf("cmp.eq");
break;
case OPCODE_CMP_NE:
fx_printf("cmp.ne");
break;
case OPCODE_CMP_LT:
fx_printf("cmp.lt");
break;
case OPCODE_CMP_GT:
fx_printf("cmp.gt");
break;
case OPCODE_CMP_LE:
fx_printf("cmp.le");
break;
case OPCODE_CMP_GE:
fx_printf("cmp.ge");
break;
case OPCODE_LAND:
fx_printf("land");
break;
case OPCODE_LOR:
fx_printf("lor");
break;
case OPCODE_LXOR:
fx_printf("lxor");
break;
case OPCODE_LNOT:
fx_printf("lnot");
break;
case OPCODE_BR:
fx_printf(
"br [yellow]#0x%04x [=%04llx]",
arg,
(long long)arg + (long long)offset);
break;
case OPCODE_BR_TRUE:
fx_printf(
"br.true [yellow]#0x%04x [=%04llx]",
arg,
(long long)arg + (long long)offset);
break;
case OPCODE_RANGE:
fx_printf("range");
break;
case OPCODE_MATCH:
fx_printf("match");
break;
case OPCODE_REPLACE:
fx_printf("replace");
break;
case OPCODE_LIKE:
fx_printf("like");
break;
case OPCODE_IN:
fx_printf("in");
break;
case OPCODE_FMT:
fx_printf("fmt");
break;
case OPCODE_CONTAINS:
fx_printf("contains");
break;
case OPCODE_SPLIT:
fx_printf("split");
break;
case OPCODE_JOIN:
fx_printf("join");
break;
case OPCODE_IS:
fx_printf("is");
break;
case OPCODE_AS:
fx_printf("as");
break;
default:
fx_printf("INVALID\n");
break;
}
fx_printf("[reset]\n");
}
void print_value(fx_value *val)
{
fx_printf("[yellow]%d[reset]\n", val->v_int);
}
+11
View File
@@ -1,6 +1,9 @@
#ifndef DEBUG_H_ #ifndef DEBUG_H_
#define DEBUG_H_ #define DEBUG_H_
#include "runtime/opcode.h"
#include "script-block.h"
#include <stdbool.h> #include <stdbool.h>
struct ast_node; struct ast_node;
@@ -8,5 +11,13 @@ struct lex_token;
extern void print_lex_token(struct lex_token *tok); extern void print_lex_token(struct lex_token *tok);
extern void print_ast_node(struct ast_node *node); extern void print_ast_node(struct ast_node *node);
extern void print_ast_node_recursive(struct ast_node *node);
extern void print_scriptblock(bshell_scriptblock *block, size_t depth);
extern void print_instruction(
size_t offset,
bshell_instruction instr,
bshell_scriptblock *container,
size_t depth);
extern void print_value(fx_value *val);
#endif #endif