bshell: re-organise build into three separate components

bshell: the front-end binary
bshell.runtime: contains the parser, compiler, and classes needed to run bshell scripts
bshell.core: contains the builtin commandlets and aliases
This commit is contained in:
2026-05-25 10:33:29 +01:00
parent 58c76a1f57
commit edfb3e24a3
165 changed files with 5173 additions and 4995 deletions
+25
View File
@@ -0,0 +1,25 @@
#include "compile-node.h"
static const struct compile_value_type array_type = {};
static const struct compile_value_type array_item_type = {};
struct compile_result compile_array(
struct compile_ctx *ctx,
struct bshell_ast_node *src)
{
struct bshell_array_ast_node *array;
array = (struct bshell_array_ast_node *)src;
size_t nr_items = fx_queue_length(&array->n_items);
for (size_t i = 0; i < nr_items; i++) {
struct compile_value *item = compile_pop_value(ctx);
compile_value_load(ctx, item);
compile_value_destroy(item);
}
bshell_scriptblock_push_instruction(
ctx->c_block,
BSHELL_OPCODE_MK_ARRAY,
nr_items);
compile_push_value(ctx, &array_type, src);
return COMPILE_OK(0);
}
+65
View File
@@ -0,0 +1,65 @@
#include "compile-node.h"
#include <bshell/compile.h>
#include <stdio.h>
static enum bshell_status block_load(
struct compile_ctx *ctx,
struct compile_value *value)
{
bshell_scriptblock_push_instruction(
ctx->c_block,
BSHELL_OPCODE_LDBLOCK,
value->v_pool);
return BSHELL_SUCCESS;
}
static const struct compile_value_type block_type = {
.v_load = block_load,
};
struct compile_result compile_block(
struct compile_ctx *ctx,
struct bshell_ast_node *src)
{
bshell_scriptblock *sub_block = bshell_scriptblock_create();
if (!sub_block) {
return COMPILE_ERR(BSHELL_ERR_NO_MEMORY);
}
enum bshell_status status = bshell_compile(src, sub_block);
if (status != BSHELL_SUCCESS) {
bshell_scriptblock_unref(sub_block);
return COMPILE_ERR(status);
}
fx_value sub_block_value = FX_VALUE_OBJECT(sub_block);
unsigned long slot = bshell_scriptblock_add_pool_value(
ctx->c_block,
&sub_block_value);
fx_value_unset(&sub_block_value);
compile_push_pool_value(ctx, &block_type, slot);
return COMPILE_OK(0);
}
enum bshell_status compile_block_immediate(
struct compile_ctx *ctx,
struct bshell_ast_node *src)
{
enum bshell_status status = BSHELL_SUCCESS;
struct bshell_block_ast_node *block = (struct bshell_block_ast_node *)
src;
fx_queue_entry *cur = fx_queue_first(&block->n_statements);
while (cur && status == BSHELL_SUCCESS) {
struct bshell_ast_node *node = fx_unbox(
struct bshell_ast_node,
cur,
n_entry);
status = compile_node(ctx, node);
cur = fx_queue_next(cur);
}
return status;
}
+74
View File
@@ -0,0 +1,74 @@
#include "compile-node.h"
enum bshell_status cmdcall_load(
struct compile_ctx *ctx,
struct compile_value *value)
{
struct bshell_cmdcall_ast_node *cmdcall;
cmdcall = (struct bshell_cmdcall_ast_node *)value->v_node;
bshell_scriptblock_push_instruction(ctx->c_block, BSHELL_OPCODE_PEXEC, 1);
return BSHELL_SUCCESS;
}
enum bshell_status pipeline_load(
struct compile_ctx *ctx,
struct compile_value *value)
{
struct bshell_pipeline_ast_node *pipeline;
pipeline = (struct bshell_pipeline_ast_node *)value->v_node;
size_t nr_items = fx_queue_length(&pipeline->n_stages);
bshell_scriptblock_push_instruction(
ctx->c_block,
BSHELL_OPCODE_PEXEC,
nr_items);
return BSHELL_SUCCESS;
}
static const struct compile_value_type cmdcall_type = {
.v_load = cmdcall_load,
};
static const struct compile_value_type pipeline_type = {
.v_load = pipeline_load,
};
struct compile_result compile_cmdcall(
struct compile_ctx *ctx,
struct bshell_ast_node *src)
{
struct bshell_cmdcall_ast_node *cmdcall;
cmdcall = (struct bshell_cmdcall_ast_node *)src;
size_t nr_args = fx_queue_length(&cmdcall->n_args);
for (size_t i = 0; i < nr_args; i++) {
struct compile_value *arg = compile_pop_value(ctx);
compile_value_load(ctx, arg);
compile_value_destroy(arg);
}
bshell_scriptblock_push_instruction(
ctx->c_block,
BSHELL_OPCODE_LDCMD,
nr_args);
compile_push_value(ctx, &cmdcall_type, src);
return COMPILE_OK(0);
}
struct compile_result compile_pipeline(
struct compile_ctx *ctx,
struct bshell_ast_node *src)
{
struct bshell_pipeline_ast_node *pipeline;
pipeline = (struct bshell_pipeline_ast_node *)src;
size_t nr_items = fx_queue_length(&pipeline->n_stages);
for (size_t i = 0; i < nr_items; i++) {
struct compile_value *item = compile_pop_value(ctx);
if (item->v_node->n_type != BSHELL_AST_CMDCALL) {
compile_value_load(ctx, item);
}
compile_value_destroy(item);
}
compile_push_value(ctx, &pipeline_type, src);
return COMPILE_OK(0);
}
+187
View File
@@ -0,0 +1,187 @@
#ifndef COMPILE_COMPILE_NODE_H_
#define COMPILE_COMPILE_NODE_H_
#include <bshell/ast.h>
#include <bshell/parse/token.h>
#include <bshell/runtime/operator.h>
#include <bshell/runtime/script-block.h>
#include <bshell/status.h>
#include <fx/queue.h>
#include <fx/vector.h>
#define COMPILE_OK(flags) \
((struct compile_result) {.r_status = BSHELL_SUCCESS, \
.r_flags = (flags)})
#define COMPILE_ERR(status) ((struct compile_result) {.r_status = (status)})
struct compile_ctx;
struct compile_value;
struct compile_result {
enum bshell_status r_status;
enum {
COMPILE_REPEAT_NODE = 0x00u,
} r_flags;
};
typedef struct compile_result (*compile_begin_impl)(struct compile_ctx *);
typedef struct compile_result (*compile_end_impl)(struct compile_ctx *);
typedef struct compile_result (
*compile_node_impl)(struct compile_ctx *, struct bshell_ast_node *);
enum compile_state_type_id {
COMPILE_NORMAL = 0,
COMPILE_FSTRING,
};
struct compile_value_type {
enum bshell_status (
*v_load)(struct compile_ctx *, struct compile_value *);
enum bshell_status (
*v_store)(struct compile_ctx *, struct compile_value *);
};
struct compile_value {
const struct compile_value_type *v_type;
enum bshell_operator_id v_op;
struct compile_value *v_left, *v_right;
struct compile_value **v_args;
size_t v_nr_args;
struct bshell_ast_node *v_node;
unsigned long v_pool;
fx_queue_entry v_entry;
};
struct compile_label {
size_t l_ip;
};
struct compile_label_ref {
fx_queue_entry ref_entry;
size_t ref_offset;
size_t ref_label_id;
};
struct compile_ctx {
fx_queue c_state, c_stack;
bshell_scriptblock *c_block;
FX_VECTOR_DECLARE(struct compile_label, c_labels);
fx_queue c_label_refs;
size_t c_depth;
};
struct compile_state_type {
size_t s_size;
compile_begin_impl s_compile_begin;
compile_end_impl s_compile_end;
const compile_node_impl *s_compile_node;
compile_node_impl s_compile_node_generic;
size_t s_nr_compile_node;
};
struct compile_state {
const struct compile_state_type *s_type;
fx_queue_entry s_entry;
size_t s_depth;
};
extern struct compile_state *compile_push_state(
struct compile_ctx *ctx,
enum compile_state_type_id state_type);
extern void compile_pop_state(struct compile_ctx *ctx);
extern struct compile_state *compile_get_state(const struct compile_ctx *ctx);
extern enum bshell_status compile_push_value(
struct compile_ctx *ctx,
const struct compile_value_type *type,
struct bshell_ast_node *node);
extern enum bshell_status compile_push_value_array(
struct compile_ctx *ctx,
const struct compile_value_type *type,
struct bshell_ast_node *node,
struct compile_value **values,
size_t nr_values);
extern enum bshell_status compile_push_pool_value(
struct compile_ctx *ctx,
const struct compile_value_type *type,
unsigned long pool_slot);
extern enum bshell_status compile_push_op(
struct compile_ctx *ctx,
struct bshell_ast_node *node,
const struct compile_value_type *type,
enum bshell_operator_id op,
struct compile_value *left,
struct compile_value *right);
extern struct compile_value *compile_pop_value(struct compile_ctx *ctx);
extern void compile_value_load(
struct compile_ctx *ctx,
struct compile_value *item);
extern void compile_value_store(
struct compile_ctx *ctx,
struct compile_value *item);
extern void compile_value_destroy(struct compile_value *item);
extern size_t compile_declare_label(struct compile_ctx *ctx);
extern void compile_define_label(struct compile_ctx *ctx, size_t label_id);
extern void compile_ref_label(struct compile_ctx *ctx, size_t label_id);
extern enum bshell_status compile_resolve_labels(struct compile_ctx *ctx);
extern struct compile_result compile_int(
struct compile_ctx *ctx,
struct bshell_ast_node *src);
extern struct compile_result compile_double(
struct compile_ctx *ctx,
struct bshell_ast_node *src);
extern struct compile_result compile_string(
struct compile_ctx *ctx,
struct bshell_ast_node *src);
extern struct compile_result compile_word(
struct compile_ctx *ctx,
struct bshell_ast_node *src);
extern struct compile_result compile_op(
struct compile_ctx *ctx,
struct bshell_ast_node *src);
extern struct compile_result compile_var(
struct compile_ctx *ctx,
struct bshell_ast_node *src);
extern struct compile_result compile_fstring(
struct compile_ctx *ctx,
struct bshell_ast_node *src);
extern struct compile_result compile_array(
struct compile_ctx *ctx,
struct bshell_ast_node *src);
extern struct compile_result compile_hashtable_item(
struct compile_ctx *ctx,
struct bshell_ast_node *src);
extern struct compile_result compile_hashtable(
struct compile_ctx *ctx,
struct bshell_ast_node *src);
extern struct compile_result compile_block(
struct compile_ctx *ctx,
struct bshell_ast_node *src);
extern struct compile_result compile_cmdcall(
struct compile_ctx *ctx,
struct bshell_ast_node *src);
extern struct compile_result compile_pipeline(
struct compile_ctx *ctx,
struct bshell_ast_node *src);
extern enum bshell_status compile_if(
struct compile_ctx *ctx,
struct bshell_ast_node *src);
extern enum bshell_status compile_block_immediate(
struct compile_ctx *ctx,
struct bshell_ast_node *src);
extern enum bshell_status compile_expression(
struct compile_ctx *ctx,
struct bshell_ast_node *src);
extern enum bshell_status compile_node(
struct compile_ctx *ctx,
struct bshell_ast_node *src);
#endif
+40
View File
@@ -0,0 +1,40 @@
#include "compile-node.h"
#include <bshell/ast.h>
#include <bshell/compile.h>
#include <bshell/status.h>
extern enum bshell_status compile_node(
struct compile_ctx *ctx,
struct bshell_ast_node *src)
{
switch (src->n_type) {
case BSHELL_AST_IF:
return compile_if(ctx, src);
case BSHELL_AST_BLOCK:
return compile_block_immediate(ctx, src);
default:
return compile_expression(ctx, src);
}
return BSHELL_SUCCESS;
}
enum bshell_status bshell_compile(
struct bshell_ast_node *src,
bshell_scriptblock *dest)
{
struct compile_ctx ctx = {.c_block = dest};
enum bshell_status status = compile_node(&ctx, src);
if (status != BSHELL_SUCCESS) {
return status;
}
status = compile_resolve_labels(&ctx);
if (status != BSHELL_SUCCESS) {
return status;
}
return BSHELL_SUCCESS;
}
+114
View File
@@ -0,0 +1,114 @@
#include "compile-node.h"
enum bshell_status int_load(
struct compile_ctx *ctx,
struct compile_value *value)
{
struct bshell_int_ast_node *i
= (struct bshell_int_ast_node *)value->v_node;
long long v;
fx_value_get_longlong(&i->n_value->tok_number, &v);
bshell_scriptblock_push_instruction(ctx->c_block, BSHELL_OPCODE_LDC_INT, v);
return BSHELL_SUCCESS;
}
enum bshell_status double_load(
struct compile_ctx *ctx,
struct compile_value *value)
{
struct bshell_double_ast_node *d
= (struct bshell_double_ast_node *)value->v_node;
double v;
fx_value_get_double(&d->n_value->tok_number, &v);
unsigned long index = bshell_scriptblock_get_double(ctx->c_block, v);
bshell_scriptblock_push_instruction(ctx->c_block, BSHELL_OPCODE_LDC_FP, index);
return BSHELL_SUCCESS;
}
enum bshell_status string_load(
struct compile_ctx *ctx,
struct compile_value *value)
{
struct bshell_string_ast_node *s
= (struct bshell_string_ast_node *)value->v_node;
unsigned long index = bshell_scriptblock_get_string(
ctx->c_block,
s->n_value->tok_str);
if (index == POOL_INDEX_INVALID) {
return BSHELL_ERR_NO_MEMORY;
}
bshell_scriptblock_push_instruction(
ctx->c_block,
BSHELL_OPCODE_LDC_STR,
index);
return BSHELL_SUCCESS;
}
enum bshell_status word_load(
struct compile_ctx *ctx,
struct compile_value *value)
{
struct bshell_word_ast_node *s
= (struct bshell_word_ast_node *)value->v_node;
unsigned long index = bshell_scriptblock_get_string(
ctx->c_block,
s->n_value->tok_str);
if (index == POOL_INDEX_INVALID) {
return BSHELL_ERR_NO_MEMORY;
}
bshell_scriptblock_push_instruction(
ctx->c_block,
BSHELL_OPCODE_LDC_STR,
index);
return BSHELL_SUCCESS;
}
static const struct compile_value_type int_type = {
.v_load = int_load,
};
static const struct compile_value_type double_type = {
.v_load = double_load,
};
static const struct compile_value_type string_type = {
.v_load = string_load,
};
static const struct compile_value_type word_type = {
.v_load = word_load,
};
struct compile_result compile_int(
struct compile_ctx *ctx,
struct bshell_ast_node *src)
{
compile_push_value(ctx, &int_type, src);
return COMPILE_OK(0);
}
struct compile_result compile_double(
struct compile_ctx *ctx,
struct bshell_ast_node *src)
{
compile_push_value(ctx, &double_type, src);
return COMPILE_OK(0);
}
struct compile_result compile_string(
struct compile_ctx *ctx,
struct bshell_ast_node *src)
{
compile_push_value(ctx, &string_type, src);
return COMPILE_OK(0);
}
struct compile_result compile_word(
struct compile_ctx *ctx,
struct bshell_ast_node *src)
{
compile_push_value(ctx, &word_type, src);
return COMPILE_OK(0);
}
+76
View File
@@ -0,0 +1,76 @@
#include "compile-node.h"
static struct bshell_ast_iterate_result do_compile_node(
struct bshell_ast_node *node,
enum bshell_ast_iteration_type it_type,
struct bshell_ast_iterator *it,
struct compile_ctx *ctx)
{
if (it_type != BSHELL_AST_ITERATION_POST) {
int flags = 0;
switch (node->n_type) {
case BSHELL_AST_BLOCK:
break;
default:
flags |= BSHELL_AST_ITERATE_ADD_CHILDREN;
break;
}
return BSHELL_AST_ITERATE_OK(flags);
}
ctx->c_depth = node->n_it.e_depth;
struct compile_state *state = compile_get_state(ctx);
while (state->s_depth >= ctx->c_depth && state->s_depth > 0) {
compile_pop_state(ctx);
state = compile_get_state(ctx);
}
compile_node_impl impl = NULL;
if (node->n_type < state->s_type->s_nr_compile_node) {
impl = state->s_type->s_compile_node[node->n_type];
}
if (!impl) {
impl = state->s_type->s_compile_node_generic;
}
if (!impl) {
return BSHELL_AST_ITERATE_OK(0);
}
struct compile_result result = impl(ctx, node);
unsigned int flags = 0;
if (result.r_flags & COMPILE_REPEAT_NODE) {
flags |= BSHELL_AST_ITERATE_REPEAT;
}
if (result.r_status == BSHELL_SUCCESS) {
return BSHELL_AST_ITERATE_OK(flags);
}
return BSHELL_AST_ITERATE_ERR(result.r_status);
}
enum bshell_status compile_expression(
struct compile_ctx *ctx,
struct bshell_ast_node *src)
{
compile_push_state(ctx, COMPILE_NORMAL);
struct bshell_ast_iterator it = {0};
bshell_ast_node_iterate(
src,
&it,
(bshell_ast_iterator_callback)do_compile_node,
ctx);
struct compile_value *result = compile_pop_value(ctx);
if (result) {
compile_value_load(ctx, result);
compile_value_destroy(result);
}
return BSHELL_SUCCESS;
}
+40
View File
@@ -0,0 +1,40 @@
#include "compile-node.h"
enum bshell_status fstring_load(
struct compile_ctx *ctx,
struct compile_value *value)
{
struct bshell_fstring_ast_node *fstring
= (struct bshell_fstring_ast_node *)value->v_node;
for (size_t i = 0; i < value->v_nr_args; i++) {
compile_value_load(ctx, value->v_args[i]);
}
bshell_scriptblock_push_instruction(
ctx->c_block,
BSHELL_OPCODE_MK_STR,
fx_queue_length(&fstring->n_elements));
return BSHELL_SUCCESS;
}
static const struct compile_value_type fstring_type = {
.v_load = fstring_load,
};
struct compile_result compile_fstring(
struct compile_ctx *ctx,
struct bshell_ast_node *src)
{
struct bshell_fstring_ast_node *fstring
= (struct bshell_fstring_ast_node *)src;
size_t nr_items = fx_queue_length(&fstring->n_elements);
struct compile_value **items = calloc(nr_items, sizeof *items);
for (size_t i = 0; i < nr_items; i++) {
struct compile_value *item = compile_pop_value(ctx);
items[i] = item;
}
compile_push_value_array(ctx, &fstring_type, src, items, nr_items);
return COMPILE_OK(0);
}
+40
View File
@@ -0,0 +1,40 @@
#include "compile-node.h"
static const struct compile_value_type hashtable_type = {};
static const struct compile_value_type hashtable_item_type = {};
struct compile_result compile_hashtable(
struct compile_ctx *ctx,
struct bshell_ast_node *src)
{
struct bshell_hashtable_ast_node *hashtable
= (struct bshell_hashtable_ast_node *)src;
size_t nr_items = fx_queue_length(&hashtable->n_items);
for (size_t i = 0; i < nr_items; i++) {
struct compile_value *item = compile_pop_value(ctx);
compile_value_load(ctx, item);
compile_value_destroy(item);
}
bshell_scriptblock_push_instruction(
ctx->c_block,
BSHELL_OPCODE_MK_HTAB,
nr_items);
compile_push_value(ctx, &hashtable_type, src);
return COMPILE_OK(0);
}
struct compile_result compile_hashtable_item(
struct compile_ctx *ctx,
struct bshell_ast_node *src)
{
struct compile_value *value = compile_pop_value(ctx);
struct compile_value *key = compile_pop_value(ctx);
compile_value_load(ctx, key);
compile_value_load(ctx, value);
compile_value_destroy(key);
compile_value_destroy(value);
compile_push_value(ctx, &hashtable_item_type, src);
return COMPILE_OK(0);
}
+79
View File
@@ -0,0 +1,79 @@
#include "compile-node.h"
enum bshell_status compile_if(
struct compile_ctx *ctx,
struct bshell_ast_node *src)
{
struct bshell_if_ast_node *if_group;
if_group = (struct bshell_if_ast_node *)src;
size_t nr_labels = fx_queue_length(&if_group->n_branches);
// add one extra label for the end of the if group
nr_labels++;
size_t *label_ids = calloc(nr_labels, sizeof *label_ids);
if (!label_ids) {
return BSHELL_ERR_NO_MEMORY;
}
size_t i;
for (i = 0; i < nr_labels; i++) {
label_ids[i] = compile_declare_label(ctx);
}
i = 0;
fx_queue_entry *cur = fx_queue_first(&if_group->n_branches);
while (cur) {
struct bshell_if_branch_ast_node *branch;
branch = fx_unbox(
struct bshell_if_branch_ast_node,
cur,
n_base.n_entry);
if (!branch->n_cond) {
compile_block_immediate(ctx, branch->n_body);
compile_ref_label(ctx, label_ids[nr_labels - 1]);
bshell_scriptblock_push_instruction(
ctx->c_block,
BSHELL_OPCODE_BR,
0);
break;
}
compile_expression(ctx, branch->n_cond);
compile_ref_label(ctx, label_ids[i++]);
bshell_scriptblock_push_instruction(
ctx->c_block,
BSHELL_OPCODE_BR_TRUE,
0);
cur = fx_queue_next(cur);
}
i = 0;
cur = fx_queue_first(&if_group->n_branches);
while (cur) {
struct bshell_if_branch_ast_node *branch = fx_unbox(
struct bshell_if_branch_ast_node,
cur,
n_base.n_entry);
if (!branch->n_cond) {
break;
}
compile_define_label(ctx, label_ids[i++]);
compile_block_immediate(ctx, branch->n_body);
cur = fx_queue_next(cur);
if (i < nr_labels - 2) {
compile_ref_label(ctx, label_ids[nr_labels - 1]);
bshell_scriptblock_push_instruction(
ctx->c_block,
BSHELL_OPCODE_BR,
0);
}
}
compile_define_label(ctx, label_ids[nr_labels - 1]);
free(label_ids);
return BSHELL_SUCCESS;
}
+67
View File
@@ -0,0 +1,67 @@
#include "compile-node.h"
size_t compile_declare_label(struct compile_ctx *ctx)
{
size_t id = ctx->c_labels.count;
struct compile_label *label = fx_vector_emplace_back(
ctx->c_labels,
NULL);
return id;
}
void compile_define_label(struct compile_ctx *ctx, size_t label_id)
{
size_t offset = 0;
bshell_scriptblock_get_text(ctx->c_block, NULL, &offset);
offset *= sizeof(bshell_instruction);
ctx->c_labels.items[label_id].l_ip = offset;
}
void compile_ref_label(struct compile_ctx *ctx, size_t label_id)
{
struct compile_label_ref *ref = malloc(sizeof *ref);
if (!ref) {
return;
}
memset(ref, 0x0, sizeof *ref);
ref->ref_label_id = label_id;
bshell_scriptblock_get_text(ctx->c_block, NULL, &ref->ref_offset);
ref->ref_offset *= sizeof(bshell_instruction);
fx_queue_push_back(&ctx->c_label_refs, &ref->ref_entry);
}
enum bshell_status compile_resolve_labels(struct compile_ctx *ctx)
{
fx_queue_entry *cur = fx_queue_pop_front(&ctx->c_label_refs);
while (cur) {
struct compile_label_ref *ref = fx_unbox(
struct compile_label_ref,
cur,
ref_entry);
struct compile_label *label = &ctx->c_labels.items
[ref->ref_label_id];
long long rel_value = (long long)label->l_ip
- (long long)ref->ref_offset;
enum bshell_opcode op;
uint32_t arg;
bshell_scriptblock_read_instruction(
ctx->c_block,
ref->ref_offset,
&op,
&arg);
arg = (uint32_t)rel_value;
bshell_scriptblock_patch_instruction(
ctx->c_block,
ref->ref_offset,
op,
arg);
free(ref);
cur = fx_queue_pop_front(&ctx->c_label_refs);
}
return BSHELL_SUCCESS;
}
+25
View File
@@ -0,0 +1,25 @@
#include "compile-node.h"
static const compile_node_impl node_compilers[] = {
[BSHELL_AST_INT] = compile_int,
[BSHELL_AST_DOUBLE] = compile_double,
[BSHELL_AST_STRING] = compile_string,
[BSHELL_AST_WORD] = compile_word,
[BSHELL_AST_OP] = compile_op,
[BSHELL_AST_VAR] = compile_var,
[BSHELL_AST_FSTRING] = compile_fstring,
[BSHELL_AST_ARRAY] = compile_array,
[BSHELL_AST_HASHTABLE] = compile_hashtable,
[BSHELL_AST_HASHTABLE_ITEM] = compile_hashtable_item,
[BSHELL_AST_CMDCALL] = compile_cmdcall,
[BSHELL_AST_PIPELINE] = compile_pipeline,
[BSHELL_AST_BLOCK] = compile_block,
};
static const size_t nr_node_compilers = sizeof node_compilers
/ sizeof node_compilers[0];
const struct compile_state_type normal_state = {
.s_size = sizeof(struct compile_state),
.s_compile_node = node_compilers,
.s_nr_compile_node = nr_node_compilers,
};
+126
View File
@@ -0,0 +1,126 @@
#include "compile-node.h"
#include <bshell/runtime/operator.h>
static enum bshell_opcode opcode_for_op(enum bshell_operator_id op)
{
switch (op) {
case BSHELL_OP_ADD:
return BSHELL_OPCODE_ADD;
case BSHELL_OP_SUBTRACT:
return BSHELL_OPCODE_SUB;
case BSHELL_OP_MULTIPLY:
return BSHELL_OPCODE_MUL;
case BSHELL_OP_DIVIDE:
return BSHELL_OPCODE_DIV;
case BSHELL_OP_MODULO:
return BSHELL_OPCODE_MOD;
case BSHELL_OP_INCREMENT:
return BSHELL_OPCODE_INC;
case BSHELL_OP_DECREMENT:
return BSHELL_OPCODE_DEC;
case BSHELL_OP_LEFT_SHIFT:
return BSHELL_OPCODE_SHL;
case BSHELL_OP_RIGHT_SHIFT:
return BSHELL_OPCODE_SHR;
case BSHELL_OP_BINARY_AND:
return BSHELL_OPCODE_BAND;
case BSHELL_OP_BINARY_OR:
return BSHELL_OPCODE_BOR;
case BSHELL_OP_BINARY_XOR:
return BSHELL_OPCODE_BXOR;
case BSHELL_OP_BINARY_NOT:
return BSHELL_OPCODE_BNOT;
case BSHELL_OP_LESS_THAN:
return BSHELL_OPCODE_CMP_LT;
case BSHELL_OP_GREATER_THAN:
return BSHELL_OPCODE_CMP_GT;
case BSHELL_OP_EQUAL:
return BSHELL_OPCODE_CMP_EQ;
case BSHELL_OP_NOT_EQUAL:
return BSHELL_OPCODE_CMP_NE;
case BSHELL_OP_LESS_EQUAL:
return BSHELL_OPCODE_CMP_LE;
case BSHELL_OP_GREATER_EQUAL:
return BSHELL_OPCODE_CMP_GE;
case BSHELL_OP_LOGICAL_AND:
return BSHELL_OPCODE_LAND;
case BSHELL_OP_LOGICAL_OR:
return BSHELL_OPCODE_LOR;
case BSHELL_OP_LOGICAL_XOR:
return BSHELL_OPCODE_LXOR;
case BSHELL_OP_LOGICAL_NOT:
return BSHELL_OPCODE_LNOT;
case BSHELL_OP_RANGE:
return BSHELL_OPCODE_RANGE;
case BSHELL_OP_MATCH:
return BSHELL_OPCODE_MATCH;
case BSHELL_OP_REPLACE:
return BSHELL_OPCODE_REPLACE;
case BSHELL_OP_LIKE:
return BSHELL_OPCODE_LIKE;
case BSHELL_OP_IN:
return BSHELL_OPCODE_IN;
case BSHELL_OP_FORMAT:
return BSHELL_OPCODE_FMT;
case BSHELL_OP_CONTAINS:
return BSHELL_OPCODE_CONTAINS;
case BSHELL_OP_USPLIT:
return BSHELL_OPCODE_SPLIT;
case BSHELL_OP_BSPLIT:
return BSHELL_OPCODE_SPLIT;
case BSHELL_OP_UJOIN:
return BSHELL_OPCODE_JOIN;
case BSHELL_OP_BJOIN:
return BSHELL_OPCODE_JOIN;
case BSHELL_OP_IS:
return BSHELL_OPCODE_IS;
case BSHELL_OP_AS:
return BSHELL_OPCODE_AS;
case BSHELL_OP_ACCESS:
return BSHELL_OPCODE_LDPROP;
default:
return BSHELL_OPCODE_NOP;
}
}
enum bshell_status op_load(struct compile_ctx *ctx, struct compile_value *value)
{
enum bshell_opcode opcode = opcode_for_op(value->v_op);
if (opcode != BSHELL_OPCODE_NOP) {
compile_value_load(ctx, value->v_right);
compile_value_load(ctx, value->v_left);
bshell_scriptblock_push_instruction(
ctx->c_block,
opcode_for_op(value->v_op),
0);
return BSHELL_SUCCESS;
}
switch (value->v_op) {
case BSHELL_OP_ASSIGN:
compile_value_load(ctx, value->v_right);
compile_value_store(ctx, value->v_left);
break;
default:
return BSHELL_ERR_NOT_SUPPORTED;
}
return BSHELL_SUCCESS;
}
static const struct compile_value_type op_type = {
.v_load = op_load,
};
struct compile_result compile_op(
struct compile_ctx *ctx,
struct bshell_ast_node *src)
{
struct bshell_op_ast_node *op = (struct bshell_op_ast_node *)src;
struct compile_value *left = NULL, *right = NULL;
left = compile_pop_value(ctx);
right = compile_pop_value(ctx);
compile_push_op(ctx, src, &op_type, op->n_op->op_id, left, right);
return COMPILE_OK(0);
}
+132
View File
@@ -0,0 +1,132 @@
#include "compile-node.h"
enum bshell_status compile_push_value(
struct compile_ctx *ctx,
const struct compile_value_type *type,
struct bshell_ast_node *node)
{
struct compile_value *item = malloc(sizeof *item);
if (!item) {
return BSHELL_ERR_NO_MEMORY;
}
memset(item, 0x0, sizeof *item);
item->v_type = type;
item->v_node = node;
fx_queue_push_back(&ctx->c_stack, &item->v_entry);
return BSHELL_SUCCESS;
}
enum bshell_status compile_push_value_array(
struct compile_ctx *ctx,
const struct compile_value_type *type,
struct bshell_ast_node *node,
struct compile_value **values,
size_t nr_values)
{
struct compile_value *item = malloc(sizeof *item);
if (!item) {
return BSHELL_ERR_NO_MEMORY;
}
memset(item, 0x0, sizeof *item);
item->v_type = type;
item->v_node = node;
item->v_args = values;
item->v_nr_args = nr_values;
fx_queue_push_back(&ctx->c_stack, &item->v_entry);
return BSHELL_SUCCESS;
}
enum bshell_status compile_push_pool_value(
struct compile_ctx *ctx,
const struct compile_value_type *type,
unsigned long pool_slot)
{
struct compile_value *item = malloc(sizeof *item);
if (!item) {
return BSHELL_ERR_NO_MEMORY;
}
memset(item, 0x0, sizeof *item);
item->v_type = type;
item->v_pool = pool_slot;
fx_queue_push_back(&ctx->c_stack, &item->v_entry);
return BSHELL_SUCCESS;
}
enum bshell_status compile_push_op(
struct compile_ctx *ctx,
struct bshell_ast_node *node,
const struct compile_value_type *type,
enum bshell_operator_id op,
struct compile_value *left,
struct compile_value *right)
{
struct compile_value *item = malloc(sizeof *item);
if (!item) {
return BSHELL_ERR_NO_MEMORY;
}
memset(item, 0x0, sizeof *item);
item->v_type = type;
item->v_node = node;
item->v_op = op;
item->v_left = left;
item->v_right = right;
fx_queue_push_back(&ctx->c_stack, &item->v_entry);
return BSHELL_SUCCESS;
}
struct compile_value *compile_pop_value(struct compile_ctx *ctx)
{
fx_queue_entry *entry = fx_queue_pop_back(&ctx->c_stack);
if (!entry) {
return NULL;
}
return fx_unbox(struct compile_value, entry, v_entry);
}
void compile_value_load(struct compile_ctx *ctx, struct compile_value *item)
{
if (item->v_type->v_load) {
item->v_type->v_load(ctx, item);
}
}
void compile_value_store(struct compile_ctx *ctx, struct compile_value *item)
{
if (item->v_type->v_store) {
item->v_type->v_store(ctx, item);
}
}
void compile_value_destroy(struct compile_value *value)
{
if (value->v_left) {
compile_value_destroy(value->v_left);
}
if (value->v_right) {
compile_value_destroy(value->v_right);
}
for (size_t i = 0; i < value->v_nr_args; i++) {
compile_value_destroy(value->v_args[i]);
}
if (value->v_args) {
free(value->v_args);
}
free(value);
}
+66
View File
@@ -0,0 +1,66 @@
#include "compile-node.h"
extern const struct compile_state_type normal_state;
static const struct compile_state_type *state_types[] = {
[COMPILE_NORMAL] = &normal_state,
};
static const size_t nr_state_types = sizeof state_types / sizeof state_types[0];
struct compile_state *compile_push_state(
struct compile_ctx *ctx,
enum compile_state_type_id state_type_id)
{
if (state_type_id >= nr_state_types) {
return NULL;
}
const struct compile_state_type *state_type = state_types
[state_type_id];
if (!state_type) {
return NULL;
}
struct compile_state *state = malloc(state_type->s_size);
if (!state) {
return NULL;
}
state->s_type = state_type;
state->s_depth = ctx->c_depth;
fx_queue_push_back(&ctx->c_state, &state->s_entry);
if (state_type->s_compile_begin) {
state_type->s_compile_begin(ctx);
}
return state;
}
void compile_pop_state(struct compile_ctx *ctx)
{
struct compile_state *state = compile_get_state(ctx);
if (!state) {
return;
}
if (!fx_queue_prev(&state->s_entry)) {
return;
}
if (state->s_type->s_compile_end) {
state->s_type->s_compile_end(ctx);
}
fx_queue_pop_back(&ctx->c_state);
free(state);
}
struct compile_state *compile_get_state(const struct compile_ctx *ctx)
{
fx_queue_entry *entry = fx_queue_last(&ctx->c_state);
if (!entry) {
return NULL;
}
return fx_unbox(struct compile_state, entry, s_entry);
}
+54
View File
@@ -0,0 +1,54 @@
#include "compile-node.h"
enum bshell_status var_load(
struct compile_ctx *ctx,
struct compile_value *value)
{
struct bshell_var_ast_node *var
= (struct bshell_var_ast_node *)value->v_node;
unsigned long index = bshell_scriptblock_get_string(
ctx->c_block,
var->n_ident->tok_str);
if (index == POOL_INDEX_INVALID) {
return BSHELL_ERR_NO_MEMORY;
}
bshell_scriptblock_push_instruction(
ctx->c_block,
BSHELL_OPCODE_LDLOCAL,
index);
return BSHELL_SUCCESS;
}
enum bshell_status var_store(
struct compile_ctx *ctx,
struct compile_value *value)
{
struct bshell_var_ast_node *var
= (struct bshell_var_ast_node *)value->v_node;
unsigned long index = bshell_scriptblock_get_string(
ctx->c_block,
var->n_ident->tok_str);
if (index == POOL_INDEX_INVALID) {
return BSHELL_ERR_NO_MEMORY;
}
bshell_scriptblock_push_instruction(
ctx->c_block,
BSHELL_OPCODE_STLOCAL,
index);
return BSHELL_SUCCESS;
}
static const struct compile_value_type var_type = {
.v_load = var_load,
.v_store = var_store,
};
struct compile_result compile_var(
struct compile_ctx *ctx,
struct bshell_ast_node *src)
{
compile_push_value(ctx, &var_type, src);
return COMPILE_OK(0);
}