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;
|
bool isLocal;
|
||||||
} Upvalue;
|
} Upvalue;
|
||||||
|
|
||||||
typedef enum { TYPE_FUNCTION, TYPE_METHOD, TYPE_SCRIPT } FunctionType;
|
typedef enum {
|
||||||
|
TYPE_FUNCTION,
|
||||||
|
TYPE_INITIALIZER,
|
||||||
|
TYPE_METHOD,
|
||||||
|
TYPE_SCRIPT
|
||||||
|
} FunctionType;
|
||||||
|
|
||||||
typedef struct Compiler {
|
typedef struct Compiler {
|
||||||
struct Compiler *enclosing;
|
struct Compiler *enclosing;
|
||||||
|
@ -159,7 +164,12 @@ static int emitJump(uint8_t instruction) {
|
||||||
}
|
}
|
||||||
|
|
||||||
static void emitReturn() {
|
static void emitReturn() {
|
||||||
|
if (current->type == TYPE_INITIALIZER) {
|
||||||
|
emitBytes(OP_GET_LOCAL, 0);
|
||||||
|
} else {
|
||||||
emitByte(OP_NIL);
|
emitByte(OP_NIL);
|
||||||
|
}
|
||||||
|
|
||||||
emitByte(OP_RETURN);
|
emitByte(OP_RETURN);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -389,6 +399,11 @@ static void method() {
|
||||||
uint8_t constant = identifierConstant(&parser.previous);
|
uint8_t constant = identifierConstant(&parser.previous);
|
||||||
|
|
||||||
FunctionType type = TYPE_METHOD;
|
FunctionType type = TYPE_METHOD;
|
||||||
|
if (parser.previous.length == 4 &&
|
||||||
|
memcmp(parser.previous.start, "init", 4) == 0) {
|
||||||
|
type = TYPE_INITIALIZER;
|
||||||
|
}
|
||||||
|
|
||||||
function(type);
|
function(type);
|
||||||
emitBytes(OP_METHOD, constant);
|
emitBytes(OP_METHOD, constant);
|
||||||
}
|
}
|
||||||
|
@ -588,6 +603,10 @@ static void returnStatement() {
|
||||||
if (match(TOKEN_SEMICOLON)) {
|
if (match(TOKEN_SEMICOLON)) {
|
||||||
emitReturn();
|
emitReturn();
|
||||||
} else {
|
} else {
|
||||||
|
if (current->type == TYPE_INITIALIZER) {
|
||||||
|
error("Can't return a value from an initializer.");
|
||||||
|
}
|
||||||
|
|
||||||
expression();
|
expression();
|
||||||
consume(TOKEN_SEMICOLON, "Expect ';' after return value.");
|
consume(TOKEN_SEMICOLON, "Expect ';' after return value.");
|
||||||
emitByte(OP_RETURN);
|
emitByte(OP_RETURN);
|
||||||
|
|
|
@ -180,6 +180,7 @@ static void markRoots() {
|
||||||
|
|
||||||
markTable(&vm.globals);
|
markTable(&vm.globals);
|
||||||
markCompilerRoots();
|
markCompilerRoots();
|
||||||
|
markObject((Obj *)vm.initString);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void traceReferences() {
|
static void traceReferences() {
|
||||||
|
|
|
@ -65,12 +65,16 @@ void initVM() {
|
||||||
initTable(&vm.globals);
|
initTable(&vm.globals);
|
||||||
initTable(&vm.strings);
|
initTable(&vm.strings);
|
||||||
|
|
||||||
|
vm.initString = NULL;
|
||||||
|
vm.initString = copyString("init", 4);
|
||||||
|
|
||||||
defineNative("clock", clockNative);
|
defineNative("clock", clockNative);
|
||||||
}
|
}
|
||||||
|
|
||||||
void freeVM() {
|
void freeVM() {
|
||||||
freeTable(&vm.globals);
|
freeTable(&vm.globals);
|
||||||
freeTable(&vm.strings);
|
freeTable(&vm.strings);
|
||||||
|
vm.initString = NULL;
|
||||||
freeObjects();
|
freeObjects();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -116,6 +120,13 @@ static bool callValue(Value callee, int argCount) {
|
||||||
case OBJ_CLASS: {
|
case OBJ_CLASS: {
|
||||||
ObjClass *klass = AS_CLASS(callee);
|
ObjClass *klass = AS_CLASS(callee);
|
||||||
vm.stackTop[-argCount - 1] = OBJ_VAL(newInstance(klass));
|
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;
|
return true;
|
||||||
}
|
}
|
||||||
case OBJ_CLOSURE:
|
case OBJ_CLOSURE:
|
||||||
|
|
|
@ -23,6 +23,7 @@ typedef struct {
|
||||||
Value *stackTop;
|
Value *stackTop;
|
||||||
Table globals;
|
Table globals;
|
||||||
Table strings;
|
Table strings;
|
||||||
|
ObjString *initString;
|
||||||
ObjUpvalue *openUpvalues;
|
ObjUpvalue *openUpvalues;
|
||||||
|
|
||||||
size_t bytesAllocated;
|
size_t bytesAllocated;
|
||||||
|
|
Loading…
Reference in a new issue