Mercurial > vim
comparison src/vim9expr.c @ 31416:f088f1d97eee v9.0.1041
patch 9.0.1041: cannot define a method in a class
Commit: https://github.com/vim/vim/commit/ffdaca9e6f3d39af6857ac52ced9385df203a152
Author: Bram Moolenaar <Bram@vim.org>
Date: Fri Dec 9 21:41:48 2022 +0000
patch 9.0.1041: cannot define a method in a class
Problem: Cannot define a method in a class.
Solution: Implement defining an object method. Make calling an object
method work.
author | Bram Moolenaar <Bram@vim.org> |
---|---|
date | Fri, 09 Dec 2022 22:45:03 +0100 |
parents | 307f68a41b03 |
children | e31fc75f6aff |
comparison
equal
deleted
inserted
replaced
31415:4fd33db887f2 | 31416:f088f1d97eee |
---|---|
246 emsg(_(e_string_list_dict_or_blob_required)); | 246 emsg(_(e_string_list_dict_or_blob_required)); |
247 } | 247 } |
248 return FAIL; | 248 return FAIL; |
249 } | 249 } |
250 return OK; | 250 return OK; |
251 } | |
252 | |
253 /* | |
254 * Compile ".member" coming after an object or class. | |
255 */ | |
256 | |
257 static int | |
258 compile_class_object_index(cctx_T *cctx, char_u **arg, type_T *type) | |
259 { | |
260 if (VIM_ISWHITE((*arg)[1])) | |
261 { | |
262 semsg(_(e_no_white_space_allowed_after_str_str), ".", *arg); | |
263 return FAIL; | |
264 } | |
265 | |
266 ++*arg; | |
267 char_u *name = *arg; | |
268 char_u *name_end = find_name_end(name, NULL, NULL, FNE_CHECK_START); | |
269 if (name_end == name) | |
270 return FAIL; | |
271 size_t len = name_end - name; | |
272 | |
273 class_T *cl = (class_T *)type->tt_member; | |
274 if (*name_end == '(') | |
275 { | |
276 // TODO | |
277 } | |
278 else if (type->tt_type == VAR_OBJECT) | |
279 { | |
280 for (int i = 0; i < cl->class_obj_member_count; ++i) | |
281 { | |
282 objmember_T *m = &cl->class_obj_members[i]; | |
283 if (STRNCMP(name, m->om_name, len) == 0 && m->om_name[len] == NUL) | |
284 { | |
285 generate_OBJ_MEMBER(cctx, i, m->om_type); | |
286 | |
287 *arg = name_end; | |
288 return OK; | |
289 } | |
290 } | |
291 | |
292 semsg(_(e_member_not_found_on_object_str_str), cl->class_name, name); | |
293 } | |
294 else | |
295 { | |
296 // TODO: class member | |
297 emsg("compile_class_object_index(): not handled"); | |
298 } | |
299 | |
300 return FAIL; | |
251 } | 301 } |
252 | 302 |
253 /* | 303 /* |
254 * Generate an instruction to load script-local variable "name", without the | 304 * Generate an instruction to load script-local variable "name", without the |
255 * leading "s:". | 305 * leading "s:". |
1795 int keeping_dict = FALSE; | 1845 int keeping_dict = FALSE; |
1796 | 1846 |
1797 for (;;) | 1847 for (;;) |
1798 { | 1848 { |
1799 char_u *p = skipwhite(*arg); | 1849 char_u *p = skipwhite(*arg); |
1850 type_T *type; | |
1800 | 1851 |
1801 if (*p == NUL || (VIM_ISWHITE(**arg) && vim9_comment_start(p))) | 1852 if (*p == NUL || (VIM_ISWHITE(**arg) && vim9_comment_start(p))) |
1802 { | 1853 { |
1803 char_u *next = peek_next_line_from_context(cctx); | 1854 char_u *next = peek_next_line_from_context(cctx); |
1804 | 1855 |
1822 | 1873 |
1823 // Do not skip over white space to find the "(", "execute 'x' (expr)" | 1874 // Do not skip over white space to find the "(", "execute 'x' (expr)" |
1824 // is not a function call. | 1875 // is not a function call. |
1825 if (**arg == '(') | 1876 if (**arg == '(') |
1826 { | 1877 { |
1827 type_T *type; | |
1828 int argcount = 0; | 1878 int argcount = 0; |
1829 | 1879 |
1830 if (generate_ppconst(cctx, ppconst) == FAIL) | 1880 if (generate_ppconst(cctx, ppconst) == FAIL) |
1831 return FAIL; | 1881 return FAIL; |
1832 ppconst->pp_is_const = FALSE; | 1882 ppconst->pp_is_const = FALSE; |
1909 if (alt != 1) | 1959 if (alt != 1) |
1910 { | 1960 { |
1911 int argcount = 1; | 1961 int argcount = 1; |
1912 garray_T *stack = &cctx->ctx_type_stack; | 1962 garray_T *stack = &cctx->ctx_type_stack; |
1913 int type_idx_start = stack->ga_len; | 1963 int type_idx_start = stack->ga_len; |
1914 type_T *type; | |
1915 int expr_isn_start = cctx->ctx_instr.ga_len; | 1964 int expr_isn_start = cctx->ctx_instr.ga_len; |
1916 int expr_isn_end; | 1965 int expr_isn_end; |
1917 int arg_isn_count; | 1966 int arg_isn_count; |
1918 | 1967 |
1919 if (alt == 2) | 1968 if (alt == 2) |
2093 keeping_dict = FALSE; | 2142 keeping_dict = FALSE; |
2094 if (generate_instr(cctx, ISN_CLEARDICT) == NULL) | 2143 if (generate_instr(cctx, ISN_CLEARDICT) == NULL) |
2095 return FAIL; | 2144 return FAIL; |
2096 } | 2145 } |
2097 if (compile_member(is_slice, &keeping_dict, cctx) == FAIL) | 2146 if (compile_member(is_slice, &keeping_dict, cctx) == FAIL) |
2147 return FAIL; | |
2148 } | |
2149 else if (*p == '.' | |
2150 && (type = get_type_on_stack(cctx, 0)) != &t_unknown | |
2151 && (type->tt_type == VAR_CLASS || type->tt_type == VAR_OBJECT)) | |
2152 { | |
2153 // class member: SomeClass.varname | |
2154 // class method: SomeClass.SomeMethod() | |
2155 // class constructor: SomeClass.new() | |
2156 // object member: someObject.varname, this.varname | |
2157 // object method: someObject.SomeMethod(), this.SomeMethod() | |
2158 if (compile_class_object_index(cctx, arg, type) == FAIL) | |
2098 return FAIL; | 2159 return FAIL; |
2099 } | 2160 } |
2100 else if (*p == '.' && p[1] != '.') | 2161 else if (*p == '.' && p[1] != '.') |
2101 { | 2162 { |
2102 // dictionary member: dict.name | 2163 // dictionary member: dict.name |