To: vim_dev@googlegroups.com Subject: Patch 9.0.1334 Fcc: outbox From: Bram Moolenaar Mime-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ------------ Patch 9.0.1334 Problem: Using tt_member for the class leads to mistakes. Solution: Add a separate tt_class field. Files: src/structs.h, src/globals.h, src/vim9compile.c, src/vim9expr.c, src/vim9type.c, src/vim9class.c, src/evalfunc.c *** ../vim-9.0.1333/src/structs.h 2023-02-20 12:16:33.340269410 +0000 --- src/structs.h 2023-02-20 20:45:56.884106740 +0000 *************** *** 1451,1457 **** int8_T tt_min_argcount; // number of non-optional arguments char_u tt_flags; // TTFLAG_ values type_T *tt_member; // for list, dict, func return type ! // for class: class_T type_T **tt_args; // func argument types, allocated }; --- 1451,1457 ---- int8_T tt_min_argcount; // number of non-optional arguments char_u tt_flags; // TTFLAG_ values type_T *tt_member; // for list, dict, func return type ! class_T *tt_class; // for class and object type_T **tt_args; // func argument types, allocated }; *** ../vim-9.0.1333/src/globals.h 2023-01-20 18:49:42.763170966 +0000 --- src/globals.h 2023-02-20 20:55:02.051866937 +0000 *************** *** 538,705 **** #ifdef DO_INIT = { // 0: t_unknown ! {VAR_UNKNOWN, 0, 0, TTFLAG_STATIC, NULL, NULL}, ! {VAR_UNKNOWN, 0, 0, TTFLAG_STATIC|TTFLAG_CONST, NULL, NULL}, // 2: t_any ! {VAR_ANY, 0, 0, TTFLAG_STATIC, NULL, NULL}, ! {VAR_ANY, 0, 0, TTFLAG_STATIC|TTFLAG_CONST, NULL, NULL}, // 4: t_void ! {VAR_VOID, 0, 0, TTFLAG_STATIC, NULL, NULL}, ! {VAR_VOID, 0, 0, TTFLAG_STATIC|TTFLAG_CONST, NULL, NULL}, // 6: t_bool ! {VAR_BOOL, 0, 0, TTFLAG_STATIC, NULL, NULL}, ! {VAR_BOOL, 0, 0, TTFLAG_STATIC|TTFLAG_CONST, NULL, NULL}, // 8: t_null ! {VAR_SPECIAL, 0, 0, TTFLAG_STATIC, NULL, NULL}, ! {VAR_SPECIAL, 0, 0, TTFLAG_STATIC|TTFLAG_CONST, NULL, NULL}, // 10: t_none ! {VAR_SPECIAL, 0, 0, TTFLAG_STATIC, NULL, NULL}, ! {VAR_SPECIAL, 0, 0, TTFLAG_STATIC|TTFLAG_CONST, NULL, NULL}, // 12: t_number ! {VAR_NUMBER, 0, 0, TTFLAG_STATIC, NULL, NULL}, ! {VAR_NUMBER, 0, 0, TTFLAG_STATIC|TTFLAG_CONST, NULL, NULL}, // 14: t_number_bool ! {VAR_NUMBER, 0, 0, TTFLAG_STATIC|TTFLAG_BOOL_OK, NULL, NULL}, ! {VAR_NUMBER, 0, 0, TTFLAG_STATIC|TTFLAG_BOOL_OK|TTFLAG_CONST, NULL, NULL}, // 16: t_number_float ! {VAR_NUMBER, 0, 0, TTFLAG_STATIC|TTFLAG_FLOAT_OK, NULL, NULL}, ! {VAR_NUMBER, 0, 0, TTFLAG_STATIC|TTFLAG_FLOAT_OK|TTFLAG_CONST, NULL, NULL}, // 18: t_float ! {VAR_FLOAT, 0, 0, TTFLAG_STATIC, NULL, NULL}, ! {VAR_FLOAT, 0, 0, TTFLAG_STATIC|TTFLAG_CONST, NULL, NULL}, // 20: t_string ! {VAR_STRING, 0, 0, TTFLAG_STATIC, NULL, NULL}, ! {VAR_STRING, 0, 0, TTFLAG_STATIC|TTFLAG_CONST, NULL, NULL}, // 22: t_blob ! {VAR_BLOB, 0, 0, TTFLAG_STATIC, NULL, NULL}, ! {VAR_BLOB, 0, 0, TTFLAG_STATIC|TTFLAG_CONST, NULL, NULL}, // 24: t_blob_null ! {VAR_BLOB, 0, 0, TTFLAG_STATIC, &t_void, NULL}, ! {VAR_BLOB, 0, 0, TTFLAG_STATIC|TTFLAG_CONST, &t_void, NULL}, // 26: t_job ! {VAR_JOB, 0, 0, TTFLAG_STATIC, NULL, NULL}, ! {VAR_JOB, 0, 0, TTFLAG_STATIC|TTFLAG_CONST, NULL, NULL}, // 28: t_channel ! {VAR_CHANNEL, 0, 0, TTFLAG_STATIC, NULL, NULL}, ! {VAR_CHANNEL, 0, 0, TTFLAG_STATIC|TTFLAG_CONST, NULL, NULL}, // 30: t_number_or_string ! {VAR_STRING, 0, 0, TTFLAG_STATIC, NULL, NULL}, ! {VAR_STRING, 0, 0, TTFLAG_STATIC|TTFLAG_CONST, NULL, NULL}, // 32: t_func_unknown ! {VAR_FUNC, -1, -1, TTFLAG_STATIC, &t_unknown, NULL}, ! {VAR_FUNC, -1, -1, TTFLAG_STATIC|TTFLAG_CONST, &t_unknown, NULL}, // 34: t_func_void ! {VAR_FUNC, -1, 0, TTFLAG_STATIC, &t_void, NULL}, ! {VAR_FUNC, -1, 0, TTFLAG_STATIC|TTFLAG_CONST, &t_void, NULL}, // 36: t_func_any ! {VAR_FUNC, -1, 0, TTFLAG_STATIC, &t_any, NULL}, ! {VAR_FUNC, -1, 0, TTFLAG_STATIC|TTFLAG_CONST, &t_any, NULL}, // 38: t_func_number ! {VAR_FUNC, -1, 0, TTFLAG_STATIC, &t_number, NULL}, ! {VAR_FUNC, -1, 0, TTFLAG_STATIC|TTFLAG_CONST, &t_number, NULL}, // 40: t_func_string ! {VAR_FUNC, -1, 0, TTFLAG_STATIC, &t_string, NULL}, ! {VAR_FUNC, -1, 0, TTFLAG_STATIC|TTFLAG_CONST, &t_string, NULL}, // 42: t_func_bool ! {VAR_FUNC, -1, 0, TTFLAG_STATIC, &t_bool, NULL}, ! {VAR_FUNC, -1, 0, TTFLAG_STATIC|TTFLAG_CONST, &t_bool, NULL}, // 44: t_func_0_void ! {VAR_FUNC, 0, 0, TTFLAG_STATIC, &t_void, NULL}, ! {VAR_FUNC, 0, 0, TTFLAG_STATIC|TTFLAG_CONST, &t_void, NULL}, // 46: t_func_0_any ! {VAR_FUNC, 0, 0, TTFLAG_STATIC, &t_any, NULL}, ! {VAR_FUNC, 0, 0, TTFLAG_STATIC|TTFLAG_CONST, &t_any, NULL}, // 48: t_func_0_number ! {VAR_FUNC, 0, 0, TTFLAG_STATIC, &t_number, NULL}, ! {VAR_FUNC, 0, 0, TTFLAG_STATIC|TTFLAG_CONST, &t_number, NULL}, // 50: t_func_0_string ! {VAR_FUNC, 0, 0, TTFLAG_STATIC, &t_string, NULL}, ! {VAR_FUNC, 0, 0, TTFLAG_STATIC|TTFLAG_CONST, &t_string, NULL}, // 52: t_list_any ! {VAR_LIST, 0, 0, TTFLAG_STATIC, &t_any, NULL}, ! {VAR_LIST, 0, 0, TTFLAG_STATIC|TTFLAG_CONST, &t_any, NULL}, // 54: t_dict_any ! {VAR_DICT, 0, 0, TTFLAG_STATIC, &t_any, NULL}, ! {VAR_DICT, 0, 0, TTFLAG_STATIC|TTFLAG_CONST, &t_any, NULL}, // 56: t_list_empty ! {VAR_LIST, 0, 0, TTFLAG_STATIC, &t_unknown, NULL}, ! {VAR_LIST, 0, 0, TTFLAG_STATIC|TTFLAG_CONST, &t_unknown, NULL}, // 58: t_dict_empty ! {VAR_DICT, 0, 0, TTFLAG_STATIC, &t_unknown, NULL}, ! {VAR_DICT, 0, 0, TTFLAG_STATIC|TTFLAG_CONST, &t_unknown, NULL}, // 60: t_list_bool ! {VAR_LIST, 0, 0, TTFLAG_STATIC, &t_bool, NULL}, ! {VAR_LIST, 0, 0, TTFLAG_STATIC|TTFLAG_CONST, &t_bool, NULL}, // 62: t_list_number ! {VAR_LIST, 0, 0, TTFLAG_STATIC, &t_number, NULL}, ! {VAR_LIST, 0, 0, TTFLAG_STATIC|TTFLAG_CONST, &t_number, NULL}, // 64: t_list_string ! {VAR_LIST, 0, 0, TTFLAG_STATIC, &t_string, NULL}, ! {VAR_LIST, 0, 0, TTFLAG_STATIC|TTFLAG_CONST, &t_string, NULL}, // 66: t_list_job ! {VAR_LIST, 0, 0, TTFLAG_STATIC, &t_job, NULL}, ! {VAR_LIST, 0, 0, TTFLAG_STATIC|TTFLAG_CONST, &t_job, NULL}, // 68: t_list_dict_any ! {VAR_LIST, 0, 0, TTFLAG_STATIC, &t_dict_any, NULL}, ! {VAR_LIST, 0, 0, TTFLAG_STATIC|TTFLAG_CONST, &t_dict_any, NULL}, // 70: t_list_list_any ! {VAR_LIST, 0, 0, TTFLAG_STATIC, &t_list_any, NULL}, ! {VAR_LIST, 0, 0, TTFLAG_STATIC|TTFLAG_CONST, &t_list_any, NULL}, // 72: t_list_list_string ! {VAR_LIST, 0, 0, TTFLAG_STATIC, &t_list_string, NULL}, ! {VAR_LIST, 0, 0, TTFLAG_STATIC|TTFLAG_CONST, &t_list_string, NULL}, // 74: t_dict_bool ! {VAR_DICT, 0, 0, TTFLAG_STATIC, &t_bool, NULL}, ! {VAR_DICT, 0, 0, TTFLAG_STATIC|TTFLAG_CONST, &t_bool, NULL}, // 76: t_dict_number ! {VAR_DICT, 0, 0, TTFLAG_STATIC, &t_number, NULL}, ! {VAR_DICT, 0, 0, TTFLAG_STATIC|TTFLAG_CONST, &t_number, NULL}, // 78: t_dict_string ! {VAR_DICT, 0, 0, TTFLAG_STATIC, &t_string, NULL}, ! {VAR_DICT, 0, 0, TTFLAG_STATIC|TTFLAG_CONST, &t_string, NULL}, // 80: t_super (VAR_CLASS with tt_member set to &t_bool ! {VAR_CLASS, 0, 0, TTFLAG_STATIC, &t_bool, NULL}, ! {VAR_CLASS, 0, 0, TTFLAG_STATIC|TTFLAG_CONST, &t_bool, NULL}, } #endif ; --- 538,705 ---- #ifdef DO_INIT = { // 0: t_unknown ! {VAR_UNKNOWN, 0, 0, TTFLAG_STATIC, NULL, NULL, NULL}, ! {VAR_UNKNOWN, 0, 0, TTFLAG_STATIC|TTFLAG_CONST, NULL, NULL, NULL}, // 2: t_any ! {VAR_ANY, 0, 0, TTFLAG_STATIC, NULL, NULL, NULL}, ! {VAR_ANY, 0, 0, TTFLAG_STATIC|TTFLAG_CONST, NULL, NULL, NULL}, // 4: t_void ! {VAR_VOID, 0, 0, TTFLAG_STATIC, NULL, NULL, NULL}, ! {VAR_VOID, 0, 0, TTFLAG_STATIC|TTFLAG_CONST, NULL, NULL, NULL}, // 6: t_bool ! {VAR_BOOL, 0, 0, TTFLAG_STATIC, NULL, NULL, NULL}, ! {VAR_BOOL, 0, 0, TTFLAG_STATIC|TTFLAG_CONST, NULL, NULL, NULL}, // 8: t_null ! {VAR_SPECIAL, 0, 0, TTFLAG_STATIC, NULL, NULL, NULL}, ! {VAR_SPECIAL, 0, 0, TTFLAG_STATIC|TTFLAG_CONST, NULL, NULL, NULL}, // 10: t_none ! {VAR_SPECIAL, 0, 0, TTFLAG_STATIC, NULL, NULL, NULL}, ! {VAR_SPECIAL, 0, 0, TTFLAG_STATIC|TTFLAG_CONST, NULL, NULL, NULL}, // 12: t_number ! {VAR_NUMBER, 0, 0, TTFLAG_STATIC, NULL, NULL, NULL}, ! {VAR_NUMBER, 0, 0, TTFLAG_STATIC|TTFLAG_CONST, NULL, NULL, NULL}, // 14: t_number_bool ! {VAR_NUMBER, 0, 0, TTFLAG_STATIC|TTFLAG_BOOL_OK, NULL, NULL, NULL}, ! {VAR_NUMBER, 0, 0, TTFLAG_STATIC|TTFLAG_BOOL_OK|TTFLAG_CONST, NULL, NULL, NULL}, // 16: t_number_float ! {VAR_NUMBER, 0, 0, TTFLAG_STATIC|TTFLAG_FLOAT_OK, NULL, NULL, NULL}, ! {VAR_NUMBER, 0, 0, TTFLAG_STATIC|TTFLAG_FLOAT_OK|TTFLAG_CONST, NULL, NULL, NULL}, // 18: t_float ! {VAR_FLOAT, 0, 0, TTFLAG_STATIC, NULL, NULL, NULL}, ! {VAR_FLOAT, 0, 0, TTFLAG_STATIC|TTFLAG_CONST, NULL, NULL, NULL}, // 20: t_string ! {VAR_STRING, 0, 0, TTFLAG_STATIC, NULL, NULL, NULL}, ! {VAR_STRING, 0, 0, TTFLAG_STATIC|TTFLAG_CONST, NULL, NULL, NULL}, // 22: t_blob ! {VAR_BLOB, 0, 0, TTFLAG_STATIC, NULL, NULL, NULL}, ! {VAR_BLOB, 0, 0, TTFLAG_STATIC|TTFLAG_CONST, NULL, NULL, NULL}, // 24: t_blob_null ! {VAR_BLOB, 0, 0, TTFLAG_STATIC, &t_void, NULL, NULL}, ! {VAR_BLOB, 0, 0, TTFLAG_STATIC|TTFLAG_CONST, &t_void, NULL, NULL}, // 26: t_job ! {VAR_JOB, 0, 0, TTFLAG_STATIC, NULL, NULL, NULL}, ! {VAR_JOB, 0, 0, TTFLAG_STATIC|TTFLAG_CONST, NULL, NULL, NULL}, // 28: t_channel ! {VAR_CHANNEL, 0, 0, TTFLAG_STATIC, NULL, NULL, NULL}, ! {VAR_CHANNEL, 0, 0, TTFLAG_STATIC|TTFLAG_CONST, NULL, NULL, NULL}, // 30: t_number_or_string ! {VAR_STRING, 0, 0, TTFLAG_STATIC, NULL, NULL, NULL}, ! {VAR_STRING, 0, 0, TTFLAG_STATIC|TTFLAG_CONST, NULL, NULL, NULL}, // 32: t_func_unknown ! {VAR_FUNC, -1, -1, TTFLAG_STATIC, &t_unknown, NULL, NULL}, ! {VAR_FUNC, -1, -1, TTFLAG_STATIC|TTFLAG_CONST, &t_unknown, NULL, NULL}, // 34: t_func_void ! {VAR_FUNC, -1, 0, TTFLAG_STATIC, &t_void, NULL, NULL}, ! {VAR_FUNC, -1, 0, TTFLAG_STATIC|TTFLAG_CONST, &t_void, NULL, NULL}, // 36: t_func_any ! {VAR_FUNC, -1, 0, TTFLAG_STATIC, &t_any, NULL, NULL}, ! {VAR_FUNC, -1, 0, TTFLAG_STATIC|TTFLAG_CONST, &t_any, NULL, NULL}, // 38: t_func_number ! {VAR_FUNC, -1, 0, TTFLAG_STATIC, &t_number, NULL, NULL}, ! {VAR_FUNC, -1, 0, TTFLAG_STATIC|TTFLAG_CONST, &t_number, NULL, NULL}, // 40: t_func_string ! {VAR_FUNC, -1, 0, TTFLAG_STATIC, &t_string, NULL, NULL}, ! {VAR_FUNC, -1, 0, TTFLAG_STATIC|TTFLAG_CONST, &t_string, NULL, NULL}, // 42: t_func_bool ! {VAR_FUNC, -1, 0, TTFLAG_STATIC, &t_bool, NULL, NULL}, ! {VAR_FUNC, -1, 0, TTFLAG_STATIC|TTFLAG_CONST, &t_bool, NULL, NULL}, // 44: t_func_0_void ! {VAR_FUNC, 0, 0, TTFLAG_STATIC, &t_void, NULL, NULL}, ! {VAR_FUNC, 0, 0, TTFLAG_STATIC|TTFLAG_CONST, &t_void, NULL, NULL}, // 46: t_func_0_any ! {VAR_FUNC, 0, 0, TTFLAG_STATIC, &t_any, NULL, NULL}, ! {VAR_FUNC, 0, 0, TTFLAG_STATIC|TTFLAG_CONST, &t_any, NULL, NULL}, // 48: t_func_0_number ! {VAR_FUNC, 0, 0, TTFLAG_STATIC, &t_number, NULL, NULL}, ! {VAR_FUNC, 0, 0, TTFLAG_STATIC|TTFLAG_CONST, &t_number, NULL, NULL}, // 50: t_func_0_string ! {VAR_FUNC, 0, 0, TTFLAG_STATIC, &t_string, NULL, NULL}, ! {VAR_FUNC, 0, 0, TTFLAG_STATIC|TTFLAG_CONST, &t_string, NULL, NULL}, // 52: t_list_any ! {VAR_LIST, 0, 0, TTFLAG_STATIC, &t_any, NULL, NULL}, ! {VAR_LIST, 0, 0, TTFLAG_STATIC|TTFLAG_CONST, &t_any, NULL, NULL}, // 54: t_dict_any ! {VAR_DICT, 0, 0, TTFLAG_STATIC, &t_any, NULL, NULL}, ! {VAR_DICT, 0, 0, TTFLAG_STATIC|TTFLAG_CONST, &t_any, NULL, NULL}, // 56: t_list_empty ! {VAR_LIST, 0, 0, TTFLAG_STATIC, &t_unknown, NULL, NULL}, ! {VAR_LIST, 0, 0, TTFLAG_STATIC|TTFLAG_CONST, &t_unknown, NULL, NULL}, // 58: t_dict_empty ! {VAR_DICT, 0, 0, TTFLAG_STATIC, &t_unknown, NULL, NULL}, ! {VAR_DICT, 0, 0, TTFLAG_STATIC|TTFLAG_CONST, &t_unknown, NULL, NULL}, // 60: t_list_bool ! {VAR_LIST, 0, 0, TTFLAG_STATIC, &t_bool, NULL, NULL}, ! {VAR_LIST, 0, 0, TTFLAG_STATIC|TTFLAG_CONST, &t_bool, NULL, NULL}, // 62: t_list_number ! {VAR_LIST, 0, 0, TTFLAG_STATIC, &t_number, NULL, NULL}, ! {VAR_LIST, 0, 0, TTFLAG_STATIC|TTFLAG_CONST, &t_number, NULL, NULL}, // 64: t_list_string ! {VAR_LIST, 0, 0, TTFLAG_STATIC, &t_string, NULL, NULL}, ! {VAR_LIST, 0, 0, TTFLAG_STATIC|TTFLAG_CONST, &t_string, NULL, NULL}, // 66: t_list_job ! {VAR_LIST, 0, 0, TTFLAG_STATIC, &t_job, NULL, NULL}, ! {VAR_LIST, 0, 0, TTFLAG_STATIC|TTFLAG_CONST, &t_job, NULL, NULL}, // 68: t_list_dict_any ! {VAR_LIST, 0, 0, TTFLAG_STATIC, &t_dict_any, NULL, NULL}, ! {VAR_LIST, 0, 0, TTFLAG_STATIC|TTFLAG_CONST, &t_dict_any, NULL, NULL}, // 70: t_list_list_any ! {VAR_LIST, 0, 0, TTFLAG_STATIC, &t_list_any, NULL, NULL}, ! {VAR_LIST, 0, 0, TTFLAG_STATIC|TTFLAG_CONST, &t_list_any, NULL, NULL}, // 72: t_list_list_string ! {VAR_LIST, 0, 0, TTFLAG_STATIC, &t_list_string, NULL, NULL}, ! {VAR_LIST, 0, 0, TTFLAG_STATIC|TTFLAG_CONST, &t_list_string, NULL, NULL}, // 74: t_dict_bool ! {VAR_DICT, 0, 0, TTFLAG_STATIC, &t_bool, NULL, NULL}, ! {VAR_DICT, 0, 0, TTFLAG_STATIC|TTFLAG_CONST, &t_bool, NULL, NULL}, // 76: t_dict_number ! {VAR_DICT, 0, 0, TTFLAG_STATIC, &t_number, NULL, NULL}, ! {VAR_DICT, 0, 0, TTFLAG_STATIC|TTFLAG_CONST, &t_number, NULL, NULL}, // 78: t_dict_string ! {VAR_DICT, 0, 0, TTFLAG_STATIC, &t_string, NULL, NULL}, ! {VAR_DICT, 0, 0, TTFLAG_STATIC|TTFLAG_CONST, &t_string, NULL, NULL}, // 80: t_super (VAR_CLASS with tt_member set to &t_bool ! {VAR_CLASS, 0, 0, TTFLAG_STATIC, &t_bool, NULL, NULL}, ! {VAR_CLASS, 0, 0, TTFLAG_STATIC|TTFLAG_CONST, &t_bool, NULL, NULL}, } #endif ; *** ../vim-9.0.1333/src/vim9compile.c 2023-02-18 18:38:33.375180762 +0000 --- src/vim9compile.c 2023-02-21 12:36:11.571449569 +0000 *************** *** 333,339 **** /* * Return TRUE if "name" is a local variable, argument, script variable or ! * imported. */ static int variable_exists(char_u *name, size_t len, cctx_T *cctx) --- 333,339 ---- /* * Return TRUE if "name" is a local variable, argument, script variable or ! * imported. Also if "name" is "this" and in a class method. */ static int variable_exists(char_u *name, size_t len, cctx_T *cctx) *************** *** 1848,1867 **** lhs->lhs_type = &t_any; } ! if (lhs->lhs_type == NULL || lhs->lhs_type->tt_member == NULL) lhs->lhs_member_type = &t_any; ! else if (lhs->lhs_type->tt_type == VAR_CLASS ! || lhs->lhs_type->tt_type == VAR_OBJECT) { // for an object or class member get the type of the member ! class_T *cl = (class_T *)lhs->lhs_type->tt_member; lhs->lhs_member_type = class_member_type(cl, after + 1, lhs->lhs_end, &lhs->lhs_member_idx); if (lhs->lhs_member_idx < 0) return FAIL; } else lhs->lhs_member_type = lhs->lhs_type->tt_member; } return OK; } --- 1848,1874 ---- lhs->lhs_type = &t_any; } ! int use_class = lhs->lhs_type->tt_type == VAR_CLASS ! || lhs->lhs_type->tt_type == VAR_OBJECT; ! if (lhs->lhs_type == NULL ! || (use_class ? lhs->lhs_type->tt_class == NULL ! : lhs->lhs_type->tt_member == NULL)) ! { lhs->lhs_member_type = &t_any; ! } ! else if (use_class) { // for an object or class member get the type of the member ! class_T *cl = lhs->lhs_type->tt_class; lhs->lhs_member_type = class_member_type(cl, after + 1, lhs->lhs_end, &lhs->lhs_member_idx); if (lhs->lhs_member_idx < 0) return FAIL; } else + { lhs->lhs_member_type = lhs->lhs_type->tt_member; + } } return OK; } *************** *** 2059,2065 **** { // "this.value": load "this" object and get the value at index // for an object or class member get the type of the member ! class_T *cl = (class_T *)lhs->lhs_type->tt_member; type_T *type = class_member_type(cl, var_start + 5, lhs->lhs_end, &lhs->lhs_member_idx); if (lhs->lhs_member_idx < 0) --- 2066,2072 ---- { // "this.value": load "this" object and get the value at index // for an object or class member get the type of the member ! class_T *cl = lhs->lhs_type->tt_class; type_T *type = class_member_type(cl, var_start + 5, lhs->lhs_end, &lhs->lhs_member_idx); if (lhs->lhs_member_idx < 0) *************** *** 2194,2200 **** if (dest_type == VAR_OBJECT) { ! class_T *cl = (class_T *)lhs->lhs_type->tt_member; if (cl->class_flags & CLASS_INTERFACE) { --- 2201,2207 ---- if (dest_type == VAR_OBJECT) { ! class_T *cl = lhs->lhs_type->tt_class; if (cl->class_flags & CLASS_INTERFACE) { *** ../vim-9.0.1333/src/vim9expr.c 2023-02-18 19:49:28.126600526 +0000 --- src/vim9expr.c 2023-02-20 20:47:57.432005338 +0000 *************** *** 263,269 **** return FAIL; } ! class_T *cl = (class_T *)type->tt_member; int is_super = type->tt_flags & TTFLAG_SUPER; if (type == &t_super) { --- 263,269 ---- return FAIL; } ! class_T *cl = type->tt_class; int is_super = type->tt_flags & TTFLAG_SUPER; if (type == &t_super) { *** ../vim-9.0.1333/src/vim9type.c 2023-02-18 14:42:40.113005575 +0000 --- src/vim9type.c 2023-02-20 21:58:37.255794651 +0000 *************** *** 86,96 **** ((type_T **)seen_types->ga_data)[seen_types->ga_len * 2 + 1] = copy; ++seen_types->ga_len; ! if (copy->tt_member != NULL ! && copy->tt_type != VAR_OBJECT && copy->tt_type != VAR_CLASS) copy->tt_member = copy_type_deep_rec(copy->tt_member, type_gap, seen_types); - if (type->tt_args != NULL) for (int i = 0; i < type->tt_argcount; ++i) copy->tt_args[i] = copy_type_deep_rec(copy->tt_args[i], --- 86,94 ---- ((type_T **)seen_types->ga_data)[seen_types->ga_len * 2 + 1] = copy; ++seen_types->ga_len; ! if (copy->tt_member != NULL) copy->tt_member = copy_type_deep_rec(copy->tt_member, type_gap, seen_types); if (type->tt_args != NULL) for (int i = 0; i < type->tt_argcount; ++i) copy->tt_args[i] = copy_type_deep_rec(copy->tt_args[i], *************** *** 144,154 **** *ret = *type; if (ret->tt_member != NULL) ! { ! // tt_member points to the class_T for VAR_CLASS and VAR_OBJECT ! if (type->tt_type != VAR_CLASS && type->tt_type != VAR_OBJECT) ! ret->tt_member = alloc_type(ret->tt_member); ! } if (type->tt_args != NULL) { --- 142,148 ---- *ret = *type; if (ret->tt_member != NULL) ! ret->tt_member = alloc_type(ret->tt_member); if (type->tt_args != NULL) { *************** *** 180,188 **** vim_free(type->tt_args); } ! // for an object and class tt_member is a pointer to the class ! if (type->tt_type != VAR_OBJECT && type->tt_type != VAR_CLASS) ! free_type(type->tt_member); vim_free(type); } --- 174,180 ---- vim_free(type->tt_args); } ! free_type(type->tt_member); vim_free(type); } *************** *** 419,424 **** --- 411,417 ---- { type_T *type; type_T *member_type = NULL; + class_T *class_type = NULL; int argcount = 0; int min_argcount = 0; *************** *** 584,592 **** } if (tv->v_type == VAR_CLASS) ! member_type = (type_T *)tv->vval.v_class; else if (tv->v_type == VAR_OBJECT && tv->vval.v_object != NULL) ! member_type = (type_T *)tv->vval.v_object->obj_class; type = get_type_ptr(type_gap); if (type == NULL) --- 577,585 ---- } if (tv->v_type == VAR_CLASS) ! class_type = tv->vval.v_class; else if (tv->v_type == VAR_OBJECT && tv->vval.v_object != NULL) ! class_type = tv->vval.v_object->obj_class; type = get_type_ptr(type_gap); if (type == NULL) *************** *** 601,606 **** --- 594,600 ---- type->tt_min_argcount -= tv->vval.v_partial->pt_argc; } type->tt_member = member_type; + type->tt_class = class_type; return type; } *************** *** 887,905 **** if (actual->tt_type == VAR_ANY) return MAYBE; // use runtime type check if (actual->tt_type != VAR_OBJECT) ! return FAIL; // don't use tt_member // 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; --- 881,897 ---- if (actual->tt_type == VAR_ANY) return MAYBE; // use runtime type check if (actual->tt_type != VAR_OBJECT) ! return FAIL; // don't use tt_class // check the class, base class or an implemented interface matches class_T *cl; ! for (cl = actual->tt_class; cl != NULL; cl = cl->class_extends) { ! if (expected->tt_class == cl) break; int i; for (i = cl->class_interface_count - 1; i >= 0; --i) ! if (expected->tt_class == cl->class_interfaces_cl[i]) break; if (i >= 0) break; *************** *** 1321,1327 **** // Although the name is that of a class or interface, the type // uses will be an object. type->tt_type = VAR_OBJECT; ! type->tt_member = (type_T *)tv.vval.v_class; clear_tv(&tv); *arg += len; --- 1313,1319 ---- // Although the name is that of a class or interface, the type // uses will be an object. type->tt_type = VAR_OBJECT; ! type->tt_class = tv.vval.v_class; clear_tv(&tv); *arg += len; *************** *** 1659,1666 **** if (type->tt_type == VAR_OBJECT || type->tt_type == VAR_CLASS) { ! char_u *class_name = type->tt_member == NULL ? (char_u *)"Unknown" ! : ((class_T *)type->tt_member)->class_name; size_t len = STRLEN(name) + STRLEN(class_name) + 3; *tofree = alloc(len); if (*tofree != NULL) --- 1651,1658 ---- if (type->tt_type == VAR_OBJECT || type->tt_type == VAR_CLASS) { ! char_u *class_name = type->tt_class == NULL ? (char_u *)"Unknown" ! : type->tt_class->class_name; size_t len = STRLEN(name) + STRLEN(class_name) + 3; *tofree = alloc(len); if (*tofree != NULL) *** ../vim-9.0.1333/src/vim9class.c 2023-02-17 21:08:46.433731097 +0000 --- src/vim9class.c 2023-02-20 20:49:58.847906348 +0000 *************** *** 990,996 **** if (nf->uf_ret_type != NULL) { nf->uf_ret_type->tt_type = VAR_OBJECT; ! nf->uf_ret_type->tt_member = (type_T *)cl; nf->uf_ret_type->tt_argcount = 0; nf->uf_ret_type->tt_args = NULL; } --- 990,996 ---- if (nf->uf_ret_type != NULL) { nf->uf_ret_type->tt_type = VAR_OBJECT; ! nf->uf_ret_type->tt_class = cl; nf->uf_ret_type->tt_argcount = 0; nf->uf_ret_type->tt_args = NULL; } *************** *** 1083,1091 **** } cl->class_type.tt_type = VAR_CLASS; ! cl->class_type.tt_member = (type_T *)cl; cl->class_object_type.tt_type = VAR_OBJECT; ! cl->class_object_type.tt_member = (type_T *)cl; cl->class_type_list = type_list; // TODO: --- 1083,1091 ---- } cl->class_type.tt_type = VAR_CLASS; ! cl->class_type.tt_class = cl; cl->class_object_type.tt_type = VAR_OBJECT; ! cl->class_object_type.tt_class = cl; cl->class_type_list = type_list; // TODO: *** ../vim-9.0.1333/src/evalfunc.c 2023-02-20 12:16:33.328269404 +0000 --- src/evalfunc.c 2023-02-20 20:52:20.847793601 +0000 *************** *** 585,591 **** { type_T *expected_member = NULL; type_T *(args[2]); ! type_T t_func_exp = {VAR_FUNC, 2, 0, 0, NULL, args}; if (context->arg_types[0].type_curr->tt_type == VAR_LIST || context->arg_types[0].type_curr->tt_type == VAR_DICT) --- 585,591 ---- { type_T *expected_member = NULL; type_T *(args[2]); ! type_T t_func_exp = {VAR_FUNC, 2, 0, 0, NULL, NULL, args}; if (context->arg_types[0].type_curr->tt_type == VAR_LIST || context->arg_types[0].type_curr->tt_type == VAR_DICT) *************** *** 699,705 **** if (type->tt_type == VAR_FUNC) { type_T *(args[2]); ! type_T t_func_exp = {VAR_FUNC, 2, 0, 0, &t_number, args}; if (context->arg_types[0].type_curr->tt_type == VAR_LIST) args[0] = context->arg_types[0].type_curr->tt_member; --- 699,705 ---- if (type->tt_type == VAR_FUNC) { type_T *(args[2]); ! type_T t_func_exp = {VAR_FUNC, 2, 0, 0, &t_number, NULL, args}; if (context->arg_types[0].type_curr->tt_type == VAR_LIST) args[0] = context->arg_types[0].type_curr->tt_member; *** ../vim-9.0.1333/src/version.c 2023-02-20 18:44:29.594912053 +0000 --- src/version.c 2023-02-20 20:58:18.712177093 +0000 *************** *** 697,698 **** --- 697,700 ---- { /* Add new patch number below this line */ + /**/ + 1334, /**/ -- Send $25.00 for handy leaflet on how to make money by selling leaflets /// 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 ///