bshell: implement bytecode generation for arithmetic expressions and if-statements

This commit is contained in:
2026-05-17 15:33:44 +01:00
parent 2cee984092
commit 0e8dc9cb6f
17 changed files with 1101 additions and 0 deletions
+12
View File
@@ -0,0 +1,12 @@
#ifndef COMPILE_H_
#define COMPILE_H_
#include "script-block.h"
struct ast_node;
extern enum bshell_status bshell_compile(
struct ast_node *src,
bshell_scriptblock *dest);
#endif
+13
View File
@@ -0,0 +1,13 @@
#include "compile-node.h"
struct compile_result compile_array(
struct compile_ctx *ctx,
struct ast_node *src)
{
struct array_ast_node *array = (struct array_ast_node *)src;
bshell_scriptblock_push_instruction(
ctx->c_block,
OPCODE_MK_ARRAY,
fx_queue_length(&array->n_items));
return COMPILE_OK(0);
}
+61
View File
@@ -0,0 +1,61 @@
#include "../compile.h"
#include "compile-node.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,
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 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 ast_node *src)
{
enum bshell_status status = BSHELL_SUCCESS;
struct block_ast_node *block = (struct block_ast_node *)src;
fx_queue_entry *cur = fx_queue_first(&block->n_statements);
while (cur && status == BSHELL_SUCCESS) {
struct ast_node *node = fx_unbox(struct ast_node, cur, n_entry);
status = compile_node(ctx, node);
cur = fx_queue_next(cur);
}
return status;
}
+72
View File
@@ -0,0 +1,72 @@
#include "compile-node.h"
enum bshell_status cmdcall_load(
struct compile_ctx *ctx,
struct compile_value *value)
{
struct cmdcall_ast_node *cmdcall = (struct cmdcall_ast_node *)
value->v_node;
bshell_scriptblock_push_instruction(ctx->c_block, OPCODE_PEXEC, 1);
return BSHELL_SUCCESS;
}
enum bshell_status pipeline_load(
struct compile_ctx *ctx,
struct compile_value *value)
{
struct pipeline_ast_node *pipeline = (struct pipeline_ast_node *)
value->v_node;
size_t nr_items = fx_queue_length(&pipeline->n_stages);
bshell_scriptblock_push_instruction(
ctx->c_block,
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 ast_node *src)
{
struct cmdcall_ast_node *cmdcall = (struct 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,
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 ast_node *src)
{
struct pipeline_ast_node *pipeline = (struct 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 != AST_CMDCALL) {
compile_value_load(ctx, item);
}
compile_value_destroy(item);
}
compile_push_value(ctx, &pipeline_type, src);
return COMPILE_OK(0);
}
+175
View File
@@ -0,0 +1,175 @@
#ifndef COMPILE_COMPILE_NODE_H_
#define COMPILE_COMPILE_NODE_H_
#include "../ast/ast.h"
#include "../operator.h"
#include "../parse/token.h"
#include "../script-block.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 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 operator_id v_op;
struct compile_value *v_left, *v_right;
struct 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 ast_node *node);
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,
const struct compile_value_type *type,
enum 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 ast_node *src);
extern struct compile_result compile_string(
struct compile_ctx *ctx,
struct ast_node *src);
extern struct compile_result compile_word(
struct compile_ctx *ctx,
struct ast_node *src);
extern struct compile_result compile_op(
struct compile_ctx *ctx,
struct ast_node *src);
extern struct compile_result compile_var(
struct compile_ctx *ctx,
struct ast_node *src);
extern struct compile_result compile_fstring(
struct compile_ctx *ctx,
struct ast_node *src);
extern struct compile_result compile_array(
struct compile_ctx *ctx,
struct ast_node *src);
extern struct compile_result compile_hashtable_item(
struct compile_ctx *ctx,
struct ast_node *src);
extern struct compile_result compile_hashtable(
struct compile_ctx *ctx,
struct ast_node *src);
extern struct compile_result compile_block(
struct compile_ctx *ctx,
struct ast_node *src);
extern struct compile_result compile_cmdcall(
struct compile_ctx *ctx,
struct ast_node *src);
extern struct compile_result compile_pipeline(
struct compile_ctx *ctx,
struct ast_node *src);
extern enum bshell_status compile_if(
struct compile_ctx *ctx,
struct ast_node *src);
extern enum bshell_status compile_block_immediate(
struct compile_ctx *ctx,
struct ast_node *src);
extern enum bshell_status compile_expression(
struct compile_ctx *ctx,
struct ast_node *src);
extern enum bshell_status compile_node(
struct compile_ctx *ctx,
struct ast_node *src);
#endif
+43
View File
@@ -0,0 +1,43 @@
#include "../compile.h"
#include "../ast/ast.h"
#include "../debug.h"
#include "../status.h"
#include "compile-node.h"
#include <stdio.h>
extern enum bshell_status compile_node(
struct compile_ctx *ctx,
struct ast_node *src)
{
switch (src->n_type) {
case AST_IF:
return compile_if(ctx, src);
case AST_BLOCK:
return compile_block_immediate(ctx, src);
default:
return compile_expression(ctx, src);
}
return BSHELL_SUCCESS;
}
enum bshell_status bshell_compile(
struct 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;
}
+85
View File
@@ -0,0 +1,85 @@
#include "compile-node.h"
enum bshell_status int_load(
struct compile_ctx *ctx,
struct compile_value *value)
{
struct int_ast_node *i = (struct int_ast_node *)value->v_node;
bshell_scriptblock_push_instruction(
ctx->c_block,
OPCODE_LDC_INT,
i->n_value->tok_int);
return BSHELL_SUCCESS;
}
enum bshell_status string_load(
struct compile_ctx *ctx,
struct compile_value *value)
{
struct string_ast_node *s = (struct 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,
OPCODE_LDC_STR,
index);
return BSHELL_SUCCESS;
}
enum bshell_status word_load(
struct compile_ctx *ctx,
struct compile_value *value)
{
struct word_ast_node *s = (struct 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,
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 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 ast_node *src)
{
compile_push_value(ctx, &int_type, src);
return COMPILE_OK(0);
}
struct compile_result compile_string(
struct compile_ctx *ctx,
struct ast_node *src)
{
compile_push_value(ctx, &string_type, src);
return COMPILE_OK(0);
}
struct compile_result compile_word(
struct compile_ctx *ctx,
struct ast_node *src)
{
compile_push_value(ctx, &word_type, src);
return COMPILE_OK(0);
}
+72
View File
@@ -0,0 +1,72 @@
#include "compile-node.h"
static struct ast_iterate_result do_compile_node(
struct ast_node *node,
enum ast_iteration_type it_type,
struct ast_iterator *it,
struct compile_ctx *ctx)
{
if (it_type != AST_ITERATION_POST) {
int flags = 0;
switch (node->n_type) {
case AST_BLOCK:
break;
default:
flags |= AST_ITERATE_ADD_CHILDREN;
break;
}
return 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 AST_ITERATE_OK(0);
}
struct compile_result result = impl(ctx, node);
unsigned int flags = 0;
if (result.r_flags & COMPILE_REPEAT_NODE) {
flags |= AST_ITERATE_REPEAT;
}
if (result.r_status == BSHELL_SUCCESS) {
return AST_ITERATE_OK(flags);
}
return AST_ITERATE_ERR(result.r_status);
}
enum bshell_status compile_expression(
struct compile_ctx *ctx,
struct ast_node *src)
{
compile_push_state(ctx, COMPILE_NORMAL);
struct ast_iterator it = {0};
ast_node_iterate(src, &it, (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;
}
+35
View File
@@ -0,0 +1,35 @@
#include "compile-node.h"
enum bshell_status fstring_load(
struct compile_ctx *ctx,
struct compile_value *value)
{
struct fstring_ast_node *fstring = (struct fstring_ast_node *)
value->v_node;
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 ast_node *src)
{
struct fstring_ast_node *fstring = (struct fstring_ast_node *)src;
size_t nr_items = fx_queue_length(&fstring->n_elements);
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,
OPCODE_MK_STR,
fx_queue_length(&fstring->n_elements));
compile_push_value(ctx, &fstring_type, src);
return COMPILE_OK(0);
}
+39
View File
@@ -0,0 +1,39 @@
#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 ast_node *src)
{
struct hashtable_ast_node *hashtable = (struct 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,
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 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);
}
+75
View File
@@ -0,0 +1,75 @@
#include "compile-node.h"
enum bshell_status compile_if(struct compile_ctx *ctx, struct ast_node *src)
{
struct if_ast_node *if_group = (struct 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 if_branch_ast_node *branch = fx_unbox(
struct 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,
OPCODE_BR,
0);
break;
}
compile_expression(ctx, branch->n_cond);
compile_ref_label(ctx, label_ids[i++]);
bshell_scriptblock_push_instruction(
ctx->c_block,
OPCODE_BR_TRUE,
0);
cur = fx_queue_next(cur);
}
i = 0;
cur = fx_queue_first(&if_group->n_branches);
while (cur) {
struct if_branch_ast_node *branch = fx_unbox(
struct 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,
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;
}
+24
View File
@@ -0,0 +1,24 @@
#include "compile-node.h"
static const compile_node_impl node_compilers[] = {
[AST_INT] = compile_int,
[AST_STRING] = compile_string,
[AST_WORD] = compile_word,
[AST_OP] = compile_op,
[AST_VAR] = compile_var,
[AST_FSTRING] = compile_fstring,
[AST_ARRAY] = compile_array,
[AST_HASHTABLE] = compile_hashtable,
[AST_HASHTABLE_ITEM] = compile_hashtable_item,
[AST_CMDCALL] = compile_cmdcall,
[AST_PIPELINE] = compile_pipeline,
[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,
};
+121
View File
@@ -0,0 +1,121 @@
#include "../operator.h"
#include "compile-node.h"
static enum bshell_opcode opcode_for_op(enum operator_id op)
{
switch (op) {
case OP_ADD:
return OPCODE_ADD;
case OP_SUBTRACT:
return OPCODE_SUB;
case OP_MULTIPLY:
return OPCODE_MUL;
case OP_DIVIDE:
return OPCODE_DIV;
case OP_MODULO:
return OPCODE_MOD;
case OP_INCREMENT:
return OPCODE_INC;
case OP_DECREMENT:
return OPCODE_DEC;
case OP_LEFT_SHIFT:
return OPCODE_SHL;
case OP_RIGHT_SHIFT:
return OPCODE_SHR;
case OP_BINARY_AND:
return OPCODE_BAND;
case OP_BINARY_OR:
return OPCODE_BOR;
case OP_BINARY_XOR:
return OPCODE_BXOR;
case OP_BINARY_NOT:
return OPCODE_BNOT;
case OP_LESS_THAN:
return OPCODE_CMP_LT;
case OP_GREATER_THAN:
return OPCODE_CMP_GT;
case OP_EQUAL:
return OPCODE_CMP_EQ;
case OP_NOT_EQUAL:
return OPCODE_CMP_NE;
case OP_LESS_EQUAL:
return OPCODE_CMP_LE;
case OP_GREATER_EQUAL:
return OPCODE_CMP_GE;
case OP_LOGICAL_AND:
return OPCODE_LAND;
case OP_LOGICAL_OR:
return OPCODE_LOR;
case OP_LOGICAL_XOR:
return OPCODE_LXOR;
case OP_LOGICAL_NOT:
return OPCODE_LNOT;
case OP_RANGE:
return OPCODE_RANGE;
case OP_MATCH:
return OPCODE_MATCH;
case OP_REPLACE:
return OPCODE_REPLACE;
case OP_LIKE:
return OPCODE_LIKE;
case OP_IN:
return OPCODE_IN;
case OP_FORMAT:
return OPCODE_FMT;
case OP_CONTAINS:
return OPCODE_CONTAINS;
case OP_USPLIT:
return OPCODE_SPLIT;
case OP_BSPLIT:
return OPCODE_SPLIT;
case OP_UJOIN:
return OPCODE_JOIN;
case OP_BJOIN:
return OPCODE_JOIN;
case OP_IS:
return OPCODE_IS;
case OP_AS:
return OPCODE_AS;
default:
return 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 != 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 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 ast_node *src)
{
struct op_ast_node *op = (struct op_ast_node *)src;
struct compile_value *left = NULL, *right = NULL;
right = compile_pop_value(ctx);
left = compile_pop_value(ctx);
compile_push_op(ctx, &op_type, op->n_op->op_id, left, right);
return COMPILE_OK(0);
}
+91
View File
@@ -0,0 +1,91 @@
#include "compile-node.h"
enum bshell_status compile_push_value(
struct compile_ctx *ctx,
const struct compile_value_type *type,
struct 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_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,
const struct compile_value_type *type,
enum 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_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)
{
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);
}
+50
View File
@@ -0,0 +1,50 @@
#include "compile-node.h"
enum bshell_status var_load(
struct compile_ctx *ctx,
struct compile_value *value)
{
struct var_ast_node *var = (struct 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,
OPCODE_LDLOCAL,
index);
return BSHELL_SUCCESS;
}
enum bshell_status var_store(
struct compile_ctx *ctx,
struct compile_value *value)
{
struct var_ast_node *var = (struct 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,
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 ast_node *src)
{
compile_push_value(ctx, &var_type, src);
return COMPILE_OK(0);
}