runtime: temporary implementation of arithmetic bytecode evaluation
This commit is contained in:
@@ -0,0 +1,91 @@
|
|||||||
|
#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;
|
||||||
|
}
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
#include "runtime.h"
|
||||||
|
|
||||||
|
#include "scope.h"
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
#ifndef RUNTIME_RUNTIME_H_
|
||||||
|
#define RUNTIME_RUNTIME_H_
|
||||||
|
|
||||||
|
#include "../script-block.h"
|
||||||
|
|
||||||
|
#include <fx/queue.h>
|
||||||
|
#include <fx/value.h>
|
||||||
|
|
||||||
|
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
|
||||||
@@ -0,0 +1,80 @@
|
|||||||
|
#include "scope.h"
|
||||||
|
|
||||||
|
#include "runtime.h"
|
||||||
|
|
||||||
|
#include <fx/vector.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
@@ -0,0 +1,48 @@
|
|||||||
|
#ifndef RUNTIME_SCOPE_H_
|
||||||
|
#define RUNTIME_SCOPE_H_
|
||||||
|
|
||||||
|
#include "../script-block.h"
|
||||||
|
|
||||||
|
#include <fx/namemap.h>
|
||||||
|
#include <fx/queue.h>
|
||||||
|
#include <fx/vector.h>
|
||||||
|
|
||||||
|
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
|
||||||
Reference in New Issue
Block a user