vm.c 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271
  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. vm.frameCount = 0;
  21. }
  22. static void runtimeError(const char *format, ...) {
  23. va_list args;
  24. va_start(args, format);
  25. vfprintf(stderr, format, args);
  26. va_end(args);
  27. fputs("\n", stderr);
  28. CallFrame *frame = &vm.frames[vm.frameCount - 1];
  29. size_t instruction = frame->ip - frame->function->chunk.code - 1;
  30. int line = frame->function->chunk.lines[instruction];
  31. fprintf(stderr, "[line %d] in script\n", line);
  32. resetStack();
  33. }
  34. void initVM() {
  35. resetStack();
  36. vm.objects = NULL;
  37. initTable(&vm.globals);
  38. initTable(&vm.strings);
  39. }
  40. static Value peek(int distance) {
  41. return vm.stackTop[-1 - distance];
  42. }
  43. static bool isFalse(Value value) {
  44. // the nil and false will return true
  45. return IS_NIL(value) || (IS_BOOL(value) && !AS_BOOL(value));
  46. }
  47. static void concatenate() {
  48. ObjString *b = AS_STRING(pop());
  49. ObjString *a = AS_STRING(pop());
  50. int length = a->length + b->length;
  51. char *chars = ALLOCATE(char, length + 1);
  52. memcpy(chars, a->chars, a->length);
  53. memcpy(chars + a->length, b->chars, b->length);
  54. chars[length] = '\0';
  55. ObjString *result = takeString(chars, length);
  56. push(OBJ_VAL(result));
  57. }
  58. static InterpretResult run() {
  59. CallFrame *frame = &vm.frames[vm.frameCount - 1];
  60. //! <macro> reads the byte currently pointed at by ip
  61. //! and then advances the instruction pointer
  62. #define READ_BYTE() (*frame->ip++)
  63. //! reads the next byte from the bytecode
  64. //! treats the resulting number as an index
  65. #define READ_CONSTANT() (frame->function->chunk.constants.values[READ_BYTE()])
  66. #define READ_SHORT() \
  67. (frame->ip += 2, (uint16_t) ((frame->ip[-2] << 8) | frame->ip[-1]))
  68. #define READ_STRING() AS_STRING(READ_CONSTANT())
  69. #define BINARY_OP(valueType, op) \
  70. do { \
  71. if (!IS_NUMBER(peek(0)) || !IS_NUMBER(peek(1))) { \
  72. runtimeError("Operands must be numbers."); \
  73. return INTERPRET_RUNTIME_ERROR; \
  74. } \
  75. double b = AS_NUMBER(pop()); \
  76. double a = AS_NUMBER(pop()); \
  77. push(valueType(a op b)); \
  78. } while (false)
  79. #ifdef DEBUG_TRACE_EXECUTION
  80. printf("!!! <Stack tracing> start\n");
  81. #endif
  82. for (;;) {
  83. #ifdef DEBUG_TRACE_EXECUTION
  84. //! <Stack tracing> start
  85. printf("------------------------\n|");
  86. for (Value *slot = vm.stack; slot < vm.stackTop; slot++) {
  87. printf("[ ");
  88. printValue(*slot);
  89. printf(" ]");
  90. }
  91. printf("\n------------------------");
  92. printf("\n");
  93. //! <Stack tracing> end
  94. disassembleInstruction(&frame->function->chunk, (int) (frame->ip - frame->function->chunk.code));
  95. #endif
  96. switch (READ_BYTE()) {
  97. case OP_CONSTANT: {
  98. Value constant = READ_CONSTANT();
  99. push(constant);
  100. break;
  101. }
  102. case OP_NIL:
  103. push(NIL_VAL);
  104. break;
  105. case OP_TRUE:
  106. push(BOOL_VAL(true));
  107. break;
  108. case OP_FALSE:
  109. push(BOOL_VAL(false));
  110. break;
  111. case OP_POP:
  112. pop();
  113. break;
  114. case OP_DEFINE_GLOBAL: {
  115. ObjString *name = READ_STRING();
  116. tableSet(&vm.globals, name, peek(0));
  117. pop();
  118. break;
  119. }
  120. case OP_GET_GLOBAL: {
  121. ObjString *name = READ_STRING();
  122. Value value;
  123. if (!tableGet(&vm.globals, name, &value)) {
  124. runtimeError("Undefined variable '%s'.", name->chars);
  125. return INTERPRET_RUNTIME_ERROR;
  126. }
  127. push(value);
  128. break;
  129. }
  130. case OP_SET_GLOBAL: {
  131. ObjString *name = READ_STRING();
  132. if (tableSet(&vm.globals, name, peek(0))) {
  133. tableDelete(&vm.globals, name);
  134. runtimeError("Undefined variable '%s'.", name->chars);
  135. return INTERPRET_RUNTIME_ERROR;
  136. }
  137. break;
  138. }
  139. case OP_GET_LOCAL: {
  140. uint8_t slot = READ_BYTE();
  141. push(frame->slots[slot]);
  142. break;
  143. }
  144. case OP_SET_LOCAL: {
  145. uint8_t slot = READ_BYTE();
  146. frame->slots[slot] = peek(0);
  147. break;
  148. }
  149. case OP_ADD: {
  150. if (IS_STRING(peek(0)) && IS_STRING(peek(1))) {
  151. // 字串拼接
  152. concatenate();
  153. } else if (IS_NUMBER(peek(0)) && IS_NUMBER(peek(1))) {
  154. double b = AS_NUMBER(pop());
  155. double a = AS_NUMBER(pop());
  156. push(NUMBER_VAL(a + b));
  157. } else {
  158. runtimeError("Operands must be two numbers or two strings.");
  159. return INTERPRET_RUNTIME_ERROR;
  160. }
  161. break;
  162. }
  163. case OP_SUBTRACT:
  164. BINARY_OP(NUMBER_VAL, -);
  165. break;
  166. case OP_MULTIPLY:
  167. BINARY_OP(NUMBER_VAL, *);
  168. break;
  169. case OP_DIVIDE:
  170. BINARY_OP(NUMBER_VAL, /);
  171. break;
  172. case OP_NOT:
  173. push(BOOL_VAL(isFalse(pop())));
  174. break;
  175. case OP_NEGATE:
  176. if (!IS_NUMBER(peek(0))) {
  177. runtimeError("Operand must be a number.");
  178. return INTERPRET_RUNTIME_ERROR;
  179. }
  180. push(NUMBER_VAL(-AS_NUMBER(pop())));
  181. break;
  182. case OP_EQUAL: {
  183. Value b = pop();
  184. Value a = pop();
  185. push(BOOL_VAL(valuesEqual(a, b)));
  186. break;
  187. }
  188. case OP_GREATER:
  189. BINARY_OP(BOOL_VAL, >);
  190. break;
  191. case OP_LESS:
  192. BINARY_OP(BOOL_VAL, <);
  193. break;
  194. case OP_PRINT: {
  195. printValue(pop());
  196. printf("\n");
  197. break;
  198. }
  199. case OP_JUMP_IF_FALSE: {
  200. uint16_t offset = READ_SHORT();
  201. if (isFalse(peek(0))) frame->ip += offset;
  202. break;
  203. }
  204. case OP_JUMP: {
  205. uint16_t offset = READ_SHORT();
  206. frame->ip += offset;
  207. break;
  208. }
  209. case OP_LOOP: {
  210. uint16_t offset = READ_SHORT();
  211. frame->ip -= offset;
  212. break;
  213. }
  214. case OP_RETURN: {
  215. // Exit interpreter.
  216. return INTERPRET_OK;
  217. }
  218. }
  219. #ifdef DEBUG_TRACE_EXECUTION
  220. printf("!!! <Stack tracing> end\n");
  221. #endif
  222. }
  223. #undef READ_BYTE
  224. #undef READ_CONSTANT
  225. #undef READ_SHORT
  226. #undef READ_STRING
  227. #undef BINARY_OP
  228. }
  229. void freeVM() {
  230. freeTable(&vm.globals);
  231. freeTable(&vm.strings);
  232. freeObjects();
  233. }
  234. InterpretResult interpret(const char *source) {
  235. ObjFunction *function = compile(source);
  236. if (function == NULL) return INTERPRET_COMPILE_ERROR;
  237. push(OBJ_VAL(function));
  238. CallFrame *frame = &vm.frames[vm.frameCount++];
  239. frame->function = function;
  240. frame->ip = function->chunk.code;
  241. frame->slots = vm.stack;
  242. return run();
  243. }
  244. void push(Value value) {
  245. *vm.stackTop = value;
  246. vm.stackTop++;
  247. }
  248. Value pop() {
  249. vm.stackTop--;
  250. //! NOTE: 出栈后,里面的值没有清除
  251. return *vm.stackTop;
  252. }