comparison src/vim9execute.c @ 30065:6cf788ab844c v9.0.0370

patch 9.0.0370: cleaning up afterwards can make a function messy Commit: https://github.com/vim/vim/commit/1d84f7608f1e41dad03b8cc7925895437775f7c0 Author: Bram Moolenaar <Bram@vim.org> Date: Sat Sep 3 21:35:53 2022 +0100 patch 9.0.0370: cleaning up afterwards can make a function messy Problem: Cleaning up afterwards can make a function messy. Solution: Add the :defer command.
author Bram Moolenaar <Bram@vim.org>
date Sat, 03 Sep 2022 22:45:03 +0200
parents d269dd3cd31d
children 6a8c2ff5b2ef
comparison
equal deleted inserted replaced
30064:a8f1fbaa43c8 30065:6cf788ab844c
99 #ifdef FEAT_PROFILE 99 #ifdef FEAT_PROFILE
100 // stack of profinfo_T used when profiling. 100 // stack of profinfo_T used when profiling.
101 static garray_T profile_info_ga = {0, 0, sizeof(profinfo_T), 20, NULL}; 101 static garray_T profile_info_ga = {0, 0, sizeof(profinfo_T), 20, NULL};
102 #endif 102 #endif
103 103
104 // Get pointer to item in the stack.
105 #define STACK_TV(idx) (((typval_T *)ectx->ec_stack.ga_data) + idx)
106
104 // Get pointer to item relative to the bottom of the stack, -1 is the last one. 107 // Get pointer to item relative to the bottom of the stack, -1 is the last one.
105 #define STACK_TV_BOT(idx) (((typval_T *)ectx->ec_stack.ga_data) + ectx->ec_stack.ga_len + (idx)) 108 #define STACK_TV_BOT(idx) (((typval_T *)ectx->ec_stack.ga_data) + ectx->ec_stack.ga_len + (idx))
109
110 // Get pointer to a local variable on the stack. Negative for arguments.
111 #define STACK_TV_VAR(idx) (((typval_T *)ectx->ec_stack.ga_data) + ectx->ec_frame_idx + STACK_FRAME_SIZE + idx)
106 112
107 void 113 void
108 to_string_error(vartype_T vartype) 114 to_string_error(vartype_T vartype)
109 { 115 {
110 semsg(_(e_cannot_convert_str_to_string), vartype_name(vartype)); 116 semsg(_(e_cannot_convert_str_to_string), vartype_name(vartype));
608 ectx->ec_iidx = 0; 614 ectx->ec_iidx = 0;
609 615
610 return OK; 616 return OK;
611 } 617 }
612 618
613 // Get pointer to item in the stack.
614 #define STACK_TV(idx) (((typval_T *)ectx->ec_stack.ga_data) + idx)
615
616 // Double linked list of funcstack_T in use. 619 // Double linked list of funcstack_T in use.
617 static funcstack_T *first_funcstack = NULL; 620 static funcstack_T *first_funcstack = NULL;
618 621
619 static void 622 static void
620 add_funcstack_to_list(funcstack_T *funcstack) 623 add_funcstack_to_list(funcstack_T *funcstack)
841 } 844 }
842 return FALSE; 845 return FALSE;
843 } 846 }
844 847
845 /* 848 /*
849 * Handle ISN_DEFER. Stack has a function reference and "argcount" arguments.
850 * The local variable that lists deferred functions is "var_idx".
851 * Returns OK or FAIL.
852 */
853 static int
854 add_defer_func(int var_idx, int argcount, ectx_T *ectx)
855 {
856 typval_T *defer_tv = STACK_TV_VAR(var_idx);
857 list_T *defer_l;
858 typval_T *func_tv;
859 list_T *l;
860 int i;
861 typval_T listval;
862
863 if (defer_tv->v_type != VAR_LIST)
864 {
865 // first one, allocate the list
866 if (rettv_list_alloc(defer_tv) == FAIL)
867 return FAIL;
868 }
869 defer_l = defer_tv->vval.v_list;
870
871 l = list_alloc_with_items(argcount + 1);
872 if (l == NULL)
873 return FAIL;
874 listval.v_type = VAR_LIST;
875 listval.vval.v_list = l;
876 listval.v_lock = 0;
877 if (list_insert_tv(defer_l, &listval,
878 defer_l == NULL ? NULL : defer_l->lv_first) == FAIL)
879 {
880 vim_free(l);
881 return FAIL;
882 }
883
884 func_tv = STACK_TV_BOT(-argcount - 1);
885 // TODO: check type is a funcref
886 list_set_item(l, 0, func_tv);
887
888 for (i = 1; i <= argcount; ++i)
889 list_set_item(l, i, STACK_TV_BOT(-argcount + i - 1));
890 ectx->ec_stack.ga_len -= argcount + 1;
891 return OK;
892 }
893
894 /*
895 * Invoked when returning from a function: Invoke any deferred calls.
896 */
897 static void
898 invoke_defer_funcs(ectx_T *ectx)
899 {
900 dfunc_T *dfunc = ((dfunc_T *)def_functions.ga_data)
901 + ectx->ec_dfunc_idx;
902 typval_T *defer_tv = STACK_TV_VAR(dfunc->df_defer_var_idx - 1);
903 listitem_T *li;
904
905 if (defer_tv->v_type != VAR_LIST)
906 return; // no function added
907 for (li = defer_tv->vval.v_list->lv_first; li != NULL; li = li->li_next)
908 {
909 list_T *l = li->li_tv.vval.v_list;
910 typval_T rettv;
911 typval_T argvars[MAX_FUNC_ARGS];
912 int i;
913 listitem_T *arg_li = l->lv_first;
914 funcexe_T funcexe;
915
916 for (i = 0; i < l->lv_len - 1; ++i)
917 {
918 arg_li = arg_li->li_next;
919 argvars[i] = arg_li->li_tv;
920 }
921
922 CLEAR_FIELD(funcexe);
923 funcexe.fe_evaluate = TRUE;
924 rettv.v_type = VAR_UNKNOWN;
925 (void)call_func(l->lv_first->li_tv.vval.v_string, -1,
926 &rettv, l->lv_len - 1, argvars, &funcexe);
927 clear_tv(&rettv);
928 }
929 }
930
931 /*
846 * Return from the current function. 932 * Return from the current function.
847 */ 933 */
848 static int 934 static int
849 func_return(ectx_T *ectx) 935 func_return(ectx_T *ectx)
850 { 936 {
874 --profile_info_ga.ga_len; 960 --profile_info_ga.ga_len;
875 } 961 }
876 } 962 }
877 #endif 963 #endif
878 964
965 if (dfunc->df_defer_var_idx > 0)
966 invoke_defer_funcs(ectx);
967
879 // No check for uf_refcount being zero, cannot think of a way that would 968 // No check for uf_refcount being zero, cannot think of a way that would
880 // happen. 969 // happen.
881 --dfunc->df_ufunc->uf_calls; 970 --dfunc->df_ufunc->uf_calls;
882 971
883 // execution context goes one level up 972 // execution context goes one level up
946 1035
947 funcdepth_decrement(); 1036 funcdepth_decrement();
948 --ex_nesting_level; 1037 --ex_nesting_level;
949 return OK; 1038 return OK;
950 } 1039 }
951
952 #undef STACK_TV
953 1040
954 /* 1041 /*
955 * Prepare arguments and rettv for calling a builtin or user function. 1042 * Prepare arguments and rettv for calling a builtin or user function.
956 */ 1043 */
957 static int 1044 static int
1729 typedef struct subs_expr_S { 1816 typedef struct subs_expr_S {
1730 ectx_T *subs_ectx; 1817 ectx_T *subs_ectx;
1731 isn_T *subs_instr; 1818 isn_T *subs_instr;
1732 int subs_status; 1819 int subs_status;
1733 } subs_expr_T; 1820 } subs_expr_T;
1734
1735 // Get pointer to item in the stack.
1736 #define STACK_TV(idx) (((typval_T *)ectx->ec_stack.ga_data) + idx)
1737
1738 // Get pointer to item at the bottom of the stack, -1 is the bottom.
1739 #undef STACK_TV_BOT
1740 #define STACK_TV_BOT(idx) (((typval_T *)ectx->ec_stack.ga_data) + ectx->ec_stack.ga_len + idx)
1741
1742 // Get pointer to a local variable on the stack. Negative for arguments.
1743 #define STACK_TV_VAR(idx) (((typval_T *)ectx->ec_stack.ga_data) + ectx->ec_frame_idx + STACK_FRAME_SIZE + idx)
1744 1821
1745 // Set when calling do_debug(). 1822 // Set when calling do_debug().
1746 static ectx_T *debug_context = NULL; 1823 static ectx_T *debug_context = NULL;
1747 static int debug_var_count; 1824 static int debug_var_count;
1748 1825
3668 ectx, iptr) == FAIL) 3745 ectx, iptr) == FAIL)
3669 goto on_error; 3746 goto on_error;
3670 } 3747 }
3671 break; 3748 break;
3672 3749
3750 // :defer func(arg)
3751 case ISN_DEFER:
3752 if (add_defer_func(iptr->isn_arg.defer.defer_var_idx,
3753 iptr->isn_arg.defer.defer_argcount, ectx) == FAIL)
3754 goto on_error;
3755 break;
3756
3673 // return from a :def function call without a value 3757 // return from a :def function call without a value
3674 case ISN_RETURN_VOID: 3758 case ISN_RETURN_VOID:
3675 if (GA_GROW_FAILS(&ectx->ec_stack, 1)) 3759 if (GA_GROW_FAILS(&ectx->ec_stack, 1))
3676 goto theend; 3760 goto theend;
3677 tv = STACK_TV_BOT(0); 3761 tv = STACK_TV_BOT(0);
5022 } 5106 }
5023 5107
5024 done: 5108 done:
5025 ret = OK; 5109 ret = OK;
5026 theend: 5110 theend:
5111 {
5112 dfunc_T *dfunc = ((dfunc_T *)def_functions.ga_data)
5113 + ectx->ec_dfunc_idx;
5114
5115 if (dfunc->df_defer_var_idx > 0)
5116 invoke_defer_funcs(ectx);
5117 }
5118
5027 dict_stack_clear(dict_stack_len_at_start); 5119 dict_stack_clear(dict_stack_len_at_start);
5028 ectx->ec_trylevel_at_start = save_trylevel_at_start; 5120 ectx->ec_trylevel_at_start = save_trylevel_at_start;
5029 return ret; 5121 return ret;
5030 } 5122 }
5031 5123
5900 cpfunc->cpf_top ? " top" : "", cpfunc->cpf_argcount); 5992 cpfunc->cpf_top ? " top" : "", cpfunc->cpf_argcount);
5901 } 5993 }
5902 break; 5994 break;
5903 case ISN_PCALL_END: 5995 case ISN_PCALL_END:
5904 smsg("%s%4d PCALL end", pfx, current); 5996 smsg("%s%4d PCALL end", pfx, current);
5997 break;
5998 case ISN_DEFER:
5999 smsg("%s%4d DEFER %d args", pfx, current,
6000 (int)iptr->isn_arg.defer.defer_argcount);
5905 break; 6001 break;
5906 case ISN_RETURN: 6002 case ISN_RETURN:
5907 smsg("%s%4d RETURN", pfx, current); 6003 smsg("%s%4d RETURN", pfx, current);
5908 break; 6004 break;
5909 case ISN_RETURN_VOID: 6005 case ISN_RETURN_VOID: