From: Brendan Hansen Date: Fri, 4 Sep 2020 19:20:10 +0000 (-0500) Subject: changed semantics of for loops; now iterable based X-Git-Url: https://git.brendanfh.com/?a=commitdiff_plain;h=b5f7205f94915548eabd3402238f251380b69858;p=onyx.git changed semantics of for loops; now iterable based --- diff --git a/core/array.onyx b/core/array.onyx index 6e06574d..ad37a554 100644 --- a/core/array.onyx +++ b/core/array.onyx @@ -49,10 +49,10 @@ array_insert :: proc (arr: ^[..] $T, idx: u32, x: T) { array_remove :: proc (arr: ^[..] $T, elem: T) { move := 0; - for i: 0, arr.count - move { + for i: 0 .. arr.count - move { if arr.data[i + move] == elem do move += 1; if move != 0 do arr.data[i] = arr.data[i + move]; - } + } arr.count -= move; } @@ -60,7 +60,7 @@ array_remove :: proc (arr: ^[..] $T, elem: T) { array_delete :: proc (arr: ^[..] $T, idx: u32) { if idx >= arr.count do return; - for i: idx, arr.count - 1 { + for i: idx .. arr.count - 1 { arr.data[i] = arr.data[i + 1]; } @@ -75,7 +75,7 @@ array_fast_delete :: proc (arr: ^[..] $T, idx: u32) { } array_contains :: proc (arr: ^[..] $T, x: T) -> bool { - for i: 0, arr.count do if arr.data[i] == x do return true; + for i: 0 .. arr.count do if arr.data[i] == x do return true; return false; } @@ -86,7 +86,7 @@ array_pop :: proc (arr: ^[..] $T) -> T { array_average :: proc (arr: ^[..] $T) -> T { sum := cast(T) 0; - for i: 0, arr.count { + for i: 0 .. arr.count { sum += arr.data[i]; } @@ -102,9 +102,9 @@ array_to_slice :: proc (arr: ^[..] $T) -> [] T { ** cmp should return >0 if left > right */ array_sort :: proc (arr: ^[..] $T, cmp: proc (T, T) -> i32) { - for i: 1, arr.count { + for i: 1 .. arr.count { x := arr.data[i]; - j := i - 1; + j := i - 1; while j >= 0 && cmp(arr.data[j], x) > 0 { arr.data[j + 1] = arr.data[j]; @@ -117,10 +117,10 @@ array_sort :: proc (arr: ^[..] $T, cmp: proc (T, T) -> i32) { array_fold :: proc (arr: ^[..] $T, init: $R, f: proc (T, R) -> R) -> R { val := init; - for i: 0, arr.count do val = f(arr.data[i], val); + for i: 0 .. arr.count do val = f(arr.data[i], val); return val; } array_map :: proc (arr: ^[..] $T, f: proc (T) -> T) { - for i: 0, arr.count do arr.data[i] = f(arr.data[i]); + for i: 0 .. arr.count do arr.data[i] = f(arr.data[i]); } diff --git a/core/memory.onyx b/core/memory.onyx index c1223d88..91da91da 100644 --- a/core/memory.onyx +++ b/core/memory.onyx @@ -3,5 +3,5 @@ package core memory_copy :: proc (dst_: rawptr, src_: rawptr, len: u32) { dst := cast(^u8) dst_; src := cast(^u8) src_; - for i: 0, len do dst[i] = src[i]; -} \ No newline at end of file + for i: 0 .. len do dst[i] = src[i]; +} diff --git a/core/ptrmap.onyx b/core/ptrmap.onyx index 8951cd00..700e77b8 100644 --- a/core/ptrmap.onyx +++ b/core/ptrmap.onyx @@ -17,7 +17,7 @@ ptrmap_init :: proc (use pmap: ^PtrMap, hash_count: i32 = 16) { array_init(^hashes, hash_count); array_init(^entries, 4); - for i: 0, hash_count do array_push(^hashes, -1); + for i: 0 .. hash_count do array_push(^hashes, -1); } ptrmap_free :: proc (use pmap: ^PtrMap) { @@ -57,7 +57,7 @@ ptrmap_get :: proc (use pmap: ^PtrMap, key: rawptr) -> rawptr { ptrmap_delete :: proc (use pmap: ^PtrMap, key: rawptr) { lr := ptrmap_lookup(pmap, key); - if lr.entry_index < 0 do return; + if lr.entry_index < 0 do return; if lr.entry_prev < 0 do hashes[lr.hash_index] = entries[lr.entry_index].next; else do hashes[lr.entry_prev] = entries[lr.entry_index].next; @@ -74,7 +74,7 @@ ptrmap_delete :: proc (use pmap: ^PtrMap, key: rawptr) { } ptrmap_clear :: proc (use pmap: ^PtrMap) { - for i: 0, hashes.count do hashes.data[i] = -1; + for i: 0 .. hashes.count do hashes.data[i] = -1; entries.count = 0; } @@ -108,4 +108,4 @@ ptrmap_lookup :: proc (use pmap: ^PtrMap, key: rawptr) -> PtrMapLookupResult { } return lr; -} \ No newline at end of file +} diff --git a/core/stdio.onyx b/core/stdio.onyx index 3d2fc0f5..f4c4cd6f 100644 --- a/core/stdio.onyx +++ b/core/stdio.onyx @@ -30,7 +30,7 @@ print :: proc #overloaded { // This works on both slices and arrays print_array :: proc (arr: $T, sep := " ") { - for i: 0, arr.count { + for i: 0 .. arr.count { print(arr.data[i]); if i != arr.count - 1 do print(sep); } diff --git a/core/string.onyx b/core/string.onyx index dea31701..6e073198 100644 --- a/core/string.onyx +++ b/core/string.onyx @@ -31,8 +31,8 @@ string_concat :: proc (s1: string, s2: string) -> string { len2 :: string_length(s2); data := cast(^u8) calloc(len1 + len2); - for i: 0, len1 do data[i] = s1[i]; - for i: 0, len2 do data[i + len1] = s2[i]; + for i: 0 .. len1 do data[i] = s1[i]; + for i: 0 .. len2 do data[i + len1] = s2[i]; return string.{ data, len1 + len2 }; } @@ -44,14 +44,14 @@ string_free :: proc (s: string) do cfree(s.data); // It documents the string_split function string_split :: proc (str: string, delim: u8) -> []string { delim_count := 0; - for i: 0, str.count do if str[i] == delim do delim_count += 1; + for i: 0 .. str.count do if str[i] == delim do delim_count += 1; strarr := cast(^string) calloc(sizeof string * (delim_count + 1)); curr_str := 0; begin := 0; - for i: 0, str.count { + for i: 0 .. str.count { if str[i] == delim { strarr[curr_str] = str.data[begin .. i]; begin = i + 1; @@ -65,7 +65,7 @@ string_split :: proc (str: string, delim: u8) -> []string { } string_substr :: proc (str: string, sub: string) -> string { - for i: 0, str.count { + for i: 0 .. str.count { while j := 0; j < sub.count && str[i + j] == sub[j] { j += 1; @@ -77,7 +77,7 @@ string_substr :: proc (str: string, sub: string) -> string { } string_contains :: proc (str: string, c: u8) -> bool { - for i: 0, str.count do if str[i] == c do return true; + for i: 0 .. str.count do if str[i] == c do return true; return false; } @@ -134,7 +134,7 @@ string_builder_add_string :: proc (use sb: ^StringBuilder, str: string) -> ^Stri len_total :: len + str.count; if cap >= len_total { - for i: 0, str.count do data[len + i] = str[i]; + for i: 0 .. str.count do data[len + i] = str[i]; len += str.count; return sb; } @@ -148,7 +148,7 @@ string_builder_add_string :: proc (use sb: ^StringBuilder, str: string) -> ^Stri data = new_data; cap = new_cap; - for i: 0, str.count do data[len + i] = str[i]; + for i: 0 .. str.count do data[len + i] = str[i]; len += str.count; return sb; } @@ -168,7 +168,7 @@ i64_to_string :: proc (n_: i64, base: u64, buf: Buffer) -> string { } str :: cast(^u8) buf.data; - for i: 0, buf.count do str[i] = #char "\0"; + for i: 0 .. buf.count do str[i] = #char "\0"; c := cast(^u8) ^str[buf.count - 1]; len := 0; @@ -275,7 +275,7 @@ string_read_line :: proc (str: ^string, out: ^string) { out.data = str.data; out.count = 0; - for i: 0, str.count { + for i: 0 .. str.count { if str.data[i] == #char "\n" do break; out.count += 1; } diff --git a/include/onyxastnodes.h b/include/onyxastnodes.h index 11815151..25677186 100644 --- a/include/onyxastnodes.h +++ b/include/onyxastnodes.h @@ -270,6 +270,13 @@ typedef enum JumpType { Jump_Type_Count, } JumpType; +typedef enum ForLoopType { + For_Loop_Invalid, + For_Loop_Range, + For_Loop_Array, + For_Loop_Slice, + For_Loop_DynArr, +} ForLoopType; // Base Nodes #define AstNode_base \ @@ -337,7 +344,10 @@ struct AstFor { // NOTE: Local defining the iteration variable AstLocal* var; - AstTyped *start, *end, *step; + // NOTE: This can be any expression, but it is checked that + // it is of a type that we know how to iterate over. + AstTyped* iter; + ForLoopType loop_type; AstBlock *stmt; }; @@ -582,6 +592,7 @@ extern AstNumLit builtin_heap_start; extern AstGlobal builtin_stack_top; extern AstType *builtin_string_type; extern AstType *builtin_range_type; +extern Type *builtin_range_type_type; typedef struct BuiltinSymbol { char* package; diff --git a/onyx b/onyx index 5e98dca5..135af032 100755 Binary files a/onyx and b/onyx differ diff --git a/progs/poly_test.onyx b/progs/poly_test.onyx index 92235e0e..2da51158 100644 --- a/progs/poly_test.onyx +++ b/progs/poly_test.onyx @@ -47,8 +47,8 @@ compose :: proc (a: A, f: proc ($A) -> $B, g: proc (B) -> $C) -> C { SOA :: struct { - b : [..] i64; a : [..] i32; + b : [..] i64; } soa_init :: proc (s: ^SOA) { @@ -62,7 +62,7 @@ soa_deinit :: proc (s: ^SOA) { } get_range :: proc (arr: ^[..] $T) -> range { - return 20 .. 26; + return 0 .. arr.count; } print_range :: proc (r: range) #add_overload print { @@ -74,6 +74,14 @@ print_range :: proc (r: range) #add_overload print { print("\n"); } +// NOTE: This function will be very useful for for loops. i.e. +// for i: 0 .. 100 |> by(2) { +// ... +// } +by :: proc (r: range, s: u32) -> range { + return range.{ low = r.low, high = r.high, step = s }; +} + main :: proc (args: [] cstring) { res := compose(5, proc (x: i32) -> i32 do return x * 3;, proc (x: i32) -> i32 do return x + 5;); @@ -87,22 +95,29 @@ main :: proc (args: [] cstring) { soa_deinit(^s); } + print("Evens from 6 to 34:\n"); + for i: 6 .. 34 |> by(2) { + print(i); + print(" "); + } + print("\n"); + print_arr_details(^s.a); print_arr_details(^s.b); - for i: 0, 100 { + for i: 0 .. 100 { array_push(^s.a, (5 * i) % 21); array_push(^s.b, 3l * cast(i64) i); } - r := ^s.a |> get_range(); + r := ^s.a |> get_range() |> by(3); print(r); + print_array(^s.a); array_sort(^s.a, cmp_dec); - array_sort(^s.b, cmp_asc); + array_sort(^s.b, cmp_dec); - print_array(s.a.data[r]); - print_array(s.a.data[21 .. 27]); + print_array(^s.a); print_array(^s.b); print("After adding...\n"); @@ -117,7 +132,7 @@ main :: proc (args: [] cstring) { ptrmap_init(^map, 50); defer ptrmap_free(^map); - for i: 0, 100 do ptrmap_put(^map, ^s.a[i], ^s.b[i]); + for i: 0 .. 100 do ptrmap_put(^map, ^s.a[i], ^s.b[i]); print("Has ^a[20]? "); print(ptrmap_has(^map, ^s.a[20])); @@ -154,7 +169,7 @@ main2 :: proc (args: [] cstring) { array_push(^iarr, 1234); - for i: 0, 12 do array_push(^iarr, i % 5); + for i: 0 .. 12 do array_push(^iarr, i % 5); print_arr_details(^iarr); print_array(^iarr); @@ -183,7 +198,7 @@ main2 :: proc (args: [] cstring) { array_init(^barr, 10); defer array_free(^barr); - for i: 0, 500 { + for i: 0 .. 500 { array_push(^barr, cast(u64) (3 * i * i + 4 * i - 2)); } @@ -202,7 +217,7 @@ main2 :: proc (args: [] cstring) { array_init(^varr); defer array_free(^varr); - for i: 0, 20 { + for i: 0 .. 20 { array_push(^varr, Vec3.{ x = i, y = i * i, @@ -220,7 +235,7 @@ main2 :: proc (args: [] cstring) { dummy := cast(^Dummy) calloc(sizeof Dummy); defer cfree(dummy); dummy.count = 5; - for i: 0, dummy.count do dummy.data[i] = i * 5; + for i: 0 .. dummy.count do dummy.data[i] = i * 5; print_array(dummy); diff --git a/src/onyxbuiltins.c b/src/onyxbuiltins.c index 4085e062..6362331e 100644 --- a/src/onyxbuiltins.c +++ b/src/onyxbuiltins.c @@ -27,6 +27,7 @@ AstGlobal builtin_stack_top = { Ast_Kind_Global, Ast_Flag_Const | Ast_Flag_Glo AstType *builtin_string_type; AstType *builtin_range_type; +Type *builtin_range_type_type; const BuiltinSymbol builtin_symbols[] = { { NULL, "void", (AstNode *) &basic_type_void }, diff --git a/src/onyxchecker.c b/src/onyxchecker.c index fc0be94e..52467ffb 100644 --- a/src/onyxchecker.c +++ b/src/onyxchecker.c @@ -97,47 +97,28 @@ b32 check_while(AstIfWhile* whilenode) { } b32 check_for(AstFor* fornode) { - if (check_expression(&fornode->start)) return 1; - if (check_expression(&fornode->end)) return 1; - if (check_expression(&fornode->step)) return 1; + if (check_expression(&fornode->iter)) return 1; + fornode->loop_type = For_Loop_Invalid; - if (fornode->var->type_node == NULL || fornode->var->type_node != fornode->start->type_node) - fornode->var->type_node = fornode->start->type_node; - fill_in_type((AstTyped *) fornode->var); + Type* iter_type = fornode->iter->type; + b32 can_iterate = 0; + if (types_are_compatible(iter_type, builtin_range_type_type)) { + can_iterate = 1; - if (!type_is_integer(fornode->start->type)) { - onyx_report_error(fornode->start->token->pos, "expected expression of integer type for start"); - return 1; - } - - if (!type_is_integer(fornode->end->type)) { - onyx_report_error(fornode->end->token->pos, "expected expression of integer type for end"); - return 1; - } - - if (!type_is_integer(fornode->step->type)) { - onyx_report_error(fornode->step->token->pos, "expected expression of integer type for step"); - return 1; - } - - // NOTE: Auto promote implicit step to the type of start - if (fornode->step->kind == Ast_Kind_NumLit) { - fornode->step->type_node = fornode->start->type_node; - fornode->step->type = fornode->start->type; - promote_numlit_to_larger((AstNumLit *) fornode->step); - } + // NOTE: Blindly copy the first range member's type which will + // be the low value. - brendanfh 2020/09/04 + fornode->var->type = builtin_range_type_type->Struct.memarr[0]->type; - if (!types_are_compatible(fornode->end->type, fornode->start->type)) { - onyx_report_error(fornode->end->token->pos, "type of end does not match type of start"); - return 1; + fornode->loop_type = For_Loop_Range; } - if (!types_are_compatible(fornode->step->type, fornode->start->type)) { - onyx_report_error(fornode->start->token->pos, "type of step does not match type of start"); + if (!can_iterate) { + onyx_report_error(fornode->iter->token->pos, + "Cannot iterate over a '%s'.", + type_get_name(iter_type)); return 1; } - if (check_block(fornode->stmt)) return 1; return 0; @@ -839,7 +820,7 @@ b32 check_array_access(AstArrayAccess* aa) { return 1; } - if (types_are_compatible(aa->expr->type, type_build_from_ast(semstate.node_allocator, builtin_range_type))) { + if (types_are_compatible(aa->expr->type, builtin_range_type_type)) { Type *of = NULL; if (aa->addr->type->kind == Type_Kind_Pointer) of = aa->addr->type->Pointer.elem; @@ -931,7 +912,7 @@ b32 check_range_literal(AstBinaryOp** prange) { if (check_expression(&range->left)) return 1; if (check_expression(&range->right)) return 1; - Type* expected_range_type = type_build_from_ast(semstate.node_allocator, builtin_range_type); + Type* expected_range_type = builtin_range_type_type; StructMember smem; type_lookup_member(expected_range_type, "low", &smem); diff --git a/src/onyxclone.c b/src/onyxclone.c index f11837fb..78100a00 100644 --- a/src/onyxclone.c +++ b/src/onyxclone.c @@ -206,9 +206,7 @@ AstNode* ast_clone(bh_allocator a, void* n) { case Ast_Kind_For: ((AstFor *) nn)->var = (AstLocal *) ast_clone(a, ((AstFor *) node)->var); - ((AstFor *) nn)->start = (AstTyped *) ast_clone(a, ((AstFor *) node)->start); - ((AstFor *) nn)->end = (AstTyped *) ast_clone(a, ((AstFor *) node)->end); - ((AstFor *) nn)->step = (AstTyped *) ast_clone(a, ((AstFor *) node)->step); + ((AstFor *) nn)->iter = (AstTyped *) ast_clone(a, ((AstFor *) node)->iter); ((AstFor *) nn)->stmt = (AstBlock *) ast_clone(a, ((AstFor *) node)->stmt); break; diff --git a/src/onyxparser.c b/src/onyxparser.c index fba93559..cacb22ae 100644 --- a/src/onyxparser.c +++ b/src/onyxparser.c @@ -853,19 +853,7 @@ static AstFor* parse_for_stmt(OnyxParser* parser) { for_node->var = var_node; expect_token(parser, ':'); - for_node->start = parse_expression(parser); - expect_token(parser, ','); - for_node->end = parse_expression(parser); - - if (parser->curr->type == ',') { - consume_token(parser); - for_node->step = parse_expression(parser); - } else { - for_node->step = make_node(AstNumLit, Ast_Kind_NumLit); - for_node->step->type_node = (AstType *) &basic_type_i32; - ((AstNumLit *) for_node->step)->value.i = 1; - } - + for_node->iter = parse_expression(parser); for_node->stmt = parse_block(parser); return for_node; diff --git a/src/onyxsymres.c b/src/onyxsymres.c index b09f447b..86afa631 100644 --- a/src/onyxsymres.c +++ b/src/onyxsymres.c @@ -306,6 +306,10 @@ static void symres_expression(AstTyped** expr) { symres_expression(&((AstBinaryOp *)(*expr))->right); (*expr)->type_node = symres_type(builtin_range_type); + + // NOTE: This is a weird place to put this so maybe put it somewhere else eventually + // - brendanfh 2020/09/04 + builtin_range_type_type = type_build_from_ast(semstate.node_allocator, builtin_range_type); break; case Ast_Kind_Function: @@ -376,11 +380,9 @@ static void symres_for(AstFor* fornode) { fornode->scope = scope_create(semstate.node_allocator, semstate.curr_scope); scope_enter(fornode->scope); - symbol_introduce(semstate.curr_scope, fornode->var->token, (AstNode *) fornode->var); + symres_expression(&fornode->iter); - symres_expression(&fornode->start); - symres_expression(&fornode->end); - symres_expression(&fornode->step); + symbol_introduce(semstate.curr_scope, fornode->var->token, (AstNode *) fornode->var); symres_block(fornode->stmt); diff --git a/src/onyxwasm.c b/src/onyxwasm.c index 1369da02..ac45c468 100644 --- a/src/onyxwasm.c +++ b/src/onyxwasm.c @@ -741,27 +741,36 @@ EMIT_FUNC(while, AstIfWhile* while_node) { *pcode = code; } -EMIT_FUNC(for, AstFor* for_node) { +EMIT_FUNC(for_range, AstFor* for_node, u64 iter_local) { bh_arr(WasmInstruction) code = *pcode; - AstLocal* var = for_node->var; - u64 tmp = local_allocate(mod->local_alloc, var); - bh_imap_put(&mod->local_map, (u64) var, tmp); + // NOTE: There are some aspects of the code below that rely on the + // low, high, and step members to be i32's. This restriction can be lifted, + // but it is important to change the code here. + // -brendanfh 2020/09/04 - b32 it_is_local = (b32) ((tmp & LOCAL_IS_WASM) != 0); + AstLocal* var = for_node->var; + b32 it_is_local = (b32) ((iter_local & LOCAL_IS_WASM) != 0); u64 offset = 0; - WasmType var_type = onyx_type_to_wasm_type(for_node->var->type); - assert(var_type == WASM_TYPE_INT32 || var_type == WASM_TYPE_INT64); - WasmInstructionType add_instr = var_type == WASM_TYPE_INT32 ? WI_I32_ADD : WI_I64_ADD; - WasmInstructionType ge_instr = var_type == WASM_TYPE_INT32 ? WI_I32_GE_S : WI_I64_GE_S; + StructMember smem; + type_lookup_member(builtin_range_type_type, "low", &smem); + u64 low_local = local_raw_allocate(mod->local_alloc, onyx_type_to_wasm_type(smem.type)); + type_lookup_member(builtin_range_type_type, "high", &smem); + u64 high_local = local_raw_allocate(mod->local_alloc, onyx_type_to_wasm_type(smem.type)); + type_lookup_member(builtin_range_type_type, "step", &smem); + u64 step_local = local_raw_allocate(mod->local_alloc, onyx_type_to_wasm_type(smem.type)); + + WIL(WI_LOCAL_SET, step_local); + WIL(WI_LOCAL_SET, high_local); + WIL(WI_LOCAL_SET, low_local); if (it_is_local) { - emit_expression(mod, &code, for_node->start); - WIL(WI_LOCAL_SET, tmp); + WIL(WI_LOCAL_GET, low_local); + WIL(WI_LOCAL_SET, iter_local); } else { emit_local_location(mod, &code, var, &offset); - emit_expression(mod, &code, for_node->start); + WIL(WI_LOCAL_GET, low_local); emit_store_instruction(mod, &code, var->type, offset); } @@ -774,14 +783,14 @@ EMIT_FUNC(for, AstFor* for_node) { bh_arr_push(mod->structured_jump_target, 2); if (it_is_local) { - WIL(WI_LOCAL_GET, tmp); + WIL(WI_LOCAL_GET, iter_local); } else { offset = 0; emit_local_location(mod, &code, var, &offset); emit_load_instruction(mod, &code, var->type, offset); } - emit_expression(mod, &code, for_node->end); - WI(ge_instr); + WIL(WI_LOCAL_GET, high_local); + WI(WI_I32_GE_S); WID(WI_COND_JUMP, 0x02); emit_block(mod, &code, for_node->stmt, 0); @@ -790,18 +799,18 @@ EMIT_FUNC(for, AstFor* for_node) { WI(WI_BLOCK_END); if (it_is_local) { - WIL(WI_LOCAL_GET, tmp); - emit_expression(mod, &code, for_node->step); - WI(add_instr); - WIL(WI_LOCAL_SET, tmp); + WIL(WI_LOCAL_GET, iter_local); + WIL(WI_LOCAL_GET, step_local); + WI(WI_I32_ADD); + WIL(WI_LOCAL_SET, iter_local); } else { offset = 0; emit_local_location(mod, &code, var, &offset); offset = 0; emit_local_location(mod, &code, var, &offset); emit_load_instruction(mod, &code, var->type, offset); - emit_expression(mod, &code, for_node->step); - WI(add_instr); + WIL(WI_LOCAL_GET, step_local); + WI(WI_I32_ADD); emit_store_instruction(mod, &code, var->type, offset); } @@ -814,6 +823,31 @@ EMIT_FUNC(for, AstFor* for_node) { WI(WI_LOOP_END); WI(WI_BLOCK_END); + type_lookup_member(builtin_range_type_type, "low", &smem); + local_raw_free(mod->local_alloc, onyx_type_to_wasm_type(smem.type)); + type_lookup_member(builtin_range_type_type, "high", &smem); + local_raw_free(mod->local_alloc, onyx_type_to_wasm_type(smem.type)); + type_lookup_member(builtin_range_type_type, "step", &smem); + local_raw_free(mod->local_alloc, onyx_type_to_wasm_type(smem.type)); + + *pcode = code; +} + +EMIT_FUNC(for, AstFor* for_node) { + bh_arr(WasmInstruction) code = *pcode; + + AstLocal* var = for_node->var; + u64 iter_local = local_allocate(mod->local_alloc, var); + bh_imap_put(&mod->local_map, (u64) var, iter_local); + + emit_expression(mod, &code, for_node->iter); + + if (for_node->loop_type == For_Loop_Range) { + emit_for_range(mod, &code, for_node, iter_local); + } else { + onyx_report_error(for_node->token->pos, "Invalid for loop type. You should probably not be seeing this..."); + } + local_free(mod->local_alloc, var); *pcode = code;