92 lines
2.2 KiB
C
92 lines
2.2 KiB
C
|
|
#include "../status.h"
|
||
|
|
#include "runtime.h"
|
||
|
|
#include "scope.h"
|
||
|
|
|
||
|
|
#include <stdio.h>
|
||
|
|
|
||
|
|
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;
|
||
|
|
}
|