@@ -20,6 +20,7 @@ static void reset_stack()
2020{
2121 vm .stack_top = vm .stack ;
2222 vm .frame_count = 0 ;
23+ vm .open_upvalues = NULL ;
2324}
2425
2526static void runtime_error (const char * format , ...)
@@ -136,9 +137,39 @@ static bool call_value(Value callee, int arg_count)
136137 return false;
137138}
138139
140+ static void close_upvalues (Value * last )
141+ {
142+ while (vm .open_upvalues != NULL && vm .open_upvalues -> location >= last )
143+ {
144+ ObjUpvalue * upvalue = vm .open_upvalues ;
145+ upvalue -> closed = * upvalue -> location ;
146+ upvalue -> location = & upvalue -> closed ;
147+ vm .open_upvalues -> next = upvalue -> next ;
148+ }
149+ }
150+
139151static ObjUpvalue * capture_upvalue (Value * local )
140152{
153+ ObjUpvalue * prev_upvalue = NULL ;
154+ ObjUpvalue * upvalue = vm .open_upvalues ;
155+
156+ while (upvalue != NULL && upvalue -> location > local )
157+ {
158+ prev_upvalue = upvalue ;
159+ upvalue = upvalue -> next ;
160+ }
161+
162+ if (upvalue != NULL && upvalue -> location == local )
163+ return upvalue ;
164+
141165 ObjUpvalue * created_upvalue = new_upvalue (local );
166+ created_upvalue -> next = upvalue ;
167+
168+ if (prev_upvalue == NULL )
169+ vm .open_upvalues = created_upvalue ;
170+ else
171+ prev_upvalue -> next = created_upvalue ;
172+
142173 return created_upvalue ;
143174}
144175
@@ -377,9 +408,16 @@ static InterpretResult run()
377408 }
378409 break ;
379410 }
411+ case OP_CLOSE_UPVALUE :
412+ {
413+ close_upvalues (vm .stack_top - 1 );
414+ pop ();
415+ break ;
416+ }
380417 case OP_RETURN :
381418 {
382419 Value result = pop ();
420+ close_upvalues (frame -> slots );
383421
384422 if (-- vm .frame_count == 0 )
385423 {
0 commit comments