Chapter 27.2
This commit is contained in:
parent
63527558a7
commit
a819a85209
4 changed files with 58 additions and 38 deletions
|
@ -34,6 +34,7 @@ typedef enum {
|
|||
OP_CLOSURE,
|
||||
OP_CLOSE_UPVALUE,
|
||||
OP_RETURN,
|
||||
OP_CLASS,
|
||||
} OpCode;
|
||||
|
||||
typedef struct {
|
||||
|
|
|
@ -362,6 +362,55 @@ static void function(FunctionType type) {
|
|||
}
|
||||
}
|
||||
|
||||
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 = -1;
|
||||
local->isCaptured = false;
|
||||
}
|
||||
|
||||
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 void classDeclaration() {
|
||||
consume(TOKEN_IDENTIFIER, "Expect class name");
|
||||
uint8_t nameConstant = identifierConstant(&parser.previous);
|
||||
declareVariable();
|
||||
|
||||
emitBytes(OP_CLASS, nameConstant);
|
||||
defineVariable(nameConstant);
|
||||
|
||||
consume(TOKEN_LEFT_BRACE, "Expect '{' before class body.");
|
||||
consume(TOKEN_RIGHT_BRACE, "Expect '}' after class body.");
|
||||
}
|
||||
|
||||
static void markInitialized() {
|
||||
if (current->scopeDepth == 0)
|
||||
return;
|
||||
|
@ -518,7 +567,9 @@ static void synchronize() {
|
|||
}
|
||||
|
||||
static void declaration() {
|
||||
if (match(TOKEN_FUN)) {
|
||||
if (match(TOKEN_CLASS)) {
|
||||
classDeclaration();
|
||||
} else if (match(TOKEN_FUN)) {
|
||||
funDeclaration();
|
||||
} else if (match(TOKEN_VAR)) {
|
||||
varDeclaration();
|
||||
|
@ -701,12 +752,6 @@ static uint8_t identifierConstant(Token *name) {
|
|||
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 int resolveLocal(Compiler *compiler, Token *name) {
|
||||
for (int i = compiler->localCount - 1; i >= 0; i--) {
|
||||
Local *local = &compiler->locals[i];
|
||||
|
@ -759,37 +804,6 @@ static int resolveUpvalue(Compiler *compiler, Token *name) {
|
|||
return -1;
|
||||
}
|
||||
|
||||
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 = -1;
|
||||
local->isCaptured = false;
|
||||
}
|
||||
|
||||
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) {
|
||||
consume(TOKEN_IDENTIFIER, errorMessage);
|
||||
|
||||
|
|
|
@ -122,6 +122,8 @@ int disassembleInstruction(Chunk *chunk, int offset) {
|
|||
return simpleInstruction("OP_CLOSE_UPVALUE", offset);
|
||||
case OP_RETURN:
|
||||
return simpleInstruction("OP_RETURN", offset);
|
||||
case OP_CLASS:
|
||||
return constantInstruction("OP_CLASS", chunk, offset);
|
||||
default:
|
||||
printf("Unknown opcode %d\n", instruction);
|
||||
return offset + 1;
|
||||
|
|
|
@ -384,6 +384,9 @@ static InterpretResult run() {
|
|||
frame = &vm.frames[vm.frameCount - 1];
|
||||
break;
|
||||
}
|
||||
case OP_CLASS:
|
||||
push(OBJ_VAL(newClass(READ_STRING())));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue