From: Brendan Hansen Date: Fri, 4 Sep 2020 13:26:57 +0000 (-0500) Subject: can subscript array with a value of type 'range'; not just a range X-Git-Url: https://git.brendanfh.com/?a=commitdiff_plain;h=3736c6bb848842842995b2d358c936452782caa1;p=onyx.git can subscript array with a value of type 'range'; not just a range literal --- diff --git a/onyx b/onyx index ca03de2a..5e98dca5 100755 Binary files a/onyx and b/onyx differ diff --git a/progs/poly_test.onyx b/progs/poly_test.onyx index 08bed003..92235e0e 100644 --- a/progs/poly_test.onyx +++ b/progs/poly_test.onyx @@ -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); diff --git a/src/onyxchecker.c b/src/onyxchecker.c index df2fdbd1..fc0be94e 100644 --- a/src/onyxchecker.c +++ b/src/onyxchecker.c @@ -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; diff --git a/src/onyxparser.c b/src/onyxparser.c index c7ff7585..fba93559 100644 --- a/src/onyxparser.c +++ b/src/onyxparser.c @@ -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; diff --git a/src/onyxwasm.c b/src/onyxwasm.c index e8385ed5..1369da02 100644 --- a/src/onyxwasm.c +++ b/src/onyxwasm.c @@ -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; }