aboutsummaryrefslogtreecommitdiffstats
path: root/clox/src/vm.c
diff options
context:
space:
mode:
Diffstat (limited to 'clox/src/vm.c')
-rw-r--r--clox/src/vm.c36
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);