#include #include "apfl.h" #include "alloc.h" #include "bytecode.h" #include "gc.h" struct instruction_list * apfl_instructions_new(struct gc *gc, int line) { struct instruction_list *ilist = apfl_gc_new_instructions(gc); if (ilist == NULL) { return NULL; } *ilist = (struct instruction_list) { .instructions = NULL, .len = 0, .cap = 0, .line = line, }; return ilist; } void apfl_instructions_deinit(struct apfl_allocator allocator, struct instruction_list *ilist) { FREE_LIST(allocator, ilist->instructions, ilist->cap); } #define GET_ARGUMENT(ilist, i, arg) \ do { \ if (i >= ilist->len) { \ return; \ } \ arg = ilist->instructions[++i]; \ } while (0) void apfl_gc_instructions_traverse(struct instruction_list *ilist, gc_visitor cb, void *opaque) { union instruction_or_arg arg; for (size_t i = 0; i < ilist->len; i++) { 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: break; case INSN_NUMBER: case INSN_LIST: case INSN_SET_LINE: i++; break; case INSN_STRING: case INSN_VAR_GET: case INSN_VAR_SET: case INSN_VAR_NEW: GET_ARGUMENT(ilist, i, arg); cb(opaque, GC_OBJECT_FROM(arg.string, GC_TYPE_STRING)); break; } } } const char * apfl_instruction_to_string(enum instruction insn) { switch (insn) { case INSN_NIL: return "INSN_NIL"; case INSN_TRUE: return "INSN_TRUE"; case INSN_FALSE: return "INSN_FALSE"; case INSN_NUMBER: return "INSN_NUMBER"; case INSN_STRING: return "INSN_STRING"; case INSN_LIST: return "INSN_LIST"; case INSN_LIST_APPEND: return "INSN_LIST_APPEND"; case INSN_LIST_EXPAND_INTO: return "INSN_LIST_EXPAND_INTO"; case INSN_DICT: return "INSN_DICT"; case INSN_DICT_APPEND_KVPAIR: return "INSN_DICT_APPEND_KVPAIR"; case INSN_GET_MEMBER: return "INSN_GET_MEMBER"; case INSN_VAR_GET: return "INSN_VAR_GET"; case INSN_VAR_SET: return "INSN_VAR_SET"; case INSN_VAR_NEW: return "INSN_VAR_NEW"; case INSN_NEXT_LINE: return "INSN_NEXT_LINE"; case INSN_SET_LINE: return "INSN_SET_LINE"; } return "??"; }