// Resets [fiber] back to an initial state where it is ready to invoke [fn]. private void ResetFiber(Obj fn) { Stack = new Obj[InitialStackSize]; Capacity = InitialStackSize; Frames = new List<CallFrame>(); // Push the stack frame for the function. StackTop = 0; NumFrames = 1; OpenUpvalues = null; Caller = null; Error = null; CallerIsTrying = false; CallFrame frame = new CallFrame { Fn = fn, StackStart = 0, Ip = 0 }; Frames.Add(frame); }
// Captures the local variable [local] into an [Upvalue]. If that local is // already in an upvalue, the existing one will be used. (This is important to // ensure that multiple closures closing over the same variable actually see // the same variable.) Otherwise, it will create a new open upvalue and add it // the fiber's list of upvalues. public ObjUpvalue CaptureUpvalue(int index) { // If there are no open upvalues at all, we must need a new one. if (OpenUpvalues == null) { OpenUpvalues = new ObjUpvalue(Stack[index], index); return OpenUpvalues; } ObjUpvalue prevUpvalue = null; ObjUpvalue upvalue = OpenUpvalues; // Walk towards the bottom of the stack until we find a previously existing // upvalue or pass where it should be. while (upvalue != null && upvalue.Index > index) { prevUpvalue = upvalue; upvalue = upvalue.Next; } // Found an existing upvalue for this local. if (upvalue != null && upvalue.Index == index) return upvalue; // We've walked past this local on the stack, so there must not be an // upvalue for it already. Make a new one and link it in in the right // place to keep the list sorted. ObjUpvalue createdUpvalue = new ObjUpvalue(Stack[index], index); if (prevUpvalue == null) { // The new one is the first one in the list. OpenUpvalues = createdUpvalue; } else { prevUpvalue.Next = createdUpvalue; } createdUpvalue.Next = upvalue; return createdUpvalue; }
public void CloseUpvalue() { if (OpenUpvalues == null) return; // Push the value back into the stack Stack[OpenUpvalues.Index] = OpenUpvalues.Container; // Remove it from the open upvalue list. OpenUpvalues = OpenUpvalues.Next; }