From 50f77b702816502a2c19c279b98fad0d8193bfcf Mon Sep 17 00:00:00 2001 From: Adnan Ioricce Date: Fri, 11 Oct 2024 13:13:21 -0300 Subject: [PATCH] [Chapter15&VM] - adding a vm to run the instructions --- clox/chunk.h | 5 ++++ clox/common.h | 2 ++ clox/debug.c | 10 +++++++ clox/main.c | 16 +++++++++++ clox/vm.c | 76 +++++++++++++++++++++++++++++++++++++++++++++++++++ clox/vm.h | 27 ++++++++++++++++++ 6 files changed, 136 insertions(+) create mode 100644 clox/vm.c create mode 100644 clox/vm.h diff --git a/clox/chunk.h b/clox/chunk.h index 466898b..2b3798f 100644 --- a/clox/chunk.h +++ b/clox/chunk.h @@ -7,6 +7,11 @@ typedef enum { OP_CONSTANT, OP_RETURN, + OP_NEGATE, + OP_ADD, + OP_SUBTRACT, + OP_MULTIPLY, + OP_DIVIDE, } OpCode; typedef struct { diff --git a/clox/common.h b/clox/common.h index c827b76..ddab699 100644 --- a/clox/common.h +++ b/clox/common.h @@ -5,4 +5,6 @@ #include #include +#define DEBUG_TRACE_EXECUTION + #endif diff --git a/clox/debug.c b/clox/debug.c index eb86d7b..8f7af21 100644 --- a/clox/debug.c +++ b/clox/debug.c @@ -36,6 +36,16 @@ int disassembleInstruction(Chunk* chunk, int offset) { switch (instruction) { case OP_CONSTANT: return constantInstruction("OP_CONSTANT", chunk, offset); + case OP_ADD: + return simpleInstruction("OP_ADD", offset); + case OP_SUBTRACT: + return simpleInstruction("OP_SUBTRACT", offset); + case OP_MULTIPLY: + return simpleInstruction("OP_MULTIPLY", offset); + case OP_DIVIDE: + return simpleInstruction("OP_DIVIDE", offset); + case OP_NEGATE: + return simpleInstruction("OP_NEGATE", offset); case OP_RETURN: return simpleInstruction("OP_RETURN", offset); default: diff --git a/clox/main.c b/clox/main.c index 804bc90..99958b0 100644 --- a/clox/main.c +++ b/clox/main.c @@ -1,15 +1,31 @@ #include "common.h" #include "chunk.h" #include "debug.h" +#include "vm.h" int main(int argc,const char* argv[]){ + initVM(); Chunk chunk; initChunk(&chunk); int constant = addConstant(&chunk, 1.2); writeChunk(&chunk, OP_CONSTANT, 123); writeChunk(&chunk, constant, 123); + constant = addConstant(&chunk, 3.4); + writeChunk(&chunk, OP_CONSTANT, 123); + writeChunk(&chunk, constant, 123); + + writeChunk(&chunk, OP_ADD, 123); + + constant = addConstant(&chunk, 5.6); + writeChunk(&chunk, OP_CONSTANT, 123); + writeChunk(&chunk, constant, 123); + + writeChunk(&chunk, OP_DIVIDE, 123); + writeChunk(&chunk, OP_NEGATE, 123); writeChunk(&chunk, OP_RETURN, 123); disassembleChunk(&chunk, "test chunk"); + interpret(&chunk); + freeVM(); freeChunk(&chunk); return 0; } diff --git a/clox/vm.c b/clox/vm.c new file mode 100644 index 0000000..4dcf6ae --- /dev/null +++ b/clox/vm.c @@ -0,0 +1,76 @@ +#include +#include "common.h" +#include "vm.h" +#include "debug.h" +VM vm; +static void resetStack() { + vm.stackTop = vm.stack; +} +void initVM() { + resetStack(); +} + +void freeVM() { + +} +void push(Value value) { + *vm.stackTop = value; + vm.stackTop++; +} +Value pop() { + vm.stackTop--; + return *vm.stackTop; +} + +static InterpretResult run() { +#define READ_BYTE() (*vm.ip++) +#define READ_CONSTANT() (vm.chunk->constants.values[READ_BYTE()]) +#define BINARY_OP(op) \ + do { \ + double b = pop(); \ + double a = pop(); \ + push(a op b); \ + } while (false) + for (;;) { +#ifdef DEBUG_TRACE_EXECUTION + printf(" "); + for (Value* slot = vm.stack; slot < vm.stackTop; slot++) { + printf("[ "); + printValue(*slot); + printf(" ]"); + } + printf("\n"); + disassembleInstruction(vm.chunk, + (int)(vm.ip - vm.chunk->code)); +#endif + uint8_t instruction; + switch (instruction = READ_BYTE()) { + case OP_CONSTANT: { + Value constant = READ_CONSTANT(); + printValue(constant); + printf("\n"); + push(constant); + break; + } + case OP_NEGATE: push(-pop()); break; + case OP_ADD: BINARY_OP(+); break; + case OP_SUBTRACT: BINARY_OP(-); break; + case OP_MULTIPLY: BINARY_OP(*); break; + case OP_DIVIDE: BINARY_OP(/); break; + case OP_RETURN: { + printValue(pop()); + printf("\n"); + return INTERPRET_OK; + } + } + } +#undef READ_CONSTANT +#undef BINARY_OP +#undef READ_BYTE +} +InterpretResult interpret(Chunk* chunk) { + vm.chunk = chunk; + vm.ip = vm.chunk->code; + return run(); +} + diff --git a/clox/vm.h b/clox/vm.h new file mode 100644 index 0000000..0df1cee --- /dev/null +++ b/clox/vm.h @@ -0,0 +1,27 @@ +#ifndef clox_vm_h +#define clox_vm_h + +#include "chunk.h" +#include "value.h" + +#define STACK_MAX 256 + +typedef struct { + Chunk* chunk; + uint8_t* ip; + Value stack[STACK_MAX]; + Value* stackTop; +} VM; +typedef enum { + INTERPRET_OK, + INTERPRET_COMPILE_ERROR, + INTERPRET_RUNTIME_ERROR +} InterpretResult; + +void initVM(); +void freeVM(); +InterpretResult interpret(Chunk* chunk); +void push(Value value); +Value pop(); + +#endif