Chapter 22

This commit is contained in:
Tom Willemse 2021-10-25 21:49:54 -07:00
parent 9de87f4495
commit 65275bde8a
4 changed files with 56 additions and 4 deletions

View file

@ -10,6 +10,8 @@ typedef enum {
OP_TRUE,
OP_FALSE,
OP_POP,
OP_GET_LOCAL,
OP_SET_LOCAL,
OP_GET_GLOBAL,
OP_DEFINE_GLOBAL,
OP_SET_GLOBAL,

View file

@ -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;
}

View file

@ -24,6 +24,12 @@ static int simpleInstruction(const char *name, int offset) {
return offset + 1;
}
static int byteInstruction(const char *name, Chunk *chunk, int offset) {
uint8_t slot = chunk->code[offset + 1];
printf("%-16s %4d\n", name, slot);
return offset + 2;
}
int disassembleInstruction(Chunk *chunk, int offset) {
printf("%04d ", offset);
if (offset > 0 && chunk->lines[offset] == chunk->lines[offset - 1]) {
@ -44,6 +50,10 @@ int disassembleInstruction(Chunk *chunk, int offset) {
return simpleInstruction("OP_FALSE", offset);
case OP_POP:
return simpleInstruction("OP_POP", offset);
case OP_GET_LOCAL:
return byteInstruction("OP_GET_LOCAL", chunk, offset);
case OP_SET_LOCAL:
return byteInstruction("OP_SET_LOCAL", chunk, offset);
case OP_GET_GLOBAL:
return constantInstruction("OP_GET_GLOBAL", chunk, offset);
case OP_DEFINE_GLOBAL:

View file

@ -115,6 +115,16 @@ static InterpretResult run() {
case OP_POP:
pop();
break;
case OP_GET_LOCAL: {
uint8_t slot = READ_BYTE();
push(vm.stack[slot]);
break;
}
case OP_SET_LOCAL: {
uint8_t slot = READ_BYTE();
vm.stack[slot] = peek(0);
break;
}
case OP_GET_GLOBAL: {
ObjString *name = READ_STRING();
Value value;