patch 9.0.1254: calling a method on an interface does not work

Problem:    Calling a method on an interface does not work.
Solution:   At runtime figure out what method to call. (closes #11901)
diff --git a/src/vim9class.c b/src/vim9class.c
index d64e35e..ecf5de7 100644
--- a/src/vim9class.c
+++ b/src/vim9class.c
@@ -201,16 +201,17 @@
  * "cl" implementing that interface.
  */
     int
-object_index_from_itf_index(class_T *itf, int idx, class_T *cl)
+object_index_from_itf_index(class_T *itf, int is_method, int idx, class_T *cl)
 {
-    if (idx > itf->class_obj_member_count)
+    if (idx > (is_method ? itf->class_obj_method_count
+						: itf->class_obj_member_count))
     {
 	siemsg("index %d out of range for interface %s", idx, itf->class_name);
 	return 0;
     }
     itf2class_T *i2c;
     for (i2c = itf->class_itf2class; i2c != NULL; i2c = i2c->i2c_next)
-	if (i2c->i2c_class == cl)
+	if (i2c->i2c_class == cl && i2c->i2c_is_method == is_method)
 	    break;
     if (i2c == NULL)
     {
@@ -789,7 +790,11 @@
 	if (cl->class_name == NULL)
 	    goto cleanup;
 
-	cl->class_extends = extends_cl;
+	if (extends_cl != NULL)
+	{
+	    cl->class_extends = extends_cl;
+	    extends_cl->class_flags |= CLASS_EXTENDED;
+	}
 
 	// Add class and object members to "cl".
 	if (add_members_to_class(&classmembers,
@@ -820,11 +825,26 @@
 	    VIM_CLEAR(ga_impl.ga_data);
 	    ga_impl.ga_len = 0;
 
+	    cl->class_interfaces_cl = intf_classes;
+	    intf_classes = NULL;
+	}
+
+	if (cl->class_interface_count > 0 || extends_cl != NULL)
+	{
 	    // For each interface add a lookuptable for the member index on the
 	    // interface to the member index in this class.
-	    for (int i = 0; i < cl->class_interface_count; ++i)
+	    // And a lookuptable for the object method index on the interface
+	    // to the object method index in this class.
+	    // Also do this for the extended class, if any.
+	    for (int i = 0; i <= cl->class_interface_count; ++i)
 	    {
-		class_T *ifcl = intf_classes[i];
+		class_T *ifcl = i < cl->class_interface_count
+					    ? cl->class_interfaces_cl[i]
+					    : extends_cl;
+		if (ifcl == NULL)
+		    continue;
+
+		// Table for members.
 		itf2class_T *if2cl = alloc_clear(sizeof(itf2class_T)
 				 + ifcl->class_obj_member_count * sizeof(int));
 		if (if2cl == NULL)
@@ -832,22 +852,64 @@
 		if2cl->i2c_next = ifcl->class_itf2class;
 		ifcl->class_itf2class = if2cl;
 		if2cl->i2c_class = cl;
+		if2cl->i2c_is_method = FALSE;
 
 		for (int if_i = 0; if_i < ifcl->class_obj_member_count; ++if_i)
-		    for (int cl_i = 0; cl_i < cl->class_obj_member_count; ++cl_i)
+		    for (int cl_i = 0; cl_i < cl->class_obj_member_count;
+									++cl_i)
 		    {
 			if (STRCMP(ifcl->class_obj_members[if_i].ocm_name,
-				     cl->class_obj_members[cl_i].ocm_name) == 0)
+				    cl->class_obj_members[cl_i].ocm_name) == 0)
 			{
 			    int *table = (int *)(if2cl + 1);
 			    table[if_i] = cl_i;
 			    break;
 			}
 		    }
-	    }
 
-	    cl->class_interfaces_cl = intf_classes;
-	    intf_classes = NULL;
+		// Table for methods.
+		if2cl = alloc_clear(sizeof(itf2class_T)
+				 + ifcl->class_obj_method_count * sizeof(int));
+		if (if2cl == NULL)
+		    goto cleanup;
+		if2cl->i2c_next = ifcl->class_itf2class;
+		ifcl->class_itf2class = if2cl;
+		if2cl->i2c_class = cl;
+		if2cl->i2c_is_method = TRUE;
+
+		for (int if_i = 0; if_i < ifcl->class_obj_method_count; ++if_i)
+		{
+		    int done = FALSE;
+		    for (int cl_i = 0; cl_i < objmethods.ga_len; ++cl_i)
+		    {
+			if (STRCMP(ifcl->class_obj_methods[if_i]->uf_name,
+			       ((ufunc_T **)objmethods.ga_data)[cl_i]->uf_name)
+									  == 0)
+			{
+			    int *table = (int *)(if2cl + 1);
+			    table[if_i] = cl_i;
+			    done = TRUE;
+			    break;
+			}
+		    }
+
+		    if (!done && extends_cl != NULL)
+		    {
+			for (int cl_i = 0;
+			     cl_i < extends_cl->class_obj_member_count; ++cl_i)
+			{
+			    if (STRCMP(ifcl->class_obj_methods[if_i]->uf_name,
+				   extends_cl->class_obj_methods[cl_i]->uf_name)
+									  == 0)
+			    {
+				int *table = (int *)(if2cl + 1);
+				table[if_i] = cl_i;
+				break;
+			    }
+			}
+		    }
+		}
+	    }
 	}
 
 	if (is_class && cl->class_class_member_count > 0)