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_JUMP_IF_FALSE,
|
||||||
OP_LOOP,
|
OP_LOOP,
|
||||||
OP_CALL,
|
OP_CALL,
|
||||||
|
OP_INVOKE,
|
||||||
OP_CLOSURE,
|
OP_CLOSURE,
|
||||||
OP_CLOSE_UPVALUE,
|
OP_CLOSE_UPVALUE,
|
||||||
OP_RETURN,
|
OP_RETURN,
|
||||||
|
|
|
@ -335,6 +335,10 @@ static void dot(bool canAssign) {
|
||||||
if (canAssign && match(TOKEN_EQUAL)) {
|
if (canAssign && match(TOKEN_EQUAL)) {
|
||||||
expression();
|
expression();
|
||||||
emitBytes(OP_SET_PROPERTY, name);
|
emitBytes(OP_SET_PROPERTY, name);
|
||||||
|
} else if (match(TOKEN_LEFT_PAREN)) {
|
||||||
|
uint8_t argCount = argumentList();
|
||||||
|
emitBytes(OP_INVOKE, name);
|
||||||
|
emitByte(argCount);
|
||||||
} else {
|
} else {
|
||||||
emitBytes(OP_GET_PROPERTY, name);
|
emitBytes(OP_GET_PROPERTY, name);
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,6 +20,15 @@ static int constantInstruction(const char *name, Chunk *chunk, int offset) {
|
||||||
return offset + 2;
|
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) {
|
static int simpleInstruction(const char *name, int offset) {
|
||||||
printf("%s\n", name);
|
printf("%s\n", name);
|
||||||
return offset + 1;
|
return offset + 1;
|
||||||
|
@ -105,6 +114,8 @@ int disassembleInstruction(Chunk *chunk, int offset) {
|
||||||
return jumpInstruction("OP_LOOP", -1, chunk, offset);
|
return jumpInstruction("OP_LOOP", -1, chunk, offset);
|
||||||
case OP_CALL:
|
case OP_CALL:
|
||||||
return byteInstruction("OP_CALL", chunk, offset);
|
return byteInstruction("OP_CALL", chunk, offset);
|
||||||
|
case OP_INVOKE:
|
||||||
|
return invokeInstruction("OP_INVOKE", chunk, offset);
|
||||||
case OP_CLOSURE: {
|
case OP_CLOSURE: {
|
||||||
offset++;
|
offset++;
|
||||||
uint8_t constant = chunk->code[offset++];
|
uint8_t constant = chunk->code[offset++];
|
||||||
|
|
|
@ -146,6 +146,33 @@ static bool callValue(Value callee, int argCount) {
|
||||||
return false;
|
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) {
|
static bool bindMethod(ObjClass *klass, ObjString *name) {
|
||||||
Value method;
|
Value method;
|
||||||
if (!tableGet(&klass->methods, name, &method)) {
|
if (!tableGet(&klass->methods, name, &method)) {
|
||||||
|
@ -424,6 +451,15 @@ static InterpretResult run() {
|
||||||
frame = &vm.frames[vm.frameCount - 1];
|
frame = &vm.frames[vm.frameCount - 1];
|
||||||
break;
|
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: {
|
case OP_CLOSURE: {
|
||||||
ObjFunction *function = AS_FUNCTION(READ_CONSTANT());
|
ObjFunction *function = AS_FUNCTION(READ_CONSTANT());
|
||||||
ObjClosure *closure = newClosure(function);
|
ObjClosure *closure = newClosure(function);
|
||||||
|
|
Loading…
Reference in a new issue