aboutsummaryrefslogtreecommitdiff
path: root/src/types.cpp
diff options
context:
space:
mode:
authorgingerBill <bill@gingerbill.org>2022-02-08 22:59:37 +0000
committergingerBill <bill@gingerbill.org>2022-02-08 22:59:37 +0000
commitc5d348515dcddbd2c29aca79f1863dd36af5476a (patch)
treef2e2c5a97c72292f98bfd40f6dca30ffaaaaf96d /src/types.cpp
parent05dd3d490de3bf10c56e65987fbbe3024b84a4a6 (diff)
Add `intrinsics.type_is_subtype_of`; `intrinsics.objc_selector_name`
Diffstat (limited to 'src/types.cpp')
-rw-r--r--src/types.cpp44
1 files changed, 44 insertions, 0 deletions
diff --git a/src/types.cpp b/src/types.cpp
index cdb31c6e1..024d644a2 100644
--- a/src/types.cpp
+++ b/src/types.cpp
@@ -3748,6 +3748,50 @@ i64 type_offset_of_from_selection(Type *type, Selection sel) {
return offset;
}
+isize check_is_assignable_to_using_subtype(Type *src, Type *dst, isize level = 0, bool src_is_ptr = false) {
+ Type *prev_src = src;
+ src = type_deref(src);
+ if (!src_is_ptr) {
+ src_is_ptr = src != prev_src;
+ }
+ src = base_type(src);
+
+ if (!is_type_struct(src)) {
+ return 0;
+ }
+
+ for_array(i, src->Struct.fields) {
+ Entity *f = src->Struct.fields[i];
+ if (f->kind != Entity_Variable || (f->flags&EntityFlag_Using) == 0) {
+ continue;
+ }
+
+ if (are_types_identical(f->type, dst)) {
+ return level+1;
+ }
+ if (src_is_ptr && is_type_pointer(dst)) {
+ if (are_types_identical(f->type, type_deref(dst))) {
+ return level+1;
+ }
+ }
+ isize nested_level = check_is_assignable_to_using_subtype(f->type, dst, level+1, src_is_ptr);
+ if (nested_level > 0) {
+ return nested_level;
+ }
+ }
+
+ return 0;
+}
+
+bool is_type_subtype_of(Type *src, Type *dst) {
+ if (are_types_identical(src, dst)) {
+ return true;
+ }
+
+ return 0 < check_is_assignable_to_using_subtype(src, dst, 0, is_type_pointer(src));
+}
+
+
Type *get_struct_field_type(Type *t, isize index) {
t = base_type(type_deref(t));