Code.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440
  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. #include "SystemFunctions.h"
  8. void codeInit(Code* c) {
  9. *c = (Code){};
  10. bufferInit(&c->code);
  11. }
  12. void codeDestroy(Code* c) {
  13. bufferDestroy(&c->code);
  14. memoryFree(c->stack);
  15. *c = (Code){};
  16. }
  17. void codeReset(Code* c) {
  18. bufferReset(&c->code);
  19. }
  20. #define POP_VALUE(name) \
  21. Value name; \
  22. if(iPopValue(c, &name)) \
  23. return true
  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), "%zu | " format, \
  29. c->code.readIndex __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 iPop(Code* c) {
  71. POP_VALUE(a);
  72. return false;
  73. }
  74. static bool iAdd(Code* c) {
  75. POP_VALUE(a);
  76. POP_VALUE(b);
  77. return iPushValue(c, INT_VALUE(b.data + a.data));
  78. }
  79. static bool iSub(Code* c) {
  80. POP_VALUE(a);
  81. POP_VALUE(b);
  82. return iPushValue(c, INT_VALUE(b.data - a.data));
  83. }
  84. static bool iMul(Code* c) {
  85. POP_VALUE(a);
  86. POP_VALUE(b);
  87. return iPushValue(c, INT_VALUE(b.data * a.data));
  88. }
  89. static bool iDiv(Code* c) {
  90. POP_VALUE(a);
  91. POP_VALUE(b);
  92. return iPushValue(c, INT_VALUE(b.data / a.data));
  93. }
  94. static bool iAnd(Code* c) {
  95. POP_VALUE(a);
  96. POP_VALUE(b);
  97. return iPushValue(c, INT_VALUE(b.data && a.data));
  98. }
  99. static bool iOr(Code* c) {
  100. POP_VALUE(a);
  101. POP_VALUE(b);
  102. return iPushValue(c, INT_VALUE(b.data || a.data));
  103. }
  104. static bool iNot(Code* c) {
  105. POP_VALUE(a);
  106. return iPushValue(c, INT_VALUE(!a.data));
  107. }
  108. static bool iEqual(Code* c) {
  109. POP_VALUE(a);
  110. POP_VALUE(b);
  111. return iPushValue(c, INT_VALUE(b.data == a.data));
  112. }
  113. static bool iNotEqual(Code* c) {
  114. POP_VALUE(a);
  115. POP_VALUE(b);
  116. return iPushValue(c, INT_VALUE(b.data != a.data));
  117. }
  118. static bool iGreater(Code* c) {
  119. POP_VALUE(a);
  120. POP_VALUE(b);
  121. return iPushValue(c, INT_VALUE(b.data > a.data));
  122. }
  123. static bool iSmaller(Code* c) {
  124. POP_VALUE(a);
  125. POP_VALUE(b);
  126. return iPushValue(c, INT_VALUE(b.data < a.data));
  127. }
  128. static bool iGreaterOrEqual(Code* c) {
  129. POP_VALUE(a);
  130. POP_VALUE(b);
  131. return iPushValue(c, INT_VALUE(b.data >= a.data));
  132. }
  133. static bool iSmallerOrEqual(Code* c) {
  134. POP_VALUE(a);
  135. POP_VALUE(b);
  136. return iPushValue(c, INT_VALUE(b.data <= a.data));
  137. }
  138. static bool iPushConstantString(Code* c) {
  139. const char* s = codeReadConstantString(c);
  140. i32 address = (i32)((const u8*)s - c->code.data);
  141. return iPushValue(c, CSTRING_VALUE(address));
  142. }
  143. static bool iPushInt(Code* c) {
  144. i32 i = 0;
  145. if(codeReadI32(c, &i)) {
  146. SET_ERROR("PushInt without value");
  147. return true;
  148. }
  149. return iPushValue(c, INT_VALUE(i));
  150. }
  151. static bool iJump(Code* c) {
  152. i32 jumpPos = 0;
  153. if(codeReadI32(c, &jumpPos)) {
  154. SET_ERROR("Jump without position");
  155. return true;
  156. }
  157. codeSetPosition(c, (size_t)jumpPos);
  158. return false;
  159. }
  160. static bool iJumpIf(Code* c) {
  161. POP_VALUE(a);
  162. i32 jumpPos = 0;
  163. if(codeReadI32(c, &jumpPos)) {
  164. SET_ERROR("JumpIf without position");
  165. return true;
  166. }
  167. if(a.data == 0) {
  168. codeSetPosition(c, (size_t)jumpPos);
  169. }
  170. return false;
  171. }
  172. static bool iJumpSub(Code* c) {
  173. i32 jumpPos = 0;
  174. i32 offset = 0;
  175. if(codeReadI32(c, &jumpPos)) {
  176. SET_ERROR("JumpSub without position");
  177. return true;
  178. } else if(codeReadI32(c, &offset)) {
  179. SET_ERROR("JumpSub without offset");
  180. return true;
  181. }
  182. i32 returnIndex = (i32)c->stackIndex - (offset + 1);
  183. if(returnIndex < 1 && returnIndex >= (i32)c->maxStackSize) {
  184. SET_ERROR("JumpSub with invalid return index");
  185. return true;
  186. }
  187. c->stack[returnIndex].data = codeGetPosition(c);
  188. c->stack[returnIndex - 1].data = c->localVariableIndex;
  189. c->localVariableIndex = returnIndex;
  190. codeSetPosition(c, (size_t)jumpPos);
  191. return false;
  192. }
  193. static bool iReturn(Code* c) {
  194. i32 popAmount = 0;
  195. if(codeReadI32(c, &popAmount)) {
  196. SET_ERROR("Return without pop amount");
  197. return true;
  198. }
  199. c->stackIndex -= (size_t)popAmount;
  200. POP_VALUE(returnAddress);
  201. POP_VALUE(variableIndex);
  202. codeSetPosition(c, (size_t)returnAddress.data);
  203. c->localVariableIndex = variableIndex.data;
  204. return false;
  205. }
  206. static bool iReturnValue(Code* c) {
  207. POP_VALUE(value);
  208. if(iReturn(c)) {
  209. return true;
  210. }
  211. return iPushValue(c, value);
  212. }
  213. static i32 iConvertAddress(Code* c, i32 address) {
  214. if(address >= 0) {
  215. return address;
  216. }
  217. return c->localVariableIndex - address;
  218. }
  219. static bool iReadVariable(Code* c) {
  220. i32 address = 0;
  221. if(codeReadI32(c, &address)) {
  222. SET_ERROR("ReadVariable without address");
  223. return true;
  224. }
  225. address = iConvertAddress(c, address);
  226. if((size_t)address >= c->stackIndex) {
  227. SET_ERROR(
  228. "ReadVariable with invalid address %d %zu", address, c->stackIndex);
  229. return true;
  230. }
  231. return iPushValue(c, c->stack[address]);
  232. }
  233. static bool iSetVariable(Code* c) {
  234. i32 address = 0;
  235. if(codeReadI32(c, &address)) {
  236. SET_ERROR("SetVariable without address");
  237. return true;
  238. }
  239. address = iConvertAddress(c, address);
  240. if((size_t)address >= c->stackIndex) {
  241. SET_ERROR("SetVariable with invalid address");
  242. return true;
  243. }
  244. POP_VALUE(a);
  245. c->stack[address] = a;
  246. return false;
  247. }
  248. static bool iPushStackVariables(Code* c) {
  249. i32 amount = 0;
  250. if(codeReadI32(c, &amount)) {
  251. SET_ERROR("PushStackVariables without amount");
  252. return true;
  253. }
  254. Value v = INT_VALUE(0);
  255. while(amount > 0) {
  256. if(iPushValue(c, v)) {
  257. return true;
  258. }
  259. amount--;
  260. }
  261. return false;
  262. }
  263. static bool iCallSystem(Code* c) {
  264. i32 amountIndex = 0;
  265. if(codeReadI32(c, &amountIndex)) {
  266. SET_ERROR("CallSystem without argument amount");
  267. return true;
  268. }
  269. i32 amount = amountIndex & 0xFF;
  270. i32 index = amountIndex >> 8;
  271. if(amount < 0 || amount > (i32)MAX_SYSTEM_FUNCTION_ARGUMENTS) {
  272. SET_ERROR("CallSystem with invalid amount");
  273. return true;
  274. }
  275. Value values[MAX_SYSTEM_FUNCTION_ARGUMENTS];
  276. for(i32 i = amount - 1; i >= 0; i--) {
  277. if(iPopValue(c, values + i)) {
  278. return true;
  279. }
  280. }
  281. SystemFunction f = getSystemFunction(index);
  282. if(f == nullptr) {
  283. SET_ERROR("Invalid system function index");
  284. return true;
  285. }
  286. Value r = {};
  287. if(f(c, &r, values, amount)) {
  288. return true;
  289. }
  290. return iPushValue(c, r);
  291. }
  292. static bool execute(Code* c, Instruction command) {
  293. switch(command) {
  294. case ADD: return iAdd(c);
  295. case SUB: return iSub(c);
  296. case MUL: return iMul(c);
  297. case DIV: return iDiv(c);
  298. case PUSH_CONSTANT_STRING: return iPushConstantString(c);
  299. case PUSH_INT32: return iPushInt(c);
  300. case POP: return iPop(c);
  301. case JUMP: return iJump(c);
  302. case JUMP_ON_0: return iJumpIf(c);
  303. case JUMP_SUB: return iJumpSub(c);
  304. case RETURN_VALUE: return iReturnValue(c);
  305. case READ_VARIABLE: return iReadVariable(c);
  306. case SET_VARIABLE: return iSetVariable(c);
  307. case PUSH_STACK_VARIABLES: return iPushStackVariables(c);
  308. case AND: return iAnd(c);
  309. case OR: return iOr(c);
  310. case NOT: return iNot(c);
  311. case EQUAL: return iEqual(c);
  312. case NOT_EQUAL: return iNotEqual(c);
  313. case GREATER: return iGreater(c);
  314. case SMALLER: return iSmaller(c);
  315. case GREATER_OR_EQUAL: return iGreaterOrEqual(c);
  316. case SMALLER_OR_EQUAL: return iSmallerOrEqual(c);
  317. case CALL_SYSTEM: return iCallSystem(c);
  318. case STOP: return true;
  319. }
  320. return false;
  321. }
  322. void codeRun(Code* c) {
  323. while(true) {
  324. Instruction i = STOP;
  325. if(bufferReadU8(&c->code, &i) || execute(c, i)) {
  326. return;
  327. }
  328. }
  329. }
  330. bool codeHasRunError(const Code* code) {
  331. return hasError(&code->error);
  332. }
  333. const char* codeGetRunError(const Code* code) {
  334. return code->error.text;
  335. }
  336. #define DUMP(name) \
  337. case name: fprintf(stderr, #name "\n"); break
  338. #define DUMP_INT(name) \
  339. case name: { \
  340. i32 v = 0; \
  341. (void)codeReadI32(&c, &v); \
  342. fprintf(stderr, #name " %d\n", v); \
  343. break; \
  344. } break
  345. #define DUMP_INT2(name) \
  346. case name: { \
  347. i32 v[2] = {}; \
  348. (void)codeReadI32(&c, v); \
  349. (void)codeReadI32(&c, v + 1); \
  350. fprintf(stderr, #name " %d %d\n", v[0], v[1]); \
  351. break; \
  352. } break
  353. void codeDump(const Code* code) {
  354. Code c = *code;
  355. while(true) {
  356. size_t start = c.code.readIndex;
  357. Instruction i = STOP;
  358. if(bufferReadU8(&c.code, &i)) {
  359. return;
  360. }
  361. fprintf(stderr, "%4zu | ", start);
  362. switch(i) {
  363. DUMP(ADD);
  364. DUMP(SUB);
  365. DUMP(MUL);
  366. DUMP(DIV);
  367. DUMP_INT(PUSH_INT32);
  368. DUMP(POP);
  369. DUMP_INT(JUMP);
  370. DUMP_INT(JUMP_ON_0);
  371. DUMP_INT2(JUMP_SUB);
  372. DUMP_INT(RETURN_VALUE);
  373. DUMP_INT(READ_VARIABLE);
  374. DUMP_INT(SET_VARIABLE);
  375. DUMP_INT(PUSH_STACK_VARIABLES);
  376. DUMP(AND);
  377. DUMP(OR);
  378. DUMP(NOT);
  379. DUMP(EQUAL);
  380. DUMP(NOT_EQUAL);
  381. DUMP(GREATER);
  382. DUMP(SMALLER);
  383. DUMP(GREATER_OR_EQUAL);
  384. DUMP(SMALLER_OR_EQUAL);
  385. DUMP_INT(CALL_SYSTEM);
  386. DUMP(STOP);
  387. case PUSH_CONSTANT_STRING:
  388. fprintf(
  389. stderr, "PUSH_CONSTANT_STRING %s\n",
  390. codeReadConstantString(&c));
  391. break;
  392. }
  393. }
  394. }