comparison src/vim9class.c @ 33506:f61713271934 v9.0.2002

patch 9.0.2002: Vim9: need cleanup of class related interface code Commit: https://github.com/vim/vim/commit/b852305dbf42f1206ecc6ae414fc200235fe2963 Author: Yegappan Lakshmanan <yegappan@yahoo.com> Date: Sun Oct 8 19:07:39 2023 +0200 patch 9.0.2002: Vim9: need cleanup of class related interface code Problem: Vim9: need cleanup of class related interface code Solution: Remove the unused class variable and class method related code for interfaces. Remove unused class variable and class method related code for interfaces. Refactor the code. Optimize the object/class member double lookup in compile_lhs(). Change unused global functions to static functions. closes: #13302 Signed-off-by: Christian Brabandt <cb@256bit.org> Co-authored-by: Yegappan Lakshmanan <yegappan@yahoo.com>
author Christian Brabandt <cb@256bit.org>
date Sun, 08 Oct 2023 19:15:06 +0200
parents bff8ac203a22
children c8bd88bdb630
comparison
equal deleted inserted replaced
33505:398e729a5cd9 33506:f61713271934
553 */ 553 */
554 static int 554 static int
555 intf_variable_present( 555 intf_variable_present(
556 char_u *intf_class_name, 556 char_u *intf_class_name,
557 ocmember_T *if_var, 557 ocmember_T *if_var,
558 int is_class_var,
559 ocmember_T *cl_mt, 558 ocmember_T *cl_mt,
560 int cl_member_count, 559 int cl_member_count,
561 class_T *extends_cl) 560 class_T *extends_cl)
562 { 561 {
563 int variable_present = FALSE; 562 int variable_present = FALSE;
598 break; 597 break;
599 } 598 }
600 599
601 if (!variable_present && extends_cl != NULL) 600 if (!variable_present && extends_cl != NULL)
602 { 601 {
603 int ext_cl_count = is_class_var 602 int ext_cl_count = extends_cl->class_obj_member_count;
604 ? extends_cl->class_class_member_count 603 ocmember_T *ext_cl_mt = extends_cl->class_obj_members;
605 : extends_cl->class_obj_member_count;
606 ocmember_T *ext_cl_mt = is_class_var
607 ? extends_cl->class_class_members
608 : extends_cl->class_obj_members;
609 return intf_variable_present(intf_class_name, if_var, 604 return intf_variable_present(intf_class_name, if_var,
610 is_class_var, ext_cl_mt, 605 ext_cl_mt, ext_cl_count,
611 ext_cl_count,
612 extends_cl->class_extends); 606 extends_cl->class_extends);
613 } 607 }
614 608
615 return variable_present; 609 return variable_present;
616 } 610 }
617 611
618 /* 612 /*
619 * Check the variables of the interface class "ifcl" match the class variables 613 * Check the variables of the interface class "ifcl" match object variables
620 * ("classmembers_gap") and object variables ("objmembers_gap") of a class. 614 * ("objmembers_gap") of a class.
621 * Returns TRUE if the class and object variables names are valid. 615 * Returns TRUE if the object variables names are valid.
622 */ 616 */
623 static int 617 static int
624 validate_interface_variables( 618 validate_interface_variables(
625 char_u *intf_class_name, 619 char_u *intf_class_name,
626 class_T *ifcl, 620 class_T *ifcl,
627 garray_T *classmembers_gap,
628 garray_T *objmembers_gap, 621 garray_T *objmembers_gap,
629 class_T *extends_cl) 622 class_T *extends_cl)
630 { 623 {
631 for (int loop = 1; loop <= 2; ++loop) 624 int if_count = ifcl->class_obj_member_count;
632 { 625 if (if_count == 0)
633 // loop == 1: check class variables 626 return TRUE;
634 // loop == 2: check object variables 627
635 int is_class_var = (loop == 1); 628 ocmember_T *if_ms = ifcl->class_obj_members;
636 int if_count = is_class_var ? ifcl->class_class_member_count 629 ocmember_T *cl_ms = (ocmember_T *)(objmembers_gap->ga_data);
637 : ifcl->class_obj_member_count; 630 int cl_count = objmembers_gap->ga_len;
638 if (if_count == 0) 631 for (int if_i = 0; if_i < if_count; ++if_i)
639 continue; 632 {
640 ocmember_T *if_ms = is_class_var ? ifcl->class_class_members 633 if (!intf_variable_present(intf_class_name, &if_ms[if_i], cl_ms,
641 : ifcl->class_obj_members; 634 cl_count, extends_cl))
642 ocmember_T *cl_ms = (ocmember_T *)(is_class_var 635 {
643 ? classmembers_gap->ga_data 636 semsg(_(e_variable_str_of_interface_str_not_implemented),
644 : objmembers_gap->ga_data); 637 if_ms[if_i].ocm_name, intf_class_name);
645 int cl_count = is_class_var ? classmembers_gap->ga_len 638 return FALSE;
646 : objmembers_gap->ga_len;
647 for (int if_i = 0; if_i < if_count; ++if_i)
648 {
649 if (!intf_variable_present(intf_class_name, &if_ms[if_i],
650 is_class_var, cl_ms, cl_count, extends_cl))
651 {
652 semsg(_(e_variable_str_of_interface_str_not_implemented),
653 if_ms[if_i].ocm_name, intf_class_name);
654 return FALSE;
655 }
656 } 639 }
657 } 640 }
658 641
659 return TRUE; 642 return TRUE;
660 } 643 }
683 * in "extends_cl". For a class method, 'is_class_method' is TRUE. 666 * in "extends_cl". For a class method, 'is_class_method' is TRUE.
684 */ 667 */
685 static int 668 static int
686 intf_method_present( 669 intf_method_present(
687 ufunc_T *if_ufunc, 670 ufunc_T *if_ufunc,
688 int is_class_method,
689 ufunc_T **cl_fp, 671 ufunc_T **cl_fp,
690 int cl_count, 672 int cl_count,
691 class_T *extends_cl) 673 class_T *extends_cl)
692 { 674 {
693 int method_present = FALSE; 675 int method_present = FALSE;
705 } 687 }
706 } 688 }
707 689
708 if (!method_present && extends_cl != NULL) 690 if (!method_present && extends_cl != NULL)
709 { 691 {
710 ufunc_T **ext_cl_fp = (ufunc_T **)(is_class_method 692 ufunc_T **ext_cl_fp = (ufunc_T **)(extends_cl->class_obj_methods);
711 ? extends_cl->class_class_functions 693 int ext_cl_count = extends_cl->class_obj_method_count;
712 : extends_cl->class_obj_methods); 694 return intf_method_present(if_ufunc, ext_cl_fp, ext_cl_count,
713 int ext_cl_count = is_class_method 695 extends_cl->class_extends);
714 ? extends_cl->class_class_function_count
715 : extends_cl->class_obj_method_count;
716 return intf_method_present(if_ufunc, is_class_method, ext_cl_fp,
717 ext_cl_count,
718 extends_cl->class_extends);
719 } 696 }
720 697
721 return method_present; 698 return method_present;
722 } 699 }
723 700
731 */ 708 */
732 static int 709 static int
733 validate_interface_methods( 710 validate_interface_methods(
734 char_u *intf_class_name, 711 char_u *intf_class_name,
735 class_T *ifcl, 712 class_T *ifcl,
736 garray_T *classfunctions_gap,
737 garray_T *objmethods_gap, 713 garray_T *objmethods_gap,
738 class_T *extends_cl) 714 class_T *extends_cl)
739 { 715 {
740 for (int loop = 1; loop <= 2; ++loop) 716 int if_count = ifcl->class_obj_method_count;
741 { 717 if (if_count == 0)
742 // loop == 1: check class methods 718 return TRUE;
743 // loop == 2: check object methods 719
744 int is_class_method = (loop == 1); 720 ufunc_T **if_fp = ifcl->class_obj_methods;
745 int if_count = is_class_method ? ifcl->class_class_function_count 721 ufunc_T **cl_fp = (ufunc_T **)(objmethods_gap->ga_data);
746 : ifcl->class_obj_method_count; 722 int cl_count = objmethods_gap->ga_len;
747 if (if_count == 0) 723 for (int if_i = 0; if_i < if_count; ++if_i)
748 continue; 724 {
749 ufunc_T **if_fp = is_class_method ? ifcl->class_class_functions 725 char_u *if_name = if_fp[if_i]->uf_name;
750 : ifcl->class_obj_methods; 726
751 ufunc_T **cl_fp = (ufunc_T **)(is_class_method 727 if (!intf_method_present(if_fp[if_i], cl_fp, cl_count, extends_cl))
752 ? classfunctions_gap->ga_data 728 {
753 : objmethods_gap->ga_data); 729 semsg(_(e_method_str_of_interface_str_not_implemented),
754 int cl_count = is_class_method ? classfunctions_gap->ga_len 730 if_name, intf_class_name);
755 : objmethods_gap->ga_len; 731 return FALSE;
756 for (int if_i = 0; if_i < if_count; ++if_i)
757 {
758 char_u *if_name = if_fp[if_i]->uf_name;
759
760 if (!intf_method_present(if_fp[if_i], is_class_method, cl_fp,
761 cl_count, extends_cl))
762 {
763 semsg(_(e_method_str_of_interface_str_not_implemented),
764 if_name, intf_class_name);
765 return FALSE;
766 }
767 } 732 }
768 } 733 }
769 734
770 return TRUE; 735 return TRUE;
771 } 736 }
779 */ 744 */
780 static int 745 static int
781 validate_implements_classes( 746 validate_implements_classes(
782 garray_T *impl_gap, 747 garray_T *impl_gap,
783 class_T **intf_classes, 748 class_T **intf_classes,
784 garray_T *classfunctions_gap,
785 garray_T *classmembers_gap,
786 garray_T *objmethods_gap, 749 garray_T *objmethods_gap,
787 garray_T *objmembers_gap, 750 garray_T *objmembers_gap,
788 class_T *extends_cl) 751 class_T *extends_cl)
789 { 752 {
790 int success = TRUE; 753 int success = TRUE;
814 class_T *ifcl = tv.vval.v_class; 777 class_T *ifcl = tv.vval.v_class;
815 intf_classes[i] = ifcl; 778 intf_classes[i] = ifcl;
816 ++ifcl->class_refcount; 779 ++ifcl->class_refcount;
817 780
818 // check the variables of the interface match the members of the class 781 // check the variables of the interface match the members of the class
819 success = validate_interface_variables(impl, ifcl, classmembers_gap, 782 success = validate_interface_variables(impl, ifcl, objmembers_gap,
820 objmembers_gap, extends_cl); 783 extends_cl);
821 784
822 // check the functions/methods of the interface match the 785 // check the functions/methods of the interface match the
823 // functions/methods of the class 786 // functions/methods of the class
824 if (success) 787 if (success)
825 success = validate_interface_methods(impl, ifcl, 788 success = validate_interface_methods(impl, ifcl, objmethods_gap,
826 classfunctions_gap, objmethods_gap, 789 extends_cl);
827 extends_cl);
828 clear_tv(&tv); 790 clear_tv(&tv);
829 } 791 }
830 792
831 return success; 793 return success;
832 } 794 }
1871 if (success && ga_impl.ga_len > 0) 1833 if (success && ga_impl.ga_len > 0)
1872 { 1834 {
1873 intf_classes = ALLOC_CLEAR_MULT(class_T *, ga_impl.ga_len); 1835 intf_classes = ALLOC_CLEAR_MULT(class_T *, ga_impl.ga_len);
1874 1836
1875 success = validate_implements_classes(&ga_impl, intf_classes, 1837 success = validate_implements_classes(&ga_impl, intf_classes,
1876 &classfunctions, &classmembers, 1838 &objmethods, &objmembers, extends_cl);
1877 &objmethods, &objmembers,
1878 extends_cl);
1879 } 1839 }
1880 1840
1881 // Check no function argument name is used as a class member. 1841 // Check no function argument name is used as a class member.
1882 if (success) 1842 if (success)
1883 success = check_func_arg_names(&classfunctions, &objmethods, 1843 success = check_func_arg_names(&classfunctions, &objmethods,
2170 emsg_var_cl_define(e_cannot_access_private_variable_str, 2130 emsg_var_cl_define(e_cannot_access_private_variable_str,
2171 m->ocm_name, 0, cl); 2131 m->ocm_name, 0, cl);
2172 return FAIL; 2132 return FAIL;
2173 } 2133 }
2174 2134
2175 // The object only contains a pointer to the class, the member
2176 // values array follows right after that.
2177 object_T *obj = rettv->vval.v_object;
2178 if (is_object) 2135 if (is_object)
2179 { 2136 {
2137 // The object only contains a pointer to the class, the member values
2138 // array follows right after that.
2139 object_T *obj = rettv->vval.v_object;
2180 typval_T *tv = (typval_T *)(obj + 1) + m_idx; 2140 typval_T *tv = (typval_T *)(obj + 1) + m_idx;
2181 copy_tv(tv, rettv); 2141 copy_tv(tv, rettv);
2142 object_unref(obj);
2182 } 2143 }
2183 else 2144 else
2145 {
2184 copy_tv(&cl->class_members_tv[m_idx], rettv); 2146 copy_tv(&cl->class_members_tv[m_idx], rettv);
2185 2147 class_unref(cl);
2186 object_unref(obj); 2148 }
2149
2150 return OK;
2151 }
2152
2153 /*
2154 * Call an object or class method "name" in class "cl". The method return
2155 * value is returned in "rettv".
2156 */
2157 static int
2158 call_oc_method(
2159 class_T *cl,
2160 char_u *name,
2161 size_t len,
2162 char_u *name_end,
2163 evalarg_T *evalarg,
2164 char_u **arg,
2165 typval_T *rettv)
2166 {
2167 ufunc_T *fp;
2168 typval_T argvars[MAX_FUNC_ARGS + 1];
2169 int argcount = 0;
2170
2171 fp = method_lookup(cl, rettv->v_type, name, len, NULL);
2172 if (fp == NULL)
2173 {
2174 method_not_found_msg(cl, rettv->v_type, name, len);
2175 return FAIL;
2176 }
2177
2178 if (*fp->uf_name == '_')
2179 {
2180 // Cannot access a private method outside of a class
2181 semsg(_(e_cannot_access_private_method_str), fp->uf_name);
2182 return FAIL;
2183 }
2184
2185 char_u *argp = name_end;
2186 int ret = get_func_arguments(&argp, evalarg, 0, argvars, &argcount);
2187 if (ret == FAIL)
2188 return FAIL;
2189
2190 funcexe_T funcexe;
2191 CLEAR_FIELD(funcexe);
2192 funcexe.fe_evaluate = TRUE;
2193 if (rettv->v_type == VAR_OBJECT)
2194 {
2195 funcexe.fe_object = rettv->vval.v_object;
2196 ++funcexe.fe_object->obj_refcount;
2197 }
2198
2199 // Clear the class or object after calling the function, in
2200 // case the refcount is one.
2201 typval_T tv_tofree = *rettv;
2202 rettv->v_type = VAR_UNKNOWN;
2203
2204 // Call the user function. Result goes into rettv;
2205 int error = call_user_func_check(fp, argcount, argvars, rettv, &funcexe,
2206 NULL);
2207
2208 // Clear the previous rettv and the arguments.
2209 clear_tv(&tv_tofree);
2210 for (int idx = 0; idx < argcount; ++idx)
2211 clear_tv(&argvars[idx]);
2212
2213 if (error != FCERR_NONE)
2214 {
2215 user_func_error(error, printable_func_name(fp), funcexe.fe_found_var);
2216 return FAIL;
2217 }
2218 *arg = argp;
2187 2219
2188 return OK; 2220 return OK;
2189 } 2221 }
2190 2222
2191 /* 2223 /*
2240 emsg(_(e_incomplete_type)); 2272 emsg(_(e_incomplete_type));
2241 return FAIL; 2273 return FAIL;
2242 } 2274 }
2243 2275
2244 if (*name_end == '(') 2276 if (*name_end == '(')
2245 { 2277 // Invoke the class or object method
2246 ufunc_T *fp; 2278 return call_oc_method(cl, name, len, name_end, evalarg, arg, rettv);
2247 2279
2248 fp = method_lookup(cl, rettv->v_type, name, len, NULL); 2280 else if (rettv->v_type == VAR_OBJECT || rettv->v_type == VAR_CLASS)
2249 if (fp == NULL)
2250 {
2251 method_not_found_msg(cl, rettv->v_type, name, len);
2252 return FAIL;
2253 }
2254
2255 typval_T argvars[MAX_FUNC_ARGS + 1];
2256 int argcount = 0;
2257
2258 if (*fp->uf_name == '_')
2259 {
2260 // Cannot access a private method outside of a class
2261 semsg(_(e_cannot_access_private_method_str), name);
2262 return FAIL;
2263 }
2264
2265 char_u *argp = name_end;
2266 int ret = get_func_arguments(&argp, evalarg, 0,
2267 argvars, &argcount);
2268 if (ret == FAIL)
2269 return FAIL;
2270
2271 funcexe_T funcexe;
2272 CLEAR_FIELD(funcexe);
2273 funcexe.fe_evaluate = TRUE;
2274 if (rettv->v_type == VAR_OBJECT)
2275 {
2276 funcexe.fe_object = rettv->vval.v_object;
2277 ++funcexe.fe_object->obj_refcount;
2278 }
2279
2280 // Clear the class or object after calling the function, in
2281 // case the refcount is one.
2282 typval_T tv_tofree = *rettv;
2283 rettv->v_type = VAR_UNKNOWN;
2284
2285 // Call the user function. Result goes into rettv;
2286 int error = call_user_func_check(fp, argcount, argvars,
2287 rettv, &funcexe, NULL);
2288
2289 // Clear the previous rettv and the arguments.
2290 clear_tv(&tv_tofree);
2291 for (int idx = 0; idx < argcount; ++idx)
2292 clear_tv(&argvars[idx]);
2293
2294 if (error != FCERR_NONE)
2295 {
2296 user_func_error(error, printable_func_name(fp),
2297 funcexe.fe_found_var);
2298 return FAIL;
2299 }
2300 *arg = argp;
2301 return OK;
2302 }
2303
2304 else if (rettv->v_type == VAR_OBJECT)
2305 { 2281 {
2306 // Search in the object member variable table and the class member 2282 // Search in the object member variable table and the class member
2307 // variable table. 2283 // variable table.
2308 if (get_member_tv(cl, TRUE, name, len, rettv) == OK) 2284 int is_object = rettv->v_type == VAR_OBJECT;
2285 if (get_member_tv(cl, is_object, name, len, rettv) == OK)
2309 { 2286 {
2310 *arg = name_end; 2287 *arg = name_end;
2311 return OK; 2288 return OK;
2312 } 2289 }
2313 2290
2314 if (did_emsg == did_emsg_save) 2291 if (did_emsg == did_emsg_save)
2315 member_not_found_msg(cl, VAR_OBJECT, name, len); 2292 member_not_found_msg(cl, is_object, name, len);
2316 }
2317
2318 else if (rettv->v_type == VAR_CLASS)
2319 {
2320 int m_idx;
2321
2322 // class member
2323 ocmember_T *m = class_member_lookup(cl, name, len, &m_idx);
2324 if (m == NULL)
2325 {
2326 member_not_found_msg(cl, VAR_CLASS, name, len);
2327 return FAIL;
2328 }
2329
2330 if (*name == '_')
2331 {
2332 emsg_var_cl_define(e_cannot_access_private_variable_str,
2333 m->ocm_name, 0, cl);
2334 return FAIL;
2335 }
2336
2337 typval_T *tv = &cl->class_members_tv[m_idx];
2338 copy_tv(tv, rettv);
2339 class_unref(cl);
2340
2341 *arg = name_end;
2342 return OK;
2343 } 2293 }
2344 2294
2345 return FAIL; 2295 return FAIL;
2346 } 2296 }
2347 2297
2431 *idx = ret_idx; 2381 *idx = ret_idx;
2432 return ret_m; 2382 return ret_m;
2433 } 2383 }
2434 2384
2435 /* 2385 /*
2386 * Returns a pointer to the class method "name" in class "cl".
2387 * Returns NULL if the method is not found.
2388 * The method index is set in "idx".
2389 */
2390 static ufunc_T *
2391 class_method_lookup(class_T *cl, char_u *name, size_t namelen, int *idx)
2392 {
2393 ufunc_T *ret_fp = NULL;
2394 int ret_idx = -1;
2395 for (int i = 0; i < cl->class_class_function_count; ++i)
2396 {
2397 ufunc_T *fp = cl->class_class_functions[i];
2398 char_u *ufname = (char_u *)fp->uf_name;
2399 if (STRNCMP(name, ufname, namelen) == 0 && ufname[namelen] == NUL)
2400 {
2401 ret_fp = fp;
2402 ret_idx = i;
2403 break;
2404 }
2405 }
2406 if (idx != NULL)
2407 *idx = ret_idx;
2408 return ret_fp;
2409 }
2410
2411 /*
2436 * Returns the index of class method "name" in the class "cl". 2412 * Returns the index of class method "name" in the class "cl".
2437 * Returns -1, if the method is not found. 2413 * Returns -1, if the method is not found.
2438 */ 2414 */
2439 int 2415 int
2440 class_method_idx(class_T *cl, char_u *name, size_t namelen) 2416 class_method_idx(class_T *cl, char_u *name, size_t namelen)
2443 class_method_lookup(cl, name, namelen, &idx); 2419 class_method_lookup(cl, name, namelen, &idx);
2444 return idx; 2420 return idx;
2445 } 2421 }
2446 2422
2447 /* 2423 /*
2448 * Returns a pointer to the class method "name" in class "cl".
2449 * Returns NULL if the method is not found.
2450 * The method index is set in "idx".
2451 */
2452 ufunc_T *
2453 class_method_lookup(class_T *cl, char_u *name, size_t namelen, int *idx)
2454 {
2455 ufunc_T *ret_fp = NULL;
2456 int ret_idx = -1;
2457 for (int i = 0; i < cl->class_class_function_count; ++i)
2458 {
2459 ufunc_T *fp = cl->class_class_functions[i];
2460 char_u *ufname = (char_u *)fp->uf_name;
2461 if (STRNCMP(name, ufname, namelen) == 0 && ufname[namelen] == NUL)
2462 {
2463 ret_fp = fp;
2464 ret_idx = i;
2465 break;
2466 }
2467 }
2468 if (idx != NULL)
2469 *idx = ret_idx;
2470 return ret_fp;
2471 }
2472
2473 /*
2474 * Returns the index of object member variable "name" in the class "cl". 2424 * Returns the index of object member variable "name" in the class "cl".
2475 * Returns -1, if the variable is not found. 2425 * Returns -1, if the variable is not found.
2476 * If "namelen" is zero, then it is assumed that "name" is NUL terminated. 2426 * If "namelen" is zero, then it is assumed that "name" is NUL terminated.
2477 */ 2427 */
2478 int 2428 static int
2479 object_member_idx(class_T *cl, char_u *name, size_t namelen) 2429 object_member_idx(class_T *cl, char_u *name, size_t namelen)
2480 { 2430 {
2481 int idx; 2431 int idx;
2482 object_member_lookup(cl, name, namelen, &idx); 2432 object_member_lookup(cl, name, namelen, &idx);
2483 return idx; 2433 return idx;
2517 *idx = ret_idx; 2467 *idx = ret_idx;
2518 return ret_m; 2468 return ret_m;
2519 } 2469 }
2520 2470
2521 /* 2471 /*
2522 * Returns the index of object method "name" in the class "cl".
2523 * Returns -1, if the method is not found.
2524 */
2525 int
2526 object_method_idx(class_T *cl, char_u *name, size_t namelen)
2527 {
2528 int idx;
2529 object_method_lookup(cl, name, namelen, &idx);
2530 return idx;
2531 }
2532
2533 /*
2534 * Returns a pointer to the object method "name" in class "cl". 2472 * Returns a pointer to the object method "name" in class "cl".
2535 * Returns NULL if the method is not found. 2473 * Returns NULL if the method is not found.
2536 * The object method index is set in "idx". 2474 * The object method index is set in "idx".
2537 */ 2475 */
2538 ufunc_T * 2476 static ufunc_T *
2539 object_method_lookup(class_T *cl, char_u *name, size_t namelen, int *idx) 2477 object_method_lookup(class_T *cl, char_u *name, size_t namelen, int *idx)
2540 { 2478 {
2541 ufunc_T *ret_fp = NULL; 2479 ufunc_T *ret_fp = NULL;
2542 int ret_idx = -1; 2480 int ret_idx = -1;
2543 for (int i = 0; i < cl->class_obj_method_count; ++i) 2481 for (int i = 0; i < cl->class_obj_method_count; ++i)
2554 } 2492 }
2555 } 2493 }
2556 if (idx != NULL) 2494 if (idx != NULL)
2557 *idx = ret_idx; 2495 *idx = ret_idx;
2558 return ret_fp; 2496 return ret_fp;
2497 }
2498
2499 /*
2500 * Returns the index of object method "name" in the class "cl".
2501 * Returns -1, if the method is not found.
2502 */
2503 int
2504 object_method_idx(class_T *cl, char_u *name, size_t namelen)
2505 {
2506 int idx;
2507 object_method_lookup(cl, name, namelen, &idx);
2508 return idx;
2559 } 2509 }
2560 2510
2561 /* 2511 /*
2562 * Lookup a class or object member variable by name. If v_type is VAR_CLASS, 2512 * Lookup a class or object member variable by name. If v_type is VAR_CLASS,
2563 * then lookup a class member variable and if it is VAR_OBJECT, then lookup a 2513 * then lookup a class member variable and if it is VAR_OBJECT, then lookup a
2680 ++to->vval.v_object->obj_refcount; 2630 ++to->vval.v_object->obj_refcount;
2681 } 2631 }
2682 } 2632 }
2683 2633
2684 /* 2634 /*
2685 * Free an object.
2686 */
2687 static void
2688 object_clear(object_T *obj)
2689 {
2690 // Avoid a recursive call, it can happen if "obj" has a circular reference.
2691 obj->obj_refcount = INT_MAX;
2692
2693 class_T *cl = obj->obj_class;
2694
2695 if (!cl)
2696 return;
2697
2698 // the member values are just after the object structure
2699 typval_T *tv = (typval_T *)(obj + 1);
2700 for (int i = 0; i < cl->class_obj_member_count; ++i)
2701 clear_tv(tv + i);
2702
2703 // Remove from the list headed by "first_object".
2704 object_cleared(obj);
2705
2706 vim_free(obj);
2707 class_unref(cl);
2708 }
2709
2710 /*
2711 * Unreference an object.
2712 */
2713 void
2714 object_unref(object_T *obj)
2715 {
2716 if (obj != NULL && --obj->obj_refcount <= 0)
2717 object_clear(obj);
2718 }
2719
2720 /*
2721 * Make a copy of a class. 2635 * Make a copy of a class.
2722 */ 2636 */
2723 void 2637 void
2724 copy_class(typval_T *from, typval_T *to) 2638 copy_class(typval_T *from, typval_T *to)
2725 { 2639 {
2864 2778
2865 /* 2779 /*
2866 * Call this function when an object has been cleared and is about to be freed. 2780 * Call this function when an object has been cleared and is about to be freed.
2867 * It is removed from the list headed by "first_object". 2781 * It is removed from the list headed by "first_object".
2868 */ 2782 */
2869 void 2783 static void
2870 object_cleared(object_T *obj) 2784 object_cleared(object_T *obj)
2871 { 2785 {
2872 if (obj->obj_next_used != NULL) 2786 if (obj->obj_next_used != NULL)
2873 obj->obj_next_used->obj_prev_used = obj->obj_prev_used; 2787 obj->obj_next_used->obj_prev_used = obj->obj_prev_used;
2874 if (obj->obj_prev_used != NULL) 2788 if (obj->obj_prev_used != NULL)
2880 if (obj == next_nonref_obj) 2794 if (obj == next_nonref_obj)
2881 next_nonref_obj = obj->obj_next_used; 2795 next_nonref_obj = obj->obj_next_used;
2882 } 2796 }
2883 2797
2884 /* 2798 /*
2799 * Free an object.
2800 */
2801 static void
2802 object_clear(object_T *obj)
2803 {
2804 // Avoid a recursive call, it can happen if "obj" has a circular reference.
2805 obj->obj_refcount = INT_MAX;
2806
2807 class_T *cl = obj->obj_class;
2808
2809 if (!cl)
2810 return;
2811
2812 // the member values are just after the object structure
2813 typval_T *tv = (typval_T *)(obj + 1);
2814 for (int i = 0; i < cl->class_obj_member_count; ++i)
2815 clear_tv(tv + i);
2816
2817 // Remove from the list headed by "first_object".
2818 object_cleared(obj);
2819
2820 vim_free(obj);
2821 class_unref(cl);
2822 }
2823
2824 /*
2825 * Unreference an object.
2826 */
2827 void
2828 object_unref(object_T *obj)
2829 {
2830 if (obj != NULL && --obj->obj_refcount <= 0)
2831 object_clear(obj);
2832 }
2833
2834 /*
2885 * Go through the list of all objects and free items without "copyID". 2835 * Go through the list of all objects and free items without "copyID".
2886 */ 2836 */
2887 int 2837 int
2888 object_free_nonref(int copyID) 2838 object_free_nonref(int copyID)
2889 { 2839 {