diff options
| author | Bruce Hill <bruce@bruce-hill.com> | 2025-02-13 15:03:22 -0500 |
|---|---|---|
| committer | Bruce Hill <bruce@bruce-hill.com> | 2025-02-13 15:03:22 -0500 |
| commit | 5be955904682300153af0abdfd6b711b9da2ac8f (patch) | |
| tree | e616bc83904817fdefa43354fa815f13daf18739 /compile.c | |
| parent | 8e0f1fa227be762cab19234abc106ba4c572077d (diff) | |
Deprecate Range datatype in favor of using iterator methods
Diffstat (limited to 'compile.c')
| -rw-r--r-- | compile.c | 64 |
1 files changed, 47 insertions, 17 deletions
@@ -500,7 +500,6 @@ PUREFUNC CORD compile_unsigned_type(type_t *t) CORD compile_type(type_t *t) { if (t == THREAD_TYPE) return "Thread_t"; - else if (t == RANGE_TYPE) return "Range_t"; else if (t == RNG_TYPE) return "RNG_t"; else if (t == MATCH_TYPE) return "Match_t"; @@ -1541,26 +1540,58 @@ static CORD _compile_statement(env_t *env, ast_t *ast) naked_body = CORD_all(naked_body, "\n", loop_ctx.skip_label, ": continue;"); CORD stop = loop_ctx.stop_label ? CORD_all("\n", loop_ctx.stop_label, ":;") : CORD_EMPTY; - type_t *iter_t = value_type(get_type(env, for_->iter)); - type_t *iter_value_t = value_type(iter_t); + // Special case for improving performance for numeric iteration: + if (for_->iter->tag == MethodCall && streq(Match(for_->iter, MethodCall)->name, "to") && + get_type(env, Match(for_->iter, MethodCall)->self)->tag == BigIntType) { + arg_ast_t *args = Match(for_->iter, MethodCall)->args; + if (!args) code_err(for_->iter, "to() needs at least one argument"); + + CORD last = CORD_EMPTY, step = CORD_EMPTY, optional_step = CORD_EMPTY; + if (!args->name || streq(args->name, "last")) { + last = compile_to_type(env, args->value, INT_TYPE); + if (args->next) { + if (args->next->name && !streq(args->next->name, "step")) + code_err(args->next->value, "Invalid argument name: %s", args->next->name); + if (get_type(env, args->next->value)->tag == OptionalType) + optional_step = compile_to_type(env, args->next->value, Type(OptionalType, .type=INT_TYPE)); + else + step = compile_to_type(env, args->next->value, INT_TYPE); + } + } else if (streq(args->name, "step")) { + if (get_type(env, args->value)->tag == OptionalType) + optional_step = compile_to_type(env, args->value, Type(OptionalType, .type=INT_TYPE)); + else + step = compile_to_type(env, args->value, INT_TYPE); + if (args->next) { + if (args->next->name && !streq(args->next->name, "last")) + code_err(args->next->value, "Invalid argument name: %s", args->next->name); + last = compile_to_type(env, args->next->value, INT_TYPE); + } + } + + if (!last) + code_err(for_->iter, "No `last` argument was given"); + + if (step && optional_step) + step = CORD_all("({ OptionalInt_t maybe_step = ", optional_step, "; maybe_step->small == 0 ? (Int$compare_value(last, first) >= 0 ? I_small(1) : I_small(-1)) : (Int_t)maybe_step; })"); + else if (!step) + step = "Int$compare_value(last, first) >= 0 ? I_small(1) : I_small(-1)"; - if (iter_value_t == RANGE_TYPE) { - CORD range = compile_to_pointer_depth(env, for_->iter, 0, false); CORD value = for_->vars ? compile(body_scope, for_->vars->ast) : "i"; - if (for_->empty) - code_err(ast, "Ranges are never empty, they always contain at least their starting element"); return CORD_all( - "{\n" - "const Range_t range = ", range, ";\n" - "if (range.step.small == 0) fail(\"This range has a 'step' of zero and will loop infinitely!\");\n" - "bool negative = (Int$compare_value(range.step, I(0)) < 0);\n" - "for (Int_t ", value, " = range.first; ({ int32_t cmp = Int$compare_value(", value, ", range.last); negative ? cmp >= 0 : cmp <= 0;}) ; ", value, " = Int$plus(", value, ", range.step)) {\n" + "for (Int_t first = ", compile(env, Match(for_->iter, MethodCall)->self), ", ", + value, " = first, " + "last = ", last, ", " + "step = ", step, "; " + "Int$compare_value(", value, ", last) != Int$compare_value(step, I_small(0)); ", value, " = Int$plus(", value, ", step)) {\n" "\t", naked_body, - "\n}", - stop, - "\n}"); + "}", + stop); } + type_t *iter_t = value_type(get_type(env, for_->iter)); + type_t *iter_value_t = value_type(iter_t); + switch (iter_value_t->tag) { case ArrayType: { type_t *item_t = Match(iter_value_t, ArrayType)->item_type; @@ -3848,7 +3879,7 @@ CORD compile(env_t *env, ast_t *ast) case StructType: { for (arg_t *field = Match(value_t, StructType)->fields; field; field = field->next) { if (streq(field->name, f->field)) { - const char *prefix = (value_t == RANGE_TYPE || value_t == MATCH_TYPE) ? "" : "$"; + const char *prefix = (value_t == MATCH_TYPE) ? "" : "$"; if (fielded_t->tag == PointerType) { CORD fielded = compile_to_pointer_depth(env, f->fielded, 1, false); return CORD_asprintf("(%r)->%s%s", fielded, prefix, f->field); @@ -4086,7 +4117,6 @@ void compile_namespace(env_t *env, const char *ns_name, ast_t *block) CORD compile_type_info(env_t *env, type_t *t) { if (t == THREAD_TYPE) return "&Thread$info"; - else if (t == RANGE_TYPE) return "&Range$info"; else if (t == MATCH_TYPE) return "&Match$info"; else if (t == RNG_TYPE) return "&RNG$info"; |
