Files
bshell/bshell.runtime/compile/if.c
T
wash edfb3e24a3 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
2026-05-25 10:33:29 +01:00

80 lines
1.8 KiB
C

#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;
}