summaryrefslogtreecommitdiff
path: root/src/vim9compile.c
diff options
context:
space:
mode:
authorBram Moolenaar <Bram@vim.org>2022-12-18 21:42:55 +0000
committerBram Moolenaar <Bram@vim.org>2022-12-18 21:42:55 +0000
commitd505d178858434e1afef0363a9fce4bcb1bc3d06 (patch)
tree358c5f600112605517bb4b92ab155ce2e55e7123 /src/vim9compile.c
parent731d00770d9006e7dab6a66e2ea86603ed5ef212 (diff)
downloadvim-git-d505d178858434e1afef0363a9fce4bcb1bc3d06.tar.gz
patch 9.0.1074: class members are not supported yetv9.0.1074
Problem: Class members are not supported yet. Solution: Add initial support for class members.
Diffstat (limited to 'src/vim9compile.c')
-rw-r--r--src/vim9compile.c77
1 files changed, 60 insertions, 17 deletions
diff --git a/src/vim9compile.c b/src/vim9compile.c
index ac321a90e..44403ece2 100644
--- a/src/vim9compile.c
+++ b/src/vim9compile.c
@@ -302,6 +302,28 @@ script_var_exists(char_u *name, size_t len, cctx_T *cctx, cstack_T *cstack)
}
/*
+ * If "name" is a class member in cctx->ctx_ufunc->uf_class return the index in
+ * class.class_class_members[].
+ * Otherwise return -1;
+ */
+ static int
+class_member_index(char_u *name, size_t len, cctx_T *cctx)
+{
+ if (cctx == NULL || cctx->ctx_ufunc == NULL
+ || cctx->ctx_ufunc->uf_class == NULL)
+ return -1;
+ class_T *cl = cctx->ctx_ufunc->uf_class;
+ for (int i = 0; i < cl->class_class_member_count; ++i)
+ {
+ ocmember_T *m = &cl->class_class_members[i];
+ if (STRNCMP(name, m->ocm_name, len) == 0
+ && m->ocm_name[len] == NUL)
+ return i;
+ }
+ return -1;
+}
+
+/*
* Return TRUE if "name" is a local variable, argument, script variable or
* imported.
*/
@@ -316,6 +338,7 @@ variable_exists(char_u *name, size_t len, cctx_T *cctx)
&& (cctx->ctx_ufunc->uf_flags & FC_OBJECT)
&& STRNCMP(name, "this", 4) == 0)))
|| script_var_exists(name, len, cctx, NULL) == OK
+ || class_member_index(name, len, cctx) >= 0
|| find_imported(name, len, FALSE) != NULL;
}
@@ -353,6 +376,9 @@ check_defined(
if (len == 1 && *p == '_')
return OK;
+ if (class_member_index(p, len, cctx) >= 0)
+ return OK;
+
if (script_var_exists(p, len, cctx, cstack) == OK)
{
if (is_arg)
@@ -1195,14 +1221,12 @@ assignment_len(char_u *p, int *heredoc)
* Generate the load instruction for "name".
*/
static void
-generate_loadvar(
- cctx_T *cctx,
- assign_dest_T dest,
- char_u *name,
- lvar_T *lvar,
- type_T *type)
+generate_loadvar(cctx_T *cctx, lhs_T *lhs)
{
- switch (dest)
+ char_u *name = lhs->lhs_name;
+ type_T *type = lhs->lhs_type;
+
+ switch (lhs->lhs_dest)
{
case dest_option:
case dest_func_option:
@@ -1245,6 +1269,7 @@ generate_loadvar(
case dest_local:
if (cctx->ctx_skip != SKIP_YES)
{
+ lvar_T *lvar = lhs->lhs_lvar;
if (lvar->lv_from_outer > 0)
generate_LOADOUTER(cctx, lvar->lv_idx, lvar->lv_from_outer,
lvar->lv_loop_depth, lvar->lv_loop_idx, type);
@@ -1252,6 +1277,10 @@ generate_loadvar(
generate_LOAD(cctx, ISN_LOAD, lvar->lv_idx, NULL, type);
}
break;
+ case dest_class_member:
+ generate_CLASSMEMBER(cctx, TRUE, lhs->lhs_class,
+ lhs->lhs_classmember_idx);
+ break;
case dest_expr:
// list or dict value should already be on the stack.
break;
@@ -1533,7 +1562,9 @@ compile_lhs(
if (lookup_local(var_start, lhs->lhs_varlen,
&lhs->lhs_local_lvar, cctx) == OK)
+ {
lhs->lhs_lvar = &lhs->lhs_local_lvar;
+ }
else
{
CLEAR_FIELD(lhs->lhs_arg_lvar);
@@ -1549,6 +1580,7 @@ compile_lhs(
lhs->lhs_lvar = &lhs->lhs_arg_lvar;
}
}
+
if (lhs->lhs_lvar != NULL)
{
if (is_decl)
@@ -1557,6 +1589,12 @@ compile_lhs(
return FAIL;
}
}
+ else if ((lhs->lhs_classmember_idx = class_member_index(
+ var_start, lhs->lhs_varlen, cctx)) >= 0)
+ {
+ lhs->lhs_dest = dest_class_member;
+ lhs->lhs_class = cctx->ctx_ufunc->uf_class;
+ }
else
{
int script_namespace = lhs->lhs_varlen > 1
@@ -1965,8 +2003,7 @@ compile_load_lhs(
return FAIL;
}
else
- generate_loadvar(cctx, lhs->lhs_dest, lhs->lhs_name,
- lhs->lhs_lvar, lhs->lhs_type);
+ generate_loadvar(cctx, lhs);
return OK;
}
@@ -2998,20 +3035,20 @@ compile_def_function(
for (int i = 0; i < ufunc->uf_class->class_obj_member_count; ++i)
{
- objmember_T *m = &ufunc->uf_class->class_obj_members[i];
- if (m->om_init != NULL)
+ ocmember_T *m = &ufunc->uf_class->class_obj_members[i];
+ if (m->ocm_init != NULL)
{
- char_u *expr = m->om_init;
+ char_u *expr = m->ocm_init;
if (compile_expr0(&expr, &cctx) == FAIL)
goto erret;
- if (!ends_excmd2(m->om_init, expr))
+ if (!ends_excmd2(m->ocm_init, expr))
{
semsg(_(e_trailing_characters_str), expr);
goto erret;
}
}
else
- push_default_value(&cctx, m->om_type->tt_type,
+ push_default_value(&cctx, m->ocm_type->tt_type,
FALSE, NULL);
generate_STORE_THIS(&cctx, i);
}
@@ -3792,6 +3829,13 @@ delete_def_function_contents(dfunc_T *dfunc, int mark_deleted)
{
int idx;
+ // In same cases the instructions may refer to a class in which the
+ // function is defined and unreferencing the class may call back here
+ // recursively. Set the df_delete_busy to avoid problems.
+ if (dfunc->df_delete_busy)
+ return;
+ dfunc->df_delete_busy = TRUE;
+
ga_clear(&dfunc->df_def_args_isn);
ga_clear_strings(&dfunc->df_var_names);
@@ -3800,14 +3844,12 @@ delete_def_function_contents(dfunc_T *dfunc, int mark_deleted)
for (idx = 0; idx < dfunc->df_instr_count; ++idx)
delete_instr(dfunc->df_instr + idx);
VIM_CLEAR(dfunc->df_instr);
- dfunc->df_instr = NULL;
}
if (dfunc->df_instr_debug != NULL)
{
for (idx = 0; idx < dfunc->df_instr_debug_count; ++idx)
delete_instr(dfunc->df_instr_debug + idx);
VIM_CLEAR(dfunc->df_instr_debug);
- dfunc->df_instr_debug = NULL;
}
#ifdef FEAT_PROFILE
if (dfunc->df_instr_prof != NULL)
@@ -3815,7 +3857,6 @@ delete_def_function_contents(dfunc_T *dfunc, int mark_deleted)
for (idx = 0; idx < dfunc->df_instr_prof_count; ++idx)
delete_instr(dfunc->df_instr_prof + idx);
VIM_CLEAR(dfunc->df_instr_prof);
- dfunc->df_instr_prof = NULL;
}
#endif
@@ -3823,6 +3864,8 @@ delete_def_function_contents(dfunc_T *dfunc, int mark_deleted)
dfunc->df_deleted = TRUE;
if (dfunc->df_ufunc != NULL)
dfunc->df_ufunc->uf_def_status = UF_NOT_COMPILED;
+
+ dfunc->df_delete_busy = FALSE;
}
/*