diff options
| author | gingerBill <gingerBill@users.noreply.github.com> | 2021-08-22 11:50:47 +0100 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2021-08-22 11:50:47 +0100 |
| commit | d3fee9d76172172a0f8a70b96938dff45f3dd7e6 (patch) | |
| tree | e3ccf349254e041a97cb8e5c5860f2b39eb3e46d /src/check_expr.cpp | |
| parent | 93b5befe45b6464f30f7a9404d1db2d84edf201f (diff) | |
| parent | 36a6805b7cdb8b5e4014b03756f969ce6548ff73 (diff) | |
Merge pull request #1093 from odin-lang/multi-pointers
Multi Pointers `[^]T`
Diffstat (limited to 'src/check_expr.cpp')
| -rw-r--r-- | src/check_expr.cpp | 98 |
1 files changed, 83 insertions, 15 deletions
diff --git a/src/check_expr.cpp b/src/check_expr.cpp index 7c46ef4ca..176685804 100644 --- a/src/check_expr.cpp +++ b/src/check_expr.cpp @@ -592,10 +592,25 @@ i64 check_distance_between_types(CheckerContext *c, Operand *operand, Type *type #if 1 - // TODO(bill): Should I allow this implicit conversion at all?! // rawptr <- ^T if (are_types_identical(type, t_rawptr) && is_type_pointer(src)) { - return 5; + return 5; + } + // rawptr <- [^]T + if (are_types_identical(type, t_rawptr) && is_type_multi_pointer(src)) { + return 5; + } + // ^T <- [^]T + if (dst->kind == Type_Pointer && src->kind == Type_MultiPointer) { + if (are_types_identical(dst->Pointer.elem, src->MultiPointer.elem)) { + return 4; + } + } + // [^]T <- ^T + if (dst->kind == Type_MultiPointer && src->kind == Type_Pointer) { + if (are_types_identical(dst->MultiPointer.elem, src->Pointer.elem)) { + return 4; + } } #endif @@ -930,6 +945,16 @@ bool is_polymorphic_type_assignable(CheckerContext *c, Type *poly, Type *source, return is_polymorphic_type_assignable(c, poly->Pointer.elem, source->Pointer.elem, true, modify_type); } return false; + + case Type_MultiPointer: + if (source->kind == Type_MultiPointer) { + isize level = check_is_assignable_to_using_subtype(source->MultiPointer.elem, poly->MultiPointer.elem); + if (level > 0) { + return true; + } + return is_polymorphic_type_assignable(c, poly->MultiPointer.elem, source->MultiPointer.elem, true, modify_type); + } + return false; case Type_Array: if (source->kind == Type_Array) { if (poly->Array.generic_count != nullptr) { @@ -2392,6 +2417,15 @@ bool check_is_castable_to(CheckerContext *c, Operand *operand, Type *y) { if (is_type_pointer(src) && is_type_pointer(dst)) { return true; } + if (is_type_multi_pointer(src) && is_type_multi_pointer(dst)) { + return true; + } + if (is_type_multi_pointer(src) && is_type_pointer(dst)) { + return true; + } + if (is_type_pointer(src) && is_type_multi_pointer(dst)) { + return true; + } // uintptr <-> pointer if (is_type_uintptr(src) && is_type_pointer(dst)) { @@ -2400,16 +2434,18 @@ bool check_is_castable_to(CheckerContext *c, Operand *operand, Type *y) { if (is_type_pointer(src) && is_type_uintptr(dst)) { return true; } + if (is_type_uintptr(src) && is_type_multi_pointer(dst)) { + return true; + } + if (is_type_multi_pointer(src) && is_type_uintptr(dst)) { + return true; + } // []byte/[]u8 <-> string (not cstring) if (is_type_u8_slice(src) && (is_type_string(dst) && !is_type_cstring(dst))) { return true; } - if ((is_type_string(src) && !is_type_cstring(src)) && is_type_u8_slice(dst)) { - // if (is_type_typed(src)) { - // return true; - // } - } + // cstring -> string if (are_types_identical(src, t_cstring) && are_types_identical(dst, t_string)) { if (operand->mode != Addressing_Constant) { @@ -2421,6 +2457,10 @@ bool check_is_castable_to(CheckerContext *c, Operand *operand, Type *y) { if (are_types_identical(src, t_cstring) && is_type_u8_ptr(dst)) { return !is_constant; } + // cstring -> [^]u8 + if (are_types_identical(src, t_cstring) && is_type_u8_multi_ptr(dst)) { + return !is_constant; + } // cstring -> rawptr if (are_types_identical(src, t_cstring) && is_type_rawptr(dst)) { return !is_constant; @@ -2430,6 +2470,10 @@ bool check_is_castable_to(CheckerContext *c, Operand *operand, Type *y) { if (is_type_u8_ptr(src) && are_types_identical(dst, t_cstring)) { return !is_constant; } + // [^]u8 -> cstring + if (is_type_u8_multi_ptr(src) && are_types_identical(dst, t_cstring)) { + return !is_constant; + } // rawptr -> cstring if (is_type_rawptr(src) && are_types_identical(dst, t_cstring)) { return !is_constant; @@ -3328,7 +3372,7 @@ void convert_to_typed(CheckerContext *c, Operand *operand, Type *target_type) { operand->type = target_type; } -bool check_index_value(CheckerContext *c, bool open_range, Ast *index_value, i64 max_count, i64 *value, Type *type_hint=nullptr) { +bool check_index_value(CheckerContext *c, Type *main_type, bool open_range, Ast *index_value, i64 max_count, i64 *value, Type *type_hint=nullptr) { Operand operand = {Addressing_Invalid}; check_expr_with_type_hint(c, &operand, index_value, type_hint); if (operand.mode == Addressing_Invalid) { @@ -3367,7 +3411,7 @@ bool check_index_value(CheckerContext *c, bool open_range, Ast *index_value, i64 if (operand.mode == Addressing_Constant && (c->state_flags & StateFlag_no_bounds_check) == 0) { BigInt i = exact_value_to_integer(operand.value).value_integer; - if (i.sign && !is_type_enum(index_type)) { + if (i.sign && !is_type_enum(index_type) && !is_type_multi_pointer(main_type)) { gbString expr_str = expr_to_string(operand.expr); error(operand.expr, "Index '%s' cannot be a negative value", expr_str); gb_string_free(expr_str); @@ -6102,6 +6146,13 @@ bool check_set_index_data(Operand *o, Type *t, bool indirection, i64 *max_count, } break; + case Type_MultiPointer: + o->type = t->MultiPointer.elem; + if (o->mode != Addressing_Constant) { + o->mode = Addressing_Variable; + } + return true; + case Type_Array: *max_count = t->Array.count; if (indirection) { @@ -8133,13 +8184,9 @@ ExprKind check_expr_base_internal(CheckerContext *c, Operand *o, Ast *node, Type } i64 index = 0; - bool ok = check_index_value(c, false, ie->index, max_count, &index, index_type_hint); + bool ok = check_index_value(c, t, false, ie->index, max_count, &index, index_type_hint); if (is_const) { if (index < 0) { - if (max_count < 0) { - - } - gbString str = expr_to_string(o->expr); error(o->expr, "Cannot index a constant '%s'", str); error_line("\tSuggestion: store the constant into a variable in order to index it with a variable index\n"); @@ -8206,6 +8253,11 @@ ExprKind check_expr_base_internal(CheckerContext *c, Operand *o, Ast *node, Type o->type = alloc_type_slice(t->Array.elem); break; + case Type_MultiPointer: + valid = true; + o->type = type_deref(o->type); + break; + case Type_Slice: valid = true; o->type = type_deref(o->type); @@ -8262,7 +8314,7 @@ ExprKind check_expr_base_internal(CheckerContext *c, Operand *o, Ast *node, Type capacity = max_count; } i64 j = 0; - if (check_index_value(c, true, nodes[i], capacity, &j)) { + if (check_index_value(c, t, true, nodes[i], capacity, &j)) { index = j; } @@ -8291,6 +8343,16 @@ ExprKind check_expr_base_internal(CheckerContext *c, Operand *o, Ast *node, Type } } + if (t->kind == Type_MultiPointer && se->high != nullptr) { + /* + x[:] -> [^]T + x[i:] -> [^]T + x[:n] -> []T + x[i:n] -> []T + */ + o->type = alloc_type_slice(t->MultiPointer.elem); + } + o->mode = Addressing_Value; if (is_type_string(t) && max_count >= 0) { @@ -8424,6 +8486,7 @@ ExprKind check_expr_base_internal(CheckerContext *c, Operand *o, Ast *node, Type case Ast_PolyType: case Ast_ProcType: case Ast_PointerType: + case Ast_MultiPointerType: case Ast_ArrayType: case Ast_DynamicArrayType: case Ast_StructType: @@ -8869,6 +8932,11 @@ gbString write_expr_to_string(gbString str, Ast *node, bool shorthand) { str = write_expr_to_string(str, pt->type, shorthand); case_end; + case_ast_node(pt, MultiPointerType, node); + str = gb_string_appendc(str, "[^]"); + str = write_expr_to_string(str, pt->type, shorthand); + case_end; + case_ast_node(at, ArrayType, node); str = gb_string_append_rune(str, '['); if (at->count != nullptr && |