Mercurial > vim
comparison src/vim9expr.c @ 31843:ffa11e2757e7 v9.0.1254
patch 9.0.1254: calling a method on an interface does not work
Commit: https://github.com/vim/vim/commit/d0200c8631582bbb16a9b585e2ca7adccc84ccdd
Author: Bram Moolenaar <Bram@vim.org>
Date: Sat Jan 28 15:19:40 2023 +0000
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 https://github.com/vim/vim/issues/11901)
author | Bram Moolenaar <Bram@vim.org> |
---|---|
date | Sat, 28 Jan 2023 16:30:04 +0100 |
parents | 5ce5d78afcc9 |
children | f1a5e67e9a1b |
comparison
equal
deleted
inserted
replaced
31842:1b6543beb560 | 31843:ffa11e2757e7 |
---|---|
319 child_count = cl->class_obj_method_count_child; | 319 child_count = cl->class_obj_method_count_child; |
320 functions = cl->class_obj_methods; | 320 functions = cl->class_obj_methods; |
321 } | 321 } |
322 | 322 |
323 ufunc_T *ufunc = NULL; | 323 ufunc_T *ufunc = NULL; |
324 for (int i = is_super ? child_count : 0; i < function_count; ++i) | 324 int fi; |
325 { | 325 for (fi = is_super ? child_count : 0; fi < function_count; ++fi) |
326 ufunc_T *fp = functions[i]; | 326 { |
327 ufunc_T *fp = functions[fi]; | |
327 // Use a separate pointer to avoid that ASAN complains about | 328 // Use a separate pointer to avoid that ASAN complains about |
328 // uf_name[] only being 4 characters. | 329 // uf_name[] only being 4 characters. |
329 char_u *ufname = (char_u *)fp->uf_name; | 330 char_u *ufname = (char_u *)fp->uf_name; |
330 if (STRNCMP(name, ufname, len) == 0 && ufname[len] == NUL) | 331 if (STRNCMP(name, ufname, len) == 0 && ufname[len] == NUL) |
331 { | 332 { |
345 // before the arguments. | 346 // before the arguments. |
346 *arg = skipwhite(name_end + 1); | 347 *arg = skipwhite(name_end + 1); |
347 int argcount = 0; | 348 int argcount = 0; |
348 if (compile_arguments(arg, cctx, &argcount, CA_NOT_SPECIAL) == FAIL) | 349 if (compile_arguments(arg, cctx, &argcount, CA_NOT_SPECIAL) == FAIL) |
349 return FAIL; | 350 return FAIL; |
350 return generate_CALL(cctx, ufunc, argcount); | 351 |
352 if (type->tt_type == VAR_OBJECT | |
353 && (cl->class_flags & (CLASS_INTERFACE | CLASS_EXTENDED))) | |
354 return generate_CALL(cctx, ufunc, cl, fi, argcount); | |
355 return generate_CALL(cctx, ufunc, NULL, 0, argcount); | |
351 } | 356 } |
352 | 357 |
353 if (type->tt_type == VAR_OBJECT) | 358 if (type->tt_type == VAR_OBJECT) |
354 { | 359 { |
355 for (int i = 0; i < cl->class_obj_member_count; ++i) | 360 for (int i = 0; i < cl->class_obj_member_count; ++i) |
362 semsg(_(e_cannot_access_private_member_str), m->ocm_name); | 367 semsg(_(e_cannot_access_private_member_str), m->ocm_name); |
363 return FAIL; | 368 return FAIL; |
364 } | 369 } |
365 | 370 |
366 *arg = name_end; | 371 *arg = name_end; |
367 if (cl->class_flags & CLASS_INTERFACE) | 372 if (cl->class_flags & (CLASS_INTERFACE | CLASS_EXTENDED)) |
368 return generate_GET_ITF_MEMBER(cctx, cl, i, m->ocm_type); | 373 return generate_GET_ITF_MEMBER(cctx, cl, i, m->ocm_type); |
369 return generate_GET_OBJ_MEMBER(cctx, i, m->ocm_type); | 374 return generate_GET_OBJ_MEMBER(cctx, i, m->ocm_type); |
370 } | 375 } |
371 } | 376 } |
372 | 377 |
1061 ufunc = find_func(name, FALSE); | 1066 ufunc = find_func(name, FALSE); |
1062 if (ufunc != NULL) | 1067 if (ufunc != NULL) |
1063 { | 1068 { |
1064 if (!func_is_global(ufunc)) | 1069 if (!func_is_global(ufunc)) |
1065 { | 1070 { |
1066 res = generate_CALL(cctx, ufunc, argcount); | 1071 res = generate_CALL(cctx, ufunc, NULL, 0, argcount); |
1067 goto theend; | 1072 goto theend; |
1068 } | 1073 } |
1069 if (!has_g_namespace | 1074 if (!has_g_namespace |
1070 && vim_strchr(ufunc->uf_name, AUTOLOAD_CHAR) == NULL) | 1075 && vim_strchr(ufunc->uf_name, AUTOLOAD_CHAR) == NULL) |
1071 { | 1076 { |
1090 } | 1095 } |
1091 | 1096 |
1092 // If we can find a global function by name generate the right call. | 1097 // If we can find a global function by name generate the right call. |
1093 if (ufunc != NULL) | 1098 if (ufunc != NULL) |
1094 { | 1099 { |
1095 res = generate_CALL(cctx, ufunc, argcount); | 1100 res = generate_CALL(cctx, ufunc, NULL, 0, argcount); |
1096 goto theend; | 1101 goto theend; |
1097 } | 1102 } |
1098 | 1103 |
1099 // A global function may be defined only later. Need to figure out at | 1104 // A global function may be defined only later. Need to figure out at |
1100 // runtime. Also handles a FuncRef at runtime. | 1105 // runtime. Also handles a FuncRef at runtime. |