diff options
author | Tom Willemse | 2022-08-14 19:56:32 -0700 |
---|---|---|
committer | Tom Willemse | 2022-08-14 19:56:32 -0700 |
commit | 62858b60e43803477e898c7993e109a94701ce70 (patch) | |
tree | 30d12b56bdf4e489372b68698252d4296fc5be4d /clox/src/vm.c | |
parent | e91006b59a143ad0083b3fb303a493f9d97e6c9b (diff) | |
download | crafting-interpreters-62858b60e43803477e898c7993e109a94701ce70.tar.gz crafting-interpreters-62858b60e43803477e898c7993e109a94701ce70.zip |
Chapter 28.5
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); |