Chapter 22
This commit is contained in:
parent
9de87f4495
commit
65275bde8a
4 changed files with 56 additions and 4 deletions
|
@ -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,
|
||||
|
|
|
@ -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 = ¤t->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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in a new issue