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