apfl/src/bytecode.h
Laria Carolin Chabowski 4d840fd817 Allow NULL as subfunction matcher
This will match all arguments and discard them. This makes the bytecode
for simple functions easier and will make it easier to construct simple
function programmatically.
2023-02-25 23:19:45 +01:00

112 lines
4.2 KiB
C

#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,
};
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
};
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);
#ifdef __cplusplus
}
#endif
#endif