can subscript array with a value of type 'range'; not just a range
authorBrendan Hansen <brendan.f.hansen@gmail.com>
Fri, 4 Sep 2020 13:26:57 +0000 (08:26 -0500)
committerBrendan Hansen <brendan.f.hansen@gmail.com>
Fri, 4 Sep 2020 13:26:57 +0000 (08:26 -0500)
literal

onyx
progs/poly_test.onyx
src/onyxchecker.c
src/onyxparser.c
src/onyxwasm.c

diff --git a/onyx b/onyx
index ca03de2a34cabab57896a0afe228f7e6cf028c4a..5e98dca56db5fec2f66e2311403c096a7aa01b04 100755 (executable)
Binary files a/onyx and b/onyx differ
index 08bed003ba4d4d822d184e00b82b826a9f6f4016..92235e0e222ee18a520dd1d27c105879922c0743 100644 (file)
@@ -62,7 +62,7 @@ soa_deinit :: proc (s: ^SOA) {
 }
 
 get_range :: proc (arr: ^[..] $T) -> range {
-    return 0 .. arr.count;
+    return 20 .. 26;
 }
 
 print_range :: proc (r: range) #add_overload print {
@@ -101,6 +101,7 @@ main :: proc (args: [] cstring) {
     array_sort(^s.a, cmp_dec);
     array_sort(^s.b, cmp_asc);
 
+    print_array(s.a.data[r]);
     print_array(s.a.data[21 .. 27]);
     print_array(^s.b);
 
index df2fdbd16e2681e6b66db2c19f1e0bec128a3d31..fc0be94e866c5e9afce9ebdaafd4700f4207273d 100644 (file)
@@ -21,7 +21,6 @@ CHECK(expression, AstTyped** expr);
 CHECK(address_of, AstAddressOf* aof);
 CHECK(dereference, AstDereference* deref);
 CHECK(array_access, AstArrayAccess* expr);
-CHECK(slice, AstArrayAccess* sl);
 CHECK(field_access, AstFieldAccess** pfield);
 CHECK(range_literal, AstBinaryOp** range);
 CHECK(size_of, AstSizeOf* so);
@@ -840,6 +839,24 @@ 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))) {
+        Type *of = NULL;
+        if (aa->addr->type->kind == Type_Kind_Pointer)
+            of = aa->addr->type->Pointer.elem;
+        else if (aa->addr->type->kind == Type_Kind_Array)
+            of = aa->addr->type->Array.elem;
+        else {
+            onyx_report_error(aa->token->pos, "Invalid type for left of slice creation.");
+            return 1;
+        }
+
+        aa->kind = Ast_Kind_Slice;
+        aa->type = type_make_slice(semstate.node_allocator, of);
+        aa->elem_size = type_size_of(of);
+
+        return 0;
+    }
+
     if (aa->expr->type->kind != Type_Kind_Basic
             || (aa->expr->type->Basic.kind != Basic_Kind_I32 && aa->expr->type->Basic.kind != Basic_Kind_U32)) {
         onyx_report_error(aa->token->pos, "Expected type u32 or i32 for index.");
@@ -877,31 +894,6 @@ b32 check_array_access(AstArrayAccess* aa) {
     return 0;
 }
 
-b32 check_slice(AstArrayAccess* sl) {
-    if (check_expression(&sl->addr)) return 1;
-    if (check_expression(&sl->expr)) return 1;
-
-    if (!type_is_pointer(sl->addr->type)) {
-        onyx_report_error(sl->token->pos, "Expected pointer or array type for left of slice creation.");
-        return 1;
-    }
-
-    Type *of = NULL;
-    if (sl->addr->type->kind == Type_Kind_Pointer)
-        of = sl->addr->type->Pointer.elem;
-    else if (sl->addr->type->kind == Type_Kind_Array)
-        of = sl->addr->type->Array.elem;
-    else {
-        onyx_report_error(sl->token->pos, "Invalid type for left of slice creation.");
-        return 1;
-    }
-
-    sl->type = type_make_slice(semstate.node_allocator, of);
-    sl->elem_size = type_size_of(of);
-
-    return 0;
-}
-
 b32 check_field_access(AstFieldAccess** pfield) {
     AstFieldAccess* field = *pfield;
     if (check_expression(&field->expr)) return 1;
@@ -962,8 +954,11 @@ b32 check_range_literal(AstBinaryOp** prange) {
     AstStructLiteral* rsl = onyx_ast_node_new(semstate.node_allocator, sizeof(AstStructLiteral), Ast_Kind_Struct_Literal);
     bh_arr_new(global_heap_allocator, rsl->values, 3);
 
-    bh_arr_push(rsl->values, range->left);
-    bh_arr_push(rsl->values, range->right);
+    bh_arr_insert_end(rsl->values, 2);
+    type_lookup_member(expected_range_type, "low", &smem);
+    rsl->values[smem.idx] = range->left;
+    type_lookup_member(expected_range_type, "high", &smem);
+    rsl->values[smem.idx] = range->right;
 
     // HACK: This relies on the third member of the 'range' struct to exist, be the step,
     // and have an intial_value.
@@ -1027,8 +1022,8 @@ b32 check_expression(AstTyped** pexpr) {
 
         case Ast_Kind_Address_Of:   retval = check_address_of((AstAddressOf *) expr); break;
         case Ast_Kind_Dereference:  retval = check_dereference((AstDereference *) expr); break;
+        case Ast_Kind_Slice:
         case Ast_Kind_Array_Access: retval = check_array_access((AstArrayAccess *) expr); break;
-        case Ast_Kind_Slice:        retval = check_slice((AstArrayAccess *) expr); break;
         case Ast_Kind_Field_Access: retval = check_field_access((AstFieldAccess **) pexpr); break;
         case Ast_Kind_Size_Of:      retval = check_size_of((AstSizeOf *) expr); break;
         case Ast_Kind_Align_Of:     retval = check_align_of((AstAlignOf *) expr); break;
index c7ff7585f753d08230a9c5f8caa7d0a6ec35dff6..fba93559f6fed994440fe3134eaebe94245983f9 100644 (file)
@@ -520,8 +520,6 @@ static AstTyped* parse_factor(OnyxParser* parser) {
                 AstTyped *expr = parse_expression(parser);
 
                 AstKind kind = Ast_Kind_Array_Access;
-                if (expr->kind == Ast_Kind_Range)
-                    kind = Ast_Kind_Slice;
 
                 AstArrayAccess *aa_node = make_node(AstArrayAccess, kind);
                 aa_node->token = open_bracket;
index e8385ed501340e47413c4a2fef090d712b58f3d5..1369da029ff2c95c8c1018df3d9e0f7e8051ddee 100644 (file)
@@ -1597,33 +1597,26 @@ EMIT_FUNC(expression, AstTyped* expr) {
         case Ast_Kind_Slice: {
             AstArrayAccess* sl = (AstArrayAccess *) expr;
 
-            AstTyped *lo, *hi;
+            emit_expression(mod, &code, sl->expr);
 
-            // NOTE: Since all ranges are converted to struct literals,
-            // we need to extract the expressions from the struct literal
-            // data. Doing it in this verbose way for robustness sake.
-            AstStructLiteral *range_literal = (AstStructLiteral *) sl->expr;
-            StructMember smem;
-            type_lookup_member(range_literal->type, "low", &smem);
-            lo = range_literal->values[smem.idx];
-            type_lookup_member(range_literal->type, "high", &smem);
-            hi = range_literal->values[smem.idx];
-
-            u64 tmp_local = local_raw_allocate(mod->local_alloc, WASM_TYPE_INT32);
+            u64 lo_local = local_raw_allocate(mod->local_alloc, WASM_TYPE_INT32);
+            u64 hi_local = local_raw_allocate(mod->local_alloc, WASM_TYPE_INT32);
 
-            emit_expression(mod, &code, lo);
-            WIL(WI_LOCAL_TEE, tmp_local);
+            WI(WI_DROP);
+            WIL(WI_LOCAL_SET, hi_local);
+            WIL(WI_LOCAL_TEE, lo_local);
             if (sl->elem_size != 1) {
                 WID(WI_I32_CONST, sl->elem_size);
                 WI(WI_I32_MUL);
             }
             emit_expression(mod, &code, sl->addr);
             WI(WI_I32_ADD);
-            emit_expression(mod, &code, hi);
-            WIL(WI_LOCAL_GET, tmp_local);
+            WIL(WI_LOCAL_GET, hi_local);
+            WIL(WI_LOCAL_GET, lo_local);
             WI(WI_I32_SUB);
 
-            local_raw_free(mod->local_alloc, tmp_local);
+            local_raw_free(mod->local_alloc, lo_local);
+            local_raw_free(mod->local_alloc, hi_local);
             break;
         }