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