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); 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)) {

View file

@ -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);

View file

@ -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;

View file

@ -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);