diff --git a/src/backends/regex.c b/src/backends/regex.c index 0b1991d..53032de 100644 --- a/src/backends/regex.c +++ b/src/backends/regex.c @@ -245,4 +245,52 @@ HParseResult *run_trace(HAllocator *mm__, HRVMProg *orig_prog, HRVMTrace *trace, return NULL; } +bool h_compile_regex(HRVMProg *prog, const HParser *parser) { + return parser->vtable->compile_to_rvm(prog, parser->env); +} + +uint16_t h_rvm_create_action(HRVMProg *prog, HSVMActionFunc action_func, void* env) { + for (uint16_t i = 0; i < prog->action_count; i++) { + if (prog->actions[i].action == action_func && prog->actions[i].env == env) + return i; + } + // Ensure that there's room in the action array... + if (!(prog->action_count & (prog->action_count + 1))) { + // needs to be scaled up. + array_size = (prog->action_count + 1) * 2; // action_count+1 is a + // power of two + prog->actions = prog->allocator->realloc(prog->actions, array_size * sizeof(*prog->actions)); + // TODO: Handle the allocation failed case nicely. + } + + HAction *action = &prog->actions[prog->action_count]; + action->action = action_func; + action->env = env; + return prog->action_count++; +} + +uint16_t h_rvm_insert_insn(HRVMProg *prog, HRVMOp op, uint16_t arg) { + // Ensure that there's room in the insn array... + if (!(prog->length & (prog->length + 1))) { + // needs to be scaled up. + array_size = (prog->length + 1) * 2; // action_count+1 is a + // power of two + prog->insns = prog->allocator->realloc(prog->insns, array_size * sizeof(*prog->insns)); + // TODO: Handle the allocation failed case nicely. + } + + prog->insns[prog->length].op = op; + prog->insns[prog->length].arg = arg; + return prog->length++; +} + +uint16_t h_rvm_get_ip(HRVMProg *prog) { + return prog->length; +} + +void h_rvm_patch_arg(HRVMProg *prog, uint16_t ip, uint16_t new_val) { + assert(prog->length > ip); + prog->insns[ip].arg = new_val; +} + // TODO: Implement the primitive actions diff --git a/src/backends/regex.h b/src/backends/regex.h index 605ff77..9d61298 100644 --- a/src/backends/regex.h +++ b/src/backends/regex.h @@ -37,12 +37,14 @@ typedef struct HSVMContext_ { // These actions all assume that the items on the stack are not // aliased anywhere. +typedef bool (*HSVMActionFunc)(HArena *arena, HSVMContext *ctx, void* env); typedef struct HSVMAction_ { - bool (*fn)(HArena *arena, HSVMContext *ctx, void* env); + HSVMActionFunc action void* env; } HSVMAction; typedef struct HRVMProg_ { + HAllocator *allocator; size_t length; size_t action_count; HRVMInsn *insns; @@ -53,7 +55,7 @@ typedef struct HRVMProg_ { bool h_compile_regex(HRVMProg *prog, const HParser* parser); // These functions are used by the compile_to_rvm method of HParser -uint16_t h_rvm_create_action(HRVMProg *prog, HSVMAction *action); +uint16_t h_rvm_create_action(HRVMProg *prog, HSVMActionFunc action_func, void* env); // returns the address of the instruction just created uint16_t h_rvm_insert_insn(HRVMProg *prog, HRVMOp op, uint16_t arg); diff --git a/src/hammer.h b/src/hammer.h index 6678db9..1d8e2a8 100644 --- a/src/hammer.h +++ b/src/hammer.h @@ -121,7 +121,7 @@ typedef struct HParserVtable_ { HParseResult* (*parse)(void *env, HParseState *state); bool (*isValidRegular)(void *env); bool (*isValidCF)(void *env); - + bool (*compile_to_rvm)(struct HRVMProg_ *prog, void* env); } HParserVtable; typedef struct HParser_ {