diff --git a/bshell/runtime/eval.c b/bshell/runtime/eval.c new file mode 100644 index 0000000..e716fd6 --- /dev/null +++ b/bshell/runtime/eval.c @@ -0,0 +1,91 @@ +#include "../status.h" +#include "runtime.h" +#include "scope.h" + +#include + +static enum bshell_status eval_instruction( + struct bshell_runtime *rt, + struct runtime_scope *scope, + bshell_instruction instr) +{ + fx_value x, y, z; + enum bshell_opcode opcode; + uint32_t arg; + bshell_instruction_decode(instr, &opcode, &arg); + + switch (opcode) { + case OPCODE_LDC_INT: + x = FX_INT(arg); + runtime_scope_push_value(scope, x); + break; + case OPCODE_ADD: + x = runtime_scope_pop_value(scope); + y = runtime_scope_pop_value(scope); + z = FX_INT(y.v_int + x.v_int); + runtime_scope_push_value(scope, z); + break; + case OPCODE_SUB: + x = runtime_scope_pop_value(scope); + y = runtime_scope_pop_value(scope); + z = FX_INT(y.v_int - x.v_int); + runtime_scope_push_value(scope, z); + break; + case OPCODE_MUL: + x = runtime_scope_pop_value(scope); + y = runtime_scope_pop_value(scope); + z = FX_INT(y.v_int * x.v_int); + runtime_scope_push_value(scope, z); + break; + case OPCODE_DIV: + x = runtime_scope_pop_value(scope); + y = runtime_scope_pop_value(scope); + z = FX_INT(y.v_int / x.v_int); + runtime_scope_push_value(scope, z); + break; + default: + fprintf(stderr, + "RUNTIME: encountered unknown opcode %02x\n", + opcode); + return BSHELL_ERR_BAD_FORMAT; + } + + scope->s_ip++; + return BSHELL_SUCCESS; +} + +static fx_value runtime_eval(struct bshell_runtime *rt) +{ + enum bshell_status status = BSHELL_SUCCESS; + while (status == BSHELL_SUCCESS) { + struct runtime_scope *scope = runtime_get_scope(rt); + if (scope->s_ip >= scope->s_nr_instr) { + break; + } + + bshell_instruction instr = scope->s_instr[scope->s_ip]; + status = eval_instruction(rt, scope, instr); + } + + struct runtime_scope *scope = runtime_get_scope(rt); + return runtime_scope_pop_value(scope); +} + +fx_value bshell_runtime_eval_global( + struct bshell_runtime *rt, + bshell_scriptblock *block) +{ + enum bshell_status status = BSHELL_SUCCESS; + runtime_scope_set_block(rt->rt_global, block); + return runtime_eval(rt); +} + +fx_value bshell_runtime_eval_script( + struct bshell_runtime *rt, + bshell_scriptblock *block) +{ + runtime_push_scope(rt, RUNTIME_SCOPE_SCRIPT, block); + fx_value result = runtime_eval(rt); + runtime_pop_scope(rt); + return result; +} diff --git a/bshell/runtime/runtime.c b/bshell/runtime/runtime.c new file mode 100644 index 0000000..6659978 --- /dev/null +++ b/bshell/runtime/runtime.c @@ -0,0 +1,25 @@ +#include "runtime.h" + +#include "scope.h" + +#include +#include + +struct bshell_runtime *bshell_runtime_create(void) +{ + struct bshell_runtime *out = malloc(sizeof *out); + if (!out) { + return NULL; + } + + memset(out, 0x0, sizeof *out); + + out->rt_global = runtime_push_scope(out, RUNTIME_SCOPE_GLOBAL, NULL); + + return out; +} + +void bshell_runtime_destroy(struct bshell_runtime *rt) +{ + free(rt); +} diff --git a/bshell/runtime/runtime.h b/bshell/runtime/runtime.h new file mode 100644 index 0000000..ac459a5 --- /dev/null +++ b/bshell/runtime/runtime.h @@ -0,0 +1,26 @@ +#ifndef RUNTIME_RUNTIME_H_ +#define RUNTIME_RUNTIME_H_ + +#include "../script-block.h" + +#include +#include + +struct runtime_scope; + +struct bshell_runtime { + struct runtime_scope *rt_global; + fx_queue rt_scope; +}; + +extern struct bshell_runtime *bshell_runtime_create(void); +extern void bshell_runtime_destroy(struct bshell_runtime *rt); + +extern fx_value bshell_runtime_eval_global( + struct bshell_runtime *rt, + bshell_scriptblock *block); +extern fx_value bshell_runtime_eval_script( + struct bshell_runtime *rt, + bshell_scriptblock *block); + +#endif diff --git a/bshell/runtime/scope.c b/bshell/runtime/scope.c new file mode 100644 index 0000000..5cb6ffd --- /dev/null +++ b/bshell/runtime/scope.c @@ -0,0 +1,80 @@ +#include "scope.h" + +#include "runtime.h" + +#include +#include +#include + +struct runtime_scope *runtime_push_scope( + struct bshell_runtime *rt, + enum runtime_scope_type type, + bshell_scriptblock *block) +{ + struct runtime_scope *out = malloc(sizeof *out); + if (!out) { + return NULL; + } + + memset(out, 0x0, sizeof *out); + + out->s_type = type; + + if (block) { + runtime_scope_set_block(out, block); + } + + fx_queue_push_back(&rt->rt_scope, &out->s_entry); + return out; +} + +void runtime_pop_scope(struct bshell_runtime *rt) +{ + fx_queue_entry *entry = fx_queue_pop_back(&rt->rt_scope); + if (!entry) { + return; + } + + struct runtime_scope *scope = fx_unbox( + struct runtime_scope, + entry, + s_entry); + /* TODO */ + free(scope); +} + +struct runtime_scope *runtime_get_scope(struct bshell_runtime *rt) +{ + fx_queue_entry *entry = fx_queue_last(&rt->rt_scope); + if (!entry) { + return NULL; + } + + return fx_unbox(struct runtime_scope, entry, s_entry); +} + +void runtime_scope_push_value(struct runtime_scope *scope, fx_value value) +{ + fx_value *slot = fx_vector_emplace_back(scope->s_stack, NULL); + if (!slot) { + return; + } + + memcpy(slot, &value, sizeof value); +} + +fx_value runtime_scope_pop_value(struct runtime_scope *scope) +{ + fx_value v = scope->s_stack.items[scope->s_stack.count - 1]; + fx_vector_pop_back(scope->s_stack, NULL); + return v; +} + +void runtime_scope_set_block( + struct runtime_scope *scope, + bshell_scriptblock *block) +{ + scope->s_block = block; + bshell_scriptblock_get_text(block, &scope->s_instr, &scope->s_nr_instr); + bshell_scriptblock_get_pool(block, &scope->s_pool, &scope->s_nr_pool); +} diff --git a/bshell/runtime/scope.h b/bshell/runtime/scope.h new file mode 100644 index 0000000..7fcb269 --- /dev/null +++ b/bshell/runtime/scope.h @@ -0,0 +1,48 @@ +#ifndef RUNTIME_SCOPE_H_ +#define RUNTIME_SCOPE_H_ + +#include "../script-block.h" + +#include +#include +#include + +struct bshell_runtime; + +enum runtime_scope_type { + RUNTIME_SCOPE_OTHER = 0, + RUNTIME_SCOPE_SCRIPT, + RUNTIME_SCOPE_GLOBAL, +}; + +struct runtime_scope { + enum runtime_scope_type s_type; + fx_queue_entry s_entry; + fx_namemap s_vars; + FX_VECTOR_DECLARE(fx_value, s_stack); + size_t s_ip; + + bshell_scriptblock *s_block; + bshell_instruction *s_instr; + size_t s_nr_instr; + fx_value *s_pool; + size_t s_nr_pool; +}; + +extern struct runtime_scope *runtime_push_scope( + struct bshell_runtime *rt, + enum runtime_scope_type type, + bshell_scriptblock *block); +extern void runtime_pop_scope(struct bshell_runtime *rt); +extern struct runtime_scope *runtime_get_scope(struct bshell_runtime *rt); + +extern void runtime_scope_push_value( + struct runtime_scope *scope, + fx_value value); +extern fx_value runtime_scope_pop_value(struct runtime_scope *scope); + +extern void runtime_scope_set_block( + struct runtime_scope *scope, + bshell_scriptblock *block); + +#endif