vm.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510
  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. vm.bytesAllocated = 0;
  58. vm.nextGC = 1024 * 1024;
  59. vm.grayCount = 0;
  60. vm.grayCapacity = 0;
  61. vm.grayStack = NULL;
  62. initTable(&vm.globals);
  63. initTable(&vm.strings);
  64. /// Native Function define.
  65. defineNative("clock", clockNative);
  66. }
  67. static Value peek(int distance) {
  68. return vm.stackTop[-1 - distance];
  69. }
  70. static bool call(ObjClosure *closure, int argCount) {
  71. if (argCount != closure->function->arity) {
  72. runtimeError("Expected %d arguments but got %d", closure->function->arity, argCount);
  73. return false;
  74. }
  75. if (vm.frameCount == FRAMES_MAX) {
  76. runtimeError("Stack overflow.");
  77. return false;
  78. }
  79. CallFrame *frame = &vm.frames[vm.frameCount++];
  80. frame->closure = closure;
  81. frame->ip = closure->function->chunk.code;
  82. frame->slots = vm.stackTop - argCount - 1;
  83. return true;
  84. }
  85. static bool callValue(Value callee, int argCount) {
  86. if (IS_OBJ(callee)) {
  87. switch (OBJ_TYPE(callee)) {
  88. case OBJ_BOUND_METHOD: {
  89. ObjBoundMethod *bound = AS_BOUND_METHOD(callee);
  90. vm.stackTop[-argCount-1] = bound->receiver;
  91. return call(bound->method, argCount);
  92. }
  93. case OBJ_CLOSURE:
  94. return call(AS_CLOSURE(callee), argCount);
  95. case OBJ_NATIVE: {
  96. NativeFn fn = AS_NATIVE(callee);
  97. Value result = fn(argCount, vm.stackTop - argCount);
  98. vm.stackTop -= argCount + 1;
  99. push(result);
  100. return true;
  101. }
  102. case OBJ_CLASS: {
  103. ObjClass *klass = AS_CLASS(callee);
  104. vm.stackTop[-argCount - 1] = OBJ_VAL(newInstance(klass));
  105. return true;
  106. }
  107. default:
  108. break;// Non-callable object type.
  109. }
  110. }
  111. runtimeError("Can only call functions and classes.");
  112. return false;
  113. }
  114. static bool isFalse(Value value) {
  115. // the nil and false will return true
  116. return IS_NIL(value) || (IS_BOOL(value) && !AS_BOOL(value));
  117. }
  118. static void concatenate() {
  119. ObjString *b = AS_STRING(peek(0));
  120. ObjString *a = AS_STRING(peek(1));
  121. int length = a->length + b->length;
  122. char *chars = ALLOCATE(char, length + 1);
  123. memcpy(chars, a->chars, a->length);
  124. memcpy(chars + a->length, b->chars, b->length);
  125. chars[length] = '\0';
  126. ObjString *result = takeString(chars, length);
  127. pop();
  128. pop();
  129. push(OBJ_VAL(result));
  130. }
  131. static ObjUpvalue *captureUpvalue(Value *local) {
  132. ObjUpvalue *preUpvalue = NULL;
  133. ObjUpvalue *upvalue = vm.openUpvalues;
  134. while (upvalue != NULL && upvalue->location > local) {
  135. preUpvalue = upvalue;
  136. upvalue = upvalue->next;
  137. }
  138. if (upvalue != NULL && upvalue->location == local) {
  139. return upvalue;
  140. }
  141. ObjUpvalue *createdUpvalue = newUpvalue(local);
  142. if (preUpvalue == NULL) {
  143. vm.openUpvalues = createdUpvalue;
  144. } else {
  145. preUpvalue->next = createdUpvalue;
  146. }
  147. return createdUpvalue;
  148. }
  149. static void closeUpvalues(Value *last) {
  150. while (vm.openUpvalues != NULL && vm.openUpvalues->location >= last) {
  151. ObjUpvalue *upvalue = vm.openUpvalues;
  152. upvalue->closed = *upvalue->location;
  153. upvalue->location = &upvalue->closed;
  154. vm.openUpvalues = upvalue->next;
  155. }
  156. }
  157. static void defineMethod(ObjString *name) {
  158. Value method = peek(0);
  159. ObjClass *klass = AS_CLASS(peek(1));
  160. tableSet(&klass->methods, name, method);
  161. pop();
  162. }
  163. static bool bindKlassMethod(ObjClass *klass, ObjString *name) {
  164. Value method;
  165. if (!tableGet(&klass->methods, name, &method)) {
  166. runtimeError("Undefined property '%s'.", name->chars);
  167. return false;
  168. }
  169. ObjBoundMethod *bound = newBoundMethod(peek(0), AS_CLOSURE(method));
  170. pop();
  171. push(OBJ_VAL(bound));
  172. return true;
  173. }
  174. /// VM run function - exec opcode
  175. /// \return
  176. static InterpretResult run() {
  177. CallFrame *frame = &vm.frames[vm.frameCount - 1];
  178. //! <macro> reads the byte currently pointed at by ip
  179. //! and then advances the instruction pointer
  180. #define READ_BYTE() (*frame->ip++)
  181. //! reads the next byte from the bytecode
  182. //! treats the resulting number as an index
  183. #define READ_CONSTANT() \
  184. (frame->closure->function->chunk.constants.values[READ_BYTE()])
  185. #define READ_SHORT() \
  186. (frame->ip += 2, (uint16_t) ((frame->ip[-2] << 8) | frame->ip[-1]))
  187. #define READ_STRING() AS_STRING(READ_CONSTANT())
  188. #define BINARY_OP(valueType, op) \
  189. do { \
  190. if (!IS_NUMBER(peek(0)) || !IS_NUMBER(peek(1))) { \
  191. runtimeError("Operands must be numbers."); \
  192. return INTERPRET_RUNTIME_ERROR; \
  193. } \
  194. double b = AS_NUMBER(pop()); \
  195. double a = AS_NUMBER(pop()); \
  196. push(valueType(a op b)); \
  197. } while (false)
  198. for (;;) {
  199. #ifdef DEBUG_TRACE_EXECUTION
  200. #ifdef DEBUG_STACK_INFO
  201. //! <Stack tracing> start
  202. printf("\n!!! <Stack tracing now>:\n");
  203. printf("------------------------\n|");
  204. for (Value *slot = vm.stack; slot < vm.stackTop; slot++) {
  205. printf("[ ");
  206. printValue(*slot);
  207. printf(" ]");
  208. }
  209. printf("\n------------------------");
  210. printf("\n");
  211. printf("\n");
  212. //! <Stack tracing> end
  213. #endif
  214. printf("The Instruction: \n");
  215. disassembleInstruction(&frame->closure->function->chunk, (int) (frame->ip - frame->closure->function->chunk.code));
  216. #endif
  217. uint8_t opCode = READ_BYTE();
  218. switch (opCode) {
  219. case OP_CONSTANT: {
  220. Value constant = READ_CONSTANT();
  221. push(constant);
  222. break;
  223. }
  224. case OP_NIL:
  225. push(NIL_VAL);
  226. break;
  227. case OP_TRUE:
  228. push(BOOL_VAL(true));
  229. break;
  230. case OP_FALSE:
  231. push(BOOL_VAL(false));
  232. break;
  233. case OP_POP:
  234. pop();
  235. break;
  236. case OP_DEFINE_GLOBAL: {
  237. ObjString *name = READ_STRING();
  238. tableSet(&vm.globals, name, peek(0));
  239. pop();
  240. break;
  241. }
  242. case OP_CLASS:
  243. push(OBJ_VAL(newClass(READ_STRING())));
  244. break;
  245. case OP_GET_GLOBAL: {
  246. ObjString *name = READ_STRING();
  247. Value value;
  248. if (!tableGet(&vm.globals, name, &value)) {
  249. runtimeError("Undefined variable '%s'.", name->chars);
  250. return INTERPRET_RUNTIME_ERROR;
  251. }
  252. push(value);
  253. break;
  254. }
  255. case OP_METHOD: {
  256. defineMethod(READ_STRING());
  257. break;
  258. }
  259. case OP_SET_GLOBAL: {
  260. ObjString *name = READ_STRING();
  261. if (tableSet(&vm.globals, name, peek(0))) {
  262. tableDelete(&vm.globals, name);
  263. runtimeError("Undefined variable '%s'.", name->chars);
  264. return INTERPRET_RUNTIME_ERROR;
  265. }
  266. break;
  267. }
  268. case OP_GET_LOCAL: {
  269. uint8_t slot = READ_BYTE();
  270. push(frame->slots[slot]);
  271. break;
  272. }
  273. case OP_SET_LOCAL: {
  274. uint8_t slot = READ_BYTE();
  275. frame->slots[slot] = peek(0);
  276. break;
  277. }
  278. case OP_ADD: {
  279. if (IS_STRING(peek(0)) && IS_STRING(peek(1))) {
  280. // 字串拼接
  281. concatenate();
  282. } else if (IS_NUMBER(peek(0)) && IS_NUMBER(peek(1))) {
  283. double b = AS_NUMBER(pop());
  284. double a = AS_NUMBER(pop());
  285. push(NUMBER_VAL(a + b));
  286. } else {
  287. runtimeError("Operands must be two numbers or two strings.");
  288. return INTERPRET_RUNTIME_ERROR;
  289. }
  290. break;
  291. }
  292. case OP_SUBTRACT:
  293. BINARY_OP(NUMBER_VAL, -);
  294. break;
  295. case OP_MULTIPLY:
  296. BINARY_OP(NUMBER_VAL, *);
  297. break;
  298. case OP_DIVIDE:
  299. BINARY_OP(NUMBER_VAL, /);
  300. break;
  301. case OP_NOT:
  302. push(BOOL_VAL(isFalse(pop())));
  303. break;
  304. case OP_NEGATE:
  305. if (!IS_NUMBER(peek(0))) {
  306. runtimeError("Operand must be a number.");
  307. return INTERPRET_RUNTIME_ERROR;
  308. }
  309. push(NUMBER_VAL(-AS_NUMBER(pop())));
  310. break;
  311. case OP_EQUAL: {
  312. Value b = pop();
  313. Value a = pop();
  314. push(BOOL_VAL(valuesEqual(a, b)));
  315. break;
  316. }
  317. case OP_GREATER:
  318. BINARY_OP(BOOL_VAL, >);
  319. break;
  320. case OP_LESS:
  321. BINARY_OP(BOOL_VAL, <);
  322. break;
  323. case OP_PRINT: {
  324. Value value = pop();
  325. printf("****PRINT**** ");
  326. printValue(value);
  327. printf("\n");
  328. break;
  329. }
  330. case OP_JUMP_IF_FALSE: {
  331. uint16_t offset = READ_SHORT();
  332. if (isFalse(peek(0))) frame->ip += offset;
  333. break;
  334. }
  335. case OP_JUMP: {
  336. uint16_t offset = READ_SHORT();
  337. frame->ip += offset;
  338. break;
  339. }
  340. case OP_LOOP: {
  341. uint16_t offset = READ_SHORT();
  342. frame->ip -= offset;
  343. break;
  344. }
  345. case OP_CALL: {
  346. int argCount = READ_BYTE();
  347. if (!callValue(peek(argCount), argCount)) {
  348. return INTERPRET_RUNTIME_ERROR;
  349. }
  350. frame = &vm.frames[vm.frameCount - 1];
  351. break;
  352. }
  353. case OP_GET_PROPERTY: {
  354. if (!IS_INSTANCE(peek(0))) {
  355. runtimeError("Only instance have properties.");
  356. return INTERPRET_RUNTIME_ERROR;
  357. }
  358. ObjInstance *instance = AS_INSTANCE(peek(0));
  359. ObjString *name = READ_STRING();
  360. Value value;
  361. if (tableGet(&instance->fields, name, &value)) {
  362. pop();// Instance
  363. push(value);
  364. break;
  365. }
  366. if (!bindKlassMethod(instance->klass, name)) {
  367. return INTERPRET_RUNTIME_ERROR;
  368. }
  369. break;
  370. }
  371. case OP_SET_PROPERTY: {
  372. if (!IS_INSTANCE(peek(1))) {
  373. runtimeError("Only instances have fields.");
  374. return INTERPRET_RUNTIME_ERROR;
  375. }
  376. ObjInstance *instance = AS_INSTANCE(peek(1));
  377. tableSet(&instance->fields, READ_STRING(), peek(0));
  378. Value value = pop();
  379. pop();
  380. push(value);
  381. break;
  382. }
  383. case OP_CLOSURE: {
  384. ObjFunction *function = AS_FUNCTION(READ_CONSTANT());
  385. ObjClosure *closure = newClosure(function);
  386. push(OBJ_VAL(closure));
  387. for (int i = 0; i < closure->upvalueCount; i++) {
  388. uint8_t isLocal = READ_BYTE();
  389. uint8_t index = READ_BYTE();
  390. if (isLocal) {
  391. closure->upvalues[i] = captureUpvalue(frame->slots + index);
  392. } else {
  393. closure->upvalues[i] = frame->closure->upvalues[index];
  394. }
  395. }
  396. break;
  397. }
  398. case OP_GET_UPVALUE: {
  399. uint8_t slot = READ_BYTE();
  400. push(*frame->closure->upvalues[slot]->location);
  401. break;
  402. }
  403. case OP_SET_UPVALUE: {
  404. uint8_t slot = READ_BYTE();
  405. *frame->closure->upvalues[slot]->location = peek(0);
  406. break;
  407. }
  408. case OP_CLOSE_UPVALUE:
  409. closeUpvalues(vm.stackTop - 1);
  410. pop();
  411. break;
  412. case OP_RETURN: {
  413. Value result = pop();
  414. closeUpvalues(frame->slots);
  415. vm.frameCount--;
  416. if (vm.frameCount == 0) {
  417. pop();
  418. return INTERPRET_OK;
  419. }
  420. vm.stackTop = frame->slots;
  421. push(result);
  422. frame = &vm.frames[vm.frameCount - 1];
  423. break;
  424. }
  425. default:
  426. break;
  427. }
  428. }
  429. #undef READ_BYTE
  430. #undef READ_CONSTANT
  431. #undef READ_SHORT
  432. #undef READ_STRING
  433. #undef BINARY_OP
  434. }
  435. void freeVM() {
  436. freeTable(&vm.globals);
  437. freeTable(&vm.strings);
  438. freeObjects();
  439. }
  440. InterpretResult interpret(const char *source) {
  441. ObjFunction *function = compile(source);
  442. if (function == NULL) return INTERPRET_COMPILE_ERROR;
  443. push(OBJ_VAL(function));
  444. ObjClosure *closure = newClosure(function);
  445. pop();
  446. push(OBJ_VAL(closure));
  447. // CallFrame *frame = &vm.frames[vm.frameCount++];
  448. // frame->function = function;
  449. // frame->ip = function->chunk.code;
  450. // frame->slots = vm.stack;
  451. call(closure, 0);
  452. return run();
  453. }
  454. void push(Value value) {
  455. *vm.stackTop = value;
  456. vm.stackTop++;
  457. #ifdef DEBUG_TRACE_EXECUTION
  458. printf(">> push stack: ");
  459. printValue(value);
  460. printf("\n");
  461. #endif
  462. }
  463. Value pop() {
  464. vm.stackTop--;
  465. //! NOTE: 出栈后,里面的值没有清除
  466. Value value = *vm.stackTop;
  467. #ifdef DEBUG_TRACE_EXECUTION
  468. printf("<< pop stack: ");
  469. printValue(value);
  470. printf("\n");
  471. #endif
  472. return value;
  473. }