diff src/vim9execute.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 60b1d266548d
children e31fc75f6aff
line wrap: on
line diff
--- a/src/vim9execute.c
+++ b/src/vim9execute.c
@@ -4225,7 +4225,7 @@ exec_instructions(ectx_T *ectx)
 		    CLEAR_FIELD(ea);
 		    ea.cmd = ea.arg = iptr->isn_arg.string;
 		    ga_init2(&lines_to_free, sizeof(char_u *), 50);
-		    define_function(&ea, NULL, &lines_to_free, NULL);
+		    define_function(&ea, NULL, &lines_to_free, FALSE);
 		    ga_clear_strings(&lines_to_free);
 		}
 		break;
@@ -5114,6 +5114,35 @@ exec_instructions(ectx_T *ectx)
 		}
 		break;
 
+	    case ISN_OBJ_MEMBER:
+		{
+		    tv = STACK_TV_BOT(-1);
+		    if (tv->v_type != VAR_OBJECT)
+		    {
+			SOURCING_LNUM = iptr->isn_lnum;
+			garray_T type_list;
+			ga_init2(&type_list, sizeof(type_T *), 10);
+			type_T *type = typval2type(tv, get_copyID(),
+						   &type_list, TVTT_DO_MEMBER);
+			char *tofree = NULL;
+			char *typename = type_name(type, &tofree);
+			semsg(_(e_object_required_found_str), typename);
+			vim_free(tofree);
+			clear_type_list(&type_list);
+			goto on_error;
+		    }
+		    int idx = iptr->isn_arg.number;
+		    object_T *obj = tv->vval.v_object;
+		    // the members are located right after the object struct
+		    typval_T *mtv = ((typval_T *)(obj + 1)) + idx;
+		    *tv = *mtv;
+
+		    // Unreference the object after getting the member, it may
+		    // be freed.
+		    object_unref(obj);
+		}
+		break;
+
 	    case ISN_CLEARDICT:
 		dict_stack_drop();
 		break;
@@ -5577,6 +5606,7 @@ call_def_function(
     typval_T	*argv,		// arguments
     int		flags,		// DEF_ flags
     partial_T	*partial,	// optional partial for context
+    object_T	*object,	// object, e.g. for this.Func()
     funccall_T	*funccal,
     typval_T	*rettv)		// return value
 {
@@ -5818,6 +5848,15 @@ call_def_function(
 	    STACK_TV_VAR(idx)->vval.v_number = 0;
 	}
 	ectx.ec_stack.ga_len += dfunc->df_varcount;
+
+	if (object != NULL)
+	{
+	    // the object is always the variable at index zero
+	    tv = STACK_TV_VAR(0);
+	    tv->v_type = VAR_OBJECT;
+	    tv->vval.v_object = object;
+	}
+
 	if (dfunc->df_has_closure)
 	{
 	    // Initialize the variable that counts how many closures were
@@ -6766,6 +6805,8 @@ list_instructions(char *pfx, isn_T *inst
 	    case ISN_MEMBER: smsg("%s%4d MEMBER", pfx, current); break;
 	    case ISN_STRINGMEMBER: smsg("%s%4d MEMBER %s", pfx, current,
 						  iptr->isn_arg.string); break;
+	    case ISN_OBJ_MEMBER: smsg("%s%4d OBJ_MEMBER %d", pfx, current,
+					     (int)iptr->isn_arg.number); break;
 	    case ISN_CLEARDICT: smsg("%s%4d CLEARDICT", pfx, current); break;
 	    case ISN_USEDICT: smsg("%s%4d USEDICT", pfx, current); break;