@@ -108,7 +108,7 @@ typedef struct {
108108 char_u * lv_name ;
109109 type_T * lv_type ;
110110 int lv_idx ; // index of the variable on the stack
111- int lv_from_outer ; // when TRUE using ctx_outer scope
111+ int lv_from_outer ; // nesting level, using ctx_outer scope
112112 int lv_const ; // when TRUE cannot be assigned to
113113 int lv_arg ; // when TRUE this is an argument
114114} lvar_T ;
@@ -149,7 +149,7 @@ static void delete_def_function_contents(dfunc_T *dfunc, int mark_deleted);
149149
150150/*
151151 * Lookup variable "name" in the local scope and return it in "lvar".
152- * "lvar->lv_from_outer" is set accordingly.
152+ * "lvar->lv_from_outer" is incremented accordingly.
153153 * If "lvar" is NULL only check if the variable can be found.
154154 * Return FAIL if not found.
155155 */
@@ -172,7 +172,7 @@ lookup_local(char_u *name, size_t len, lvar_T *lvar, cctx_T *cctx)
172172 if (lvar != NULL )
173173 {
174174 * lvar = * lvp ;
175- lvar -> lv_from_outer = FALSE ;
175+ lvar -> lv_from_outer = 0 ;
176176 }
177177 return OK ;
178178 }
@@ -186,7 +186,7 @@ lookup_local(char_u *name, size_t len, lvar_T *lvar, cctx_T *cctx)
186186 if (lvar != NULL )
187187 {
188188 cctx -> ctx_outer_used = TRUE;
189- lvar -> lv_from_outer = TRUE ;
189+ ++ lvar -> lv_from_outer ;
190190 }
191191 return OK ;
192192 }
@@ -258,7 +258,7 @@ arg_exists(
258258 if (arg_exists (name , len , idxp , type , gen_load_outer , cctx -> ctx_outer )
259259 == OK )
260260 {
261- * gen_load_outer = TRUE ;
261+ ++ * gen_load_outer ;
262262 return OK ;
263263 }
264264 }
@@ -1175,6 +1175,23 @@ generate_STORE(cctx_T *cctx, isntype_T isn_type, int idx, char_u *name)
11751175 return OK ;
11761176}
11771177
1178+ /*
1179+ * Generate an ISN_STOREOUTER instruction.
1180+ */
1181+ static int
1182+ generate_STOREOUTER (cctx_T * cctx , int idx , int level )
1183+ {
1184+ isn_T * isn ;
1185+
1186+ RETURN_OK_IF_SKIP (cctx );
1187+ if ((isn = generate_instr_drop (cctx , ISN_STOREOUTER , 1 )) == NULL )
1188+ return FAIL ;
1189+ isn -> isn_arg .outer .outer_idx = idx ;
1190+ isn -> isn_arg .outer .outer_depth = level ;
1191+
1192+ return OK ;
1193+ }
1194+
11781195/*
11791196 * Generate an ISN_STORENR instruction (short for ISN_PUSHNR + ISN_STORE)
11801197 */
@@ -1233,6 +1250,27 @@ generate_LOAD(
12331250 return OK ;
12341251}
12351252
1253+ /*
1254+ * Generate an ISN_LOADOUTER instruction
1255+ */
1256+ static int
1257+ generate_LOADOUTER (
1258+ cctx_T * cctx ,
1259+ int idx ,
1260+ int nesting ,
1261+ type_T * type )
1262+ {
1263+ isn_T * isn ;
1264+
1265+ RETURN_OK_IF_SKIP (cctx );
1266+ if ((isn = generate_instr_type (cctx , ISN_LOADOUTER , type )) == NULL )
1267+ return FAIL ;
1268+ isn -> isn_arg .outer .outer_idx = idx ;
1269+ isn -> isn_arg .outer .outer_depth = nesting ;
1270+
1271+ return OK ;
1272+ }
1273+
12361274/*
12371275 * Generate an ISN_LOADV instruction for v:var.
12381276 */
@@ -1439,6 +1477,11 @@ generate_FUNCREF(cctx_T *cctx, ufunc_T *ufunc)
14391477 isn -> isn_arg .funcref .fr_func = ufunc -> uf_dfunc_idx ;
14401478 cctx -> ctx_has_closure = 1 ;
14411479
1480+ // if the referenced function is a closure, it may use items further up in
1481+ // the nested context, including this one.
1482+ if (ufunc -> uf_flags & FC_CLOSURE )
1483+ cctx -> ctx_ufunc -> uf_flags |= FC_CLOSURE ;
1484+
14421485 if (ga_grow (stack , 1 ) == FAIL )
14431486 return FAIL ;
14441487 ((type_T * * )stack -> ga_data )[stack -> ga_len ] =
@@ -2589,15 +2632,15 @@ compile_load(
25892632 size_t len = end - * arg ;
25902633 int idx ;
25912634 int gen_load = FALSE;
2592- int gen_load_outer = FALSE ;
2635+ int gen_load_outer = 0 ;
25932636
25942637 name = vim_strnsave (* arg , end - * arg );
25952638 if (name == NULL )
25962639 return FAIL ;
25972640
25982641 if (arg_exists (* arg , len , & idx , & type , & gen_load_outer , cctx ) == OK )
25992642 {
2600- if (! gen_load_outer )
2643+ if (gen_load_outer == 0 )
26012644 gen_load = TRUE;
26022645 }
26032646 else
@@ -2608,8 +2651,8 @@ compile_load(
26082651 {
26092652 type = lvar .lv_type ;
26102653 idx = lvar .lv_idx ;
2611- if (lvar .lv_from_outer )
2612- gen_load_outer = TRUE ;
2654+ if (lvar .lv_from_outer != 0 )
2655+ gen_load_outer = lvar . lv_from_outer ;
26132656 else
26142657 gen_load = TRUE;
26152658 }
@@ -2631,9 +2674,9 @@ compile_load(
26312674 }
26322675 if (gen_load )
26332676 res = generate_LOAD (cctx , ISN_LOAD , idx , NULL , type );
2634- if (gen_load_outer )
2677+ if (gen_load_outer > 0 )
26352678 {
2636- res = generate_LOAD (cctx , ISN_LOADOUTER , idx , NULL , type );
2679+ res = generate_LOADOUTER (cctx , idx , gen_load_outer , type );
26372680 cctx -> ctx_outer_used = TRUE;
26382681 }
26392682 }
@@ -5120,9 +5163,9 @@ generate_loadvar(
51205163 generate_LOADV (cctx , name + 2 , TRUE);
51215164 break ;
51225165 case dest_local :
5123- if (lvar -> lv_from_outer )
5124- generate_LOAD (cctx , ISN_LOADOUTER , lvar -> lv_idx ,
5125- NULL , type );
5166+ if (lvar -> lv_from_outer > 0 )
5167+ generate_LOADOUTER (cctx , lvar -> lv_idx , lvar -> lv_from_outer ,
5168+ type );
51265169 else
51275170 generate_LOAD (cctx , ISN_LOAD , lvar -> lv_idx , NULL , type );
51285171 break ;
@@ -6178,7 +6221,7 @@ compile_assignment(char_u *arg, exarg_T *eap, cmdidx_T cmdidx, cctx_T *cctx)
61786221
61796222 // optimization: turn "var = 123" from ISN_PUSHNR +
61806223 // ISN_STORE into ISN_STORENR
6181- if (! lhs .lhs_lvar -> lv_from_outer
6224+ if (lhs .lhs_lvar -> lv_from_outer == 0
61826225 && instr -> ga_len == instr_count + 1
61836226 && isn -> isn_type == ISN_PUSHNR )
61846227 {
@@ -6190,9 +6233,9 @@ compile_assignment(char_u *arg, exarg_T *eap, cmdidx_T cmdidx, cctx_T *cctx)
61906233 if (stack -> ga_len > 0 )
61916234 -- stack -> ga_len ;
61926235 }
6193- else if (lhs .lhs_lvar -> lv_from_outer )
6194- generate_STORE (cctx , ISN_STOREOUTER ,
6195- lhs .lhs_lvar -> lv_idx , NULL );
6236+ else if (lhs .lhs_lvar -> lv_from_outer > 0 )
6237+ generate_STOREOUTER (cctx , lhs . lhs_lvar -> lv_idx ,
6238+ lhs .lhs_lvar -> lv_from_outer );
61966239 else
61976240 generate_STORE (cctx , ISN_STORE , lhs .lhs_lvar -> lv_idx , NULL );
61986241 }
0 commit comments