diff options
| author | gingerBill <bill@gingerbill.org> | 2022-09-08 16:52:51 +0100 |
|---|---|---|
| committer | gingerBill <bill@gingerbill.org> | 2022-09-08 16:52:51 +0100 |
| commit | f77709e67e405419b5e60c6645e2483484aeb010 (patch) | |
| tree | 70312ce811a5fc2988d46d0e5560f90fb060e2c3 /src/check_builtin.cpp | |
| parent | 81e3b64ecda857458b8e0762bdf6156cdaa1cb74 (diff) | |
Add `intrinsics.type_convert_variants_to_pointers` and `reflect.get_union_as_ptr_variants`
Diffstat (limited to 'src/check_builtin.cpp')
| -rw-r--r-- | src/check_builtin.cpp | 40 |
1 files changed, 40 insertions, 0 deletions
diff --git a/src/check_builtin.cpp b/src/check_builtin.cpp index 07eeeacca..f0db6afc4 100644 --- a/src/check_builtin.cpp +++ b/src/check_builtin.cpp @@ -4613,6 +4613,46 @@ bool check_builtin_procedure(CheckerContext *c, Operand *operand, Ast *call, i32 operand->mode = Addressing_Type; break; + case BuiltinProc_type_convert_variants_to_pointers: + if (operand->mode != Addressing_Type) { + error(operand->expr, "Expected a type for '%.*s'", LIT(builtin_name)); + } else { + Type *bt = base_type(operand->type); + if (is_type_polymorphic(bt)) { + // IGNORE polymorphic types + return true; + } else if (bt->kind != Type_Union) { + gbString t = type_to_string(operand->type); + error(operand->expr, "Expected a union type for '%.*s', got %s", LIT(builtin_name), t); + gb_string_free(t); + + operand->mode = Addressing_Invalid; + operand->type = t_invalid; + return false; + } else if (bt->Union.is_polymorphic) { + gbString t = type_to_string(operand->type); + error(operand->expr, "Expected a non-polymorphic union type for '%.*s', got %s", LIT(builtin_name), t); + gb_string_free(t); + + operand->mode = Addressing_Invalid; + operand->type = t_invalid; + return false; + } + + Type *new_type = alloc_type_union(); + auto variants = slice_make<Type *>(permanent_allocator(), bt->Union.variants.count); + for_array(i, bt->Union.variants) { + variants[i] = alloc_type_pointer(bt->Union.variants[i]); + } + new_type->Union.variants = variants; + + // NOTE(bill): Is this even correct? + new_type->Union.scope = bt->Union.scope; + + operand->type = new_type; + } + operand->mode = Addressing_Type; + break; case BuiltinProc_type_is_boolean: case BuiltinProc_type_is_integer: |