vm.c 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201
  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 "vm.h"
  11. #include "common.h"
  12. #include "compiler.h"
  13. #include "debug.h"
  14. #include "memory.h"
  15. #include <stdarg.h>
  16. VM vm;
  17. /// \brief 重置栈
  18. static void resetStack() {
  19. vm.stackTop = vm.stack;// 指针指向栈底
  20. }
  21. static void runtimeError(const char *format, ...) {
  22. va_list args;
  23. va_start(args, format);
  24. vfprintf(stderr, format, args);
  25. va_end(args);
  26. fputs("\n", stderr);
  27. size_t instruction = vm.ip - vm.chunk->code - 1;
  28. int line = vm.chunk->lines[instruction];
  29. fprintf(stderr, "[line %d] in script\n", line);
  30. resetStack();
  31. }
  32. void initVM() {
  33. resetStack();
  34. vm.objects = NULL;
  35. initTable(&vm.strings);
  36. }
  37. static Value peek(int distance) {
  38. return vm.stackTop[-1 - distance];
  39. }
  40. static bool isFalse(Value value) {
  41. // the nil and false will return true
  42. return IS_NIL(value) || (IS_BOOL(value) && !AS_BOOL(value));
  43. }
  44. static void concatenate() {
  45. ObjString *b = AS_STRING(pop());
  46. ObjString *a = AS_STRING(pop());
  47. int length = a->length + b->length;
  48. char *chars = ALLOCATE(char, length + 1);
  49. memcpy(chars, a->chars, a->length);
  50. memcpy(chars + a->length, b->chars, b->length);
  51. chars[length] = '\0';
  52. ObjString *result = takeString(chars, length);
  53. push(OBJ_VAL(result));
  54. }
  55. static InterpretResult run() {
  56. //! <macro> reads the byte currently pointed at by ip
  57. //! and then advances the instruction pointer
  58. #define READ_BYTE() (*vm.ip++)
  59. //! reads the next byte from the bytecode
  60. //! treats the resulting number as an index
  61. #define READ_CONSTANT() (vm.chunk->constants.values[READ_BYTE()])
  62. #define BINARY_OP(valueType, op) \
  63. do { \
  64. if (!IS_NUMBER(peek(0)) || !IS_NUMBER(peek(1))) { \
  65. runtimeError("Operands must be numbers."); \
  66. return INTERPRET_RUNTIME_ERROR; \
  67. } \
  68. double b = AS_NUMBER(pop()); \
  69. double a = AS_NUMBER(pop()); \
  70. push(valueType(a op b)); \
  71. } while (false)
  72. for (;;) {
  73. #ifdef DEBUG_TRACE_EXECUTION
  74. //! <Stack tracing> start
  75. printf("------------------------\n|");
  76. for (Value *slot = vm.stack; slot < vm.stackTop; slot++) {
  77. printf("[ ");
  78. printValue(*slot);
  79. printf(" ]");
  80. }
  81. printf("\n------------------------");
  82. printf("\n");
  83. //! <Stack tracing> end
  84. disassembleInstruction(vm.chunk, (int) (vm.ip - vm.chunk->code));
  85. #endif
  86. switch (READ_BYTE()) {
  87. case OP_CONSTANT: {
  88. Value constant = READ_CONSTANT();
  89. push(constant);
  90. break;
  91. }
  92. case OP_NIL:
  93. push(NIL_VAL);
  94. break;
  95. case OP_TRUE:
  96. push(BOOL_VAL(true));
  97. break;
  98. case OP_FALSE:
  99. push(BOOL_VAL(false));
  100. break;
  101. case OP_ADD: {
  102. if (IS_STRING(peek(0)) && IS_STRING(peek(1))) {
  103. // 字串拼接
  104. concatenate();
  105. } else if (IS_NUMBER(peek(0)) && IS_NUMBER(peek(1))) {
  106. double b = AS_NUMBER(pop());
  107. double a = AS_NUMBER(pop());
  108. push(NUMBER_VAL(a + b));
  109. } else {
  110. runtimeError("Operands must be two numbers or two strings.");
  111. return INTERPRET_RUNTIME_ERROR;
  112. }
  113. break;
  114. }
  115. case OP_SUBTRACT:
  116. BINARY_OP(NUMBER_VAL, -);
  117. break;
  118. case OP_MULTIPLY:
  119. BINARY_OP(NUMBER_VAL, *);
  120. break;
  121. case OP_DIVIDE:
  122. BINARY_OP(NUMBER_VAL, /);
  123. break;
  124. case OP_NOT:
  125. push(BOOL_VAL(isFalse(pop())));
  126. break;
  127. case OP_NEGATE:
  128. if (!IS_NUMBER(peek(0))) {
  129. runtimeError("Operand must be a number.");
  130. return INTERPRET_RUNTIME_ERROR;
  131. }
  132. push(NUMBER_VAL(-AS_NUMBER(pop())));
  133. break;
  134. case OP_EQUAL: {
  135. Value b = pop();
  136. Value a = pop();
  137. push(BOOL_VAL(valuesEqual(a, b)));
  138. break;
  139. }
  140. case OP_GREATER:
  141. BINARY_OP(BOOL_VAL, >);
  142. break;
  143. case OP_LESS:
  144. BINARY_OP(BOOL_VAL, <);
  145. break;
  146. case OP_RETURN: {
  147. printValue(pop());
  148. printf("\n");
  149. return INTERPRET_OK;
  150. }
  151. }
  152. }
  153. #undef READ_BYTE
  154. #undef READ_CONSTANT
  155. #undef BINARY_OP
  156. }
  157. void freeVM() {
  158. freeTable(&vm.strings);
  159. freeObjects();
  160. }
  161. InterpretResult interpret(const char *source) {
  162. Chunk chunk;
  163. initChunk(&chunk);
  164. if (!compile(source, &chunk)) {
  165. freeChunk(&chunk);
  166. return INTERPRET_COMPILE_ERROR;
  167. }
  168. vm.chunk = &chunk;
  169. vm.ip = vm.chunk->code;
  170. InterpretResult result = run();
  171. freeChunk(&chunk);
  172. return result;
  173. }
  174. void push(Value value) {
  175. *vm.stackTop = value;
  176. vm.stackTop++;
  177. }
  178. Value pop() {
  179. vm.stackTop--;
  180. //! NOTE: 出栈后,里面的值没有清除
  181. return *vm.stackTop;
  182. }