Add multi-pointer types [^]T

This commit is contained in:
gingerBill
2021-08-21 23:10:21 +01:00
parent 01a888fced
commit 6a77fc4cdd
10 changed files with 286 additions and 50 deletions

View File

@@ -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) {