diff src/vim9compile.c @ 19328:e99e6d794597 v8.2.0222

patch 8.2.0222: Vim9: optional function arguments don't work yet Commit: https://github.com/vim/vim/commit/170fcfcf250954d76fca86e3fed088ddfdb49383 Author: Bram Moolenaar <Bram@vim.org> Date: Thu Feb 6 17:51:35 2020 +0100 patch 8.2.0222: Vim9: optional function arguments don't work yet Problem: Vim9: optional function arguments don't work yet. Solution: Implement optional function arguments.
author Bram Moolenaar <Bram@vim.org>
date Thu, 06 Feb 2020 18:00:04 +0100
parents 17dc6282f370
children 9c8b803fe598
line wrap: on
line diff
--- a/src/vim9compile.c
+++ b/src/vim9compile.c
@@ -956,11 +956,12 @@ generate_BCALL(cctx_T *cctx, int func_id
  * Return FAIL if the number of arguments is wrong.
  */
     static int
-generate_CALL(cctx_T *cctx, ufunc_T *ufunc, int argcount)
+generate_CALL(cctx_T *cctx, ufunc_T *ufunc, int pushed_argcount)
 {
     isn_T	*isn;
     garray_T	*stack = &cctx->ctx_type_stack;
     int		regular_args = ufunc->uf_args.ga_len;
+    int		argcount = pushed_argcount;
 
     if (argcount > regular_args && !has_varargs(ufunc))
     {
@@ -978,9 +979,13 @@ generate_CALL(cctx_T *cctx, ufunc_T *ufu
     {
 	int count = argcount - regular_args;
 
-	// TODO: add default values for optional arguments?
-	generate_NEWLIST(cctx, count < 0 ? 0 : count);
-	argcount = regular_args + 1;
+	// If count is negative an empty list will be added after evaluating
+	// default values for missing optional arguments.
+	if (count >= 0)
+	{
+	    generate_NEWLIST(cctx, count);
+	    argcount = regular_args + 1;
+	}
     }
 
     if ((isn = generate_instr(cctx,
@@ -4600,6 +4605,44 @@ compile_def_function(ufunc_T *ufunc, int
     // Most modern script version.
     current_sctx.sc_version = SCRIPT_VERSION_VIM9;
 
+    if (ufunc->uf_def_args.ga_len > 0)
+    {
+	int	count = ufunc->uf_def_args.ga_len;
+	int	i;
+	char_u	*arg;
+	int	off = STACK_FRAME_SIZE + (ufunc->uf_va_name != NULL ? 1 : 0);
+
+	// Produce instructions for the default values of optional arguments.
+	// Store the instruction index in uf_def_arg_idx[] so that we know
+	// where to start when the function is called, depending on the number
+	// of arguments.
+	ufunc->uf_def_arg_idx = ALLOC_CLEAR_MULT(int, count + 1);
+	if (ufunc->uf_def_arg_idx == NULL)
+	    goto erret;
+	for (i = 0; i < count; ++i)
+	{
+	    ufunc->uf_def_arg_idx[i] = instr->ga_len;
+	    arg = ((char_u **)(ufunc->uf_def_args.ga_data))[i];
+	    if (compile_expr1(&arg, &cctx) == FAIL
+		    || generate_STORE(&cctx, ISN_STORE,
+						i - count - off, NULL) == FAIL)
+		goto erret;
+	}
+
+	// If a varargs is following, push an empty list.
+	if (ufunc->uf_va_name != NULL)
+	{
+	    if (generate_NEWLIST(&cctx, 0) == FAIL
+		    || generate_STORE(&cctx, ISN_STORE, -off, NULL) == FAIL)
+		goto erret;
+	}
+
+	ufunc->uf_def_arg_idx[count] = instr->ga_len;
+    }
+
+    /*
+     * Loop over all the lines of the function and generate instructions.
+     */
     for (;;)
     {
 	if (line != NULL && *line == '|')