runtime: implement opcodes to run commands and load/store variables and properties
This commit is contained in:
+378
-10
@@ -1,7 +1,13 @@
|
|||||||
|
#include "../format/format.h"
|
||||||
#include "../status.h"
|
#include "../status.h"
|
||||||
|
#include "cmdcall.h"
|
||||||
|
#include "pipeline.h"
|
||||||
#include "runtime.h"
|
#include "runtime.h"
|
||||||
#include "scope.h"
|
#include "scope.h"
|
||||||
|
|
||||||
|
#include <fx/collections/array.h>
|
||||||
|
#include <fx/collections/hashtable.h>
|
||||||
|
#include <fx/string.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
static enum bshell_status eval_instruction(
|
static enum bshell_status eval_instruction(
|
||||||
@@ -11,38 +17,378 @@ static enum bshell_status eval_instruction(
|
|||||||
{
|
{
|
||||||
fx_value x, y, z;
|
fx_value x, y, z;
|
||||||
enum bshell_opcode opcode;
|
enum bshell_opcode opcode;
|
||||||
|
fx_status status;
|
||||||
|
enum bshell_status bstatus = BSHELL_SUCCESS;
|
||||||
uint32_t arg;
|
uint32_t arg;
|
||||||
|
fx_type_id type;
|
||||||
|
fx_value *pool_value = NULL;
|
||||||
|
bshell_variable *var = NULL;
|
||||||
|
const char *s = NULL;
|
||||||
bshell_instruction_decode(instr, &opcode, &arg);
|
bshell_instruction_decode(instr, &opcode, &arg);
|
||||||
|
|
||||||
switch (opcode) {
|
switch (opcode) {
|
||||||
case OPCODE_LDC_INT:
|
case OPCODE_LDC_INT:
|
||||||
x = FX_INT(arg);
|
x = FX_INT(arg);
|
||||||
runtime_scope_push_value(scope, x);
|
runtime_scope_push_value(scope, &x);
|
||||||
|
fx_value_unset(&x);
|
||||||
|
break;
|
||||||
|
case OPCODE_LDC_FP:
|
||||||
|
pool_value = bshell_scriptblock_get_pool_value(
|
||||||
|
scope->s_block,
|
||||||
|
arg,
|
||||||
|
FX_TYPE_DOUBLE);
|
||||||
|
if (pool_value) {
|
||||||
|
runtime_scope_push_value(scope, pool_value);
|
||||||
|
} else {
|
||||||
|
fprintf(stderr, "RUNTIME: invalid ldc.fp operand\n");
|
||||||
|
return BSHELL_ERR_BAD_SYNTAX;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case OPCODE_LDC_STR:
|
||||||
|
pool_value = bshell_scriptblock_get_pool_value(
|
||||||
|
scope->s_block,
|
||||||
|
arg,
|
||||||
|
FX_TYPE_STRING);
|
||||||
|
if (!pool_value) {
|
||||||
|
pool_value = bshell_scriptblock_get_pool_value(
|
||||||
|
scope->s_block,
|
||||||
|
arg,
|
||||||
|
FX_TYPE_CSTR);
|
||||||
|
}
|
||||||
|
if (pool_value) {
|
||||||
|
runtime_scope_push_value(scope, pool_value);
|
||||||
|
} else {
|
||||||
|
fprintf(stderr, "RUNTIME: invalid ldc.str operand\n");
|
||||||
|
return BSHELL_ERR_BAD_SYNTAX;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case OPCODE_ADD:
|
case OPCODE_ADD:
|
||||||
x = runtime_scope_pop_value(scope);
|
x = runtime_scope_pop_value(scope);
|
||||||
y = runtime_scope_pop_value(scope);
|
y = runtime_scope_pop_value(scope);
|
||||||
z = FX_INT(y.v_int + x.v_int);
|
type = fx_value_get_common_type(&x, &y);
|
||||||
runtime_scope_push_value(scope, z);
|
if (!type) {
|
||||||
|
fprintf(stderr,
|
||||||
|
"RUNTIME: cannot apply operator to operands of "
|
||||||
|
"incompatible type\n");
|
||||||
|
return BSHELL_ERR_NOT_SUPPORTED;
|
||||||
|
}
|
||||||
|
status = fx_value_change_type(&y, &y, type);
|
||||||
|
if (!FX_OK(status)) {
|
||||||
|
fprintf(stderr,
|
||||||
|
"RUNTIME: cannot convert operand to the "
|
||||||
|
"necessary type\n");
|
||||||
|
return BSHELL_ERR_NOT_SUPPORTED;
|
||||||
|
}
|
||||||
|
status = fx_value_change_type(&x, &x, type);
|
||||||
|
if (!FX_OK(status)) {
|
||||||
|
fprintf(stderr,
|
||||||
|
"RUNTIME: cannot convert operand to the "
|
||||||
|
"necessary type\n");
|
||||||
|
return BSHELL_ERR_NOT_SUPPORTED;
|
||||||
|
}
|
||||||
|
status = fx_value_add(&x, &y, &z);
|
||||||
|
if (!FX_OK(status)) {
|
||||||
|
fprintf(stderr,
|
||||||
|
"RUNTIME: operands do not support specified "
|
||||||
|
"operator\n");
|
||||||
|
return BSHELL_ERR_NOT_SUPPORTED;
|
||||||
|
}
|
||||||
|
runtime_scope_push_value(scope, &z);
|
||||||
|
fx_value_unset(&z);
|
||||||
break;
|
break;
|
||||||
case OPCODE_SUB:
|
case OPCODE_SUB:
|
||||||
x = runtime_scope_pop_value(scope);
|
x = runtime_scope_pop_value(scope);
|
||||||
y = runtime_scope_pop_value(scope);
|
y = runtime_scope_pop_value(scope);
|
||||||
z = FX_INT(y.v_int - x.v_int);
|
type = fx_value_get_common_type(&x, &y);
|
||||||
runtime_scope_push_value(scope, z);
|
if (!type) {
|
||||||
|
fprintf(stderr,
|
||||||
|
"RUNTIME: cannot apply operator to operands of "
|
||||||
|
"incompatible type\n");
|
||||||
|
return BSHELL_ERR_NOT_SUPPORTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
status = fx_value_subtract(&x, &y, &z);
|
||||||
|
if (!FX_OK(status)) {
|
||||||
|
fprintf(stderr,
|
||||||
|
"RUNTIME: operands do not support specified "
|
||||||
|
"operator\n");
|
||||||
|
return BSHELL_ERR_NOT_SUPPORTED;
|
||||||
|
}
|
||||||
|
runtime_scope_push_value(scope, &z);
|
||||||
|
fx_value_unset(&z);
|
||||||
break;
|
break;
|
||||||
case OPCODE_MUL:
|
case OPCODE_MUL:
|
||||||
x = runtime_scope_pop_value(scope);
|
x = runtime_scope_pop_value(scope);
|
||||||
y = runtime_scope_pop_value(scope);
|
y = runtime_scope_pop_value(scope);
|
||||||
z = FX_INT(y.v_int * x.v_int);
|
type = fx_value_get_common_type(&x, &y);
|
||||||
runtime_scope_push_value(scope, z);
|
if (!type) {
|
||||||
|
fprintf(stderr,
|
||||||
|
"RUNTIME: cannot apply operator to operands of "
|
||||||
|
"incompatible type\n");
|
||||||
|
return BSHELL_ERR_NOT_SUPPORTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
status = fx_value_multiply(&x, &y, &z);
|
||||||
|
if (!FX_OK(status)) {
|
||||||
|
fprintf(stderr,
|
||||||
|
"RUNTIME: operands do not support specified "
|
||||||
|
"operator\n");
|
||||||
|
return BSHELL_ERR_NOT_SUPPORTED;
|
||||||
|
}
|
||||||
|
runtime_scope_push_value(scope, &z);
|
||||||
|
fx_value_unset(&z);
|
||||||
break;
|
break;
|
||||||
case OPCODE_DIV:
|
case OPCODE_DIV:
|
||||||
x = runtime_scope_pop_value(scope);
|
x = runtime_scope_pop_value(scope);
|
||||||
y = runtime_scope_pop_value(scope);
|
y = runtime_scope_pop_value(scope);
|
||||||
z = FX_INT(y.v_int / x.v_int);
|
status = fx_value_change_type(&x, &x, FX_TYPE_DOUBLE);
|
||||||
runtime_scope_push_value(scope, z);
|
if (!FX_OK(status)) {
|
||||||
|
fprintf(stderr,
|
||||||
|
"RUNTIME: operands do not support specified "
|
||||||
|
"operator\n");
|
||||||
|
return BSHELL_ERR_NOT_SUPPORTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
status = fx_value_change_type(&y, &y, FX_TYPE_DOUBLE);
|
||||||
|
if (!FX_OK(status)) {
|
||||||
|
fprintf(stderr,
|
||||||
|
"RUNTIME: operands do not support specified "
|
||||||
|
"operator\n");
|
||||||
|
return BSHELL_ERR_NOT_SUPPORTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
status = fx_value_divide(&x, &y, &z);
|
||||||
|
if (!FX_OK(status)) {
|
||||||
|
fprintf(stderr,
|
||||||
|
"RUNTIME: operands do not support specified "
|
||||||
|
"operator\n");
|
||||||
|
return BSHELL_ERR_NOT_SUPPORTED;
|
||||||
|
}
|
||||||
|
runtime_scope_push_value(scope, &z);
|
||||||
|
fx_value_unset(&z);
|
||||||
break;
|
break;
|
||||||
|
case OPCODE_LDLOCAL:
|
||||||
|
pool_value = bshell_scriptblock_get_pool_value(
|
||||||
|
scope->s_block,
|
||||||
|
arg,
|
||||||
|
FX_TYPE_STRING);
|
||||||
|
if (!pool_value) {
|
||||||
|
fprintf(stderr, "RUNTIME: invalid ldlocal operand\n");
|
||||||
|
return BSHELL_ERR_BAD_SYNTAX;
|
||||||
|
}
|
||||||
|
|
||||||
|
fx_value_get_cstr(pool_value, &s);
|
||||||
|
var = bshell_runtime_find_var(rt, s);
|
||||||
|
if (var) {
|
||||||
|
runtime_scope_push_value(
|
||||||
|
scope,
|
||||||
|
bshell_variable_get_value(var));
|
||||||
|
} else {
|
||||||
|
runtime_scope_push_value(scope, &FX_VALUE_EMPTY);
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
case OPCODE_LDBLOCK:
|
||||||
|
pool_value = bshell_scriptblock_get_pool_value(
|
||||||
|
scope->s_block,
|
||||||
|
arg,
|
||||||
|
BSHELL_TYPE_SCRIPTBLOCK);
|
||||||
|
if (!pool_value) {
|
||||||
|
fprintf(stderr, "RUNTIME: invalid ldblock operand\n");
|
||||||
|
return BSHELL_ERR_BAD_SYNTAX;
|
||||||
|
}
|
||||||
|
|
||||||
|
runtime_scope_push_value(scope, pool_value);
|
||||||
|
|
||||||
|
break;
|
||||||
|
case OPCODE_LDPROP: {
|
||||||
|
/* container */
|
||||||
|
x = runtime_scope_pop_value(scope);
|
||||||
|
/* property */
|
||||||
|
y = runtime_scope_pop_value(scope);
|
||||||
|
|
||||||
|
const fx_type *ty = fx_type_get_by_id(x.v_type);
|
||||||
|
if (!ty) {
|
||||||
|
fx_value_unset(&x);
|
||||||
|
fx_value_unset(&y);
|
||||||
|
runtime_scope_push_value(scope, &FX_VALUE_EMPTY);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
fx_stringstream *strm = fx_stringstream_create();
|
||||||
|
fx_value_to_string(&y, strm, NULL);
|
||||||
|
fx_value_unset(&y);
|
||||||
|
|
||||||
|
const fx_property *prop = fx_type_get_property(
|
||||||
|
ty,
|
||||||
|
fx_stringstream_ptr(strm));
|
||||||
|
fx_stringstream_unref(strm);
|
||||||
|
|
||||||
|
if (!prop) {
|
||||||
|
fx_value_unset(&x);
|
||||||
|
runtime_scope_push_value(scope, &FX_VALUE_EMPTY);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
fx_property_get_value(prop, &x, &z);
|
||||||
|
fx_value_unset(&x);
|
||||||
|
runtime_scope_push_value(scope, &z);
|
||||||
|
fx_value_unset(&z);
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case OPCODE_STLOCAL:
|
||||||
|
x = runtime_scope_pop_value(scope);
|
||||||
|
pool_value = bshell_scriptblock_get_pool_value(
|
||||||
|
scope->s_block,
|
||||||
|
arg,
|
||||||
|
FX_TYPE_CSTR);
|
||||||
|
if (!pool_value) {
|
||||||
|
fprintf(stderr, "RUNTIME: invalid stlocal operand\n");
|
||||||
|
return BSHELL_ERR_BAD_SYNTAX;
|
||||||
|
}
|
||||||
|
|
||||||
|
fx_value_get_cstr(pool_value, &s);
|
||||||
|
var = bshell_runtime_find_var(rt, s);
|
||||||
|
if (!var) {
|
||||||
|
var = bshell_runtime_define_var(rt, s);
|
||||||
|
}
|
||||||
|
|
||||||
|
bshell_variable_set_value(var, &x);
|
||||||
|
runtime_scope_push_value(scope, &x);
|
||||||
|
fx_value_unset(&x);
|
||||||
|
break;
|
||||||
|
case OPCODE_MK_STR: {
|
||||||
|
fx_string *result = fx_string_create();
|
||||||
|
fx_stringstream *strm = fx_stringstream_create();
|
||||||
|
|
||||||
|
while (arg > 0) {
|
||||||
|
x = runtime_scope_pop_value(scope);
|
||||||
|
fx_stringstream_reset(strm);
|
||||||
|
fx_value_to_string(&x, strm, NULL);
|
||||||
|
fx_string_prepend_cstr(
|
||||||
|
result,
|
||||||
|
fx_stringstream_ptr(strm));
|
||||||
|
fx_value_unset(&x);
|
||||||
|
arg--;
|
||||||
|
}
|
||||||
|
|
||||||
|
fx_stringstream_unref(strm);
|
||||||
|
y = FX_VALUE_OBJECT(result);
|
||||||
|
runtime_scope_push_value(scope, &y);
|
||||||
|
fx_value_unset(&y);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case OPCODE_MK_HTAB: {
|
||||||
|
fx_hashtable *result = fx_hashtable_create();
|
||||||
|
|
||||||
|
while (arg > 0) {
|
||||||
|
fx_value key = runtime_scope_pop_value(scope);
|
||||||
|
fx_value value = runtime_scope_pop_value(scope);
|
||||||
|
fx_hashtable_put(result, &key, &value);
|
||||||
|
fx_value_unset(&key);
|
||||||
|
fx_value_unset(&value);
|
||||||
|
arg--;
|
||||||
|
}
|
||||||
|
|
||||||
|
y = FX_VALUE_OBJECT(result);
|
||||||
|
runtime_scope_push_value(scope, &y);
|
||||||
|
fx_value_unset(&y);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case OPCODE_MK_ARRAY: {
|
||||||
|
fx_array *result = fx_array_create();
|
||||||
|
|
||||||
|
while (arg > 0) {
|
||||||
|
fx_value value = runtime_scope_pop_value(scope);
|
||||||
|
fx_array_push_front(result, value);
|
||||||
|
fx_value_unset(&value);
|
||||||
|
arg--;
|
||||||
|
}
|
||||||
|
|
||||||
|
y = FX_VALUE_OBJECT(result);
|
||||||
|
runtime_scope_push_value(scope, &y);
|
||||||
|
fx_value_unset(&y);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case OPCODE_LDCMD: {
|
||||||
|
bshell_cmdcall *result = bshell_cmdcall_create();
|
||||||
|
|
||||||
|
while (arg > 0) {
|
||||||
|
fx_value cmd_arg = runtime_scope_pop_value(scope);
|
||||||
|
bshell_cmdcall_push_arg(result, cmd_arg);
|
||||||
|
fx_value_unset(&cmd_arg);
|
||||||
|
arg--;
|
||||||
|
}
|
||||||
|
|
||||||
|
bstatus = bshell_cmdcall_resolve(result, rt);
|
||||||
|
if (bstatus != BSHELL_SUCCESS) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
y = FX_VALUE_OBJECT(result);
|
||||||
|
runtime_scope_push_value(scope, &y);
|
||||||
|
fx_value_unset(&y);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case OPCODE_PEXEC: {
|
||||||
|
bshell_pipeline *pipeline = bshell_pipeline_create();
|
||||||
|
bool single = (arg == 1);
|
||||||
|
while (arg > 0) {
|
||||||
|
fx_value cmd = runtime_scope_pop_value(scope);
|
||||||
|
bshell_cmdcall *cmdcall = NULL;
|
||||||
|
if (fx_value_is_type(&cmd, BSHELL_TYPE_CMDCALL)) {
|
||||||
|
fx_value_get_object(&cmd, &cmdcall);
|
||||||
|
bshell_pipeline_add_cmdcall(pipeline, cmdcall);
|
||||||
|
} else {
|
||||||
|
bshell_pipeline_add_input_value(
|
||||||
|
pipeline,
|
||||||
|
cmd,
|
||||||
|
true);
|
||||||
|
}
|
||||||
|
|
||||||
|
fx_value_unset(&cmd);
|
||||||
|
arg--;
|
||||||
|
}
|
||||||
|
|
||||||
|
int end_of_data = 0;
|
||||||
|
bool columns_initialised = false;
|
||||||
|
fx_value record = FX_VALUE_EMPTY;
|
||||||
|
struct table_format_ctx table_ctx;
|
||||||
|
table_format_ctx_init(&table_ctx, fx_stdout);
|
||||||
|
while (1) {
|
||||||
|
bstatus = bshell_pipeline_pump_record(
|
||||||
|
pipeline,
|
||||||
|
rt,
|
||||||
|
&record,
|
||||||
|
&end_of_data);
|
||||||
|
if (bstatus != BSHELL_SUCCESS || end_of_data) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!record.v_type) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!columns_initialised) {
|
||||||
|
const fx_type *ty = fx_type_get_by_id(
|
||||||
|
record.v_type);
|
||||||
|
table_format_ctx_prepare_columns_from_format(
|
||||||
|
&table_ctx,
|
||||||
|
ty,
|
||||||
|
NULL);
|
||||||
|
table_format_ctx_print_headers(&table_ctx);
|
||||||
|
columns_initialised = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
table_format_ctx_print_record(&table_ctx, &record);
|
||||||
|
fx_value_unset(&record);
|
||||||
|
}
|
||||||
|
|
||||||
|
table_format_ctx_cleanup(&table_ctx);
|
||||||
|
bshell_pipeline_unref(pipeline);
|
||||||
|
break;
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
fprintf(stderr,
|
fprintf(stderr,
|
||||||
"RUNTIME: encountered unknown opcode %02x\n",
|
"RUNTIME: encountered unknown opcode %02x\n",
|
||||||
@@ -51,7 +397,7 @@ static enum bshell_status eval_instruction(
|
|||||||
}
|
}
|
||||||
|
|
||||||
scope->s_ip++;
|
scope->s_ip++;
|
||||||
return BSHELL_SUCCESS;
|
return bstatus;
|
||||||
}
|
}
|
||||||
|
|
||||||
static fx_value runtime_eval(struct bshell_runtime *rt)
|
static fx_value runtime_eval(struct bshell_runtime *rt)
|
||||||
@@ -89,3 +435,25 @@ fx_value bshell_runtime_eval_script(
|
|||||||
runtime_pop_scope(rt);
|
runtime_pop_scope(rt);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fx_value bshell_runtime_eval(struct bshell_runtime *rt)
|
||||||
|
{
|
||||||
|
return runtime_eval(rt);
|
||||||
|
}
|
||||||
|
|
||||||
|
enum bshell_status bshell_runtime_push_scope(
|
||||||
|
struct bshell_runtime *rt,
|
||||||
|
bshell_scriptblock *block)
|
||||||
|
{
|
||||||
|
struct runtime_scope *scope = runtime_push_scope(
|
||||||
|
rt,
|
||||||
|
RUNTIME_SCOPE_SCRIPT,
|
||||||
|
block);
|
||||||
|
return scope ? BSHELL_SUCCESS : BSHELL_ERR_NO_MEMORY;
|
||||||
|
}
|
||||||
|
|
||||||
|
enum bshell_status bshell_runtime_pop_scope(struct bshell_runtime *rt)
|
||||||
|
{
|
||||||
|
runtime_pop_scope(rt);
|
||||||
|
return BSHELL_SUCCESS;
|
||||||
|
}
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ enum bshell_opcode {
|
|||||||
OPCODE_NOP = 0,
|
OPCODE_NOP = 0,
|
||||||
OPCODE_LDC_INT,
|
OPCODE_LDC_INT,
|
||||||
OPCODE_LDC_STR,
|
OPCODE_LDC_STR,
|
||||||
|
OPCODE_LDC_FP,
|
||||||
OPCODE_LDGLOBAL,
|
OPCODE_LDGLOBAL,
|
||||||
OPCODE_LDLOCAL,
|
OPCODE_LDLOCAL,
|
||||||
OPCODE_LDBLOCK,
|
OPCODE_LDBLOCK,
|
||||||
|
|||||||
@@ -15,11 +15,94 @@ struct bshell_runtime *bshell_runtime_create(void)
|
|||||||
memset(out, 0x0, sizeof *out);
|
memset(out, 0x0, sizeof *out);
|
||||||
|
|
||||||
out->rt_global = runtime_push_scope(out, RUNTIME_SCOPE_GLOBAL, NULL);
|
out->rt_global = runtime_push_scope(out, RUNTIME_SCOPE_GLOBAL, NULL);
|
||||||
|
out->rt_aliases = fx_hashtable_create();
|
||||||
|
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
void bshell_runtime_destroy(struct bshell_runtime *rt)
|
void bshell_runtime_destroy(struct bshell_runtime *rt)
|
||||||
{
|
{
|
||||||
|
fx_hashtable_unref(rt->rt_aliases);
|
||||||
free(rt);
|
free(rt);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bshell_variable *bshell_runtime_find_var(
|
||||||
|
struct bshell_runtime *rt,
|
||||||
|
const char *name)
|
||||||
|
{
|
||||||
|
bshell_variable *var = NULL;
|
||||||
|
fx_queue_entry *cur = fx_queue_last(&rt->rt_scope);
|
||||||
|
while (cur) {
|
||||||
|
struct runtime_scope *scope = fx_unbox(
|
||||||
|
struct runtime_scope,
|
||||||
|
cur,
|
||||||
|
s_entry);
|
||||||
|
var = var_map_get(&scope->s_vars, name);
|
||||||
|
if (var) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
cur = fx_queue_prev(cur);
|
||||||
|
}
|
||||||
|
|
||||||
|
return var;
|
||||||
|
}
|
||||||
|
|
||||||
|
bshell_variable *bshell_runtime_define_var(
|
||||||
|
struct bshell_runtime *rt,
|
||||||
|
const char *name)
|
||||||
|
{
|
||||||
|
struct runtime_scope *scope = runtime_get_scope(rt);
|
||||||
|
if (!scope) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
bshell_variable *var = bshell_variable_create(name);
|
||||||
|
if (!var) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
var_map_put(&scope->s_vars, var);
|
||||||
|
return var;
|
||||||
|
}
|
||||||
|
|
||||||
|
bshell_command *bshell_runtime_find_command(
|
||||||
|
struct bshell_runtime *rt,
|
||||||
|
const char *callable_name)
|
||||||
|
{
|
||||||
|
bshell_command *alias = NULL, *func = NULL;
|
||||||
|
const fx_value *alias_v = fx_hashtable_get(
|
||||||
|
rt->rt_aliases,
|
||||||
|
&FX_CSTR(callable_name));
|
||||||
|
if (alias_v) {
|
||||||
|
fx_value_get_object(alias_v, &alias);
|
||||||
|
bshell_command_ref(alias);
|
||||||
|
return alias;
|
||||||
|
}
|
||||||
|
|
||||||
|
fx_queue_entry *cur = fx_queue_last(&rt->rt_scope);
|
||||||
|
while (cur) {
|
||||||
|
struct runtime_scope *scope = fx_unbox(
|
||||||
|
struct runtime_scope,
|
||||||
|
cur,
|
||||||
|
s_entry);
|
||||||
|
const fx_value *func_v = fx_hashtable_get(
|
||||||
|
scope->s_functions,
|
||||||
|
&FX_CSTR(callable_name));
|
||||||
|
if (func_v) {
|
||||||
|
fx_value_get_object(func_v, &func);
|
||||||
|
bshell_command_ref(func);
|
||||||
|
return func;
|
||||||
|
}
|
||||||
|
|
||||||
|
cur = fx_queue_prev(cur);
|
||||||
|
}
|
||||||
|
|
||||||
|
bshell_command *cmd = bshell_command_find_static(callable_name);
|
||||||
|
if (cmd) {
|
||||||
|
return cmd;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* TODO find native executables */
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,8 +1,11 @@
|
|||||||
#ifndef RUNTIME_RUNTIME_H_
|
#ifndef RUNTIME_RUNTIME_H_
|
||||||
#define RUNTIME_RUNTIME_H_
|
#define RUNTIME_RUNTIME_H_
|
||||||
|
|
||||||
|
#include "../command/command.h"
|
||||||
#include "../script-block.h"
|
#include "../script-block.h"
|
||||||
|
#include "var.h"
|
||||||
|
|
||||||
|
#include <fx/collections/hashtable.h>
|
||||||
#include <fx/queue.h>
|
#include <fx/queue.h>
|
||||||
#include <fx/value.h>
|
#include <fx/value.h>
|
||||||
|
|
||||||
@@ -10,6 +13,7 @@ struct runtime_scope;
|
|||||||
|
|
||||||
struct bshell_runtime {
|
struct bshell_runtime {
|
||||||
struct runtime_scope *rt_global;
|
struct runtime_scope *rt_global;
|
||||||
|
fx_hashtable *rt_aliases;
|
||||||
fx_queue rt_scope;
|
fx_queue rt_scope;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -23,4 +27,21 @@ extern fx_value bshell_runtime_eval_script(
|
|||||||
struct bshell_runtime *rt,
|
struct bshell_runtime *rt,
|
||||||
bshell_scriptblock *block);
|
bshell_scriptblock *block);
|
||||||
|
|
||||||
|
extern bshell_variable *bshell_runtime_find_var(
|
||||||
|
struct bshell_runtime *rt,
|
||||||
|
const char *name);
|
||||||
|
extern bshell_variable *bshell_runtime_define_var(
|
||||||
|
struct bshell_runtime *rt,
|
||||||
|
const char *name);
|
||||||
|
|
||||||
|
extern bshell_command *bshell_runtime_find_command(
|
||||||
|
struct bshell_runtime *rt,
|
||||||
|
const char *callable_name);
|
||||||
|
|
||||||
|
extern enum bshell_status bshell_runtime_push_scope(
|
||||||
|
struct bshell_runtime *rt,
|
||||||
|
bshell_scriptblock *block);
|
||||||
|
extern enum bshell_status bshell_runtime_pop_scope(struct bshell_runtime *rt);
|
||||||
|
extern fx_value bshell_runtime_eval(struct bshell_runtime *rt);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
+11
-2
@@ -19,6 +19,7 @@ struct runtime_scope *runtime_push_scope(
|
|||||||
memset(out, 0x0, sizeof *out);
|
memset(out, 0x0, sizeof *out);
|
||||||
|
|
||||||
out->s_type = type;
|
out->s_type = type;
|
||||||
|
out->s_functions = fx_hashtable_create();
|
||||||
|
|
||||||
if (block) {
|
if (block) {
|
||||||
runtime_scope_set_block(out, block);
|
runtime_scope_set_block(out, block);
|
||||||
@@ -40,6 +41,7 @@ void runtime_pop_scope(struct bshell_runtime *rt)
|
|||||||
entry,
|
entry,
|
||||||
s_entry);
|
s_entry);
|
||||||
/* TODO */
|
/* TODO */
|
||||||
|
fx_hashtable_unref(scope->s_functions);
|
||||||
free(scope);
|
free(scope);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -53,18 +55,24 @@ struct runtime_scope *runtime_get_scope(struct bshell_runtime *rt)
|
|||||||
return fx_unbox(struct runtime_scope, entry, s_entry);
|
return fx_unbox(struct runtime_scope, entry, s_entry);
|
||||||
}
|
}
|
||||||
|
|
||||||
void runtime_scope_push_value(struct runtime_scope *scope, fx_value value)
|
void runtime_scope_push_value(
|
||||||
|
struct runtime_scope *scope,
|
||||||
|
const fx_value *value)
|
||||||
{
|
{
|
||||||
fx_value *slot = fx_vector_emplace_back(scope->s_stack, NULL);
|
fx_value *slot = fx_vector_emplace_back(scope->s_stack, NULL);
|
||||||
if (!slot) {
|
if (!slot) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
memcpy(slot, &value, sizeof value);
|
fx_value_copy(slot, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
fx_value runtime_scope_pop_value(struct runtime_scope *scope)
|
fx_value runtime_scope_pop_value(struct runtime_scope *scope)
|
||||||
{
|
{
|
||||||
|
if (scope->s_stack.count == 0) {
|
||||||
|
return FX_VALUE_EMPTY;
|
||||||
|
}
|
||||||
|
|
||||||
fx_value v = scope->s_stack.items[scope->s_stack.count - 1];
|
fx_value v = scope->s_stack.items[scope->s_stack.count - 1];
|
||||||
fx_vector_pop_back(scope->s_stack, NULL);
|
fx_vector_pop_back(scope->s_stack, NULL);
|
||||||
return v;
|
return v;
|
||||||
@@ -75,6 +83,7 @@ void runtime_scope_set_block(
|
|||||||
bshell_scriptblock *block)
|
bshell_scriptblock *block)
|
||||||
{
|
{
|
||||||
scope->s_block = block;
|
scope->s_block = block;
|
||||||
|
scope->s_ip = 0;
|
||||||
bshell_scriptblock_get_text(block, &scope->s_instr, &scope->s_nr_instr);
|
bshell_scriptblock_get_text(block, &scope->s_instr, &scope->s_nr_instr);
|
||||||
bshell_scriptblock_get_pool(block, &scope->s_pool, &scope->s_nr_pool);
|
bshell_scriptblock_get_pool(block, &scope->s_pool, &scope->s_nr_pool);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,7 +2,9 @@
|
|||||||
#define RUNTIME_SCOPE_H_
|
#define RUNTIME_SCOPE_H_
|
||||||
|
|
||||||
#include "../script-block.h"
|
#include "../script-block.h"
|
||||||
|
#include "var-map.h"
|
||||||
|
|
||||||
|
#include <fx/collections/hashtable.h>
|
||||||
#include <fx/namemap.h>
|
#include <fx/namemap.h>
|
||||||
#include <fx/queue.h>
|
#include <fx/queue.h>
|
||||||
#include <fx/vector.h>
|
#include <fx/vector.h>
|
||||||
@@ -18,7 +20,8 @@ enum runtime_scope_type {
|
|||||||
struct runtime_scope {
|
struct runtime_scope {
|
||||||
enum runtime_scope_type s_type;
|
enum runtime_scope_type s_type;
|
||||||
fx_queue_entry s_entry;
|
fx_queue_entry s_entry;
|
||||||
fx_namemap s_vars;
|
struct var_map s_vars;
|
||||||
|
fx_hashtable *s_functions;
|
||||||
FX_VECTOR_DECLARE(fx_value, s_stack);
|
FX_VECTOR_DECLARE(fx_value, s_stack);
|
||||||
size_t s_ip;
|
size_t s_ip;
|
||||||
|
|
||||||
@@ -38,7 +41,7 @@ extern struct runtime_scope *runtime_get_scope(struct bshell_runtime *rt);
|
|||||||
|
|
||||||
extern void runtime_scope_push_value(
|
extern void runtime_scope_push_value(
|
||||||
struct runtime_scope *scope,
|
struct runtime_scope *scope,
|
||||||
fx_value value);
|
const fx_value *value);
|
||||||
extern fx_value runtime_scope_pop_value(struct runtime_scope *scope);
|
extern fx_value runtime_scope_pop_value(struct runtime_scope *scope);
|
||||||
|
|
||||||
extern void runtime_scope_set_block(
|
extern void runtime_scope_set_block(
|
||||||
|
|||||||
Reference in New Issue
Block a user