END
v9.CheckScriptSuccess(lines)
+ lines =<< trim END
+ vim9script
+
+ export def Floats(x: float, y = 2.0, z = 5.0)
+ g:result = printf("%.2f %.2f %.2f", x, y, z)
+ enddef
+ END
+ writefile(lines, 'Xlib.vim', 'D')
+
+ # test using a function reference in script-local variable
+ lines =<< trim END
+ vim9script
+
+ import './Xlib.vim'
+ const Floatfunc = Xlib.Floats
+ Floatfunc(1.0, v:none, 3.0)
+ END
+ v9.CheckScriptSuccess(lines)
+ assert_equal('1.00 2.00 3.00', g:result)
+ unlet g:result
+
+ # test calling the imported function
+ lines =<< trim END
+ vim9script
+
+ import './Xlib.vim'
+ Xlib.Floats(1.0, v:none, 3.0)
+ END
+ v9.CheckScriptSuccess(lines)
+ assert_equal('1.00 2.00 3.00', g:result)
+ unlet g:result
+
# TODO: this should give an error for using a missing argument
# lines =<< trim END
# vim9script
}
}
+/*
+ * Check the argument types "argvars[argcount]" for "name" using the
+ * information in "funcexe". When "base_included" then "funcexe->fe_basetv"
+ * is already included in "argvars[]".
+ * Will do nothing if "funcexe->fe_check_type" is NULL or
+ * "funcexe->fe_evaluate" is FALSE;
+ * Returns an FCERR_ value.
+ */
+ static funcerror_T
+may_check_argument_types(
+ funcexe_T *funcexe,
+ typval_T *argvars,
+ int argcount,
+ int base_included,
+ char_u *name)
+{
+ if (funcexe->fe_check_type != NULL && funcexe->fe_evaluate)
+ {
+ // Check that the argument types are OK for the types of the funcref.
+ if (check_argument_types(funcexe->fe_check_type,
+ argvars, argcount,
+ base_included ? NULL : funcexe->fe_basetv,
+ name) == FAIL)
+ return FCERR_OTHER;
+ }
+ return FCERR_NONE;
+}
+
/*
* Call a function with its resolved parameters
*
}
}
- if (error == FCERR_NONE && funcexe->fe_check_type != NULL
- && funcexe->fe_evaluate)
- {
- // Check that the argument types are OK for the types of the funcref.
- if (check_argument_types(funcexe->fe_check_type,
- argvars, argcount, funcexe->fe_basetv,
- (name != NULL) ? name : funcname) == FAIL)
- error = FCERR_OTHER;
- }
+ if (error == FCERR_NONE)
+ // check the argument types if possible
+ error = may_check_argument_types(funcexe, argvars, argcount, FALSE,
+ (name != NULL) ? name : funcname);
if (error == FCERR_NONE && funcexe->fe_evaluate)
{
error = FCERR_DELETED;
else if (fp != NULL)
{
+ int need_arg_check = FALSE;
+ if (funcexe->fe_check_type == NULL)
+ {
+ funcexe->fe_check_type = fp->uf_func_type;
+ need_arg_check = TRUE;
+ }
+
if (funcexe->fe_argv_func != NULL)
+ {
// postponed filling in the arguments, do it now
argcount = funcexe->fe_argv_func(argcount, argvars,
- argv_clear, fp);
+ argv_clear, fp);
+ need_arg_check = TRUE;
+ }
if (funcexe->fe_basetv != NULL)
{
argcount++;
argvars = argv;
argv_base = 1;
+ need_arg_check = TRUE;
}
- error = call_user_func_check(fp, argcount, argvars, rettv,
+ // Check the argument types now that the function type and all
+ // argument values are known, if not done above.
+ if (need_arg_check)
+ error = may_check_argument_types(funcexe, argvars, argcount,
+ TRUE, (name != NULL) ? name : funcname);
+ if (error == FCERR_NONE || error == FCERR_UNKNOWN)
+ error = call_user_func_check(fp, argcount, argvars, rettv,
funcexe, selfdict);
}
}