diff options
| author | gingerBill <bill@gingerbill.org> | 2021-08-21 23:10:21 +0100 |
|---|---|---|
| committer | gingerBill <bill@gingerbill.org> | 2021-08-21 23:10:21 +0100 |
| commit | 6a77fc4cdd35b2ecd1c32f7c5f2e249d6e225d91 (patch) | |
| tree | da479dcee4640fa3a21b440478644f7c67206bfc /src/check_expr.cpp | |
| parent | 01a888fcedbdcfa4bd86de6e3346104cad8faa8a (diff) | |
Add multi-pointer types `[^]T`
Diffstat (limited to 'src/check_expr.cpp')
| -rw-r--r-- | src/check_expr.cpp | 82 |
1 files changed, 67 insertions, 15 deletions
diff --git a/src/check_expr.cpp b/src/check_expr.cpp index 7c46ef4ca..68009882f 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 (is_type_pointer(dst) && is_type_multi_pointer(src)) { + if (are_types_identical(dst->Pointer.elem, src->MultiPointer.elem)) { + return 4; + } + } + // [^]T <- ^T + if (is_type_multi_pointer(dst) && is_type_pointer(src)) { + if (are_types_identical(dst->MultiPointer.elem, src->Pointer.elem)) { + return 4; + } } #endif @@ -2392,6 +2407,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 +2424,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 +2447,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 +2460,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 +3362,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 +3401,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 +6136,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 +8174,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 +8243,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 +8304,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 +8333,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) { |