@@ -196,6 +196,32 @@ add_members_to_class(
196196 return OK ;
197197}
198198
199+ /*
200+ * Convert a member index "idx" of interface "itf" to the member index of class
201+ * "cl" implementing that interface.
202+ */
203+ int
204+ object_index_from_itf_index (class_T * itf , int idx , class_T * cl )
205+ {
206+ if (idx > itf -> class_obj_member_count )
207+ {
208+ siemsg ("index %d out of range for interface %s" , idx , itf -> class_name );
209+ return 0 ;
210+ }
211+ itf2class_T * i2c ;
212+ for (i2c = itf -> class_itf2class ; i2c != NULL ; i2c = i2c -> i2c_next )
213+ if (i2c -> i2c_class == cl )
214+ break ;
215+ if (i2c == NULL )
216+ {
217+ siemsg ("class %s not found on interface %s" ,
218+ cl -> class_name , itf -> class_name );
219+ return 0 ;
220+ }
221+ int * table = (int * )(i2c + 1 );
222+ return table [idx ];
223+ }
224+
199225/*
200226 * Handle ":class" and ":abstract class" up to ":endclass".
201227 * Handle ":interface" up to ":endinterface".
@@ -765,22 +791,6 @@ ex_class(exarg_T *eap)
765791
766792 cl -> class_extends = extends_cl ;
767793
768- if (ga_impl .ga_len > 0 )
769- {
770- // Move the "implements" names into the class.
771- cl -> class_interface_count = ga_impl .ga_len ;
772- cl -> class_interfaces = ALLOC_MULT (char_u * , ga_impl .ga_len );
773- if (cl -> class_interfaces == NULL )
774- goto cleanup ;
775- for (int i = 0 ; i < ga_impl .ga_len ; ++ i )
776- cl -> class_interfaces [i ] = ((char_u * * )ga_impl .ga_data )[i ];
777- VIM_CLEAR (ga_impl .ga_data );
778- ga_impl .ga_len = 0 ;
779-
780- cl -> class_interfaces_cl = intf_classes ;
781- intf_classes = NULL ;
782- }
783-
784794 // Add class and object members to "cl".
785795 if (add_members_to_class (& classmembers ,
786796 extends_cl == NULL ? NULL
@@ -798,6 +808,48 @@ ex_class(exarg_T *eap)
798808 & cl -> class_obj_member_count ) == FAIL )
799809 goto cleanup ;
800810
811+ if (ga_impl .ga_len > 0 )
812+ {
813+ // Move the "implements" names into the class.
814+ cl -> class_interface_count = ga_impl .ga_len ;
815+ cl -> class_interfaces = ALLOC_MULT (char_u * , ga_impl .ga_len );
816+ if (cl -> class_interfaces == NULL )
817+ goto cleanup ;
818+ for (int i = 0 ; i < ga_impl .ga_len ; ++ i )
819+ cl -> class_interfaces [i ] = ((char_u * * )ga_impl .ga_data )[i ];
820+ VIM_CLEAR (ga_impl .ga_data );
821+ ga_impl .ga_len = 0 ;
822+
823+ // For each interface add a lookuptable for the member index on the
824+ // interface to the member index in this class.
825+ for (int i = 0 ; i < cl -> class_interface_count ; ++ i )
826+ {
827+ class_T * ifcl = intf_classes [i ];
828+ itf2class_T * if2cl = alloc_clear (sizeof (itf2class_T )
829+ + ifcl -> class_obj_member_count * sizeof (int ));
830+ if (if2cl == NULL )
831+ goto cleanup ;
832+ if2cl -> i2c_next = ifcl -> class_itf2class ;
833+ ifcl -> class_itf2class = if2cl ;
834+ if2cl -> i2c_class = cl ;
835+
836+ for (int if_i = 0 ; if_i < ifcl -> class_obj_member_count ; ++ if_i )
837+ for (int cl_i = 0 ; cl_i < cl -> class_obj_member_count ; ++ cl_i )
838+ {
839+ if (STRCMP (ifcl -> class_obj_members [if_i ].ocm_name ,
840+ cl -> class_obj_members [cl_i ].ocm_name ) == 0 )
841+ {
842+ int * table = (int * )(if2cl + 1 );
843+ table [if_i ] = cl_i ;
844+ break ;
845+ }
846+ }
847+ }
848+
849+ cl -> class_interfaces_cl = intf_classes ;
850+ intf_classes = NULL ;
851+ }
852+
801853 if (is_class && cl -> class_class_member_count > 0 )
802854 {
803855 // Allocate a typval for each class member and initialize it.
@@ -1411,6 +1463,13 @@ class_unref(class_T *cl)
14111463 vim_free (cl -> class_interfaces );
14121464 vim_free (cl -> class_interfaces_cl );
14131465
1466+ itf2class_T * next ;
1467+ for (itf2class_T * i2c = cl -> class_itf2class ; i2c != NULL ; i2c = next )
1468+ {
1469+ next = i2c -> i2c_next ;
1470+ vim_free (i2c );
1471+ }
1472+
14141473 for (int i = 0 ; i < cl -> class_class_member_count ; ++ i )
14151474 {
14161475 ocmember_T * m = & cl -> class_class_members [i ];
0 commit comments