|
|
@@ -21,6 +21,7 @@ VM vm;
|
|
|
static void resetStack() {
|
|
|
vm.stackTop = vm.stack;// 指针指向栈底
|
|
|
vm.frameCount = 0;
|
|
|
+ vm.openUpvalues = NULL;
|
|
|
}
|
|
|
|
|
|
static void runtimeError(const char *format, ...) {
|
|
|
@@ -125,9 +126,34 @@ static void concatenate() {
|
|
|
push(OBJ_VAL(result));
|
|
|
}
|
|
|
static ObjUpvalue *captureUpvalue(Value *local) {
|
|
|
+ ObjUpvalue *preUpvalue = NULL;
|
|
|
+ ObjUpvalue *upvalue = vm.openUpvalues;
|
|
|
+ while (upvalue != NULL && upvalue->location > local) {
|
|
|
+ preUpvalue = upvalue;
|
|
|
+ upvalue = upvalue->next;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (upvalue != NULL && upvalue->location == local) {
|
|
|
+ return upvalue;
|
|
|
+ }
|
|
|
+
|
|
|
ObjUpvalue *createdUpvalue = newUpvalue(local);
|
|
|
+ if (preUpvalue == NULL) {
|
|
|
+ vm.openUpvalues = createdUpvalue;
|
|
|
+ } else {
|
|
|
+ preUpvalue->next = createdUpvalue;
|
|
|
+ }
|
|
|
return createdUpvalue;
|
|
|
}
|
|
|
+static void closeUpvalues(Value* last) {
|
|
|
+ while (vm.openUpvalues != NULL && vm.openUpvalues->location >= last) {
|
|
|
+ ObjUpvalue * upvalue = vm.openUpvalues;
|
|
|
+ upvalue->closed = *upvalue->location;
|
|
|
+ upvalue->location = &upvalue->closed;
|
|
|
+ vm.openUpvalues = upvalue->next;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
/// VM run function - exec opcode
|
|
|
/// \return
|
|
|
static InterpretResult run() {
|
|
|
@@ -326,8 +352,13 @@ static InterpretResult run() {
|
|
|
*frame->closure->upvalues[slot]->location = peek(0);
|
|
|
break;
|
|
|
}
|
|
|
+ case OP_CLOSE_UPVALUE:
|
|
|
+ closeUpvalues(vm.stackTop - 1);
|
|
|
+ pop();
|
|
|
+ break;
|
|
|
case OP_RETURN: {
|
|
|
Value result = pop();
|
|
|
+ closeUpvalues(frame->slots);
|
|
|
vm.frameCount--;
|
|
|
if (vm.frameCount == 0) {
|
|
|
pop();
|