Chapter 28.5
This commit is contained in:
parent
e91006b59a
commit
62858b60e4
4 changed files with 52 additions and 0 deletions
|
@ -33,6 +33,7 @@ typedef enum {
|
|||
OP_JUMP_IF_FALSE,
|
||||
OP_LOOP,
|
||||
OP_CALL,
|
||||
OP_INVOKE,
|
||||
OP_CLOSURE,
|
||||
OP_CLOSE_UPVALUE,
|
||||
OP_RETURN,
|
||||
|
|
|
@ -335,6 +335,10 @@ static void dot(bool canAssign) {
|
|||
if (canAssign && match(TOKEN_EQUAL)) {
|
||||
expression();
|
||||
emitBytes(OP_SET_PROPERTY, name);
|
||||
} else if (match(TOKEN_LEFT_PAREN)) {
|
||||
uint8_t argCount = argumentList();
|
||||
emitBytes(OP_INVOKE, name);
|
||||
emitByte(argCount);
|
||||
} else {
|
||||
emitBytes(OP_GET_PROPERTY, name);
|
||||
}
|
||||
|
|
|
@ -20,6 +20,15 @@ static int constantInstruction(const char *name, Chunk *chunk, int offset) {
|
|||
return offset + 2;
|
||||
}
|
||||
|
||||
static int invokeInstruction(const char *name, Chunk *chunk, int offset) {
|
||||
uint8_t constant = chunk->code[offset + 1];
|
||||
uint8_t argCount = chunk->code[offset + 2];
|
||||
printf("%-16s (%d args) %4d '", name, argCount, constant);
|
||||
printValue(chunk->constants.values[constant]);
|
||||
printf("'\n'");
|
||||
return offset + 3;
|
||||
}
|
||||
|
||||
static int simpleInstruction(const char *name, int offset) {
|
||||
printf("%s\n", name);
|
||||
return offset + 1;
|
||||
|
@ -105,6 +114,8 @@ int disassembleInstruction(Chunk *chunk, int offset) {
|
|||
return jumpInstruction("OP_LOOP", -1, chunk, offset);
|
||||
case OP_CALL:
|
||||
return byteInstruction("OP_CALL", chunk, offset);
|
||||
case OP_INVOKE:
|
||||
return invokeInstruction("OP_INVOKE", chunk, offset);
|
||||
case OP_CLOSURE: {
|
||||
offset++;
|
||||
uint8_t constant = chunk->code[offset++];
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in a new issue