Chapter 24.1
This commit is contained in:
parent
37ac05af6d
commit
9025da8168
4 changed files with 80 additions and 0 deletions
|
@ -288,6 +288,51 @@ static void expressionStatement() {
|
||||||
emitByte(OP_POP);
|
emitByte(OP_POP);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void forStatement() {
|
||||||
|
beginScope();
|
||||||
|
consume(TOKEN_LEFT_PAREN, "Expect '(' after 'for'.");
|
||||||
|
if (match(TOKEN_SEMICOLON)) {
|
||||||
|
// No initializer
|
||||||
|
} else if (match(TOKEN_VAR)) {
|
||||||
|
varDeclaration();
|
||||||
|
} else {
|
||||||
|
expressionStatement();
|
||||||
|
}
|
||||||
|
|
||||||
|
int loopStart = currentChunk()->count;
|
||||||
|
int exitJump = -1;
|
||||||
|
if (!match(TOKEN_SEMICOLON)) {
|
||||||
|
expression();
|
||||||
|
consume(TOKEN_SEMICOLON, "Expect ';' after loop condition.");
|
||||||
|
|
||||||
|
// Jump out of the loop if the condition is false.
|
||||||
|
exitJump = emitJump(OP_JUMP_IF_FALSE);
|
||||||
|
emitByte(OP_POP); /* Condition. */
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!match(TOKEN_RIGHT_PAREN)) {
|
||||||
|
int bodyJump = emitJump(OP_JUMP);
|
||||||
|
int incrementStart = currentChunk()->count;
|
||||||
|
expression();
|
||||||
|
emitByte(OP_POP);
|
||||||
|
consume(TOKEN_RIGHT_PAREN, "Expect ')' after for clauses.");
|
||||||
|
|
||||||
|
emitLoop(loopStart);
|
||||||
|
loopStart = incrementStart;
|
||||||
|
patchJump(bodyJump);
|
||||||
|
}
|
||||||
|
|
||||||
|
statement();
|
||||||
|
emitLoop(loopStart);
|
||||||
|
|
||||||
|
if (exitJump != -1) {
|
||||||
|
patchJump(exitJump);
|
||||||
|
emitByte(OP_POP); /* Condition. */
|
||||||
|
}
|
||||||
|
|
||||||
|
endScope();
|
||||||
|
}
|
||||||
|
|
||||||
static void ifStatement() {
|
static void ifStatement() {
|
||||||
consume(TOKEN_LEFT_PAREN, "Expect '(' after 'if'.");
|
consume(TOKEN_LEFT_PAREN, "Expect '(' after 'if'.");
|
||||||
expression();
|
expression();
|
||||||
|
@ -366,6 +411,8 @@ static void declaration() {
|
||||||
static void statement() {
|
static void statement() {
|
||||||
if (match(TOKEN_PRINT)) {
|
if (match(TOKEN_PRINT)) {
|
||||||
printStatement();
|
printStatement();
|
||||||
|
} else if (match(TOKEN_FOR)) {
|
||||||
|
forStatement();
|
||||||
} else if (match(TOKEN_IF)) {
|
} else if (match(TOKEN_IF)) {
|
||||||
ifStatement();
|
ifStatement();
|
||||||
} else if (match(TOKEN_WHILE)) {
|
} else if (match(TOKEN_WHILE)) {
|
||||||
|
|
|
@ -17,6 +17,12 @@ void *reallocate(void *pointer, size_t oldSize, size_t newSize) {
|
||||||
|
|
||||||
static void freeObject(Obj *object) {
|
static void freeObject(Obj *object) {
|
||||||
switch (object->type) {
|
switch (object->type) {
|
||||||
|
case OBJ_FUNCTION: {
|
||||||
|
ObjFunction *function = (ObjFunction *)object;
|
||||||
|
freeChunk(&function->chunk);
|
||||||
|
FREE(ObjFunction, object);
|
||||||
|
break;
|
||||||
|
}
|
||||||
case OBJ_STRING: {
|
case OBJ_STRING: {
|
||||||
ObjString *string = (ObjString *)object;
|
ObjString *string = (ObjString *)object;
|
||||||
FREE_ARRAY(char, string->chars, string->length + 1);
|
FREE_ARRAY(char, string->chars, string->length + 1);
|
||||||
|
|
|
@ -19,6 +19,14 @@ static Obj *allocateObject(size_t size, ObjType type) {
|
||||||
return object;
|
return object;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ObjFunction *newFunction() {
|
||||||
|
ObjFunction *function = ALLOCATE_OBJ(ObjFunction, OBJ_FUNCTION);
|
||||||
|
function->arity = 0;
|
||||||
|
function->name = NULL;
|
||||||
|
initChunk(&function->chunk);
|
||||||
|
return function;
|
||||||
|
}
|
||||||
|
|
||||||
static ObjString *allocateString(char *chars, int length, uint32_t hash) {
|
static ObjString *allocateString(char *chars, int length, uint32_t hash) {
|
||||||
ObjString *string = ALLOCATE_OBJ(ObjString, OBJ_STRING);
|
ObjString *string = ALLOCATE_OBJ(ObjString, OBJ_STRING);
|
||||||
string->length = length;
|
string->length = length;
|
||||||
|
@ -60,8 +68,15 @@ ObjString *copyString(const char *chars, int length) {
|
||||||
return allocateString(heapChars, length, hash);
|
return allocateString(heapChars, length, hash);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void printFunction(ObjFunction *function) {
|
||||||
|
printf("<fn %s>", function->name->chars);
|
||||||
|
}
|
||||||
|
|
||||||
void printObject(Value value) {
|
void printObject(Value value) {
|
||||||
switch (OBJ_TYPE(value)) {
|
switch (OBJ_TYPE(value)) {
|
||||||
|
case OBJ_FUNCTION:
|
||||||
|
printFunction(AS_FUNCTION(value));
|
||||||
|
break;
|
||||||
case OBJ_STRING:
|
case OBJ_STRING:
|
||||||
printf("%s", AS_CSTRING(value));
|
printf("%s", AS_CSTRING(value));
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -1,17 +1,21 @@
|
||||||
#ifndef OBJECT_H
|
#ifndef OBJECT_H
|
||||||
#define OBJECT_H
|
#define OBJECT_H
|
||||||
|
|
||||||
|
#include "chunk.h"
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
#include "value.h"
|
#include "value.h"
|
||||||
|
|
||||||
#define OBJ_TYPE(value) (AS_OBJ(value)->type)
|
#define OBJ_TYPE(value) (AS_OBJ(value)->type)
|
||||||
|
|
||||||
|
#define IS_FUNCTION(value) isObjType(value, OBJ_FUNCTION)
|
||||||
#define IS_STRING(value) isObjType(value, OBJ_STRING)
|
#define IS_STRING(value) isObjType(value, OBJ_STRING)
|
||||||
|
|
||||||
|
#define AS_FUNCTION(value) ((ObjFunction *)AS_OBJ(value))
|
||||||
#define AS_STRING(value) ((ObjString *)AS_OBJ(value))
|
#define AS_STRING(value) ((ObjString *)AS_OBJ(value))
|
||||||
#define AS_CSTRING(value) (((ObjString *)AS_OBJ(value))->chars)
|
#define AS_CSTRING(value) (((ObjString *)AS_OBJ(value))->chars)
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
|
OBJ_FUNCTION,
|
||||||
OBJ_STRING,
|
OBJ_STRING,
|
||||||
} ObjType;
|
} ObjType;
|
||||||
|
|
||||||
|
@ -20,6 +24,13 @@ struct Obj {
|
||||||
struct Obj *next;
|
struct Obj *next;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
Obj obj;
|
||||||
|
int arity;
|
||||||
|
Chunk chunk;
|
||||||
|
ObjString *name;
|
||||||
|
} ObjFunction;
|
||||||
|
|
||||||
struct ObjString {
|
struct ObjString {
|
||||||
Obj obj;
|
Obj obj;
|
||||||
int length;
|
int length;
|
||||||
|
@ -27,6 +38,7 @@ struct ObjString {
|
||||||
uint32_t hash;
|
uint32_t hash;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
ObjFunction *newFunction();
|
||||||
ObjString *takeString(char *chars, int length);
|
ObjString *takeString(char *chars, int length);
|
||||||
ObjString *copyString(const char *chars, int length);
|
ObjString *copyString(const char *chars, int length);
|
||||||
void printObject(Value value);
|
void printObject(Value value);
|
||||||
|
|
Loading…
Reference in a new issue