vm.c 5.0 KB

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