|
|
@@ -28,11 +28,19 @@ static void runtimeError(const char *format, ...) {
|
|
|
vfprintf(stderr, format, args);
|
|
|
va_end(args);
|
|
|
fputs("\n", stderr);
|
|
|
+ for (int i = vm.frameCount - 1; i >= 0; i--) {
|
|
|
+ CallFrame *frame = &vm.frames[i];
|
|
|
+ ObjFunction *function = frame->function;
|
|
|
+ size_t instruction = frame->ip - frame->function->chunk.code - 1;
|
|
|
+ int line = function->chunk.lines[instruction];
|
|
|
+ fprintf(stderr, "[line %d] in ", line);
|
|
|
+ if (function->name == NULL) {
|
|
|
+ fprintf(stderr, "script\n");
|
|
|
+ } else {
|
|
|
+ fprintf(stderr, "%s()\n", function->name->chars);
|
|
|
+ }
|
|
|
+ }
|
|
|
|
|
|
- CallFrame *frame = &vm.frames[vm.frameCount - 1];
|
|
|
- size_t instruction = frame->ip - frame->function->chunk.code - 1;
|
|
|
- int line = frame->function->chunk.lines[instruction];
|
|
|
- fprintf(stderr, "[line %d] in script\n", line);
|
|
|
resetStack();
|
|
|
}
|
|
|
|
|
|
@@ -46,6 +54,36 @@ void initVM() {
|
|
|
static Value peek(int distance) {
|
|
|
return vm.stackTop[-1 - distance];
|
|
|
}
|
|
|
+static bool call(ObjFunction *function, int argCount) {
|
|
|
+ if (argCount != function->arity) {
|
|
|
+ runtimeError("Expected %d arguments but got %d", function->arity, argCount);
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (vm.frameCount == FRAMES_MAX) {
|
|
|
+ runtimeError("Stack overflow.");
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ CallFrame *frame = &vm.frames[vm.frameCount++];
|
|
|
+ frame->function = function;
|
|
|
+ frame->ip = function->chunk.code;
|
|
|
+ frame->slots = vm.stackTop - argCount - 1;
|
|
|
+ return true;
|
|
|
+}
|
|
|
+static bool callValue(Value callee, int argCount) {
|
|
|
+ if (IS_OBJ(callee)) {
|
|
|
+ switch (OBJ_TYPE(callee)) {
|
|
|
+ case OBJ_FUNCTION:
|
|
|
+ return call(AS_FUNCTION(callee), argCount);
|
|
|
+ default:
|
|
|
+ break;// Non-callable object type.
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ runtimeError("Can only call functions and classes.");
|
|
|
+ return false;
|
|
|
+}
|
|
|
static bool isFalse(Value value) {
|
|
|
// the nil and false will return true
|
|
|
return IS_NIL(value) || (IS_BOOL(value) && !AS_BOOL(value));
|
|
|
@@ -86,12 +124,10 @@ static InterpretResult run() {
|
|
|
push(valueType(a op b)); \
|
|
|
} while (false)
|
|
|
|
|
|
-#ifdef DEBUG_TRACE_EXECUTION
|
|
|
- printf("!!! <Stack tracing> start\n");
|
|
|
-#endif
|
|
|
for (;;) {
|
|
|
#ifdef DEBUG_TRACE_EXECUTION
|
|
|
//! <Stack tracing> start
|
|
|
+ printf("\n!!! <Stack tracing now>:\n");
|
|
|
printf("------------------------\n|");
|
|
|
for (Value *slot = vm.stack; slot < vm.stackTop; slot++) {
|
|
|
printf("[ ");
|
|
|
@@ -99,11 +135,16 @@ static InterpretResult run() {
|
|
|
printf(" ]");
|
|
|
}
|
|
|
printf("\n------------------------");
|
|
|
+
|
|
|
+ printf("\n");
|
|
|
printf("\n");
|
|
|
//! <Stack tracing> end
|
|
|
+
|
|
|
+ printf("The Instruction: \n");
|
|
|
disassembleInstruction(&frame->function->chunk, (int) (frame->ip - frame->function->chunk.code));
|
|
|
#endif
|
|
|
- switch (READ_BYTE()) {
|
|
|
+ uint8_t opCode = READ_BYTE();
|
|
|
+ switch (opCode) {
|
|
|
case OP_CONSTANT: {
|
|
|
Value constant = READ_CONSTANT();
|
|
|
push(constant);
|
|
|
@@ -221,14 +262,30 @@ static InterpretResult run() {
|
|
|
frame->ip -= offset;
|
|
|
break;
|
|
|
}
|
|
|
+ case OP_CALL: {
|
|
|
+ int argCount = READ_BYTE();
|
|
|
+ if (!callValue(peek(argCount), argCount)) {
|
|
|
+ return INTERPRET_RUNTIME_ERROR;
|
|
|
+ }
|
|
|
+ frame = &vm.frames[vm.frameCount - 1];
|
|
|
+ break;
|
|
|
+ }
|
|
|
case OP_RETURN: {
|
|
|
- // Exit interpreter.
|
|
|
- return INTERPRET_OK;
|
|
|
+ Value result = pop();
|
|
|
+ vm.frameCount--;
|
|
|
+ if (vm.frameCount == 0) {
|
|
|
+ pop();
|
|
|
+ return INTERPRET_OK;
|
|
|
+ }
|
|
|
+
|
|
|
+ vm.stackTop = frame->slots;
|
|
|
+ push(result);
|
|
|
+ frame = &vm.frames[vm.frameCount - 1];
|
|
|
+ break;
|
|
|
}
|
|
|
+ default:
|
|
|
+ break;
|
|
|
}
|
|
|
-#ifdef DEBUG_TRACE_EXECUTION
|
|
|
- printf("!!! <Stack tracing> end\n");
|
|
|
-#endif
|
|
|
}
|
|
|
|
|
|
#undef READ_BYTE
|
|
|
@@ -250,10 +307,11 @@ InterpretResult interpret(const char *source) {
|
|
|
|
|
|
push(OBJ_VAL(function));
|
|
|
|
|
|
- CallFrame *frame = &vm.frames[vm.frameCount++];
|
|
|
- frame->function = function;
|
|
|
- frame->ip = function->chunk.code;
|
|
|
- frame->slots = vm.stack;
|
|
|
+ // CallFrame *frame = &vm.frames[vm.frameCount++];
|
|
|
+ // frame->function = function;
|
|
|
+ // frame->ip = function->chunk.code;
|
|
|
+ // frame->slots = vm.stack;
|
|
|
+ call(function, 0);
|
|
|
|
|
|
return run();
|
|
|
}
|