To: vim_dev@googlegroups.com Subject: Patch 9.0.1184 Fcc: outbox From: Bram Moolenaar Mime-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ------------ Patch 9.0.1184 Problem: Interface of an object is not recognized when checking type. Solution: Use the interface implemented by an object. Files: src/vim9type.c, src/structs.h, src/vim9class.c, src/testdir/test_vim9_class.vim *** ../vim-9.0.1183/src/vim9type.c 2023-01-11 21:14:11.832106048 +0000 --- src/vim9type.c 2023-01-12 13:54:29.918762015 +0000 *************** *** 876,886 **** --- 876,896 ---- } else if (expected->tt_type == VAR_OBJECT) { + // check the class, base class or an implemented interface matches class_T *cl; for (cl = (class_T *)actual->tt_member; cl != NULL; cl = cl->class_extends) + { if ((class_T *)expected->tt_member == cl) break; + int i; + for (i = cl->class_interface_count - 1; i >= 0; --i) + if ((class_T *)expected->tt_member + == cl->class_interfaces_cl[i]) + break; + if (i >= 0) + break; + } if (cl == NULL) ret = FAIL; } *** ../vim-9.0.1183/src/structs.h 2023-01-11 15:59:01.175405240 +0000 --- src/structs.h 2023-01-12 13:47:23.316980720 +0000 *************** *** 1500,1505 **** --- 1500,1506 ---- // interfaces declared for the class int class_interface_count; char_u **class_interfaces; // allocated array of names + class_T **class_interfaces_cl; // interfaces (counts as reference) // class members: "static varname" int class_class_member_count; *** ../vim-9.0.1183/src/vim9class.c 2023-01-11 15:59:01.175405240 +0000 --- src/vim9class.c 2023-01-12 14:22:27.662808427 +0000 *************** *** 582,590 **** --- 582,594 ---- } VIM_CLEAR(extends); + class_T **intf_classes = NULL; + // Check all "implements" entries are valid. if (success && ga_impl.ga_len > 0) { + intf_classes = ALLOC_CLEAR_MULT(class_T *, ga_impl.ga_len); + for (int i = 0; i < ga_impl.ga_len && success; ++i) { char_u *impl = ((char_u **)ga_impl.ga_data)[i]; *************** *** 605,612 **** success = FALSE; } - // check the members of the interface match the members of the class class_T *ifcl = tv.vval.v_class; for (int loop = 1; loop <= 2 && success; ++loop) { // loop == 1: check class members --- 609,619 ---- success = FALSE; } class_T *ifcl = tv.vval.v_class; + intf_classes[i] = ifcl; + ++ifcl->class_refcount; + + // check the members of the interface match the members of the class for (int loop = 1; loop <= 2 && success; ++loop) { // loop == 1: check class members *************** *** 717,722 **** --- 724,732 ---- cl->class_interfaces[i] = ((char_u **)ga_impl.ga_data)[i]; VIM_CLEAR(ga_impl.ga_data); ga_impl.ga_len = 0; + + cl->class_interfaces_cl = intf_classes; + intf_classes = NULL; } // Add class and object members to "cl". *************** *** 930,935 **** --- 940,957 ---- { vim_free(cl->class_name); vim_free(cl->class_class_functions); + if (cl->class_interfaces != NULL) + { + for (int i = 0; i < cl->class_interface_count; ++i) + vim_free(cl->class_interfaces[i]); + vim_free(cl->class_interfaces); + } + if (cl->class_interfaces_cl != NULL) + { + for (int i = 0; i < cl->class_interface_count; ++i) + class_unref(cl->class_interfaces_cl[i]); + vim_free(cl->class_interfaces_cl); + } vim_free(cl->class_obj_members); vim_free(cl->class_obj_methods); vim_free(cl); *************** *** 937,942 **** --- 959,971 ---- vim_free(extends); class_unref(extends_cl); + + if (intf_classes != NULL) + { + for (int i = 0; i < ga_impl.ga_len; ++i) + class_unref(intf_classes[i]); + vim_free(intf_classes); + } ga_clear_strings(&ga_impl); for (int round = 1; round <= 2; ++round) *************** *** 1321,1328 **** --- 1350,1362 ---- class_unref(cl->class_extends); for (int i = 0; i < cl->class_interface_count; ++i) + { vim_free(((char_u **)cl->class_interfaces)[i]); + if (cl->class_interfaces_cl[i] != NULL) + class_unref(cl->class_interfaces_cl[i]); + } vim_free(cl->class_interfaces); + vim_free(cl->class_interfaces_cl); for (int i = 0; i < cl->class_class_member_count; ++i) { *** ../vim-9.0.1183/src/testdir/test_vim9_class.vim 2023-01-11 21:14:11.832106048 +0000 --- src/testdir/test_vim9_class.vim 2023-01-12 14:25:03.343498208 +0000 *************** *** 455,460 **** --- 455,478 ---- var o: One = Two.new() END v9.CheckScriptFailure(lines, 'E1012: Type mismatch; expected object but got object') + + lines =<< trim END + vim9script + + interface One + def GetMember(): number + endinterface + class Two implements One + this.one = 1 + def GetMember(): number + return this.one + enddef + endclass + + var o: One = Two.new(5) + assert_equal(5, o.GetMember()) + END + v9.CheckScriptSuccess(lines) enddef def Test_class_member() *** ../vim-9.0.1183/src/version.c 2023-01-12 12:33:25.428525183 +0000 --- src/version.c 2023-01-12 13:35:55.706192841 +0000 *************** *** 697,698 **** --- 697,700 ---- { /* Add new patch number below this line */ + /**/ + 1184, /**/ -- Normal people believe that if it ain't broke, don't fix it. Engineers believe that if it ain't broke, it doesn't have enough features yet. (Scott Adams - The Dilbert principle) /// Bram Moolenaar -- Bram@Moolenaar.net -- http://www.Moolenaar.net \\\ /// \\\ \\\ sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ /// \\\ help me help AIDS victims -- http://ICCF-Holland.org ///