mirror of
https://github.com/Ed94/Odin.git
synced 2026-07-15 15:41:26 -07:00
Pointer arithmetic builtin procedures
This commit is contained in:
@@ -70,102 +70,6 @@ b32 check_is_terminating(Checker *c, AstNode *node) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
b32 check_is_assignable_to(Checker *c, Operand *operand, Type *type) {
|
||||
if (operand->mode == Addressing_Invalid ||
|
||||
type == t_invalid) {
|
||||
return true;
|
||||
}
|
||||
|
||||
Type *s = operand->type;
|
||||
|
||||
if (are_types_identical(s, type))
|
||||
return true;
|
||||
|
||||
Type *sb = get_base_type(s);
|
||||
Type *tb = get_base_type(type);
|
||||
|
||||
if (is_type_untyped(sb)) {
|
||||
switch (tb->kind) {
|
||||
case Type_Basic:
|
||||
if (operand->mode == Addressing_Constant)
|
||||
return check_value_is_expressible(c, operand->value, tb, NULL);
|
||||
if (sb->kind == Type_Basic)
|
||||
return sb->Basic.kind == Basic_UntypedBool && is_type_boolean(tb);
|
||||
break;
|
||||
case Type_Pointer:
|
||||
return sb->Basic.kind == Basic_UntypedPointer;
|
||||
}
|
||||
}
|
||||
|
||||
if (are_types_identical(sb, tb) && (!is_type_named(sb) || !is_type_named(tb)))
|
||||
return true;
|
||||
|
||||
if (is_type_pointer(sb) && is_type_rawptr(tb))
|
||||
return true;
|
||||
|
||||
if (is_type_rawptr(sb) && is_type_pointer(tb))
|
||||
return true;
|
||||
|
||||
if (sb->kind == Type_Array && tb->kind == Type_Array) {
|
||||
if (are_types_identical(sb->Array.elem, tb->Array.elem)) {
|
||||
return sb->Array.count == tb->Array.count;
|
||||
}
|
||||
}
|
||||
|
||||
if (sb->kind == Type_Slice && tb->kind == Type_Slice) {
|
||||
if (are_types_identical(sb->Slice.elem, tb->Slice.elem)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return false;
|
||||
|
||||
}
|
||||
|
||||
|
||||
// NOTE(bill): `content_name` is for debugging
|
||||
// TODO(bill): Maybe allow assignment to tuples?
|
||||
void check_assignment(Checker *c, Operand *operand, Type *type, String context_name) {
|
||||
check_not_tuple(c, operand);
|
||||
if (operand->mode == Addressing_Invalid)
|
||||
return;
|
||||
|
||||
if (is_type_untyped(operand->type)) {
|
||||
Type *target_type = type;
|
||||
|
||||
if (type == NULL)
|
||||
target_type = default_type(operand->type);
|
||||
convert_to_typed(c, operand, target_type);
|
||||
if (operand->mode == Addressing_Invalid)
|
||||
return;
|
||||
}
|
||||
|
||||
if (type != NULL) {
|
||||
if (!check_is_assignable_to(c, operand, type)) {
|
||||
gbString type_string = type_to_string(type);
|
||||
gbString op_type_string = type_to_string(operand->type);
|
||||
gbString expr_str = expr_to_string(operand->expr);
|
||||
defer (gb_string_free(type_string));
|
||||
defer (gb_string_free(op_type_string));
|
||||
defer (gb_string_free(expr_str));
|
||||
|
||||
|
||||
// TODO(bill): is this a good enough error message?
|
||||
error(&c->error_collector, ast_node_token(operand->expr),
|
||||
"Cannot assign value `%s` of type `%s` to `%s` in %.*s",
|
||||
expr_str,
|
||||
op_type_string,
|
||||
type_string,
|
||||
LIT(context_name));
|
||||
|
||||
operand->mode = Addressing_Invalid;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Type *check_assignment_variable(Checker *c, Operand *op_a, AstNode *lhs) {
|
||||
if (op_a->mode == Addressing_Invalid ||
|
||||
op_a->type == t_invalid) {
|
||||
|
||||
Reference in New Issue
Block a user