aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGravatar Tom Willemse2022-08-14 16:11:39 -0700
committerGravatar Tom Willemse2022-08-14 16:11:39 -0700
commitcb42c811218b30ff9ff1a194b18fe3d85ea68a50 (patch)
tree5d0b5d6388ab6cdda9323fddf96d49364a0dd8f8
parent7871383a400f0a37dbd8459755aa9f98e2742f7a (diff)
downloadcrafting-interpreters-cb42c811218b30ff9ff1a194b18fe3d85ea68a50.tar.gz
crafting-interpreters-cb42c811218b30ff9ff1a194b18fe3d85ea68a50.zip
Chapter 28.4
-rw-r--r--clox/src/compiler.c23
-rw-r--r--clox/src/memory.c1
-rw-r--r--clox/src/vm.c11
-rw-r--r--clox/src/vm.h1
4 files changed, 34 insertions, 2 deletions
diff --git a/clox/src/compiler.c b/clox/src/compiler.c
index a773e97..4dded64 100644
--- a/clox/src/compiler.c
+++ b/clox/src/compiler.c
@@ -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);
diff --git a/clox/src/memory.c b/clox/src/memory.c
index b93b6d6..abf1cdd 100644
--- a/clox/src/memory.c
+++ b/clox/src/memory.c
@@ -180,6 +180,7 @@ static void markRoots() {
markTable(&vm.globals);
markCompilerRoots();
+ markObject((Obj *)vm.initString);
}
static void traceReferences() {
diff --git a/clox/src/vm.c b/clox/src/vm.c
index 6b15a3a..d248609 100644
--- a/clox/src/vm.c
+++ b/clox/src/vm.c
@@ -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:
diff --git a/clox/src/vm.h b/clox/src/vm.h
index e108daa..18495c8 100644
--- a/clox/src/vm.h
+++ b/clox/src/vm.h
@@ -23,6 +23,7 @@ typedef struct {
Value *stackTop;
Table globals;
Table strings;
+ ObjString *initString;
ObjUpvalue *openUpvalues;
size_t bytesAllocated;