diff src/userfunc.c @ 31396:307f68a41b03 v9.0.1031

patch 9.0.1031: Vim9 class is not implemented yet Commit: https://github.com/vim/vim/commit/00b28d6c23d8e662cab27e461825777c0a2e387a Author: Bram Moolenaar <Bram@vim.org> Date: Thu Dec 8 15:32:33 2022 +0000 patch 9.0.1031: Vim9 class is not implemented yet Problem: Vim9 class is not implemented yet. Solution: Add very basic class support.
author Bram Moolenaar <Bram@vim.org>
date Thu, 08 Dec 2022 16:45:03 +0100
parents 684e6dfa2fba
children f088f1d97eee
line wrap: on
line diff
--- a/src/userfunc.c
+++ b/src/userfunc.c
@@ -214,6 +214,8 @@ get_function_args(
     garray_T	*default_args,
     int		skip,
     exarg_T	*eap,		// can be NULL
+    class_T	*class_arg,
+    garray_T	*newlines,	// function body lines
     garray_T	*lines_to_free)
 {
     int		mustend = FALSE;
@@ -292,6 +294,51 @@ get_function_args(
 		}
 	    }
 	}
+	else if (class_arg != NULL && STRNCMP(p, "this.", 5) == 0)
+	{
+	    // this.memberName
+	    p += 5;
+	    arg = p;
+	    while (ASCII_ISALNUM(*p) || *p == '_')
+		++p;
+
+	    // TODO: check the argument is indeed a member
+	    if (newargs != NULL && ga_grow(newargs, 1) == FAIL)
+		return FAIL;
+	    if (newargs != NULL)
+	    {
+		((char_u **)(newargs->ga_data))[newargs->ga_len] =
+						    vim_strnsave(arg, p - arg);
+		newargs->ga_len++;
+
+		if (argtypes != NULL && ga_grow(argtypes, 1) == OK)
+		{
+		    // TODO: use the actual type
+		    ((char_u **)argtypes->ga_data)[argtypes->ga_len++] =
+						  vim_strsave((char_u *)"any");
+
+		    // Add a line to the function body for the assignment.
+		    if (ga_grow(newlines, 1) == OK)
+		    {
+			// "this.name = name"
+			int len = 5 + (p - arg) + 3 + (p - arg) + 1;
+			char_u *assignment = alloc(len);
+			if (assignment != NULL)
+			{
+			    c = *p;
+			    *p = NUL;
+			    vim_snprintf((char *)assignment, len,
+						     "this.%s = %s", arg, arg);
+			    *p = c;
+			    ((char_u **)(newlines->ga_data))[
+					      newlines->ga_len++] = assignment;
+			}
+		    }
+		}
+	    }
+	    if (*p == ',')
+		++p;
+	}
 	else
 	{
 	    char_u *np;
@@ -1389,7 +1436,7 @@ get_lambda_tv(
     s = *arg + 1;
     ret = get_function_args(&s, equal_arrow ? ')' : '-', NULL,
 	    types_optional ? &argtypes : NULL, types_optional, evalarg,
-					NULL, &default_args, TRUE, NULL, NULL);
+			    NULL, &default_args, TRUE, NULL, NULL, NULL, NULL);
     if (ret == FAIL || skip_arrow(s, equal_arrow, &ret_type, NULL) == NULL)
     {
 	if (types_optional)
@@ -1406,7 +1453,7 @@ get_lambda_tv(
     ret = get_function_args(arg, equal_arrow ? ')' : '-', pnewargs,
 	    types_optional ? &argtypes : NULL, types_optional, evalarg,
 					    &varargs, &default_args,
-					    FALSE, NULL, NULL);
+					    FALSE, NULL, NULL, NULL, NULL);
     if (ret == FAIL
 		  || (s = skip_arrow(*arg, equal_arrow, &ret_type,
 		equal_arrow || vim9script ? &white_error : NULL)) == NULL)
@@ -1733,7 +1780,7 @@ emsg_funcname(char *ermsg, char_u *name)
  * Return them in "*argvars[MAX_FUNC_ARGS + 1]" and the count in "argcount".
  * On failure FAIL is returned but the "argvars[argcount]" are still set.
  */
-    static int
+    int
 get_func_arguments(
 	char_u	    **arg,
 	evalarg_T   *evalarg,
@@ -1809,7 +1856,7 @@ get_func_tv(
     funcexe_T	*funcexe)	// various values
 {
     char_u	*argp;
-    int		ret = OK;
+    int		ret;
     typval_T	argvars[MAX_FUNC_ARGS + 1];	// vars for arguments
     int		argcount = 0;			// number of arguments found
     int		vim9script = in_vim9script();
@@ -4370,10 +4417,15 @@ list_functions(regmatch_T *regmatch)
  * When "name_arg" is not NULL this is a nested function, using "name_arg" for
  * the function name.
  * "lines_to_free" is a list of strings to be freed later.
+ * If "class_arg" is not NULL then the function is defined in this class.
  * Returns a pointer to the function or NULL if no function defined.
  */
     ufunc_T *
-define_function(exarg_T *eap, char_u *name_arg, garray_T *lines_to_free)
+define_function(
+	exarg_T	    *eap,
+	char_u	    *name_arg,
+	garray_T    *lines_to_free,
+	class_T	    *class_arg)
 {
     int		j;
     int		c;
@@ -4488,8 +4540,9 @@ define_function(exarg_T *eap, char_u *na
 	    p = eap->arg;
 	}
 
-	name = save_function_name(&p, &is_global, eap->skip,
-					TFN_NO_AUTOLOAD | TFN_NEW_FUNC, &fudi);
+	int tfn_flags = TFN_NO_AUTOLOAD | TFN_NEW_FUNC
+					      | (class_arg == 0 ? 0 : TFN_INT);
+	name = save_function_name(&p, &is_global, eap->skip, tfn_flags, &fudi);
 	paren = (vim_strchr(p, '(') != NULL);
 	if (name == NULL && (fudi.fd_dict == NULL || !paren) && !eap->skip)
 	{
@@ -4690,7 +4743,7 @@ define_function(exarg_T *eap, char_u *na
     if (get_function_args(&p, ')', &newargs,
 			eap->cmdidx == CMD_def ? &argtypes : NULL, FALSE,
 			 NULL, &varargs, &default_args, eap->skip,
-			 eap, lines_to_free) == FAIL)
+			 eap, class_arg, &newlines, lines_to_free) == FAIL)
 	goto errret_2;
     whitep = p;
 
@@ -5145,7 +5198,7 @@ ex_function(exarg_T *eap)
     garray_T lines_to_free;
 
     ga_init2(&lines_to_free, sizeof(char_u *), 50);
-    (void)define_function(eap, NULL, &lines_to_free);
+    (void)define_function(eap, NULL, &lines_to_free, NULL);
     ga_clear_strings(&lines_to_free);
 }