Code.c 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237
  1. #include "Code.h"
  2. #include <stdio.h>
  3. #include <string.h>
  4. #include "Code.h"
  5. #include "Constants.h"
  6. #include "Memory.h"
  7. void codeInit(Code* c) {
  8. *c = (Code){};
  9. bufferInit(&c->code);
  10. }
  11. void codeDestroy(Code* c) {
  12. bufferDestroy(&c->code);
  13. memoryFree(c->stack);
  14. *c = (Code){};
  15. }
  16. void codeReset(Code* c) {
  17. bufferReset(&c->code);
  18. }
  19. #define POP_VALUE(name) \
  20. Value name; \
  21. if(iPopValue(c, &name)) \
  22. return true
  23. #define INT_VALUE(value) ((Value){.type = VT_INT32, .data = (value)})
  24. #define CSTRING_VALUE(value) \
  25. ((Value){.type = VT_CONSTANT_STRING, .data = (value)})
  26. #define SET_ERROR(format, ...) \
  27. snprintf( \
  28. c->error.text, sizeof(c->error.text), \
  29. format __VA_OPT__(, ) __VA_ARGS__)
  30. [[nodiscard]] static bool codeReadI32(Code* c, i32* i) {
  31. return bufferReadI32(&c->code, i);
  32. }
  33. [[nodiscard]] static const char* codeReadConstantString(Code* c) {
  34. return bufferReadString(&c->code);
  35. }
  36. static void codeSetPosition(Code* c, size_t pos) {
  37. c->code.readIndex = pos;
  38. }
  39. static i32 codeGetPosition(Code* c) {
  40. return (i32)c->code.readIndex;
  41. }
  42. static bool iPushValue(Code* c, Value v) {
  43. while(c->stackIndex >= c->maxStackSize) {
  44. size_t newSize = c->maxStackSize <= 0 ? 16 : (c->maxStackSize * 5) / 4;
  45. if(newSize >= MAX_STACK_VALUES) {
  46. SET_ERROR("Stack overflow");
  47. return true;
  48. }
  49. Value* newValues = memoryAllocate(sizeof(Value) * newSize);
  50. if(newValues == nullptr) {
  51. SET_ERROR("Out of memory for stack");
  52. return true;
  53. }
  54. memcpy(newValues, c->stack, sizeof(Value) * c->stackIndex);
  55. memoryFree(c->stack);
  56. c->stack = newValues;
  57. c->maxStackSize = newSize;
  58. }
  59. c->stack[c->stackIndex++] = v;
  60. return false;
  61. }
  62. static bool iPopValue(Code* c, Value* v) {
  63. if(c->stackIndex <= 0) {
  64. SET_ERROR("Pop on empty stack");
  65. return true;
  66. }
  67. *v = c->stack[--c->stackIndex];
  68. return false;
  69. }
  70. static bool iAdd(Code* c) {
  71. POP_VALUE(a);
  72. POP_VALUE(b);
  73. return iPushValue(c, INT_VALUE(a.data + b.data));
  74. }
  75. static bool iPushConstantString(Code* c) {
  76. const char* s = codeReadConstantString(c);
  77. i32 address = (i32)((const u8*)s - c->code.data);
  78. return iPushValue(c, CSTRING_VALUE(address));
  79. }
  80. static bool iPushInt(Code* c) {
  81. i32 i = 0;
  82. if(codeReadI32(c, &i)) {
  83. SET_ERROR("PushInt without value");
  84. return true;
  85. }
  86. return iPushValue(c, INT_VALUE(i));
  87. }
  88. static bool iPrint(Code* c) {
  89. POP_VALUE(a);
  90. switch(a.type) {
  91. case VT_INT32: printf("%d", a.data); break;
  92. case VT_CONSTANT_STRING: printf("%s", c->code.data + a.data); break;
  93. }
  94. return false;
  95. }
  96. static bool iPrintNewline() {
  97. putchar('\n');
  98. return false;
  99. }
  100. static bool iJump(Code* c) {
  101. i32 jumpPos = 0;
  102. if(codeReadI32(c, &jumpPos)) {
  103. SET_ERROR("Jump without position");
  104. return true;
  105. }
  106. codeSetPosition(c, (size_t)jumpPos);
  107. return false;
  108. }
  109. static bool iJumpIf(Code* c) {
  110. POP_VALUE(a);
  111. i32 jumpPos = 0;
  112. if(codeReadI32(c, &jumpPos)) {
  113. SET_ERROR("JumpIf without position");
  114. return true;
  115. }
  116. if(a.data == 0) {
  117. codeSetPosition(c, (size_t)jumpPos);
  118. }
  119. return false;
  120. }
  121. static bool iJumpSub(Code* c) {
  122. i32 jumpPos = 0;
  123. if(codeReadI32(c, &jumpPos)) {
  124. SET_ERROR("JumpSub without position");
  125. return true;
  126. } else if(iPushValue(c, INT_VALUE(codeGetPosition(c)))) {
  127. return true;
  128. }
  129. codeSetPosition(c, (size_t)jumpPos);
  130. return false;
  131. }
  132. static bool iReturn(Code* c) {
  133. POP_VALUE(a);
  134. codeSetPosition(c, (size_t)a.data);
  135. return false;
  136. }
  137. static bool iReadVariable(Code* c) {
  138. i32 address = 0;
  139. if(codeReadI32(c, &address)) {
  140. SET_ERROR("ReadVariable without address");
  141. return true;
  142. } else if((size_t)address >= c->stackIndex) {
  143. SET_ERROR("ReadVariable with invalid address");
  144. return true;
  145. }
  146. return iPushValue(c, c->stack[address]);
  147. }
  148. static bool iSetVariable(Code* c) {
  149. i32 address = 0;
  150. if(codeReadI32(c, &address)) {
  151. SET_ERROR("SetVariable without address");
  152. return true;
  153. } else if((size_t)address >= c->stackIndex) {
  154. SET_ERROR("SetVariable with invalid address");
  155. return true;
  156. }
  157. POP_VALUE(a);
  158. c->stack[address] = a;
  159. return false;
  160. }
  161. static bool iPushStackVariables(Code* c) {
  162. i32 amount = 0;
  163. if(codeReadI32(c, &amount)) {
  164. SET_ERROR("PushStackVariables without amount");
  165. return true;
  166. }
  167. Value v = INT_VALUE(0);
  168. while(amount > 0) {
  169. if(iPushValue(c, v)) {
  170. return true;
  171. }
  172. amount--;
  173. }
  174. return false;
  175. }
  176. static bool execute(Code* c, Instruction command) {
  177. switch(command) {
  178. case ADD: return iAdd(c);
  179. case PUSH_CONSTANT_STRING: return iPushConstantString(c);
  180. case PUSH_INT64: return iPushInt(c);
  181. case PRINT: return iPrint(c);
  182. case PRINT_NEWLINE: return iPrintNewline();
  183. case JUMP: return iJump(c);
  184. case JUMP_ON_0: return iJumpIf(c);
  185. case JUMP_SUB: return iJumpSub(c);
  186. case RETURN: return iReturn(c);
  187. case READ_VARIABLE: return iReadVariable(c);
  188. case SET_VARIABLE: return iSetVariable(c);
  189. case PUSH_STACK_VARIABLES: return iPushStackVariables(c);
  190. case STOP: return true;
  191. }
  192. return false;
  193. }
  194. void codeRun(Code* c) {
  195. while(true) {
  196. Instruction i = STOP;
  197. if(bufferReadU8(&c->code, &i) || execute(c, i)) {
  198. return;
  199. }
  200. }
  201. }
  202. bool codeHasRunError(const Code* code) {
  203. return hasError(&code->error);
  204. }
  205. const char* codeGetRunError(const Code* code) {
  206. return code->error.text;
  207. }