bytecode: Add a function to dump bytecode

This also exposes it as a global function and removes the debug statements
in the compiler.
This commit is contained in:
Laria 2022-07-28 20:49:29 +02:00
parent 1630314dc7
commit 41d0ee6132
4 changed files with 150 additions and 15 deletions

View file

@ -4,6 +4,7 @@
#include "alloc.h"
#include "bytecode.h"
#include "format.h"
#include "gc.h"
struct instruction_list *
@ -206,3 +207,133 @@ apfl_matcher_instructions_deinit(struct apfl_allocator allocator, struct matcher
{
FREE_LIST(allocator, milist->instructions, milist->cap);
}
static bool
bytecode_dump_milist(unsigned indent, struct apfl_format_writer w, struct matcher_instruction_list *milist)
{
for (size_t i = 0; i < milist->len; i++) {
FMT_TRY(apfl_format_put_indent(w, indent));
FMT_TRY(apfl_format_put_string(w, apfl_matcher_instruction_to_string(milist->instructions[i].instruction)));
switch (milist->instructions[i].instruction) {
case MATCHER_IGNORE:
case MATCHER_ENTER_LIST:
case MATCHER_LEAVE_LIST:
case MATCHER_CONTINUE_FROM_END:
case MATCHER_REMAINDING:
break;
case MATCHER_CAPTURE:
case MATCHER_CHECK_CONST:
case MATCHER_CHECK_PRED:
if (i >= milist->len) {
FMT_TRY(apfl_format_put_string(w, "Bytecode corrupted"));
return false;
}
FMT_TRY(apfl_format_put_string(w, " "));
FMT_TRY(apfl_format_put_int(w, (int)milist->instructions[++i].index));
break;
}
FMT_TRY(apfl_format_put_char(w, '\n'));
}
return true;
}
#define GET_ARGUMENT_FOR_DUMP(w, ilist, i, arg) \
do { \
if (i >= ilist->len) { \
FMT_TRY(apfl_format_put_string(w, "Bytecode corrupted")); \
return false; \
} \
arg = ilist->instructions[++i]; \
} while (0)
static bool
bytecode_dump_ilist(unsigned indent, struct apfl_format_writer w, struct instruction_list *ilist)
{
union instruction_or_arg arg;
for (size_t i = 0; i < ilist->len; i++) {
FMT_TRY(apfl_format_put_indent(w, indent));
FMT_TRY(apfl_format_put_string(w, apfl_instruction_to_string(ilist->instructions[i].instruction)));
switch (ilist->instructions[i].instruction) {
case INSN_NIL:
case INSN_TRUE:
case INSN_FALSE:
case INSN_LIST_APPEND:
case INSN_LIST_EXPAND_INTO:
case INSN_DICT:
case INSN_DICT_APPEND_KVPAIR:
case INSN_GET_MEMBER:
case INSN_NEXT_LINE:
case INSN_DROP:
case INSN_CALL:
case INSN_MATCHER_MUST_MATCH:
case INSN_MATCHER_DROP:
break;
case INSN_NUMBER:
GET_ARGUMENT_FOR_DUMP(w, ilist, i, arg);
FMT_TRY(apfl_format_put_string(w, " "));
FMT_TRY(apfl_format_put_number(w, arg.number));
break;
case INSN_LIST:
case INSN_SET_LINE:
GET_ARGUMENT_FOR_DUMP(w, ilist, i, arg);
FMT_TRY(apfl_format_put_string(w, " "));
FMT_TRY(apfl_format_put_int(w, (int)arg.count));
break;
case INSN_GET_BY_INDEX_KEEP:
case INSN_MATCHER_SET_VAL:
GET_ARGUMENT_FOR_DUMP(w, ilist, i, arg);
FMT_TRY(apfl_format_put_string(w, " "));
FMT_TRY(apfl_format_put_int(w, (int)arg.index));
break;
case INSN_STRING:
case INSN_VAR_GET:
case INSN_VAR_SET:
case INSN_VAR_SET_LOCAL:
case INSN_VAR_NEW:
case INSN_VAR_NEW_LOCAL:
case INSN_MOVE_TO_LOCAL_VAR:
GET_ARGUMENT_FOR_DUMP(w, ilist, i, arg);
FMT_TRY(apfl_format_put_string(w, " "));
FMT_TRY(apfl_format_put_string(w, *arg.string));
break;
case INSN_FUNC:
GET_ARGUMENT_FOR_DUMP(w, ilist, i, arg);
FMT_TRY(apfl_format_put_string(w, " ilist{\n"));
FMT_TRY(bytecode_dump_ilist(indent+1, w, arg.body));
FMT_TRY(apfl_format_put_indent(w, indent));
FMT_TRY(apfl_format_put_string(w, "}"));
break;
case INSN_MATCHER_LOAD:
GET_ARGUMENT_FOR_DUMP(w, ilist, i, arg);
FMT_TRY(apfl_format_put_string(w, " milist{\n"));
FMT_TRY(bytecode_dump_milist(indent+1, w, arg.matcher));
FMT_TRY(apfl_format_put_indent(w, indent));
FMT_TRY(apfl_format_put_string(w, "}"));
break;
case INSN_VAR_SET_FROM_MATCHER:
case INSN_VAR_SET_LOCAL_FROM_MATCHER:
GET_ARGUMENT_FOR_DUMP(w, ilist, i, arg);
FMT_TRY(apfl_format_put_string(w, " "));
FMT_TRY(apfl_format_put_string(w, *arg.string));
FMT_TRY(apfl_format_put_string(w, ", "));
GET_ARGUMENT_FOR_DUMP(w, ilist, i, arg);
FMT_TRY(apfl_format_put_int(w, (int)arg.index));
break;
}
FMT_TRY(apfl_format_put_char(w, '\n'));
}
return true;
}
bool
apfl_bytecode_dump(struct apfl_format_writer w, struct instruction_list *ilist)
{
return bytecode_dump_ilist(0, w, ilist);
}

View file

@ -94,6 +94,8 @@ void apfl_gc_instructions_traverse(struct instruction_list *, gc_visitor, void *
struct matcher_instruction_list *apfl_matcher_instructions_new(struct gc *);
void apfl_matcher_instructions_deinit(struct apfl_allocator, struct matcher_instruction_list *);
bool apfl_bytecode_dump(struct apfl_format_writer, struct instruction_list *);
#ifdef __cplusplus
}
#endif

View file

@ -9,14 +9,6 @@
#include "resizable.h"
#include "strings.h"
#define DEBUG_COMPILING 0
#if DEBUG_COMPILING
# define DEBUG_LOG(...) fprintf(stderr, __VA_ARGS__);
#else
# define DEBUG_LOG(...)
#endif
struct compiler {
struct gc *gc;
struct apfl_error error;
@ -63,9 +55,7 @@ ilist_ensure_cap(struct compiler *compiler, struct instruction_list *ilist, size
ilist->instructions[ilist->len] = (union instruction_or_arg) { \
.member = data, \
}; \
ilist->len++; \
\
DEBUG_LOG("ilist %p " dbgfmt "\n", (void *)ilist, __VA_ARGS__);
ilist->len++;
static void
ilist_put_insn(struct instruction_list *ilist, enum instruction instruction)
@ -132,8 +122,6 @@ milist_put_insn(struct matcher_instruction_list *milist, enum matcher_instructio
.instruction = instruction,
};
milist->len++;
DEBUG_LOG("milist %p: put_insn: %s\n", (void *)milist, apfl_matcher_instruction_to_string(instruction));
}
static void
@ -146,8 +134,6 @@ milist_put_index(struct matcher_instruction_list *milist, size_t index)
.index = index,
};
milist->len++;
DEBUG_LOG("milist %p: put_index: %d\n", (void *)milist, (int)index);
}
static bool

View file

@ -3,6 +3,7 @@
#include "apfl.h"
#include "bytecode.h"
#include "context.h"
#include "globals.h"
#include "scope.h"
@ -175,6 +176,20 @@ dump(apfl_ctx ctx)
TRY_FORMAT(ctx, apfl_debug_print_val(ctx, -1, w));
}
static void
disasm(apfl_ctx ctx)
{
struct apfl_format_writer w = apfl_format_file_writer(stdout);
apfl_get_list_member_by_index(ctx, 0, 0);
apfl_drop(ctx, 0);
struct apfl_value value = apfl_stack_must_get(ctx, -1);
if (value.type != VALUE_FUNC) {
apfl_raise_const_error(ctx, APFL_RESULT_ERR, apfl_messages.wrong_type);
}
TRY_FORMAT(ctx, apfl_bytecode_dump(w, value.func->body));
}
static const struct global_def globals[] = {
{"if", impl_if},
{"==", impl_eq},
@ -184,6 +199,7 @@ static const struct global_def globals[] = {
{"/", impl_div},
{"print", print},
{"dump", dump},
{"disasm", disasm},
{NULL, NULL},
};