#ifndef APFL_BYTECODE_H #define APFL_BYTECODE_H #ifdef __cplusplus extern "C" { #endif #include "apfl.h" #include "gc.h" enum matcher_instruction { MATCHER_IGNORE, MATCHER_CAPTURE_TO_VAR, // with name MATCHER_CAPTURE_TO_VAR_LOCAL, // with name MATCHER_CAPTURE_TO_VAR_WITH_PATH, // with name, index and len MATCHER_CAPTURE_TO_VAR_LOCAL_WITH_PATH, // with name, index and len MATCHER_CHECK_CONST, // with index as values index MATCHER_CHECK_PRED, // with index as values index MATCHER_ENTER_LIST, MATCHER_LEAVE_LIST, MATCHER_CONTINUE_FROM_END, MATCHER_REMAINDING, MATCHER_UNPACK_PAIR, }; union matcher_instruction_or_arg { enum matcher_instruction instruction; size_t index; size_t len; struct apfl_string *string; }; struct matcher_instruction_list { union matcher_instruction_or_arg *instructions; size_t len; size_t cap; size_t value_count; size_t capture_count; }; enum instruction { INSN_NIL, // ( -- nil) INSN_TRUE, // ( -- true) INSN_FALSE, // ( -- false) INSN_NUMBER, // ( -- number), arg: number INSN_STRING, // ( -- string), arg: string INSN_LIST, // ( -- list), arg: count (preallocation hint) INSN_LIST_APPEND, // ( list val -- list' ) INSN_LIST_EXPAND_INTO, // ( list list -- list' ) INSN_DICT, // ( -- dict ) INSN_DICT_APPEND_KVPAIR, // ( dict key value -- dict' ) INSN_GET_MEMBER, // ( list/dict key -- value ) INSN_GET_BY_INDEX_KEEP, // ( list/dict -- list/dict value ), arg: index INSN_VAR_GET, // ( -- value ), arg: string INSN_VAR_SET, // ( value -- value ), arg: string INSN_VAR_SET_LOCAL, // ( value -- value ), arg: string INSN_VAR_NEW, // ( -- ), arg: string INSN_VAR_NEW_LOCAL, // ( -- ), arg: string INSN_MOVE_TO_LOCAL_VAR, // ( value -- ), arg: string INSN_NEXT_LINE, // ( -- ) INSN_SET_LINE, // ( -- ), arg: count (new line number) INSN_DROP, // ( value -- ) INSN_DUP, // ( value -- value value) INSN_CALL, // ( func list -- value ) INSN_FUNC, // ( -- func ), arg: count INSN_FUNC_ADD_SUBFUNC, // ( func -- func' ), arg: body; pops a matcher from the matcher stack INSN_FUNC_ADD_SUBFUNC_ANYARGS, // ( func -- func' ), arg: body INSN_FUNC_SET_NAME, // ( func -- func' ), arg: string INSN_MATCHER_PUSH, // ( -- ), arg: matcher; pushes a matcher onto the matcher stack INSN_MATCHER_SET_VAL, // ( val -- ), arg: index INSN_MATCHER_MUST_MATCH, // ( val -- ); pops a matcher from the matcher stack INSN_BUILD_PAIR, // ( val val -- pair ) }; union instruction_or_arg { enum instruction instruction; struct apfl_string *string; apfl_number number; size_t count; size_t index; struct instruction_list *body; struct matcher_instruction_list *matcher; }; struct instruction_list { union instruction_or_arg *instructions; size_t len; size_t cap; size_t line; struct apfl_string *filename; }; const char *apfl_instruction_to_string(enum instruction); const char *apfl_matcher_instruction_to_string(enum matcher_instruction); struct instruction_list *apfl_instructions_new(struct gc *, size_t line, struct apfl_string *filename); void apfl_instructions_deinit(struct apfl_allocator, struct instruction_list *); void apfl_gc_instructions_traverse(struct instruction_list *, gc_visitor, void *); void apfl_gc_matcher_instructions_traverse(struct matcher_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_matcher(unsigned indent, struct apfl_io_writer w, struct matcher_instruction_list *milist); bool apfl_bytecode_dump(unsigned indent, struct apfl_io_writer w, struct instruction_list *ilist); bool apfl_bytecode_serialize( struct apfl_allocator, struct apfl_io_writer, struct instruction_list * ); struct instruction_list *apfl_bytecode_unserialize( struct gc *gc, struct apfl_io_reader r ); #ifdef __cplusplus } #endif #endif