Mercurial > vim
diff 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 |
line wrap: on
line diff
--- a/src/vim9expr.c +++ b/src/vim9expr.c @@ -251,6 +251,56 @@ compile_member(int is_slice, int *keepin } /* + * Compile ".member" coming after an object or class. + */ + + static int +compile_class_object_index(cctx_T *cctx, char_u **arg, type_T *type) +{ + if (VIM_ISWHITE((*arg)[1])) + { + semsg(_(e_no_white_space_allowed_after_str_str), ".", *arg); + return FAIL; + } + + ++*arg; + char_u *name = *arg; + char_u *name_end = find_name_end(name, NULL, NULL, FNE_CHECK_START); + if (name_end == name) + return FAIL; + size_t len = name_end - name; + + class_T *cl = (class_T *)type->tt_member; + if (*name_end == '(') + { + // TODO + } + else if (type->tt_type == VAR_OBJECT) + { + for (int i = 0; i < cl->class_obj_member_count; ++i) + { + objmember_T *m = &cl->class_obj_members[i]; + if (STRNCMP(name, m->om_name, len) == 0 && m->om_name[len] == NUL) + { + generate_OBJ_MEMBER(cctx, i, m->om_type); + + *arg = name_end; + return OK; + } + } + + semsg(_(e_member_not_found_on_object_str_str), cl->class_name, name); + } + else + { + // TODO: class member + emsg("compile_class_object_index(): not handled"); + } + + return FAIL; +} + +/* * Generate an instruction to load script-local variable "name", without the * leading "s:". * Also finds imported variables. @@ -1797,6 +1847,7 @@ compile_subscript( for (;;) { char_u *p = skipwhite(*arg); + type_T *type; if (*p == NUL || (VIM_ISWHITE(**arg) && vim9_comment_start(p))) { @@ -1824,7 +1875,6 @@ compile_subscript( // is not a function call. if (**arg == '(') { - type_T *type; int argcount = 0; if (generate_ppconst(cctx, ppconst) == FAIL) @@ -1911,7 +1961,6 @@ compile_subscript( int argcount = 1; garray_T *stack = &cctx->ctx_type_stack; int type_idx_start = stack->ga_len; - type_T *type; int expr_isn_start = cctx->ctx_instr.ga_len; int expr_isn_end; int arg_isn_count; @@ -2097,6 +2146,18 @@ compile_subscript( if (compile_member(is_slice, &keeping_dict, cctx) == FAIL) return FAIL; } + else if (*p == '.' + && (type = get_type_on_stack(cctx, 0)) != &t_unknown + && (type->tt_type == VAR_CLASS || type->tt_type == VAR_OBJECT)) + { + // class member: SomeClass.varname + // class method: SomeClass.SomeMethod() + // class constructor: SomeClass.new() + // object member: someObject.varname, this.varname + // object method: someObject.SomeMethod(), this.SomeMethod() + if (compile_class_object_index(cctx, arg, type) == FAIL) + return FAIL; + } else if (*p == '.' && p[1] != '.') { // dictionary member: dict.name