vm.c 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147
  1. /**
  2. ******************************************************************************
  3. * @file : vm.c
  4. * @author : simon
  5. * @brief : Interpret the bytecode from chunk
  6. * @attention : None
  7. * @date : 2023/8/17
  8. ******************************************************************************
  9. */
  10. #include <stdarg.h>
  11. #include "common.h"
  12. #include "vm.h"
  13. #include "debug.h"
  14. #include "compiler.h"
  15. VM vm;
  16. /// \brief 重置栈
  17. static void resetStack() {
  18. vm.stackTop = vm.stack; // 指针指向栈底
  19. }
  20. static void runtimeError(const char *format, ...) {
  21. va_list args;
  22. va_start(args, format);
  23. vfprintf(stderr, format, args);
  24. va_end(args);
  25. fputs("\n", stderr);
  26. size_t instruction = vm.ip - vm.chunk->code - 1;
  27. int line = vm.chunk->lines[instruction];
  28. fprintf(stderr, "[line %d] in script\n", line);
  29. resetStack();
  30. }
  31. void initVM() {
  32. resetStack();
  33. }
  34. static Value peek(int distance) {
  35. return vm.stackTop[-1 - distance];
  36. }
  37. static InterpretResult run() {
  38. //! <macro> reads the byte currently pointed at by ip
  39. //! and then advances the instruction pointer
  40. #define READ_BYTE() (*vm.ip++)
  41. //! reads the next byte from the bytecode
  42. //! treats the resulting number as an index
  43. #define READ_CONSTANT() (vm.chunk->constants.values[READ_BYTE()])
  44. #define BINARY_OP(valueType, op) \
  45. do { \
  46. if (!IS_NUMBER(peek(0)) || !IS_NUMBER(peek(1))) { \
  47. runtimeError("Operands must be numbers."); \
  48. return INTERPRET_RUNTIME_ERROR; \
  49. } \
  50. double b = AS_NUMBER(pop()); \
  51. double a = AS_NUMBER(pop()); \
  52. push(valueType(a op b)); \
  53. } while(false)
  54. for (;;) {
  55. #ifdef DEBUG_TRACE_EXECUTION
  56. //! <Stack tracing> start
  57. printf("------------------------\n|");
  58. for (Value *slot = vm.stack; slot < vm.stackTop; slot++) {
  59. printf("[ ");
  60. printValue(*slot);
  61. printf(" ]");
  62. }
  63. printf("\n------------------------");
  64. printf("\n");
  65. //! <Stack tracing> end
  66. disassembleInstruction(vm.chunk, (int) (vm.ip - vm.chunk->code));
  67. #endif
  68. switch (READ_BYTE()) {
  69. case OP_CONSTANT: {
  70. Value constant = READ_CONSTANT();
  71. push(constant);
  72. break;
  73. }
  74. case OP_ADD:
  75. BINARY_OP(NUMBER_VAL, +);
  76. break;
  77. case OP_SUBTRACT:
  78. BINARY_OP(NUMBER_VAL, -);
  79. break;
  80. case OP_MULTIPLY:
  81. BINARY_OP(NUMBER_VAL, *);
  82. break;
  83. case OP_DIVIDE:
  84. BINARY_OP(NUMBER_VAL, /);
  85. break;
  86. case OP_NEGATE:
  87. if (!IS_NUMBER(peek(0))) {
  88. runtimeError("Operand must be a number.");
  89. return INTERPRET_RUNTIME_ERROR;
  90. }
  91. push(NUMBER_VAL(-AS_NUMBER(pop())));
  92. break;
  93. case OP_RETURN: {
  94. printValue(pop());
  95. printf("\n");
  96. return INTERPRET_OK;
  97. }
  98. }
  99. }
  100. #undef READ_BYTE
  101. #undef READ_CONSTANT
  102. #undef BINARY_OP
  103. }
  104. void freeVM() {
  105. }
  106. InterpretResult interpret(const char *source) {
  107. Chunk chunk;
  108. initChunk(&chunk);
  109. if (!compile(source, &chunk)) {
  110. freeChunk(&chunk);
  111. return INTERPRET_COMPILE_ERROR;
  112. }
  113. vm.chunk = &chunk;
  114. vm.ip = vm.chunk->code;
  115. InterpretResult result = run();
  116. freeChunk(&chunk);
  117. return result;
  118. }
  119. void push(Value value) {
  120. *vm.stackTop = value;
  121. vm.stackTop++;
  122. }
  123. Value pop() {
  124. vm.stackTop--;
  125. //! NOTE: 出栈后,里面的值没有清除
  126. return *vm.stackTop;
  127. }