Chapter 25.1
This commit is contained in:
parent
3da4016d57
commit
1ae50814d3
8 changed files with 56 additions and 14 deletions
|
@ -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;
|
||||||
|
|
||||||
|
|
|
@ -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() {
|
||||||
|
|
|
@ -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:
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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();
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
|
Loading…
Reference in a new issue