ex_let_one(
    char_u	*arg,		// points to variable name
    typval_T	*tv,		// value to assign to variable
    int		copy,		// copy value from "tv"
    int		flags,		// ASSIGN_CONST, ASSIGN_FINAL, etc.
    char_u	*endchars,	// valid chars after variable name  or NULL
    char_u	*op,		// "+", "-", "."  or NULL
    int		var_idx)	// variable index for "let [a, b] = list"
{
    char_u	*arg_end = NULL;

    if (in_vim9script() && (flags & (ASSIGN_NO_DECL | ASSIGN_DECL)) == 0
			&& (flags & (ASSIGN_CONST | ASSIGN_FINAL)) == 0
				  && vim_strchr((char_u *)"$@&", *arg) != NULL)
    {
	vim9_declare_error(arg);
	return NULL;
    }

    if (*arg == '$')
    {
	// ":let $VAR = expr": Set environment variable.
	return ex_let_env(arg, tv, flags, endchars, op);
    }
    else if (*arg == '&')
    {
	// ":let &option = expr": Set option value.
	// ":let &l:option = expr": Set local option value.
	// ":let &g:option = expr": Set global option value.
	// ":for &ts in range(8)": Set option value for for loop
	return ex_let_option(arg, tv, flags, endchars, op);
    }
    else if (*arg == '@')
    {
	// ":let @r = expr": Set register contents.
	return ex_let_register(arg, tv, flags, endchars, op);
    }
    else if (eval_isnamec1(*arg) || *arg == '{')
    {
	lval_T	lv;
	char_u	*p;

	// ":let var = expr": Set internal variable.
	// ":let var: type = expr": Set internal variable with type.
	// ":let {expr} = expr": Idem, name made with curly braces
	p = get_lval(arg, tv, &lv, FALSE, FALSE,
		(flags & (ASSIGN_NO_DECL | ASSIGN_DECL))
					   ? GLV_NO_DECL : 0, FNE_CHECK_START);
	if (p != NULL && lv.ll_name != NULL)
	{
	    if (endchars != NULL && vim_strchr(endchars,
					   *skipwhite(lv.ll_name_end)) == NULL)
	    {
		emsg(_(e_unexpected_characters_in_let));
	    }
	    else
	    {
		set_var_lval(&lv, p, tv, copy, flags, op, var_idx);
		arg_end = lv.ll_name_end;
	    }
	}
	clear_lval(&lv);
    }
    else
	semsg(_(e_invalid_argument_str), arg);

    return arg_end;
}
ex_let_one(
    char_u	*arg,		 
    typval_T	*tv,		 
    int		copy,		 
    int		flags,		 
    char_u	*endchars,	 
    char_u	*op,		 
    int		var_idx)	 
{
    char_u	*arg_end = NULL;

    if (in_vim9script() && (flags & (ASSIGN_NO_DECL | ASSIGN_DECL)) == 0
			&& (flags & (ASSIGN_CONST | ASSIGN_FINAL)) == 0
				  && vim_strchr((char_u *)"$@&", *arg) != NULL)
    {
	vim9_declare_error(arg);
	return NULL;
    }

    if (*arg == '$')
    {
	 
	return ex_let_env(arg, tv, flags, endchars, op);
    }
    else if (*arg == '&')
    {
	 
	 
	 
	 
	return ex_let_option(arg, tv, flags, endchars, op);
    }
    else if (*arg == '@')
    {
	 
	return ex_let_register(arg, tv, flags, endchars, op);
    }
    else if (eval_isnamec1(*arg) || *arg == '{')
    {
	lval_T	lv;
	char_u	*p;

	 
	 
	 
	p = get_lval(arg, tv, &lv, FALSE, FALSE,
		(flags & (ASSIGN_NO_DECL | ASSIGN_DECL))
					   ? GLV_NO_DECL : 0, FNE_CHECK_START);
	if (p != NULL && lv.ll_name != NULL)
	{
	    if (endchars != NULL && vim_strchr(endchars,
					   *skipwhite(lv.ll_name_end)) == NULL)
	    {
		emsg(_(e_unexpected_characters_in_let));
	    }
	    else
	    {
		set_var_lval(&lv, p, tv, copy, flags, op, var_idx);
		arg_end = lv.ll_name_end;
	    }
	}
	clear_lval(&lv);
    }
    else
	semsg(_(e_invalid_argument_str), arg);

    return arg_end;
}