vm.c 16 KB

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