Chapter 25.1

This commit is contained in:
Tom Willemse 2022-03-23 17:00:22 -07:00
parent 3da4016d57
commit 1ae50814d3
8 changed files with 56 additions and 14 deletions

View file

@ -29,6 +29,7 @@ typedef enum {
OP_JUMP_IF_FALSE, OP_JUMP_IF_FALSE,
OP_LOOP, OP_LOOP,
OP_CALL, OP_CALL,
OP_CLOSURE,
OP_RETURN, OP_RETURN,
} OpCode; } OpCode;

View file

@ -339,7 +339,7 @@ static void function(FunctionType type) {
block(); block();
ObjFunction *function = endCompiler(); ObjFunction *function = endCompiler();
emitBytes(OP_CONSTANT, makeConstant(OBJ_VAL(function))); emitBytes(OP_CLOSURE, makeConstant(OBJ_VAL(function)));
} }
static void markInitialized() { static void markInitialized() {

View file

@ -96,6 +96,14 @@ int disassembleInstruction(Chunk *chunk, int offset) {
return jumpInstruction("OP_LOOP", -1, chunk, offset); return jumpInstruction("OP_LOOP", -1, chunk, offset);
case OP_CALL: case OP_CALL:
return byteInstruction("OP_CALL", chunk, offset); return byteInstruction("OP_CALL", chunk, offset);
case OP_CLOSURE: {
offset++;
uint8_t constant = chunk->code[offset++];
printf("%-16s %4d", "OP_CLOSURE", constant);
printValue(chunk->constants.values[constant]);
printf("\n");
return offset;
}
case OP_RETURN: case OP_RETURN:
return simpleInstruction("OP_RETURN", offset); return simpleInstruction("OP_RETURN", offset);
default: default:

View file

@ -17,6 +17,10 @@ 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_CLOSURE: {
FREE(ObjClosure, object);
break;
}
case OBJ_FUNCTION: { case OBJ_FUNCTION: {
ObjFunction *function = (ObjFunction *)object; ObjFunction *function = (ObjFunction *)object;
freeChunk(&function->chunk); freeChunk(&function->chunk);

View file

@ -19,6 +19,12 @@ static Obj *allocateObject(size_t size, ObjType type) {
return object; return object;
} }
ObjClosure *newClosure(ObjFunction *function) {
ObjClosure *closure = ALLOCATE_OBJ(ObjClosure, OBJ_CLOSURE);
closure->function = function;
return closure;
}
ObjFunction *newFunction() { ObjFunction *newFunction() {
ObjFunction *function = ALLOCATE_OBJ(ObjFunction, OBJ_FUNCTION); ObjFunction *function = ALLOCATE_OBJ(ObjFunction, OBJ_FUNCTION);
function->arity = 0; function->arity = 0;
@ -84,6 +90,9 @@ static void printFunction(ObjFunction *function) {
void printObject(Value value) { void printObject(Value value) {
switch (OBJ_TYPE(value)) { switch (OBJ_TYPE(value)) {
case OBJ_CLOSURE:
printFunction(AS_CLOSURE(value)->function);
break;
case OBJ_FUNCTION: case OBJ_FUNCTION:
printFunction(AS_FUNCTION(value)); printFunction(AS_FUNCTION(value));
break; break;

View file

@ -7,16 +7,19 @@
#define OBJ_TYPE(value) (AS_OBJ(value)->type) #define OBJ_TYPE(value) (AS_OBJ(value)->type)
#define IS_CLOSURE(value) isObjType(value, OBJ_CLOSURE)
#define IS_FUNCTION(value) isObjType(value, OBJ_FUNCTION) #define IS_FUNCTION(value) isObjType(value, OBJ_FUNCTION)
#define IS_NATIVE(value) isObjType(value, OBJ_NATIVE) #define IS_NATIVE(value) isObjType(value, OBJ_NATIVE)
#define IS_STRING(value) isObjType(value, OBJ_STRING) #define IS_STRING(value) isObjType(value, OBJ_STRING)
#define AS_CLOSURE(value) ((ObjClosure *)AS_OBJ(value))
#define AS_FUNCTION(value) ((ObjFunction *)AS_OBJ(value)) #define AS_FUNCTION(value) ((ObjFunction *)AS_OBJ(value))
#define AS_NATIVE(value) (((ObjNative *)AS_OBJ(value))->function) #define AS_NATIVE(value) (((ObjNative *)AS_OBJ(value))->function)
#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_CLOSURE,
OBJ_FUNCTION, OBJ_FUNCTION,
OBJ_NATIVE, OBJ_NATIVE,
OBJ_STRING, OBJ_STRING,
@ -48,6 +51,12 @@ struct ObjString {
uint32_t hash; uint32_t hash;
}; };
typedef struct {
Obj obj;
ObjFunction *function;
} ObjClosure;
ObjClosure *newClosure(ObjFunction *function);
ObjFunction *newFunction(); ObjFunction *newFunction();
ObjNative *newNative(NativeFn function); ObjNative *newNative(NativeFn function);
ObjString *takeString(char *chars, int length); ObjString *takeString(char *chars, int length);

View file

@ -30,7 +30,7 @@ static void runtimeError(const char *format, ...) {
for (int i = vm.frameCount; i >= 0; i--) { for (int i = vm.frameCount; i >= 0; i--) {
CallFrame *frame = &vm.frames[i]; CallFrame *frame = &vm.frames[i];
ObjFunction *function = frame->function; ObjFunction *function = frame->closure->function;
size_t instruction = frame->ip - function->chunk.code - 1; size_t instruction = frame->ip - function->chunk.code - 1;
fprintf(stderr, "[line %d] in ", function->chunk.lines[instruction]); fprintf(stderr, "[line %d] in ", function->chunk.lines[instruction]);
if (function->name == NULL) { if (function->name == NULL) {
@ -79,9 +79,9 @@ Value pop() {
static Value peek(int distance) { return vm.stackTop[-1 - distance]; } static Value peek(int distance) { return vm.stackTop[-1 - distance]; }
static bool call(ObjFunction *function, int argCount) { static bool call(ObjClosure *closure, int argCount) {
if (argCount != function->arity) { if (argCount != closure->function->arity) {
runtimeError("Expected %d argumetns but got %d.", function->arity, runtimeError("Expected %d arguments but got %d.", closure->function->arity,
argCount); argCount);
return false; return false;
} }
@ -92,8 +92,8 @@ static bool call(ObjFunction *function, int argCount) {
} }
CallFrame *frame = &vm.frames[vm.frameCount++]; CallFrame *frame = &vm.frames[vm.frameCount++];
frame->function = function; frame->closure = closure;
frame->ip = function->chunk.code; frame->ip = closure->function->chunk.code;
frame->slots = vm.stackTop - argCount - 1; frame->slots = vm.stackTop - argCount - 1;
return true; return true;
} }
@ -101,8 +101,8 @@ static bool call(ObjFunction *function, int argCount) {
static bool callValue(Value callee, int argCount) { static bool callValue(Value callee, int argCount) {
if (IS_OBJ(callee)) { if (IS_OBJ(callee)) {
switch (OBJ_TYPE(callee)) { switch (OBJ_TYPE(callee)) {
case OBJ_FUNCTION: case OBJ_CLOSURE:
return call(AS_FUNCTION(callee), argCount); return call(AS_CLOSURE(callee), argCount);
case OBJ_NATIVE: { case OBJ_NATIVE: {
NativeFn native = AS_NATIVE(callee); NativeFn native = AS_NATIVE(callee);
Value result = native(argCount, vm.stackTop - argCount); Value result = native(argCount, vm.stackTop - argCount);
@ -144,7 +144,8 @@ static InterpretResult run() {
#define READ_SHORT() \ #define READ_SHORT() \
(frame->ip += 2, (uint16_t)((frame->ip[-2] << 8) | frame->ip[-1])) (frame->ip += 2, (uint16_t)((frame->ip[-2] << 8) | frame->ip[-1]))
#define READ_CONSTANT() (frame->function->chunk.constants.values[READ_BYTE()]) #define READ_CONSTANT() \
(frame->closure->function->chunk.constants.values[READ_BYTE()])
#define READ_STRING() AS_STRING(READ_CONSTANT()) #define READ_STRING() AS_STRING(READ_CONSTANT())
#define BINARY_OP(valueType, op) \ #define BINARY_OP(valueType, op) \
do { \ do { \
@ -165,8 +166,9 @@ static InterpretResult run() {
printf(" ]"); printf(" ]");
} }
printf("\n"); printf("\n");
disassembleInstruction(&frame->function->chunk, disassembleInstruction(
(int)(frame->ip - frame->function->chunk.code)); &frame->closure->function->chunk,
(int)(frame->ip - frame->closure->function->chunk.code));
#endif #endif
uint8_t instruction; uint8_t instruction;
@ -296,6 +298,12 @@ static InterpretResult run() {
frame = &vm.frames[vm.frameCount - 1]; frame = &vm.frames[vm.frameCount - 1];
break; break;
} }
case OP_CLOSURE: {
ObjFunction *function = AS_FUNCTION(READ_CONSTANT());
ObjClosure *closure = newClosure(function);
push(OBJ_VAL(closure));
break;
}
case OP_RETURN: { case OP_RETURN: {
Value result = pop(); Value result = pop();
vm.frameCount--; vm.frameCount--;
@ -325,7 +333,10 @@ InterpretResult interpret(const char *source) {
return INTERPRET_COMPILE_ERROR; return INTERPRET_COMPILE_ERROR;
push(OBJ_VAL(function)); push(OBJ_VAL(function));
call(function, 0); ObjClosure *closure = newClosure(function);
pop();
push(OBJ_VAL(closure));
call(closure, 0);
return run(); return run();
} }

View file

@ -10,7 +10,7 @@
#define STACK_MAX (FRAMES_MAX * UINT8_COUNT) #define STACK_MAX (FRAMES_MAX * UINT8_COUNT)
typedef struct { typedef struct {
ObjFunction *function; ObjClosure *closure;
uint8_t *ip; uint8_t *ip;
Value *slots; Value *slots;
} CallFrame; } CallFrame;