diff options
| author | Bruce Hill <bruce@bruce-hill.com> | 2025-08-24 19:34:13 -0400 |
|---|---|---|
| committer | Bruce Hill <bruce@bruce-hill.com> | 2025-08-24 19:34:13 -0400 |
| commit | 7a69fe78adcc6abc596e6b1386cded7c57da67e1 (patch) | |
| tree | 2b317e863c018eef69995660ef22e8dd0a97031d /src | |
| parent | 92a5cf818d0345bed5d04a30ff87ffd94f46eb84 (diff) | |
Move while/repeat/skip/stop into loops file
Diffstat (limited to 'src')
| -rw-r--r-- | src/compile/forloops.h | 8 | ||||
| -rw-r--r-- | src/compile/loops.c (renamed from src/compile/forloops.c) | 90 | ||||
| -rw-r--r-- | src/compile/loops.h | 12 | ||||
| -rw-r--r-- | src/compile/statements.c | 87 |
4 files changed, 106 insertions, 91 deletions
diff --git a/src/compile/forloops.h b/src/compile/forloops.h deleted file mode 100644 index 51c57c92..00000000 --- a/src/compile/forloops.h +++ /dev/null @@ -1,8 +0,0 @@ -// This file defines how to compile `for` loops -#pragma once - -#include "../ast.h" -#include "../environment.h" -#include "../stdlib/datatypes.h" - -Text_t compile_for_loop(env_t *env, ast_t *ast); diff --git a/src/compile/forloops.c b/src/compile/loops.c index 4cb44b32..6adb6700 100644 --- a/src/compile/forloops.c +++ b/src/compile/loops.c @@ -1,4 +1,4 @@ -// This file defines how to compile `for` loops +// This file defines how to compile loops #include <gmp.h> @@ -20,6 +20,7 @@ #include "statements.h" #include "types.h" +public Text_t compile_for_loop(env_t *env, ast_t *ast) { DeclareMatch(for_, ast, For); @@ -365,3 +366,90 @@ Text_t compile_for_loop(env_t *env, ast_t *ast) { default: code_err(for_->iter, "Iteration is not implemented for type: ", type_to_str(iter_t)); } } + +public +Text_t compile_repeat(env_t *env, ast_t *ast) { + ast_t *body = Match(ast, Repeat)->body; + env_t *scope = fresh_scope(env); + loop_ctx_t loop_ctx = (loop_ctx_t){ + .loop_name = "repeat", + .deferred = scope->deferred, + .next = env->loop_ctx, + }; + scope->loop_ctx = &loop_ctx; + Text_t body_code = compile_statement(scope, body); + if (loop_ctx.skip_label.length > 0) body_code = Texts(body_code, "\n", loop_ctx.skip_label, ": continue;"); + Text_t loop = Texts("for (;;) {\n\t", body_code, "\n}"); + if (loop_ctx.stop_label.length > 0) loop = Texts(loop, "\n", loop_ctx.stop_label, ":;"); + return loop; +} + +public +Text_t compile_while(env_t *env, ast_t *ast) { + DeclareMatch(while_, ast, While); + env_t *scope = fresh_scope(env); + loop_ctx_t loop_ctx = (loop_ctx_t){ + .loop_name = "while", + .deferred = scope->deferred, + .next = env->loop_ctx, + }; + scope->loop_ctx = &loop_ctx; + Text_t body = compile_statement(scope, while_->body); + if (loop_ctx.skip_label.length > 0) body = Texts(body, "\n", loop_ctx.skip_label, ": continue;"); + Text_t loop = + Texts("while (", while_->condition ? compile(scope, while_->condition) : Text("yes"), ") {\n\t", body, "\n}"); + if (loop_ctx.stop_label.length > 0) loop = Texts(loop, "\n", loop_ctx.stop_label, ":;"); + return loop; +} + +public +Text_t compile_skip(env_t *env, ast_t *ast) { + const char *target = Match(ast, Skip)->target; + for (loop_ctx_t *ctx = env->loop_ctx; ctx; ctx = ctx->next) { + bool matched = !target || strcmp(target, ctx->loop_name) == 0; + for (ast_list_t *var = ctx->loop_vars; var && !matched; var = var ? var->next : NULL) + matched = (strcmp(target, Match(var->ast, Var)->name) == 0); + + if (matched) { + if (ctx->skip_label.length == 0) { + static int64_t skip_label_count = 1; + ctx->skip_label = Texts("skip_", String(skip_label_count)); + ++skip_label_count; + } + Text_t code = EMPTY_TEXT; + for (deferral_t *deferred = env->deferred; deferred && deferred != ctx->deferred; deferred = deferred->next) + code = Texts(code, compile_statement(deferred->defer_env, deferred->block)); + if (code.length > 0) return Texts("{\n", code, "goto ", ctx->skip_label, ";\n}\n"); + else return Texts("goto ", ctx->skip_label, ";"); + } + } + if (env->loop_ctx) code_err(ast, "This is not inside any loop"); + else if (target) code_err(ast, "No loop target named '", target, "' was found"); + else return Text("continue;"); +} + +public +Text_t compile_stop(env_t *env, ast_t *ast) { + const char *target = Match(ast, Stop)->target; + for (loop_ctx_t *ctx = env->loop_ctx; ctx; ctx = ctx->next) { + bool matched = !target || strcmp(target, ctx->loop_name) == 0; + for (ast_list_t *var = ctx->loop_vars; var && !matched; var = var ? var->next : var) + matched = (strcmp(target, Match(var->ast, Var)->name) == 0); + + if (matched) { + if (ctx->stop_label.length == 0) { + static int64_t stop_label_count = 1; + ctx->stop_label = Texts("stop_", String(stop_label_count)); + ++stop_label_count; + } + Text_t code = EMPTY_TEXT; + for (deferral_t *deferred = env->deferred; deferred && deferred != ctx->deferred; deferred = deferred->next) + code = Texts(code, compile_statement(deferred->defer_env, deferred->block)); + if (code.length > 0) return Texts("{\n", code, "goto ", ctx->stop_label, ";\n}\n"); + else return Texts("goto ", ctx->stop_label, ";"); + } + } + if (env->loop_ctx) code_err(ast, "This is not inside any loop"); + else if (target) code_err(ast, "No loop target named '", target, "' was found"); + else return Text("break;"); +} diff --git a/src/compile/loops.h b/src/compile/loops.h new file mode 100644 index 00000000..762c72f0 --- /dev/null +++ b/src/compile/loops.h @@ -0,0 +1,12 @@ +// This file defines how to compile loops +#pragma once + +#include "../ast.h" +#include "../environment.h" +#include "../stdlib/datatypes.h" + +Text_t compile_for_loop(env_t *env, ast_t *ast); +Text_t compile_repeat(env_t *env, ast_t *ast); +Text_t compile_while(env_t *env, ast_t *ast); +Text_t compile_skip(env_t *env, ast_t *ast); +Text_t compile_stop(env_t *env, ast_t *ast); diff --git a/src/compile/statements.c b/src/compile/statements.c index 3ba560d2..bccec75d 100644 --- a/src/compile/statements.c +++ b/src/compile/statements.c @@ -21,8 +21,8 @@ #include "declarations.h" #include "doctests.h" #include "expressions.h" -#include "forloops.h" #include "functions.h" +#include "loops.h" #include "promotions.h" #include "statements.h" #include "whens.h" @@ -113,56 +113,8 @@ static Text_t _compile_statement(env_t *env, ast_t *ast) { case ConvertDef: { return EMPTY_TEXT; } - case Skip: { - const char *target = Match(ast, Skip)->target; - for (loop_ctx_t *ctx = env->loop_ctx; ctx; ctx = ctx->next) { - bool matched = !target || strcmp(target, ctx->loop_name) == 0; - for (ast_list_t *var = ctx->loop_vars; var && !matched; var = var ? var->next : NULL) - matched = (strcmp(target, Match(var->ast, Var)->name) == 0); - - if (matched) { - if (ctx->skip_label.length == 0) { - static int64_t skip_label_count = 1; - ctx->skip_label = Texts("skip_", String(skip_label_count)); - ++skip_label_count; - } - Text_t code = EMPTY_TEXT; - for (deferral_t *deferred = env->deferred; deferred && deferred != ctx->deferred; - deferred = deferred->next) - code = Texts(code, compile_statement(deferred->defer_env, deferred->block)); - if (code.length > 0) return Texts("{\n", code, "goto ", ctx->skip_label, ";\n}\n"); - else return Texts("goto ", ctx->skip_label, ";"); - } - } - if (env->loop_ctx) code_err(ast, "This is not inside any loop"); - else if (target) code_err(ast, "No loop target named '", target, "' was found"); - else return Text("continue;"); - } - case Stop: { - const char *target = Match(ast, Stop)->target; - for (loop_ctx_t *ctx = env->loop_ctx; ctx; ctx = ctx->next) { - bool matched = !target || strcmp(target, ctx->loop_name) == 0; - for (ast_list_t *var = ctx->loop_vars; var && !matched; var = var ? var->next : var) - matched = (strcmp(target, Match(var->ast, Var)->name) == 0); - - if (matched) { - if (ctx->stop_label.length == 0) { - static int64_t stop_label_count = 1; - ctx->stop_label = Texts("stop_", String(stop_label_count)); - ++stop_label_count; - } - Text_t code = EMPTY_TEXT; - for (deferral_t *deferred = env->deferred; deferred && deferred != ctx->deferred; - deferred = deferred->next) - code = Texts(code, compile_statement(deferred->defer_env, deferred->block)); - if (code.length > 0) return Texts("{\n", code, "goto ", ctx->stop_label, ";\n}\n"); - else return Texts("goto ", ctx->stop_label, ";"); - } - } - if (env->loop_ctx) code_err(ast, "This is not inside any loop"); - else if (target) code_err(ast, "No loop target named '", target, "' was found"); - else return Text("break;"); - } + case Skip: return compile_skip(env, ast); + case Stop: return compile_stop(env, ast); case Pass: return Text(";"); case Defer: { ast_t *body = Match(ast, Defer)->body; @@ -217,37 +169,8 @@ static Text_t _compile_statement(env_t *env, ast_t *ast) { return Texts(code, "return;"); } } - case While: { - DeclareMatch(while_, ast, While); - env_t *scope = fresh_scope(env); - loop_ctx_t loop_ctx = (loop_ctx_t){ - .loop_name = "while", - .deferred = scope->deferred, - .next = env->loop_ctx, - }; - scope->loop_ctx = &loop_ctx; - Text_t body = compile_statement(scope, while_->body); - if (loop_ctx.skip_label.length > 0) body = Texts(body, "\n", loop_ctx.skip_label, ": continue;"); - Text_t loop = Texts("while (", while_->condition ? compile(scope, while_->condition) : Text("yes"), ") {\n\t", - body, "\n}"); - if (loop_ctx.stop_label.length > 0) loop = Texts(loop, "\n", loop_ctx.stop_label, ":;"); - return loop; - } - case Repeat: { - ast_t *body = Match(ast, Repeat)->body; - env_t *scope = fresh_scope(env); - loop_ctx_t loop_ctx = (loop_ctx_t){ - .loop_name = "repeat", - .deferred = scope->deferred, - .next = env->loop_ctx, - }; - scope->loop_ctx = &loop_ctx; - Text_t body_code = compile_statement(scope, body); - if (loop_ctx.skip_label.length > 0) body_code = Texts(body_code, "\n", loop_ctx.skip_label, ": continue;"); - Text_t loop = Texts("for (;;) {\n\t", body_code, "\n}"); - if (loop_ctx.stop_label.length > 0) loop = Texts(loop, "\n", loop_ctx.stop_label, ":;"); - return loop; - } + case While: return compile_while(env, ast); + case Repeat: return compile_repeat(env, ast); case For: return compile_for_loop(env, ast); case If: return compile_if_statement(env, ast); case Block: return compile_block(env, ast); |
