debug.c 3.6 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495
  1. //
  2. // Created by 李晓明 on 2023/8/16.
  3. //
  4. #include "debug.h"
  5. #include "value.h"
  6. #include <stdio.h>
  7. static int constantInstruction(const char *, Chunk *, int);
  8. static int simpleInstruction(const char *name, int offset);
  9. static int byteInstruction(const char *name, Chunk *chunk, int offset);
  10. void disassembleChunk(Chunk *chunk, const char *name) {
  11. printf("== %s STARTING ==\n", name);
  12. for (int offset = 0; offset < chunk->count;) {
  13. offset = disassembleInstruction(chunk, offset);
  14. }
  15. printf("== %s END ==\n", name);
  16. }
  17. static int jumpInstruction(const char *name, int sign, Chunk *chunk, int offset) {
  18. uint16_t jump = (uint16_t) (chunk->code[offset + 1] << 8);
  19. jump |= chunk->code[offset + 2];
  20. printf("%-16s %4d -> %d\n", name, offset, offset + 3 + sign * jump);
  21. return offset + 3;
  22. }
  23. int disassembleInstruction(Chunk *chunk, int offset) {
  24. printf("%04d ", offset);
  25. if (offset > 0 && chunk->lines[offset] == chunk->lines[offset - 1]) {
  26. printf(" | ");
  27. } else {
  28. printf("%4d ", chunk->lines[offset]);
  29. }
  30. uint8_t instruction = chunk->code[offset];
  31. switch (instruction) {
  32. case OP_CONSTANT: return constantInstruction("OP_CONSTANT", chunk, offset);
  33. case OP_NIL: return simpleInstruction("OP_NIL", offset);
  34. case OP_TRUE: return simpleInstruction("OP_TRUE", offset);
  35. case OP_FALSE: return simpleInstruction("OP_FALSE", offset);
  36. case OP_POP: return simpleInstruction("OP_POP", offset);
  37. case OP_DEFINE_GLOBAL: return constantInstruction("OP_DEFINE_GLOBAL", chunk, offset);
  38. case OP_GET_GLOBAL: return constantInstruction("OP_GET_GLOBAL", chunk, offset);
  39. case OP_SET_GLOBAL: return constantInstruction("OP_SET_GLOBAL", chunk, offset);
  40. case OP_GET_LOCAL: return byteInstruction("OP_GET_LOCAL", chunk, offset);
  41. case OP_SET_LOCAL: return byteInstruction("OP_SET_LOCAL", chunk, offset);
  42. case OP_ADD: return simpleInstruction("OP_ADD", offset);
  43. case OP_SUBTRACT: return simpleInstruction("OP_SUBTRACT", offset);
  44. case OP_MULTIPLY: return simpleInstruction("OP_MULTIPLY", offset);
  45. case OP_DIVIDE: return simpleInstruction("OP_DIVIDE", offset);
  46. case OP_NOT: return simpleInstruction("OP_NOT", offset);
  47. case OP_NEGATE: return simpleInstruction("OP_NEGATE", offset);
  48. case OP_EQUAL: return simpleInstruction("OP_EQUAL", offset);
  49. case OP_GREATER: return simpleInstruction("OP_GREATER", offset);
  50. case OP_LESS: return simpleInstruction("OP_LESS", offset);
  51. case OP_PRINT: return simpleInstruction("OP_PRINT", offset);
  52. case OP_JUMP: return jumpInstruction("OP_JUMP", 1, chunk, offset);
  53. case OP_LOOP: return jumpInstruction("OP_LOOP", -1, chunk, offset);
  54. case OP_CALL: return byteInstruction("OP_CALL", chunk, offset);
  55. case OP_JUMP_IF_FALSE: return jumpInstruction("OP_JUMP_IF_FALSE", 1, chunk, offset);
  56. case OP_RETURN: return simpleInstruction("OP_RETURN", offset);
  57. default:
  58. printf("Unknown opcode %d\n", instruction);
  59. return offset + 1;
  60. }
  61. }
  62. /**
  63. * @brief 打印常量指令
  64. * @param name
  65. * @param chunk
  66. * @param offset
  67. * @return
  68. */
  69. static int constantInstruction(const char *name, Chunk *chunk, int offset) {
  70. uint8_t constant = chunk->code[offset + 1];
  71. printf("%-16s %4d '", name, constant);
  72. printValue(chunk->constants.values[constant]);
  73. printf("'\n");
  74. return offset + 2;
  75. }
  76. /**
  77. * @brief 打印指令
  78. * @param name 名称
  79. * @param offset 偏移
  80. * @return
  81. */
  82. static int simpleInstruction(const char *name, int offset) {
  83. printf("%s\n", name);
  84. return offset + 1;
  85. }
  86. static int byteInstruction(const char *name, Chunk *chunk, int offset) {
  87. uint8_t slot = chunk->code[offset + 1];
  88. printf("%-16s %4d\n", name, slot);
  89. return offset + 2;
  90. }