Chapter 22.3
This commit is contained in:
parent
42a7e26292
commit
9de87f4495
1 changed files with 55 additions and 1 deletions
|
@ -1,5 +1,6 @@
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
#include "compiler.h"
|
#include "compiler.h"
|
||||||
|
@ -151,7 +152,15 @@ static void endCompiler() {
|
||||||
|
|
||||||
static void beginScope() { current->scopeDepth++; }
|
static void beginScope() { current->scopeDepth++; }
|
||||||
|
|
||||||
static void endScope() { current->scopeDepth--; }
|
static void endScope() {
|
||||||
|
current->scopeDepth--;
|
||||||
|
|
||||||
|
while (current->localCount > 0 &&
|
||||||
|
current->locals[current->localCount - 1].depth > current->scopeDepth) {
|
||||||
|
emitByte(OP_POP);
|
||||||
|
current->localCount--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void expression();
|
static void expression();
|
||||||
static void statement();
|
static void statement();
|
||||||
|
@ -419,12 +428,57 @@ static uint8_t identifierConstant(Token *name) {
|
||||||
return makeConstant(OBJ_VAL(copyString(name->start, name->length)));
|
return makeConstant(OBJ_VAL(copyString(name->start, name->length)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool identifiersEqual(Token *a, Token *b) {
|
||||||
|
if (a->length != b->length)
|
||||||
|
return false;
|
||||||
|
return memcmp(a->start, b->start, a->length) == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void addLocal(Token name) {
|
||||||
|
if (current->localCount == UINT8_COUNT) {
|
||||||
|
error("Too many local variables in function.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Local *local = ¤t->locals[current->localCount++];
|
||||||
|
local->name = name;
|
||||||
|
local->depth = current->scopeDepth;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void declareVariable() {
|
||||||
|
if (current->scopeDepth == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
Token *name = &parser.previous;
|
||||||
|
for (int i = current->localCount - 1; i >= 0; i--) {
|
||||||
|
Local *local = ¤t->locals[i];
|
||||||
|
if (local->depth != -1 && local->depth < current->scopeDepth) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (identifiersEqual(name, &local->name)) {
|
||||||
|
error("Already a variable with this name in this scope.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
addLocal(*name);
|
||||||
|
}
|
||||||
|
|
||||||
static uint8_t parseVariable(const char *errorMessage) {
|
static uint8_t parseVariable(const char *errorMessage) {
|
||||||
consume(TOKEN_IDENTIFIER, errorMessage);
|
consume(TOKEN_IDENTIFIER, errorMessage);
|
||||||
|
|
||||||
|
declareVariable();
|
||||||
|
if (current->scopeDepth > 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
return identifierConstant(&parser.previous);
|
return identifierConstant(&parser.previous);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void defineVariable(uint8_t global) {
|
static void defineVariable(uint8_t global) {
|
||||||
|
if (current->scopeDepth > 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
emitBytes(OP_DEFINE_GLOBAL, global);
|
emitBytes(OP_DEFINE_GLOBAL, global);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue