451 lines
8.4 KiB
C
451 lines
8.4 KiB
C
#include "debug.h"
|
|
|
|
#include "ast/ast.h"
|
|
#include "parse/token.h"
|
|
#include "runtime/opcode.h"
|
|
#include "script-block.h"
|
|
|
|
#include <fx/string.h>
|
|
#include <fx/term/print.h>
|
|
#include <stdio.h>
|
|
|
|
extern void print_lex_token(struct lex_token *tok)
|
|
{
|
|
printf("[%lu:%lu - %lu:%lu] ",
|
|
tok->tok_start.c_row,
|
|
tok->tok_start.c_col,
|
|
tok->tok_end.c_row,
|
|
tok->tok_end.c_col);
|
|
|
|
switch (tok->tok_type) {
|
|
case TOK_KEYWORD:
|
|
fx_puts("[magenta]");
|
|
break;
|
|
case TOK_SYMBOL:
|
|
fx_puts("[blue]");
|
|
break;
|
|
case TOK_INT:
|
|
case TOK_DOUBLE:
|
|
case TOK_VAR:
|
|
case TOK_VAR_SPLAT:
|
|
fx_puts("[yellow]");
|
|
break;
|
|
case TOK_OPERATOR:
|
|
fx_puts("[red]");
|
|
break;
|
|
case TOK_WORD:
|
|
case TOK_WORD_START:
|
|
case TOK_WORD_END:
|
|
fx_puts("[cyan]");
|
|
break;
|
|
case TOK_STRING:
|
|
case TOK_STR_START:
|
|
case TOK_STR_END:
|
|
fx_puts("[green]");
|
|
break;
|
|
case TOK_LINEFEED:
|
|
fx_puts("[dark_grey]");
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
fx_puts(token_type_to_string(tok->tok_type));
|
|
|
|
switch (tok->tok_type) {
|
|
case TOK_WORD:
|
|
case TOK_FLAG:
|
|
case TOK_STRING:
|
|
case TOK_VAR:
|
|
case TOK_VAR_SPLAT:
|
|
printf("(%s)", tok->tok_str);
|
|
break;
|
|
case TOK_OPERATOR:
|
|
printf("(%s)", token_operator_to_string(tok->tok_operator));
|
|
break;
|
|
case TOK_SYMBOL:
|
|
printf("(%s)", token_symbol_to_string(tok->tok_symbol));
|
|
break;
|
|
case TOK_KEYWORD:
|
|
printf("(%s)", token_keyword_to_string(tok->tok_keyword));
|
|
break;
|
|
case TOK_INT:
|
|
printf("(%lld)", tok->tok_int);
|
|
break;
|
|
case TOK_DOUBLE:
|
|
printf("(%lf)", tok->tok_double);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
fx_puts("[reset]\n");
|
|
}
|
|
|
|
void print_ast_node(struct ast_node *node)
|
|
{
|
|
for (unsigned long i = 0; i < node->n_it.e_depth; i++) {
|
|
fx_puts(" ");
|
|
}
|
|
|
|
switch (node->n_type) {
|
|
case AST_IF:
|
|
case AST_IF_BRANCH:
|
|
case AST_BLOCK:
|
|
case AST_FUNC:
|
|
case AST_STMT_LIST:
|
|
fx_puts("[magenta]");
|
|
break;
|
|
case AST_REDIRECTION:
|
|
case AST_PIPELINE:
|
|
case AST_OP:
|
|
case AST_ARRAY:
|
|
case AST_HASHTABLE:
|
|
case AST_HASHTABLE_ITEM:
|
|
fx_puts("[blue]");
|
|
break;
|
|
case AST_CMDCALL:
|
|
case AST_NULL:
|
|
fx_puts("[red]");
|
|
break;
|
|
case AST_INT:
|
|
case AST_DOUBLE:
|
|
case AST_VAR:
|
|
fx_puts("[yellow]");
|
|
break;
|
|
case AST_WORD:
|
|
fx_puts("[cyan]");
|
|
break;
|
|
case AST_STRING:
|
|
case AST_FSTRING:
|
|
fx_puts("[green]");
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
fx_printf("%s", ast_node_type_to_string(node->n_type));
|
|
|
|
char s[128] = {0};
|
|
fx_bstr str;
|
|
fx_bstr_begin(&str, s, sizeof s);
|
|
ast_node_to_string(node, &str);
|
|
|
|
if (fx_bstr_get_size(&str)) {
|
|
fx_printf("(%s)", fx_bstr_end(&str));
|
|
}
|
|
|
|
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);
|
|
}
|
|
}
|
|
|
|
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);
|
|
}
|