vm.c 8.5 KB

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