diff options
Diffstat (limited to 'clox/src/vm.c')
-rw-r--r-- | clox/src/vm.c | 36 |
1 files changed, 36 insertions, 0 deletions
diff --git a/clox/src/vm.c b/clox/src/vm.c index d248609..b5cb1cc 100644 --- a/clox/src/vm.c +++ b/clox/src/vm.c @@ -146,6 +146,33 @@ static bool callValue(Value callee, int argCount) { return false; } +static bool invokeFromClass(ObjClass *klass, ObjString *name, int argCount) { + Value method; + if (!tableGet(&klass->methods, name, &method)) { + runtimeError("Undefined property '%s'.", name->chars); + return false; + } + return call(AS_CLOSURE(method), argCount); +} + +static bool invoke(ObjString *name, int argCount) { + Value receiver = peek(argCount); + + if (!IS_INSTANCE(receiver)) { + runtimeError("Only instances have methods."); + return false; + } + + ObjInstance *instance = AS_INSTANCE(receiver); + + Value value; + if (tableGet(&instance->fields, name, &value)) { + vm.stackTop[-argCount - 1] = value; + return callValue(value, argCount); + } + return invokeFromClass(instance->klass, name, argCount); +} + static bool bindMethod(ObjClass *klass, ObjString *name) { Value method; if (!tableGet(&klass->methods, name, &method)) { @@ -424,6 +451,15 @@ static InterpretResult run() { frame = &vm.frames[vm.frameCount - 1]; break; } + case OP_INVOKE: { + ObjString *method = READ_STRING(); + int argCount = READ_BYTE(); + if (!invoke(method, argCount)) { + return INTERPRET_RUNTIME_ERROR; + } + frame = &vm.frames[vm.frameCount - 1]; + break; + } case OP_CLOSURE: { ObjFunction *function = AS_FUNCTION(READ_CONSTANT()); ObjClosure *closure = newClosure(function); |