added iteration by pointer to for loops
authorBrendan Hansen <brendan.f.hansen@gmail.com>
Sat, 5 Sep 2020 04:50:58 +0000 (23:50 -0500)
committerBrendan Hansen <brendan.f.hansen@gmail.com>
Sat, 5 Sep 2020 04:50:58 +0000 (23:50 -0500)
core/array.onyx
include/onyxastnodes.h
onyx
progs/poly_test.onyx
src/onyxchecker.c
src/onyxparser.c
src/onyxwasm.c

index ad37a554146d461f644654f9093428ece80da64a..0d314deb33183d1dc820b31214db92b9d0d58296 100644 (file)
@@ -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;
 }
 
index 25677186776f75672c7f8503e1d7f9378c33ceaf..599a5adbc78532b849429179db9feaf1bd74fe68 100644 (file)
@@ -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 93a0ad264e39c9958cd53ffcdb64a33865eabca9..72b0bd66b59e0791e368135e90b59027dae26985 100755 (executable)
Binary files a/onyx and b/onyx differ
index 78ba380752fbb25d99f11c67db3b554e220a98bc..b025dbd3f6c81dcca25c8f80a817036f1c2215fb 100644 (file)
@@ -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);
index 3fed3fccbdd316bfaeb5053d2a5f5e0ccf46caa9..165b7d516efeefeb4333a2e73f5268118875a1ee 100644 (file)
@@ -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;
     }
 
index cacb22ae9cdf02a89ae28322bb3fa3e394a8f572..fe9c353d91504ec3f1ed87ff42d721906572ef3c 100644 (file)
@@ -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;
 
index 1b6237eb6fe275f2d509e54205ef6c69099b060d..7534e82746b00cb08d956a3a0d764ffeeaf5f929 100644 (file)
@@ -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);
+            }
         }
     }