Chapter 24.1

This commit is contained in:
Tom Willemse 2022-01-21 21:24:26 -08:00
parent 37ac05af6d
commit 9025da8168
4 changed files with 80 additions and 0 deletions

View file

@ -288,6 +288,51 @@ static void expressionStatement() {
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() {
consume(TOKEN_LEFT_PAREN, "Expect '(' after 'if'.");
expression();
@ -366,6 +411,8 @@ static void declaration() {
static void statement() {
if (match(TOKEN_PRINT)) {
printStatement();
} else if (match(TOKEN_FOR)) {
forStatement();
} else if (match(TOKEN_IF)) {
ifStatement();
} else if (match(TOKEN_WHILE)) {

View file

@ -17,6 +17,12 @@ void *reallocate(void *pointer, size_t oldSize, size_t newSize) {
static void freeObject(Obj *object) {
switch (object->type) {
case OBJ_FUNCTION: {
ObjFunction *function = (ObjFunction *)object;
freeChunk(&function->chunk);
FREE(ObjFunction, object);
break;
}
case OBJ_STRING: {
ObjString *string = (ObjString *)object;
FREE_ARRAY(char, string->chars, string->length + 1);

View file

@ -19,6 +19,14 @@ static Obj *allocateObject(size_t size, ObjType type) {
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) {
ObjString *string = ALLOCATE_OBJ(ObjString, OBJ_STRING);
string->length = length;
@ -60,8 +68,15 @@ ObjString *copyString(const char *chars, int length) {
return allocateString(heapChars, length, hash);
}
static void printFunction(ObjFunction *function) {
printf("<fn %s>", function->name->chars);
}
void printObject(Value value) {
switch (OBJ_TYPE(value)) {
case OBJ_FUNCTION:
printFunction(AS_FUNCTION(value));
break;
case OBJ_STRING:
printf("%s", AS_CSTRING(value));
break;

View file

@ -1,17 +1,21 @@
#ifndef OBJECT_H
#define OBJECT_H
#include "chunk.h"
#include "common.h"
#include "value.h"
#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 AS_FUNCTION(value) ((ObjFunction *)AS_OBJ(value))
#define AS_STRING(value) ((ObjString *)AS_OBJ(value))
#define AS_CSTRING(value) (((ObjString *)AS_OBJ(value))->chars)
typedef enum {
OBJ_FUNCTION,
OBJ_STRING,
} ObjType;
@ -20,6 +24,13 @@ struct Obj {
struct Obj *next;
};
typedef struct {
Obj obj;
int arity;
Chunk chunk;
ObjString *name;
} ObjFunction;
struct ObjString {
Obj obj;
int length;
@ -27,6 +38,7 @@ struct ObjString {
uint32_t hash;
};
ObjFunction *newFunction();
ObjString *takeString(char *chars, int length);
ObjString *copyString(const char *chars, int length);
void printObject(Value value);