#include #include #include #include #include // While or for loops gen_res_t gen_loop(fzl_gen_t *gen, fzl_node_t *node) { if (!gen || !node) return gen_error; fzl_gen_ctx_t *ctx = gen_ctx(gen, FZL_GEN_CTX_TYPE_LOOP, node); if (!ctx) return gen_error; gen_op(gen, FZL_OPCODE_MK_ENVTABLE); if (node->loop.init) if (gen_common(gen, node->loop.init).error) return gen_error; size_t start_ip = gen->ops_count; if (node->loop.cond) { if (gen_common(gen, node->loop.cond).error) return gen_error; } else { gen_op(gen, FZL_OPCODE_PUSHNUM); gen_word(gen, 1); } gen_op(gen, FZL_OPCODE_JZ); ctx->loop.breaks[ctx->loop.breaks_count++] = gen->ops_count; gen_word(gen, 0); if (gen_common(gen, node->loop.body).error) return gen_error; if (node->loop.step) if (gen_common(gen, node->loop.step).error) return gen_error; gen_op(gen, FZL_OPCODE_JMP); gen_word(gen, start_ip); // backpatch `break`s for (size_t i = 0; i < ctx->loop.breaks_count; i++) gen->ops[ctx->loop.breaks[i]] = gen->ops_count; gen_op(gen, FZL_OPCODE_RM_ENVTABLE); for (size_t i = gen->syms_top - 1; i > ctx->level; i--) fzl_freesymt(gen->syms[--gen->syms_top]); ctx = gen_fin_ctx(gen); if (!ctx) return gen_error; return gen_ok_null; }