Chapter 28.4
This commit is contained in:
parent
7871383a40
commit
cb42c81121
4 changed files with 34 additions and 2 deletions
|
@ -51,7 +51,12 @@ typedef struct {
|
|||
bool isLocal;
|
||||
} Upvalue;
|
||||
|
||||
typedef enum { TYPE_FUNCTION, TYPE_METHOD, TYPE_SCRIPT } FunctionType;
|
||||
typedef enum {
|
||||
TYPE_FUNCTION,
|
||||
TYPE_INITIALIZER,
|
||||
TYPE_METHOD,
|
||||
TYPE_SCRIPT
|
||||
} FunctionType;
|
||||
|
||||
typedef struct Compiler {
|
||||
struct Compiler *enclosing;
|
||||
|
@ -159,7 +164,12 @@ static int emitJump(uint8_t instruction) {
|
|||
}
|
||||
|
||||
static void emitReturn() {
|
||||
emitByte(OP_NIL);
|
||||
if (current->type == TYPE_INITIALIZER) {
|
||||
emitBytes(OP_GET_LOCAL, 0);
|
||||
} else {
|
||||
emitByte(OP_NIL);
|
||||
}
|
||||
|
||||
emitByte(OP_RETURN);
|
||||
}
|
||||
|
||||
|
@ -389,6 +399,11 @@ static void method() {
|
|||
uint8_t constant = identifierConstant(&parser.previous);
|
||||
|
||||
FunctionType type = TYPE_METHOD;
|
||||
if (parser.previous.length == 4 &&
|
||||
memcmp(parser.previous.start, "init", 4) == 0) {
|
||||
type = TYPE_INITIALIZER;
|
||||
}
|
||||
|
||||
function(type);
|
||||
emitBytes(OP_METHOD, constant);
|
||||
}
|
||||
|
@ -588,6 +603,10 @@ static void returnStatement() {
|
|||
if (match(TOKEN_SEMICOLON)) {
|
||||
emitReturn();
|
||||
} else {
|
||||
if (current->type == TYPE_INITIALIZER) {
|
||||
error("Can't return a value from an initializer.");
|
||||
}
|
||||
|
||||
expression();
|
||||
consume(TOKEN_SEMICOLON, "Expect ';' after return value.");
|
||||
emitByte(OP_RETURN);
|
||||
|
|
|
@ -180,6 +180,7 @@ static void markRoots() {
|
|||
|
||||
markTable(&vm.globals);
|
||||
markCompilerRoots();
|
||||
markObject((Obj *)vm.initString);
|
||||
}
|
||||
|
||||
static void traceReferences() {
|
||||
|
|
|
@ -65,12 +65,16 @@ void initVM() {
|
|||
initTable(&vm.globals);
|
||||
initTable(&vm.strings);
|
||||
|
||||
vm.initString = NULL;
|
||||
vm.initString = copyString("init", 4);
|
||||
|
||||
defineNative("clock", clockNative);
|
||||
}
|
||||
|
||||
void freeVM() {
|
||||
freeTable(&vm.globals);
|
||||
freeTable(&vm.strings);
|
||||
vm.initString = NULL;
|
||||
freeObjects();
|
||||
}
|
||||
|
||||
|
@ -116,6 +120,13 @@ static bool callValue(Value callee, int argCount) {
|
|||
case OBJ_CLASS: {
|
||||
ObjClass *klass = AS_CLASS(callee);
|
||||
vm.stackTop[-argCount - 1] = OBJ_VAL(newInstance(klass));
|
||||
Value initializer;
|
||||
if (tableGet(&klass->methods, vm.initString, &initializer)) {
|
||||
return call(AS_CLOSURE(initializer), argCount);
|
||||
} else if (argCount != 0) {
|
||||
runtimeError("Expected 0 arguments but got %d.", argCount);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
case OBJ_CLOSURE:
|
||||
|
|
|
@ -23,6 +23,7 @@ typedef struct {
|
|||
Value *stackTop;
|
||||
Table globals;
|
||||
Table strings;
|
||||
ObjString *initString;
|
||||
ObjUpvalue *openUpvalues;
|
||||
|
||||
size_t bytesAllocated;
|
||||
|
|
Loading…
Reference in a new issue