vm.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425
  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. #include <time.h>
  17. VM vm;
  18. /// \brief 重置栈
  19. static void resetStack() {
  20. vm.stackTop = vm.stack;// 指针指向栈底
  21. vm.frameCount = 0;
  22. vm.openUpvalues = NULL;
  23. }
  24. static void runtimeError(const char *format, ...) {
  25. va_list args;
  26. va_start(args, format);
  27. vfprintf(stderr, format, args);
  28. va_end(args);
  29. fputs("\n", stderr);
  30. for (int i = vm.frameCount - 1; i >= 0; i--) {
  31. CallFrame *frame = &vm.frames[i];
  32. ObjFunction *function = frame->closure->function;
  33. size_t instruction = frame->ip - function->chunk.code - 1;
  34. int line = function->chunk.lines[instruction];
  35. fprintf(stderr, "[line %d] in ", line);
  36. if (function->name == NULL) {
  37. fprintf(stderr, "script\n");
  38. } else {
  39. fprintf(stderr, "%s()\n", function->name->chars);
  40. }
  41. }
  42. resetStack();
  43. }
  44. static void defineNative(const char *name, NativeFn function) {
  45. push(OBJ_VAL(copyString(name, (int) strlen(name))));
  46. push(OBJ_VAL(newNative(function)));
  47. tableSet(&vm.globals, AS_STRING(vm.stack[0]), vm.stack[1]);
  48. pop();
  49. pop();
  50. }
  51. static Value clockNative(int argCount, Value *args) {
  52. return NUMBER_VAL((double) clock() / CLOCKS_PER_SEC);
  53. }
  54. void initVM() {
  55. resetStack();
  56. vm.objects = NULL;
  57. initTable(&vm.globals);
  58. initTable(&vm.strings);
  59. /// Native Function define.
  60. defineNative("clock", clockNative);
  61. }
  62. static Value peek(int distance) {
  63. return vm.stackTop[-1 - distance];
  64. }
  65. static bool call(ObjClosure *closure, int argCount) {
  66. if (argCount != closure->function->arity) {
  67. runtimeError("Expected %d arguments but got %d", closure->function->arity, argCount);
  68. return false;
  69. }
  70. if (vm.frameCount == FRAMES_MAX) {
  71. runtimeError("Stack overflow.");
  72. return false;
  73. }
  74. CallFrame *frame = &vm.frames[vm.frameCount++];
  75. frame->closure = closure;
  76. frame->ip = closure->function->chunk.code;
  77. frame->slots = vm.stackTop - argCount - 1;
  78. return true;
  79. }
  80. static bool callValue(Value callee, int argCount) {
  81. if (IS_OBJ(callee)) {
  82. switch (OBJ_TYPE(callee)) {
  83. case OBJ_CLOSURE:
  84. return call(AS_CLOSURE(callee), argCount);
  85. case OBJ_NATIVE: {
  86. NativeFn fn = AS_NATIVE(callee);
  87. Value result = fn(argCount, vm.stackTop - argCount);
  88. vm.stackTop -= argCount + 1;
  89. push(result);
  90. return true;
  91. }
  92. default:
  93. break;// Non-callable object type.
  94. }
  95. }
  96. runtimeError("Can only call functions and classes.");
  97. return false;
  98. }
  99. static bool isFalse(Value value) {
  100. // the nil and false will return true
  101. return IS_NIL(value) || (IS_BOOL(value) && !AS_BOOL(value));
  102. }
  103. static void concatenate() {
  104. ObjString *b = AS_STRING(pop());
  105. ObjString *a = AS_STRING(pop());
  106. int length = a->length + b->length;
  107. char *chars = ALLOCATE(char, length + 1);
  108. memcpy(chars, a->chars, a->length);
  109. memcpy(chars + a->length, b->chars, b->length);
  110. chars[length] = '\0';
  111. ObjString *result = takeString(chars, length);
  112. push(OBJ_VAL(result));
  113. }
  114. static ObjUpvalue *captureUpvalue(Value *local) {
  115. ObjUpvalue *preUpvalue = NULL;
  116. ObjUpvalue *upvalue = vm.openUpvalues;
  117. while (upvalue != NULL && upvalue->location > local) {
  118. preUpvalue = upvalue;
  119. upvalue = upvalue->next;
  120. }
  121. if (upvalue != NULL && upvalue->location == local) {
  122. return upvalue;
  123. }
  124. ObjUpvalue *createdUpvalue = newUpvalue(local);
  125. if (preUpvalue == NULL) {
  126. vm.openUpvalues = createdUpvalue;
  127. } else {
  128. preUpvalue->next = createdUpvalue;
  129. }
  130. return createdUpvalue;
  131. }
  132. static void closeUpvalues(Value *last) {
  133. while (vm.openUpvalues != NULL && vm.openUpvalues->location >= last) {
  134. ObjUpvalue *upvalue = vm.openUpvalues;
  135. upvalue->closed = *upvalue->location;
  136. upvalue->location = &upvalue->closed;
  137. vm.openUpvalues = upvalue->next;
  138. }
  139. }
  140. /// VM run function - exec opcode
  141. /// \return
  142. static InterpretResult run() {
  143. CallFrame *frame = &vm.frames[vm.frameCount - 1];
  144. //! <macro> reads the byte currently pointed at by ip
  145. //! and then advances the instruction pointer
  146. #define READ_BYTE() (*frame->ip++)
  147. //! reads the next byte from the bytecode
  148. //! treats the resulting number as an index
  149. #define READ_CONSTANT() \
  150. (frame->closure->function->chunk.constants.values[READ_BYTE()])
  151. #define READ_SHORT() \
  152. (frame->ip += 2, (uint16_t) ((frame->ip[-2] << 8) | frame->ip[-1]))
  153. #define READ_STRING() AS_STRING(READ_CONSTANT())
  154. #define BINARY_OP(valueType, op) \
  155. do { \
  156. if (!IS_NUMBER(peek(0)) || !IS_NUMBER(peek(1))) { \
  157. runtimeError("Operands must be numbers."); \
  158. return INTERPRET_RUNTIME_ERROR; \
  159. } \
  160. double b = AS_NUMBER(pop()); \
  161. double a = AS_NUMBER(pop()); \
  162. push(valueType(a op b)); \
  163. } while (false)
  164. for (;;) {
  165. #ifdef DEBUG_TRACE_EXECUTION
  166. #ifdef DEBUG_STACK_INFO
  167. //! <Stack tracing> start
  168. printf("\n!!! <Stack tracing now>:\n");
  169. printf("------------------------\n|");
  170. for (Value *slot = vm.stack; slot < vm.stackTop; slot++) {
  171. printf("[ ");
  172. printValue(*slot);
  173. printf(" ]");
  174. }
  175. printf("\n------------------------");
  176. printf("\n");
  177. printf("\n");
  178. //! <Stack tracing> end
  179. #endif
  180. printf("The Instruction: \n");
  181. disassembleInstruction(&frame->closure->function->chunk, (int) (frame->ip - frame->closure->function->chunk.code));
  182. #endif
  183. uint8_t opCode = READ_BYTE();
  184. switch (opCode) {
  185. case OP_CONSTANT: {
  186. Value constant = READ_CONSTANT();
  187. push(constant);
  188. break;
  189. }
  190. case OP_NIL:
  191. push(NIL_VAL);
  192. break;
  193. case OP_TRUE:
  194. push(BOOL_VAL(true));
  195. break;
  196. case OP_FALSE:
  197. push(BOOL_VAL(false));
  198. break;
  199. case OP_POP:
  200. pop();
  201. break;
  202. case OP_DEFINE_GLOBAL: {
  203. ObjString *name = READ_STRING();
  204. tableSet(&vm.globals, name, peek(0));
  205. pop();
  206. break;
  207. }
  208. case OP_GET_GLOBAL: {
  209. ObjString *name = READ_STRING();
  210. Value value;
  211. if (!tableGet(&vm.globals, name, &value)) {
  212. runtimeError("Undefined variable '%s'.", name->chars);
  213. return INTERPRET_RUNTIME_ERROR;
  214. }
  215. push(value);
  216. break;
  217. }
  218. case OP_SET_GLOBAL: {
  219. ObjString *name = READ_STRING();
  220. if (tableSet(&vm.globals, name, peek(0))) {
  221. tableDelete(&vm.globals, name);
  222. runtimeError("Undefined variable '%s'.", name->chars);
  223. return INTERPRET_RUNTIME_ERROR;
  224. }
  225. break;
  226. }
  227. case OP_GET_LOCAL: {
  228. uint8_t slot = READ_BYTE();
  229. push(frame->slots[slot]);
  230. break;
  231. }
  232. case OP_SET_LOCAL: {
  233. uint8_t slot = READ_BYTE();
  234. frame->slots[slot] = peek(0);
  235. break;
  236. }
  237. case OP_ADD: {
  238. if (IS_STRING(peek(0)) && IS_STRING(peek(1))) {
  239. // 字串拼接
  240. concatenate();
  241. } else if (IS_NUMBER(peek(0)) && IS_NUMBER(peek(1))) {
  242. double b = AS_NUMBER(pop());
  243. double a = AS_NUMBER(pop());
  244. push(NUMBER_VAL(a + b));
  245. } else {
  246. runtimeError("Operands must be two numbers or two strings.");
  247. return INTERPRET_RUNTIME_ERROR;
  248. }
  249. break;
  250. }
  251. case OP_SUBTRACT:
  252. BINARY_OP(NUMBER_VAL, -);
  253. break;
  254. case OP_MULTIPLY:
  255. BINARY_OP(NUMBER_VAL, *);
  256. break;
  257. case OP_DIVIDE:
  258. BINARY_OP(NUMBER_VAL, /);
  259. break;
  260. case OP_NOT:
  261. push(BOOL_VAL(isFalse(pop())));
  262. break;
  263. case OP_NEGATE:
  264. if (!IS_NUMBER(peek(0))) {
  265. runtimeError("Operand must be a number.");
  266. return INTERPRET_RUNTIME_ERROR;
  267. }
  268. push(NUMBER_VAL(-AS_NUMBER(pop())));
  269. break;
  270. case OP_EQUAL: {
  271. Value b = pop();
  272. Value a = pop();
  273. push(BOOL_VAL(valuesEqual(a, b)));
  274. break;
  275. }
  276. case OP_GREATER:
  277. BINARY_OP(BOOL_VAL, >);
  278. break;
  279. case OP_LESS:
  280. BINARY_OP(BOOL_VAL, <);
  281. break;
  282. case OP_PRINT: {
  283. printValue(pop());
  284. printf("\n");
  285. break;
  286. }
  287. case OP_JUMP_IF_FALSE: {
  288. uint16_t offset = READ_SHORT();
  289. if (isFalse(peek(0))) frame->ip += offset;
  290. break;
  291. }
  292. case OP_JUMP: {
  293. uint16_t offset = READ_SHORT();
  294. frame->ip += offset;
  295. break;
  296. }
  297. case OP_LOOP: {
  298. uint16_t offset = READ_SHORT();
  299. frame->ip -= offset;
  300. break;
  301. }
  302. case OP_CALL: {
  303. int argCount = READ_BYTE();
  304. if (!callValue(peek(argCount), argCount)) {
  305. return INTERPRET_RUNTIME_ERROR;
  306. }
  307. frame = &vm.frames[vm.frameCount - 1];
  308. break;
  309. }
  310. case OP_CLOSURE: {
  311. ObjFunction *function = AS_FUNCTION(READ_CONSTANT());
  312. ObjClosure *closure = newClosure(function);
  313. push(OBJ_VAL(closure));
  314. for (int i = 0; i < closure->upvalueCount; i++) {
  315. uint8_t isLocal = READ_BYTE();
  316. uint8_t index = READ_BYTE();
  317. if (isLocal) {
  318. closure->upvalues[i] = captureUpvalue(frame->slots + index);
  319. } else {
  320. closure->upvalues[i] = frame->closure->upvalues[index];
  321. }
  322. }
  323. break;
  324. }
  325. case OP_GET_UPVALUE: {
  326. uint8_t slot = READ_BYTE();
  327. push(*frame->closure->upvalues[slot]->location);
  328. break;
  329. }
  330. case OP_SET_UPVALUE: {
  331. uint8_t slot = READ_BYTE();
  332. *frame->closure->upvalues[slot]->location = peek(0);
  333. break;
  334. }
  335. case OP_CLOSE_UPVALUE:
  336. closeUpvalues(vm.stackTop - 1);
  337. pop();
  338. break;
  339. case OP_RETURN: {
  340. Value result = pop();
  341. closeUpvalues(frame->slots);
  342. vm.frameCount--;
  343. if (vm.frameCount == 0) {
  344. pop();
  345. return INTERPRET_OK;
  346. }
  347. vm.stackTop = frame->slots;
  348. push(result);
  349. frame = &vm.frames[vm.frameCount - 1];
  350. break;
  351. }
  352. default:
  353. break;
  354. }
  355. }
  356. #undef READ_BYTE
  357. #undef READ_CONSTANT
  358. #undef READ_SHORT
  359. #undef READ_STRING
  360. #undef BINARY_OP
  361. }
  362. void freeVM() {
  363. freeTable(&vm.globals);
  364. freeTable(&vm.strings);
  365. freeObjects();
  366. }
  367. InterpretResult interpret(const char *source) {
  368. ObjFunction *function = compile(source);
  369. if (function == NULL) return INTERPRET_COMPILE_ERROR;
  370. push(OBJ_VAL(function));
  371. ObjClosure *closure = newClosure(function);
  372. pop();
  373. push(OBJ_VAL(closure));
  374. // CallFrame *frame = &vm.frames[vm.frameCount++];
  375. // frame->function = function;
  376. // frame->ip = function->chunk.code;
  377. // frame->slots = vm.stack;
  378. call(closure, 0);
  379. return run();
  380. }
  381. void push(Value value) {
  382. *vm.stackTop = value;
  383. vm.stackTop++;
  384. #ifdef DEBUG_TRACE_EXECUTION
  385. printf("push stack: ");
  386. printValue(value);
  387. printf("\n");
  388. #endif
  389. }
  390. Value pop() {
  391. vm.stackTop--;
  392. //! NOTE: 出栈后,里面的值没有清除
  393. return *vm.stackTop;
  394. }