diff options
Diffstat (limited to 'src/nvim/eval/user_funcs.c')
-rw-r--r-- | src/nvim/eval/user_funcs.c | 91 |
1 files changed, 91 insertions, 0 deletions
diff --git a/src/nvim/eval/user_funcs.c b/src/nvim/eval/user_funcs.c index 7de9922f96..487d290f6b 100644 --- a/src/nvim/eval/user_funcs.c +++ b/src/nvim/eval/user_funcs.c @@ -3018,6 +3018,30 @@ int current_func_returned(void) return current_funccal->returned; } +bool free_unref_funccal(int copyID, int testing) +{ + bool did_free = false; + bool did_free_funccal = false; + + for (funccall_T **pfc = &previous_funccal; *pfc != NULL;) { + if (can_free_funccal(*pfc, copyID)) { + funccall_T *fc = *pfc; + *pfc = fc->caller; + free_funccal(fc, true); + did_free = true; + did_free_funccal = true; + } else { + pfc = &(*pfc)->caller; + } + } + if (did_free_funccal) { + // When a funccal was freed some more items might be garbage + // collected, so run again. + (void)garbage_collect(testing); + } + return did_free; +} + // Get function call environment based on backtrace debug level funccall_T *get_funccal(void) { @@ -3047,6 +3071,16 @@ hashtab_T *get_funccal_local_ht(void) return &get_funccal()->l_vars.dv_hashtab; } +/// Return the l: scope variable. +/// Return NULL if there is no current funccal. +dictitem_T *get_funccal_local_var(void) +{ + if (current_funccal == NULL) { + return NULL; + } + return (dictitem_T *)&get_funccal()->l_vars_var; +} + /// Return the hashtable used for argument in the current funccal. /// Return NULL if there is no current funccal. hashtab_T *get_funccal_args_ht(void) @@ -3057,6 +3091,16 @@ hashtab_T *get_funccal_args_ht(void) return &get_funccal()->l_avars.dv_hashtab; } +/// Return the a: scope variable. +/// Return NULL if there is no current funccal. +dictitem_T *get_funccal_args_var(void) +{ + if (current_funccal == NULL) { + return NULL; + } + return (dictitem_T *)¤t_funccal->l_avars_var; +} + /* * List function variables, if there is a function. */ @@ -3068,6 +3112,17 @@ void list_func_vars(int *first) } } +/// If "ht" is the hashtable for local variables in the current funccal, return +/// the dict that contains it. +/// Otherwise return NULL. +dict_T *get_current_funccal_dict(hashtab_T *ht) +{ + if (current_funccal != NULL && ht == ¤t_funccal->l_vars.dv_hashtab) { + return ¤t_funccal->l_vars; + } + return NULL; +} + /// Search hashitem in parent scope. hashitem_T *find_hi_in_scoped_ht(const char *name, hashtab_T **pht) { @@ -3134,6 +3189,18 @@ dictitem_T *find_var_in_scoped_ht(const char *name, const size_t namelen, return v; } +/// Set "copyID + 1" in previous_funccal and callers. +bool set_ref_in_previous_funccal(int copyID) +{ + bool abort = false; + + for (funccall_T *fc = previous_funccal; fc != NULL; fc = fc->caller) { + abort = abort || set_ref_in_ht(&fc->l_vars.dv_hashtab, copyID + 1, NULL); + abort = abort || set_ref_in_ht(&fc->l_avars.dv_hashtab, copyID + 1, NULL); + } + return abort; +} + static bool set_ref_in_funccal(funccall_T *fc, int copyID) { bool abort = false; @@ -3147,6 +3214,18 @@ static bool set_ref_in_funccal(funccall_T *fc, int copyID) return abort; } +/// Set "copyID" in all local vars and arguments in the call stack. +bool set_ref_in_call_stack(int copyID) +{ + bool abort = false; + + for (funccall_T *fc = current_funccal; fc != NULL; fc = fc->caller) { + abort = abort || set_ref_in_ht(&fc->l_vars.dv_hashtab, copyID, NULL); + abort = abort || set_ref_in_ht(&fc->l_avars.dv_hashtab, copyID, NULL); + } + return abort; +} + /// Set "copyID" in all functions available by name. bool set_ref_in_functions(int copyID) { @@ -3168,6 +3247,18 @@ bool set_ref_in_functions(int copyID) return abort; } +/// Set "copyID" in all function arguments. +bool set_ref_in_func_args(int copyID) +{ + bool abort = false; + + for (int i = 0; i < funcargs.ga_len; i++) { + abort = abort || set_ref_in_item(((typval_T **)funcargs.ga_data)[i], + copyID, NULL, NULL); + } + return abort; +} + /// Mark all lists and dicts referenced through function "name" with "copyID". /// "list_stack" is used to add lists to be marked. Can be NULL. /// "ht_stack" is used to add hashtabs to be marked. Can be NULL. |