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_TRUE,
|
||||||
OP_FALSE,
|
OP_FALSE,
|
||||||
OP_POP,
|
OP_POP,
|
||||||
|
OP_GET_LOCAL,
|
||||||
|
OP_SET_LOCAL,
|
||||||
OP_GET_GLOBAL,
|
OP_GET_GLOBAL,
|
||||||
OP_DEFINE_GLOBAL,
|
OP_DEFINE_GLOBAL,
|
||||||
OP_SET_GLOBAL,
|
OP_SET_GLOBAL,
|
||||||
|
|
|
@ -170,6 +170,7 @@ static void parsePrecedence(Precedence precedence);
|
||||||
static uint8_t parseVariable(const char *name);
|
static uint8_t parseVariable(const char *name);
|
||||||
static void defineVariable(uint8_t global);
|
static void defineVariable(uint8_t global);
|
||||||
static uint8_t identifierConstant(Token *name);
|
static uint8_t identifierConstant(Token *name);
|
||||||
|
static int resolveLocal(Compiler *compiler, Token *name);
|
||||||
|
|
||||||
static void binary(bool canAssign) {
|
static void binary(bool canAssign) {
|
||||||
TokenType operatorType = parser.previous.type;
|
TokenType operatorType = parser.previous.type;
|
||||||
|
@ -321,13 +322,23 @@ static void string(bool canAssign) {
|
||||||
}
|
}
|
||||||
|
|
||||||
static void namedVariable(Token name, 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)) {
|
if (canAssign && match(TOKEN_EQUAL)) {
|
||||||
expression();
|
expression();
|
||||||
emitBytes(OP_SET_GLOBAL, arg);
|
emitBytes(setOp, arg);
|
||||||
} else {
|
} 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;
|
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) {
|
static void addLocal(Token name) {
|
||||||
if (current->localCount == UINT8_COUNT) {
|
if (current->localCount == UINT8_COUNT) {
|
||||||
error("Too many local variables in function.");
|
error("Too many local variables in function.");
|
||||||
|
@ -442,7 +467,7 @@ static void addLocal(Token name) {
|
||||||
|
|
||||||
Local *local = ¤t->locals[current->localCount++];
|
Local *local = ¤t->locals[current->localCount++];
|
||||||
local->name = name;
|
local->name = name;
|
||||||
local->depth = current->scopeDepth;
|
local->depth = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void declareVariable() {
|
static void declareVariable() {
|
||||||
|
@ -474,8 +499,13 @@ static uint8_t parseVariable(const char *errorMessage) {
|
||||||
return identifierConstant(&parser.previous);
|
return identifierConstant(&parser.previous);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void markInitialized() {
|
||||||
|
current->locals[current->localCount - 1].depth = current->scopeDepth;
|
||||||
|
}
|
||||||
|
|
||||||
static void defineVariable(uint8_t global) {
|
static void defineVariable(uint8_t global) {
|
||||||
if (current->scopeDepth > 0) {
|
if (current->scopeDepth > 0) {
|
||||||
|
markInitialized();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -24,6 +24,12 @@ static int simpleInstruction(const char *name, int offset) {
|
||||||
return offset + 1;
|
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) {
|
int disassembleInstruction(Chunk *chunk, int offset) {
|
||||||
printf("%04d ", offset);
|
printf("%04d ", offset);
|
||||||
if (offset > 0 && chunk->lines[offset] == chunk->lines[offset - 1]) {
|
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);
|
return simpleInstruction("OP_FALSE", offset);
|
||||||
case OP_POP:
|
case OP_POP:
|
||||||
return simpleInstruction("OP_POP", offset);
|
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:
|
case OP_GET_GLOBAL:
|
||||||
return constantInstruction("OP_GET_GLOBAL", chunk, offset);
|
return constantInstruction("OP_GET_GLOBAL", chunk, offset);
|
||||||
case OP_DEFINE_GLOBAL:
|
case OP_DEFINE_GLOBAL:
|
||||||
|
|
|
@ -115,6 +115,16 @@ static InterpretResult run() {
|
||||||
case OP_POP:
|
case OP_POP:
|
||||||
pop();
|
pop();
|
||||||
break;
|
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: {
|
case OP_GET_GLOBAL: {
|
||||||
ObjString *name = READ_STRING();
|
ObjString *name = READ_STRING();
|
||||||
Value value;
|
Value value;
|
||||||
|
|
Loading…
Reference in a new issue