summaryrefslogtreecommitdiffstats
path: root/src/eval.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/eval.c')
-rw-r--r--src/eval.c164
1 files changed, 131 insertions, 33 deletions
diff --git a/src/eval.c b/src/eval.c
index 69b8374..51ee604 100644
--- a/src/eval.c
+++ b/src/eval.c
@@ -549,6 +549,7 @@ skip_expr_concatenate(
((char_u **)gap->ga_data)[gap->ga_len - 1];
((char_u **)gap->ga_data)[gap->ga_len - 1] = NULL;
ga_clear_strings(gap);
+ ga_clear(freegap);
}
else
{
@@ -574,16 +575,16 @@ skip_expr_concatenate(
/*
* Convert "tv" to a string.
- * When "convert" is TRUE convert a List into a sequence of lines.
+ * When "join_list" is TRUE convert a List into a sequence of lines.
* Returns an allocated string (NULL when out of memory).
*/
char_u *
-typval2string(typval_T *tv, int convert)
+typval2string(typval_T *tv, int join_list)
{
garray_T ga;
char_u *retval;
- if (convert && tv->v_type == VAR_LIST)
+ if (join_list && tv->v_type == VAR_LIST)
{
ga_init2(&ga, sizeof(char), 80);
if (tv->vval.v_list != NULL)
@@ -595,6 +596,16 @@ typval2string(typval_T *tv, int convert)
ga_append(&ga, NUL);
retval = (char_u *)ga.ga_data;
}
+ else if (tv->v_type == VAR_LIST || tv->v_type == VAR_DICT)
+ {
+ char_u *tofree;
+ char_u numbuf[NUMBUFLEN];
+
+ retval = tv2string(tv, &tofree, numbuf, 0);
+ // Make a copy if we have a value but it's not in allocated memory.
+ if (retval != NULL && tofree == NULL)
+ retval = vim_strsave(retval);
+ }
else
retval = vim_strsave(tv_get_string(tv));
return retval;
@@ -603,13 +614,13 @@ typval2string(typval_T *tv, int convert)
/*
* Top level evaluation function, returning a string. Does not handle line
* breaks.
- * When "convert" is TRUE convert a List into a sequence of lines.
+ * When "join_list" is TRUE convert a List into a sequence of lines.
* Return pointer to allocated memory, or NULL for failure.
*/
char_u *
eval_to_string_eap(
char_u *arg,
- int convert,
+ int join_list,
exarg_T *eap,
int use_simple_function)
{
@@ -627,7 +638,7 @@ eval_to_string_eap(
retval = NULL;
else
{
- retval = typval2string(&tv, convert);
+ retval = typval2string(&tv, join_list);
clear_tv(&tv);
}
clear_evalarg(&evalarg, NULL);
@@ -638,10 +649,10 @@ eval_to_string_eap(
char_u *
eval_to_string(
char_u *arg,
- int convert,
+ int join_list,
int use_simple_function)
{
- return eval_to_string_eap(arg, convert, NULL, use_simple_function);
+ return eval_to_string_eap(arg, join_list, NULL, use_simple_function);
}
/*
@@ -1119,7 +1130,18 @@ get_lval_check_access(
if (*p == '[' || *p == '.')
break;
if ((flags & GLV_READ_ONLY) == 0)
- msg = e_variable_is_not_writable_str;
+ {
+ if (IS_ENUM(cl))
+ {
+ if (om->ocm_type->tt_type == VAR_OBJECT)
+ semsg(_(e_enumvalue_str_cannot_be_modified),
+ cl->class_name, om->ocm_name);
+ else
+ msg = e_variable_is_not_writable_str;
+ }
+ else
+ msg = e_variable_is_not_writable_str;
+ }
break;
case VIM_ACCESS_ALL:
break;
@@ -1135,6 +1157,91 @@ get_lval_check_access(
}
/*
+ * Get lval information for a variable imported from script "imp_sid". On
+ * success, updates "lp" with the variable name, type, script ID and typval.
+ * The variable name starts at or after "p".
+ * If "rettv" is not NULL it points to the value to be assigned. This used to
+ * match the rhs and lhs types.
+ * Returns a pointer to the character after the variable name if the imported
+ * variable is valid and writable.
+ * Returns NULL if the variable is not exported or typval is not found or the
+ * rhs type doesn't match the lhs type or the variable is not writable.
+ */
+ static char_u *
+get_lval_imported(
+ lval_T *lp,
+ typval_T *rettv,
+ scid_T imp_sid,
+ char_u *p,
+ dictitem_T **dip,
+ int fne_flags,
+ int vim9script)
+{
+ ufunc_T *ufunc;
+ type_T *type = NULL;
+ int cc;
+ int rc = FAIL;
+
+ p = skipwhite(p);
+
+ import_check_sourced_sid(&imp_sid);
+ lp->ll_sid = imp_sid;
+ lp->ll_name = p;
+ p = find_name_end(lp->ll_name, NULL, NULL, fne_flags);
+ lp->ll_name_end = p;
+
+ // check the item is exported
+ cc = *p;
+ *p = NUL;
+ if (find_exported(imp_sid, lp->ll_name, &ufunc, &type, NULL, NULL,
+ TRUE) == -1)
+ goto failed;
+
+ if (vim9script && type != NULL)
+ {
+ where_T where = WHERE_INIT;
+
+ // In a vim9 script, do type check and make sure the variable is
+ // writable.
+ if (check_typval_type(type, rettv, where) == FAIL)
+ goto failed;
+ }
+
+ // Get the typval for the exported item
+ hashtab_T *ht = &SCRIPT_VARS(imp_sid);
+ if (ht == NULL)
+ goto failed;
+
+ dictitem_T *di = find_var_in_ht(ht, 0, lp->ll_name, TRUE);
+ if (di == NULL)
+ // script is autoloaded. So variable will be found later
+ goto success;
+
+ *dip = di;
+
+ // Check whether the variable is writable.
+ svar_T *sv = find_typval_in_script(&di->di_tv, imp_sid, FALSE);
+ if (sv != NULL && sv->sv_const != 0)
+ {
+ semsg(_(e_cannot_change_readonly_variable_str), lp->ll_name);
+ goto failed;
+ }
+
+ // check whether variable is locked
+ if (value_check_lock(di->di_tv.v_lock, lp->ll_name, FALSE))
+ goto failed;
+
+ lp->ll_tv = &di->di_tv;
+
+success:
+ rc = OK;
+
+failed:
+ *p = cc;
+ return rc == OK ? p : NULL;
+}
+
+/*
* Get an lval: variable, Dict item or List item that can be assigned a value
* to: "name", "na{me}", "name[expr]", "name[expr:expr]", "name[expr][expr]",
* "name.key", "name.key[expr]" etc.
@@ -1166,7 +1273,7 @@ get_lval(
char_u *p;
char_u *expr_start, *expr_end;
int cc;
- dictitem_T *v;
+ dictitem_T *v = NULL;
typval_T var1;
typval_T var2;
int empty1 = FALSE;
@@ -1300,28 +1407,13 @@ get_lval(
if (*p == '.')
{
imported_T *import = find_imported(lp->ll_name, p - lp->ll_name, TRUE);
-
if (import != NULL)
{
- ufunc_T *ufunc;
- type_T *type;
-
- import_check_sourced_sid(&import->imp_sid);
- lp->ll_sid = import->imp_sid;
- lp->ll_name = skipwhite(p + 1);
- p = find_name_end(lp->ll_name, NULL, NULL, fne_flags);
- lp->ll_name_end = p;
-
- // check the item is exported
- cc = *p;
- *p = NUL;
- if (find_exported(import->imp_sid, lp->ll_name, &ufunc, &type,
- NULL, NULL, TRUE) == -1)
- {
- *p = cc;
+ p++; // skip '.'
+ p = get_lval_imported(lp, rettv, import->imp_sid, p, &v,
+ fne_flags, vim9script);
+ if (p == NULL)
return NULL;
- }
- *p = cc;
}
}
@@ -1341,7 +1433,7 @@ get_lval(
lp->ll_tv = lval_root->lr_tv;
v = NULL;
}
- else
+ else if (lp->ll_tv == NULL)
{
cc = *p;
*p = NUL;
@@ -6310,9 +6402,15 @@ echo_string_core(
case VAR_CLASS:
{
class_T *cl = tv->vval.v_class;
- size_t len = 6 + (cl == NULL ? 9 : STRLEN(cl->class_name)) + 1;
+ char *s = "class";
+ if (IS_INTERFACE(cl))
+ s = "interface";
+ else if (IS_ENUM(cl))
+ s = "enum";
+ size_t len = STRLEN(s) + 1 +
+ (cl == NULL ? 9 : STRLEN(cl->class_name)) + 1;
r = *tofree = alloc(len);
- vim_snprintf((char *)r, len, "class %s",
+ vim_snprintf((char *)r, len, "%s %s", s,
cl == NULL ? "[unknown]" : (char *)cl->class_name);
}
break;
@@ -6806,7 +6904,7 @@ find_name_end(
int br_nest = 0;
char_u *p;
int len;
- int allow_curly = (flags & FNE_ALLOW_CURLY) || !in_vim9script();
+ int allow_curly = !in_vim9script();
if (expr_start != NULL)
{