aboutsummaryrefslogtreecommitdiffstats
path: root/clox/src/compiler.c
diff options
context:
space:
mode:
authorGravatar Tom Willemse2021-10-25 21:49:54 -0700
committerGravatar Tom Willemse2021-10-25 21:49:54 -0700
commit65275bde8a82f54710a65d6e6563394bb850b7ef (patch)
tree5fce3c2af65f1b5ae55823b28bd139860ff05f5c /clox/src/compiler.c
parent9de87f449518415a7cc181d4592f28185aa5d6a0 (diff)
downloadcrafting-interpreters-65275bde8a82f54710a65d6e6563394bb850b7ef.tar.gz
crafting-interpreters-65275bde8a82f54710a65d6e6563394bb850b7ef.zip
Chapter 22
Diffstat (limited to 'clox/src/compiler.c')
-rw-r--r--clox/src/compiler.c38
1 files changed, 34 insertions, 4 deletions
diff --git a/clox/src/compiler.c b/clox/src/compiler.c
index 98de087..a964b79 100644
--- a/clox/src/compiler.c
+++ b/clox/src/compiler.c
@@ -170,6 +170,7 @@ static void parsePrecedence(Precedence precedence);
static uint8_t parseVariable(const char *name);
static void defineVariable(uint8_t global);
static uint8_t identifierConstant(Token *name);
+static int resolveLocal(Compiler *compiler, Token *name);
static void binary(bool canAssign) {
TokenType operatorType = parser.previous.type;
@@ -321,13 +322,23 @@ static void string(bool canAssign) {
}
static void namedVariable(Token name, bool canAssign) {
- uint8_t arg = identifierConstant(&name);
+ uint8_t getOp, setOp;
+ int arg = resolveLocal(current, &name);
+
+ if (arg != -1) {
+ getOp = OP_GET_LOCAL;
+ setOp = OP_SET_LOCAL;
+ } else {
+ arg = identifierConstant(&name);
+ getOp = OP_GET_GLOBAL;
+ setOp = OP_SET_GLOBAL;
+ }
if (canAssign && match(TOKEN_EQUAL)) {
expression();
- emitBytes(OP_SET_GLOBAL, arg);
+ emitBytes(setOp, arg);
} else {
- emitBytes(OP_GET_GLOBAL, arg);
+ emitBytes(getOp, arg);
}
}
@@ -434,6 +445,20 @@ static bool identifiersEqual(Token *a, Token *b) {
return memcmp(a->start, b->start, a->length) == 0;
}
+static int resolveLocal(Compiler *compiler, Token *name) {
+ for (int i = compiler->localCount - 1; i >= 0; i--) {
+ Local *local = &compiler->locals[i];
+ if (identifiersEqual(name, &local->name)) {
+ if (local->depth == -1) {
+ error("Can't read local variable in its own initializer.");
+ }
+ return i;
+ }
+ }
+
+ return -1;
+}
+
static void addLocal(Token name) {
if (current->localCount == UINT8_COUNT) {
error("Too many local variables in function.");
@@ -442,7 +467,7 @@ static void addLocal(Token name) {
Local *local = &current->locals[current->localCount++];
local->name = name;
- local->depth = current->scopeDepth;
+ local->depth = -1;
}
static void declareVariable() {
@@ -474,8 +499,13 @@ static uint8_t parseVariable(const char *errorMessage) {
return identifierConstant(&parser.previous);
}
+static void markInitialized() {
+ current->locals[current->localCount - 1].depth = current->scopeDepth;
+}
+
static void defineVariable(uint8_t global) {
if (current->scopeDepth > 0) {
+ markInitialized();
return;
}