Browse Source

Fix subtype polymorphism

Ginger Bill 9 years ago
parent
commit
ff6e21cb87
3 changed files with 38 additions and 17 deletions
  1. 2 2
      examples/demo.odin
  2. 6 2
      src/checker/expr.cpp
  3. 30 13
      src/codegen/ssa.cpp

+ 2 - 2
examples/demo.odin

@@ -33,8 +33,8 @@ main :: proc() {
 	print_f32(f.jump_height); nl()
 	print_f32(parent.jump_height); nl()
 
-	print_name(f.entity, Vec3{1, 2, 3})
-	print_name(parent.entity, Vec3{3, 2, 1})
+	print_name(f, Vec3{1, 2, 3})
+	print_name(parent, Vec3{3, 2, 1})
 
 
 }

+ 6 - 2
src/checker/expr.cpp

@@ -15,7 +15,7 @@ void     update_expr_type          (Checker *c, AstNode *e, Type *type, b32 fina
 
 
 
-b32 check_is_assignable_to_using_subtype(Checker *c, Type *dst, Type *src) {
+b32 check_is_assignable_to_using_subtype(Type *dst, Type *src) {
 	Type *prev_src = src;
 	// Type *prev_dst = dst;
 	src = get_base_type(type_deref(src));
@@ -35,6 +35,10 @@ b32 check_is_assignable_to_using_subtype(Checker *c, Type *dst, Type *src) {
 						return true;
 					}
 				}
+				b32 ok = check_is_assignable_to_using_subtype(dst, f->type);
+				if (ok) {
+					return true;
+				}
 			}
 		}
 	}
@@ -91,7 +95,7 @@ b32 check_is_assignable_to(Checker *c, Operand *operand, Type *type, b32 is_argu
 
 	if (is_argument) {
 		// NOTE(bill): Polymorphism for subtyping
-		if (check_is_assignable_to_using_subtype(c, type, src)) {
+		if (check_is_assignable_to_using_subtype(type, src)) {
 			return true;
 		}
 	}

+ 30 - 13
src/codegen/ssa.cpp

@@ -1288,7 +1288,34 @@ ssaValue *ssa_emit_string(ssaProcedure *proc, ssaValue *elem, ssaValue *len) {
 	return str;
 }
 
-
+String lookup_polymorphic_field(CheckerInfo *info, Type *dst, Type *src) {
+	Type *prev_src = src;
+	// Type *prev_dst = dst;
+	src = get_base_type(type_deref(src));
+	// dst = get_base_type(type_deref(dst));
+	b32 src_is_ptr = src != prev_src;
+	// b32 dst_is_ptr = dst != prev_dst;
+
+	GB_ASSERT(src->kind == Type_Struct);
+	for (isize i = 0; i < src->Struct.field_count; i++) {
+		Entity *f = src->Struct.fields[i];
+		if (f->kind == Entity_Variable && f->Variable.anonymous) {
+			if (are_types_identical(dst, f->type)) {
+				return f->token.string;
+			}
+			if (src_is_ptr && is_type_pointer(dst)) {
+				if (are_types_identical(type_deref(dst), f->type)) {
+					return f->token.string;
+				}
+			}
+			String name = lookup_polymorphic_field(info, dst, f->type);
+			if (name.len > 0) {
+				return name;
+			}
+		}
+	}
+	return make_string("");
+}
 
 
 ssaValue *ssa_emit_conv(ssaProcedure *proc, ssaValue *value, Type *t, b32 is_argument) {
@@ -1394,18 +1421,8 @@ ssaValue *ssa_emit_conv(ssaProcedure *proc, ssaValue *value, Type *t, b32 is_arg
 		Type *sb = get_base_type(type_deref(src));
 		b32 src_is_ptr = src != sb;
 		if (sb->kind == Type_Struct) {
-			// NOTE(bill): Check
-			String field_name = {};
-			for (isize i = 0; i < sb->Struct.field_count; i++) {
-				Entity *f = sb->Struct.fields[i];
-				if (f->kind == Entity_Variable && f->Variable.anonymous) {
-					if (are_types_identical(t, f->type)) {
-						field_name = f->token.string;
-						break;
-					}
-				}
-			}
-
+			String field_name = lookup_polymorphic_field(proc->module->info, t, src);
+			// gb_printf("field_name: %.*s\n", LIT(field_name));
 			if (field_name.len > 0) {
 				// NOTE(bill): It can be casted
 				Selection sel = lookup_field(sb, field_name, false);