diff --git a/include/chunk.h b/include/chunk.h index ad65318..3701bdd 100644 --- a/include/chunk.h +++ b/include/chunk.h @@ -7,6 +7,11 @@ typedef enum { OP_CONSTANT_LONG, OP_CONSTANT, + OP_ADD, + OP_SUBTRACT, + OP_MULTIPLY, + OP_DIVIDE, + OP_NEGATE, OP_RETURN, OP_COUNT, }OpCode; diff --git a/include/common.h b/include/common.h index 5f15404..1a35aaa 100644 --- a/include/common.h +++ b/include/common.h @@ -4,5 +4,6 @@ #include #include #include +#define DEBUG_TRACE_EXECUTION #endif diff --git a/include/vm.h b/include/vm.h index 264b216..784356b 100644 --- a/include/vm.h +++ b/include/vm.h @@ -2,13 +2,29 @@ #define VM_INLCUDED #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, + INTERPRET_RESULT_COUNT, +} InterpretResult; + void initVM(void); void freeVM(void); +InterpretResult interpret(Chunk *chunk); +void push(Value value); +Value pop(); + #endif diff --git a/src/debug.c b/src/debug.c index fae8016..6105770 100644 --- a/src/debug.c +++ b/src/debug.c @@ -43,10 +43,19 @@ int disassembleInstruction(Chunk *chunk, int offset){ switch(instruction){ case OP_CONSTANT: return constantInstruction("OP_CONSTANT", chunk,offset); - case OP_CONSTANT_LONG: return longConstantInstruction("OP_CONSTANT_LONG", 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/src/vm.c b/src/vm.c index 4ccdfe8..14fa041 100644 --- a/src/vm.c +++ b/src/vm.c @@ -1,11 +1,75 @@ #include "../include/common.h" #include "../include/vm.h" +#include "../include/debug.h" +#include - +VM vm; +static void resetStack(void){ + vm.stackTop = vm.stack; +} void initVM(void){ - + resetStack(); } void freeVM(void){ } +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(;;){ +#ifndef 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(); + push(constant); + 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_NEGATE: push(-pop()); break; + case OP_RETURN: { + printValue(pop()); + printf("\n"); + return INTERPRET_OK; + } + } + } +#undef BINARY_OP +#undef READ_CONSTANT +#undef READ_BYTE +} + +InterpretResult interpret(Chunk *chunk){ + vm.chunk = chunk; + vm.ip = vm.chunk->code; + return run(); +} diff --git a/tests/01_main.c b/tests/01_main.c index ac83ce9..0b9e3a5 100644 --- a/tests/01_main.c +++ b/tests/01_main.c @@ -9,12 +9,23 @@ int main(void){ Chunk chunk; initChunk(&chunk); - int constant = addConstant(&chunk,1.2); - writeChunk(&chunk, OP_CONSTANT,10); - writeChunk(&chunk,constant,10); - // writeChunk(&chunk, OP_RETURN,10); + int constant = addConstant(&chunk,1.25); + writeChunk(&chunk, OP_CONSTANT,1); + writeChunk(&chunk,constant,1); + + + + constant = addConstant(&chunk,10); + writeChunk(&chunk, OP_CONSTANT,2); + writeChunk(&chunk,constant,2); + + + writeChunk(&chunk, OP_DIVIDE, 3); + writeChunk(&chunk, OP_RETURN,5); disassembleChunk(&chunk,"Test Chunk"); + int res = interpret(&chunk); + (void) res; freeVM(); freeChunk(&chunk);