Pointer arithmetic builtin procedures

This commit is contained in:
Ginger Bill
2016-08-27 11:05:08 +01:00
parent 3a189b9c1c
commit ae75ab169b
6 changed files with 391 additions and 143 deletions
-96
View File
@@ -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) {