From: Brendan Hansen Date: Sat, 5 Sep 2020 04:50:58 +0000 (-0500) Subject: added iteration by pointer to for loops X-Git-Url: https://git.brendanfh.com/?a=commitdiff_plain;h=8842089f02f651d9c45e4d507422a4aa014dc0b3;p=onyx.git added iteration by pointer to for loops --- diff --git a/core/array.onyx b/core/array.onyx index ad37a554..0d314deb 100644 --- a/core/array.onyx +++ b/core/array.onyx @@ -86,9 +86,7 @@ array_pop :: proc (arr: ^[..] $T) -> T { array_average :: proc (arr: ^[..] $T) -> T { sum := cast(T) 0; - for i: 0 .. arr.count { - sum += arr.data[i]; - } + for it: *arr do sum += it; return sum / cast(T) arr.count; } @@ -117,7 +115,7 @@ 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 it: *arr do val = f(it, val); return val; } diff --git a/include/onyxastnodes.h b/include/onyxastnodes.h index 25677186..599a5adb 100644 --- a/include/onyxastnodes.h +++ b/include/onyxastnodes.h @@ -350,6 +350,10 @@ struct AstFor { ForLoopType loop_type; AstBlock *stmt; + + // ROBUSTNESS: This should be able to be set by a compile time variable at some point. + // But for now, this will do. + b32 by_pointer : 1; }; struct AstIfWhile { AstNode_base; diff --git a/onyx b/onyx index 93a0ad26..72b0bd66 100755 Binary files a/onyx and b/onyx differ diff --git a/progs/poly_test.onyx b/progs/poly_test.onyx index 78ba3807..b025dbd3 100644 --- a/progs/poly_test.onyx +++ b/progs/poly_test.onyx @@ -133,6 +133,12 @@ main :: proc (args: [] cstring) { } print("\n"); + for ^vec: s.c { + print(vec); + print(" "); + } + print("\n"); + array_sort(^s.a, cmp_dec); array_sort(^s.b, cmp_dec); diff --git a/src/onyxchecker.c b/src/onyxchecker.c index 3fed3fcc..165b7d51 100644 --- a/src/onyxchecker.c +++ b/src/onyxchecker.c @@ -103,6 +103,11 @@ b32 check_for(AstFor* fornode) { Type* iter_type = fornode->iter->type; b32 can_iterate = 0; if (types_are_compatible(iter_type, builtin_range_type_type)) { + if (fornode->by_pointer) { + onyx_report_error(fornode->var->token->pos, "Cannot iterate by pointer over a range."); + return 1; + } + can_iterate = 1; // NOTE: Blindly copy the first range member's type which will @@ -114,14 +119,18 @@ b32 check_for(AstFor* fornode) { else if (iter_type->kind == Type_Kind_Slice) { can_iterate = 1; - fornode->var->type = iter_type->Slice.ptr_to_data->Pointer.elem; + if (fornode->by_pointer) fornode->var->type = iter_type->Slice.ptr_to_data; + else fornode->var->type = iter_type->Slice.ptr_to_data->Pointer.elem; + fornode->loop_type = For_Loop_Slice; } else if (iter_type->kind == Type_Kind_DynArray) { can_iterate = 1; - fornode->var->type = iter_type->DynArray.ptr_to_data->Pointer.elem; + if (fornode->by_pointer) fornode->var->type = iter_type->DynArray.ptr_to_data; + else fornode->var->type = iter_type->DynArray.ptr_to_data->Pointer.elem; + fornode->loop_type = For_Loop_DynArr; } diff --git a/src/onyxparser.c b/src/onyxparser.c index cacb22ae..fe9c353d 100644 --- a/src/onyxparser.c +++ b/src/onyxparser.c @@ -846,9 +846,13 @@ static AstFor* parse_for_stmt(OnyxParser* parser) { AstFor* for_node = make_node(AstFor, Ast_Kind_For); for_node->token = expect_token(parser, Token_Type_Keyword_For); + if (parser->curr->type == '^') { + consume_token(parser); + for_node->by_pointer = 1; + } + AstLocal* var_node = make_node(AstLocal, Ast_Kind_Local); var_node->token = expect_token(parser, Token_Type_Symbol); - var_node->type_node = (AstType *) &basic_type_i32; for_node->var = var_node; diff --git a/src/onyxwasm.c b/src/onyxwasm.c index 1b6237eb..7534e827 100644 --- a/src/onyxwasm.c +++ b/src/onyxwasm.c @@ -848,14 +848,23 @@ EMIT_FUNC(for_slice, AstFor* for_node, u64 iter_local) { // start_ptr // - u64 end_ptr_local = local_raw_allocate(mod->local_alloc, WASM_TYPE_INT32); - u64 ptr_local = local_raw_allocate(mod->local_alloc, WASM_TYPE_INT32); + u64 end_ptr_local, ptr_local; + end_ptr_local = local_raw_allocate(mod->local_alloc, WASM_TYPE_INT32); + + if (for_node->by_pointer) { + ptr_local = iter_local; + } else { + ptr_local = local_raw_allocate(mod->local_alloc, WASM_TYPE_INT32); + } AstLocal* var = for_node->var; - u64 elem_size = type_size_of(var->type); b32 it_is_local = (b32) ((iter_local & LOCAL_IS_WASM) != 0); u64 offset = 0; + u64 elem_size; + if (for_node->by_pointer) elem_size = type_size_of(var->type->Pointer.elem); + else elem_size = type_size_of(var->type); + WIL(WI_LOCAL_SET, end_ptr_local); WIL(WI_LOCAL_TEE, ptr_local); WIL(WI_LOCAL_GET, end_ptr_local); @@ -879,23 +888,25 @@ EMIT_FUNC(for_slice, AstFor* for_node, u64 iter_local) { WI(WI_I32_GE_S); WID(WI_COND_JUMP, 0x02); - // NOTE: Storing structs requires that the location to store it is, - // the top most thing on the stack. Everything requires it to be - // 'under' the other element being stored. -brendanfh 2020/09/04 - if (!it_is_local && var->type->kind != Type_Kind_Struct) { - emit_local_location(mod, &code, var, &offset); - } + if (!for_node->by_pointer) { + // NOTE: Storing structs requires that the location to store it is, + // the top most thing on the stack. Everything requires it to be + // 'under' the other element being stored. -brendanfh 2020/09/04 + if (!it_is_local && var->type->kind != Type_Kind_Struct) { + emit_local_location(mod, &code, var, &offset); + } - WIL(WI_LOCAL_GET, ptr_local); - emit_load_instruction(mod, &code, var->type, 0); - if (it_is_local) { - WIL(WI_LOCAL_SET, iter_local); - } else { - if (var->type->kind != Type_Kind_Struct) { - emit_store_instruction(mod, &code, var->type, offset); + WIL(WI_LOCAL_GET, ptr_local); + emit_load_instruction(mod, &code, var->type, 0); + if (it_is_local) { + WIL(WI_LOCAL_SET, iter_local); } else { - emit_local_location(mod, &code, var, &offset); - emit_store_instruction(mod, &code, var->type, offset); + if (var->type->kind != Type_Kind_Struct) { + emit_store_instruction(mod, &code, var->type, offset); + } else { + emit_local_location(mod, &code, var, &offset); + emit_store_instruction(mod, &code, var->type, offset); + } } }