| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147 |
- /**
- ******************************************************************************
- * @file : vm.c
- * @author : simon
- * @brief : Interpret the bytecode from chunk
- * @attention : None
- * @date : 2023/8/17
- ******************************************************************************
- */
- #include <stdarg.h>
- #include "common.h"
- #include "vm.h"
- #include "debug.h"
- #include "compiler.h"
- VM vm;
- /// \brief 重置栈
- static void resetStack() {
- vm.stackTop = vm.stack; // 指针指向栈底
- }
- static void runtimeError(const char *format, ...) {
- va_list args;
- va_start(args, format);
- vfprintf(stderr, format, args);
- va_end(args);
- fputs("\n", stderr);
- size_t instruction = vm.ip - vm.chunk->code - 1;
- int line = vm.chunk->lines[instruction];
- fprintf(stderr, "[line %d] in script\n", line);
- resetStack();
- }
- void initVM() {
- resetStack();
- }
- static Value peek(int distance) {
- return vm.stackTop[-1 - distance];
- }
- static InterpretResult run() {
- //! <macro> reads the byte currently pointed at by ip
- //! and then advances the instruction pointer
- #define READ_BYTE() (*vm.ip++)
- //! reads the next byte from the bytecode
- //! treats the resulting number as an index
- #define READ_CONSTANT() (vm.chunk->constants.values[READ_BYTE()])
- #define BINARY_OP(valueType, op) \
- do { \
- if (!IS_NUMBER(peek(0)) || !IS_NUMBER(peek(1))) { \
- runtimeError("Operands must be numbers."); \
- return INTERPRET_RUNTIME_ERROR; \
- } \
- double b = AS_NUMBER(pop()); \
- double a = AS_NUMBER(pop()); \
- push(valueType(a op b)); \
- } while(false)
- for (;;) {
- #ifdef DEBUG_TRACE_EXECUTION
- //! <Stack tracing> start
- printf("------------------------\n|");
- for (Value *slot = vm.stack; slot < vm.stackTop; slot++) {
- printf("[ ");
- printValue(*slot);
- printf(" ]");
- }
- printf("\n------------------------");
- printf("\n");
- //! <Stack tracing> end
- disassembleInstruction(vm.chunk, (int) (vm.ip - vm.chunk->code));
- #endif
- switch (READ_BYTE()) {
- case OP_CONSTANT: {
- Value constant = READ_CONSTANT();
- push(constant);
- break;
- }
- case OP_ADD:
- BINARY_OP(NUMBER_VAL, +);
- break;
- case OP_SUBTRACT:
- BINARY_OP(NUMBER_VAL, -);
- break;
- case OP_MULTIPLY:
- BINARY_OP(NUMBER_VAL, *);
- break;
- case OP_DIVIDE:
- BINARY_OP(NUMBER_VAL, /);
- break;
- case OP_NEGATE:
- if (!IS_NUMBER(peek(0))) {
- runtimeError("Operand must be a number.");
- return INTERPRET_RUNTIME_ERROR;
- }
- push(NUMBER_VAL(-AS_NUMBER(pop())));
- break;
- case OP_RETURN: {
- printValue(pop());
- printf("\n");
- return INTERPRET_OK;
- }
- }
- }
- #undef READ_BYTE
- #undef READ_CONSTANT
- #undef BINARY_OP
- }
- void freeVM() {
- }
- InterpretResult interpret(const char *source) {
- Chunk chunk;
- initChunk(&chunk);
- if (!compile(source, &chunk)) {
- freeChunk(&chunk);
- return INTERPRET_COMPILE_ERROR;
- }
- vm.chunk = &chunk;
- vm.ip = vm.chunk->code;
- InterpretResult result = run();
- freeChunk(&chunk);
- return result;
- }
- void push(Value value) {
- *vm.stackTop = value;
- vm.stackTop++;
- }
- Value pop() {
- vm.stackTop--;
- //! NOTE: 出栈后,里面的值没有清除
- return *vm.stackTop;
- }
|