Compiler.c 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732
  1. #include <setjmp.h>
  2. #include <stdarg.h>
  3. #include <stdio.h>
  4. #include "Compiler.h"
  5. #include "FunctionMap.h"
  6. #include "Operation.h"
  7. #include "StringIntMap.h"
  8. #include "Tokenizer.h"
  9. #define ERROR_LENGTH 256
  10. #define RETURN_BUFFER 16
  11. #define BREAK_BUFFER 32
  12. static jmp_buf errorJump;
  13. static char error[ERROR_LENGTH] = {'\0'};
  14. static ByteCode* code;
  15. static int16 line = 1;
  16. static int varIndex = 0;
  17. static StringIntMap vars[2];
  18. static FunctionMap functions;
  19. static int returns[RETURN_BUFFER];
  20. static int returnIndex = 0;
  21. static int returnState = 0;
  22. static int breaks[BREAK_BUFFER];
  23. static int breakIndex = 0;
  24. static int forWhileStack = 0;
  25. static int continueAt = 0;
  26. static void cError(const char* format, ...) {
  27. va_list args;
  28. va_start(args, format);
  29. vsnprintf(error, ERROR_LENGTH, format, args);
  30. va_end(args);
  31. longjmp(errorJump, 0);
  32. }
  33. static int cAddVar(const char* var) {
  34. int index = vars[varIndex].entries;
  35. simAdd(vars + varIndex, var, &index);
  36. return index;
  37. }
  38. static void cUnexpectedToken(Token t) {
  39. cError("unexpected token on line %d: %s", line, tGetTokenName(t));
  40. }
  41. static void cAddOperation(Operation token) {
  42. unsigned char c = token;
  43. bcAddBytes(code, &c, 1);
  44. }
  45. static int cReserveInt() {
  46. return bcReserveBytes(code, sizeof(int));
  47. }
  48. static void cSetInt(int p, int i) {
  49. bcSetBytes(code, p, &i, sizeof(int));
  50. }
  51. static void cAddInt(int i) {
  52. bcAddBytes(code, &i, sizeof(int));
  53. }
  54. static void cAddInt16(int16 i) {
  55. bcAddBytes(code, &i, sizeof(int16));
  56. }
  57. static void cAddFloat(float f) {
  58. bcAddBytes(code, &f, sizeof(float));
  59. }
  60. static int cAddPush(int offset) {
  61. cAddOperation(OP_PUSH_VARS);
  62. int p = cReserveInt();
  63. cAddInt(offset);
  64. return p;
  65. }
  66. static void cAddPop(int p, int vars) {
  67. cAddOperation(OP_POP_VARS);
  68. cAddInt(vars);
  69. cSetInt(p, vars);
  70. }
  71. static Token cReadTokenAndLine() {
  72. Token t = tReadToken();
  73. if(tReadInt16(&line)) {
  74. return t;
  75. }
  76. return T_END;
  77. }
  78. static void cConsumeToken(Token wanted) {
  79. Token t = cReadTokenAndLine();
  80. if(wanted != t) {
  81. cError("unexpected token on line %d: expected '%s' got '%s'", line, tGetTokenName(wanted), tGetTokenName(t));
  82. }
  83. }
  84. static bool cConsumeTokenIf(Token t) {
  85. if(tPeekToken() == t) {
  86. cReadTokenAndLine();
  87. return true;
  88. }
  89. return false;
  90. }
  91. static void cConstantInt() {
  92. int value;
  93. if(!tReadInt(&value)) {
  94. cError("int token without an int on line %d", line);
  95. }
  96. cAddOperation(OP_PUSH_INT);
  97. cAddInt(value);
  98. }
  99. static void cConstantFloat() {
  100. float value;
  101. if(!tReadFloat(&value)) {
  102. cError("float token without a float on line %d", line);
  103. }
  104. cAddOperation(OP_PUSH_FLOAT);
  105. cAddFloat(value);
  106. }
  107. static const char* cReadString() {
  108. const char* literal = tReadString();
  109. if(literal == NULL) {
  110. cError("literal without string on line %d", line);
  111. }
  112. return literal;
  113. }
  114. static void cGetVar(const char* var) {
  115. cAddOperation(OP_GET);
  116. cAddInt(cAddVar(var));
  117. }
  118. static void cExpression();
  119. static int cCallFunctionArguments() {
  120. int arguments = 0;
  121. while(!cConsumeTokenIf(T_CLOSE_BRACKET)) {
  122. arguments++;
  123. cExpression();
  124. if(cConsumeTokenIf(T_COMMA) && tPeekToken() == T_CLOSE_BRACKET) {
  125. cUnexpectedToken(tPeekToken());
  126. }
  127. }
  128. return arguments;
  129. }
  130. static void cCallFunction(const char* literal, bool noReturn) {
  131. cAddOperation(OP_PUSH_INT);
  132. cAddInt(0);
  133. int arguments = cCallFunctionArguments();
  134. Function* f = fmSearch(&functions, literal, arguments);
  135. cAddOperation(OP_GOSUB);
  136. if(f == NULL) {
  137. fmEnqueue(&functions, literal, arguments, line, cReserveInt(), noReturn);
  138. cAddInt(arguments);
  139. cAddOperation(OP_NOTHING);
  140. } else {
  141. if(!noReturn && !f->returns) {
  142. cError("function '%s' needs a return value on line %d", f->name, line);
  143. }
  144. cAddInt(f->address);
  145. cAddInt(arguments);
  146. if(f->returns && noReturn) {
  147. cAddOperation(OP_POP);
  148. }
  149. }
  150. }
  151. static void cPostIncrement(const char* literal) {
  152. cAddOperation(OP_POST_INCREMENT);
  153. cAddInt(cAddVar(literal));
  154. }
  155. static void cPostDecrement(const char* literal) {
  156. cAddOperation(OP_POST_DECREMENT);
  157. cAddInt(cAddVar(literal));
  158. }
  159. static void cLiteral() {
  160. const char* literal = cReadString();
  161. if(cConsumeTokenIf(T_OPEN_BRACKET)) {
  162. cCallFunction(literal, false);
  163. } else if(cConsumeTokenIf(T_INCREMENT)) {
  164. cPostIncrement(literal);
  165. } else if(cConsumeTokenIf(T_DECREMENT)) {
  166. cPostDecrement(literal);
  167. } else {
  168. cGetVar(literal);
  169. }
  170. }
  171. static void cPrimary() {
  172. Token t = cReadTokenAndLine();
  173. switch(t) {
  174. case T_INT: cConstantInt(); break;
  175. case T_FLOAT: cConstantFloat(); break;
  176. case T_NULL: cAddOperation(OP_PUSH_NULL); break;
  177. case T_TRUE: cAddOperation(OP_PUSH_TRUE); break;
  178. case T_FALSE: cAddOperation(OP_PUSH_FALSE); break;
  179. case T_OPEN_BRACKET:
  180. cExpression();
  181. cConsumeToken(T_CLOSE_BRACKET);
  182. break;
  183. case T_LITERAL: cLiteral(); break;
  184. default: cUnexpectedToken(t); break;
  185. }
  186. }
  187. static void cPreIncrement() {
  188. cConsumeToken(T_LITERAL);
  189. cAddOperation(OP_PRE_INCREMENT);
  190. cAddInt(cAddVar(cReadString()));
  191. }
  192. static void cPreDecrement() {
  193. cConsumeToken(T_LITERAL);
  194. cAddOperation(OP_PRE_DECREMENT);
  195. cAddInt(cAddVar(cReadString()));
  196. }
  197. static void cPreUnary() {
  198. if(cConsumeTokenIf(T_SUB)) {
  199. cPrimary();
  200. cAddOperation(OP_INVERT_SIGN);
  201. } else if(cConsumeTokenIf(T_INCREMENT)) {
  202. cPreIncrement();
  203. } else if(cConsumeTokenIf(T_DECREMENT)) {
  204. cPreDecrement();
  205. } else if(cConsumeTokenIf(T_NOT)) {
  206. int counter = 1;
  207. while(cConsumeTokenIf(T_NOT)) {
  208. counter++;
  209. }
  210. cPrimary();
  211. cAddOperation(OP_NOT);
  212. if((counter & 1) == 0) {
  213. cAddOperation(OP_NOT);
  214. }
  215. } else if(cConsumeTokenIf(T_BIT_NOT)) {
  216. cPrimary();
  217. cAddOperation(OP_BIT_NOT);
  218. } else {
  219. cPrimary();
  220. }
  221. }
  222. static void cMul() {
  223. cPreUnary();
  224. while(true) {
  225. if(cConsumeTokenIf(T_MUL)) {
  226. cPreUnary();
  227. cAddOperation(OP_MUL);
  228. } else if(cConsumeTokenIf(T_DIV)) {
  229. cPreUnary();
  230. cAddOperation(OP_DIV);
  231. } else if(cConsumeTokenIf(T_MOD)) {
  232. cPreUnary();
  233. cAddOperation(OP_MOD);
  234. } else {
  235. break;
  236. }
  237. }
  238. }
  239. static void cAdd() {
  240. cMul();
  241. while(true) {
  242. if(cConsumeTokenIf(T_ADD)) {
  243. cMul();
  244. cAddOperation(OP_ADD);
  245. } else if(cConsumeTokenIf(T_SUB)) {
  246. cMul();
  247. cAddOperation(OP_SUB);
  248. } else {
  249. break;
  250. }
  251. }
  252. }
  253. static void cShift() {
  254. cAdd();
  255. while(true) {
  256. if(cConsumeTokenIf(T_LEFT_SHIFT)) {
  257. cAdd();
  258. cAddOperation(OP_LEFT_SHIFT);
  259. } else if(cConsumeTokenIf(T_RIGHT_SHIFT)) {
  260. cAdd();
  261. cAddOperation(OP_RIGHT_SHIFT);
  262. } else {
  263. break;
  264. }
  265. }
  266. }
  267. static void cComparison() {
  268. cShift();
  269. while(true) {
  270. if(cConsumeTokenIf(T_LESS)) {
  271. cShift();
  272. cAddOperation(OP_LESS);
  273. } else if(cConsumeTokenIf(T_LESS_EQUAL)) {
  274. cShift();
  275. cAddOperation(OP_GREATER);
  276. cAddOperation(OP_NOT);
  277. } else if(cConsumeTokenIf(T_GREATER)) {
  278. cShift();
  279. cAddOperation(OP_GREATER);
  280. } else if(cConsumeTokenIf(T_GREATER_EQUAL)) {
  281. cShift();
  282. cAddOperation(OP_LESS);
  283. cAddOperation(OP_NOT);
  284. } else {
  285. break;
  286. }
  287. }
  288. }
  289. static void cEqual() {
  290. cComparison();
  291. while(true) {
  292. if(cConsumeTokenIf(T_EQUAL)) {
  293. cComparison();
  294. cAddOperation(OP_EQUAL);
  295. } else if(cConsumeTokenIf(T_NOT_EQUAL)) {
  296. cComparison();
  297. cAddOperation(OP_EQUAL);
  298. cAddOperation(OP_NOT);
  299. } else {
  300. break;
  301. }
  302. }
  303. }
  304. static void cBitAnd() {
  305. cEqual();
  306. while(cConsumeTokenIf(T_BIT_AND)) {
  307. cEqual();
  308. cAddOperation(OP_BIT_AND);
  309. }
  310. }
  311. static void cBitXor() {
  312. cBitAnd();
  313. while(cConsumeTokenIf(T_BIT_XOR)) {
  314. cBitAnd();
  315. cAddOperation(OP_BIT_XOR);
  316. }
  317. }
  318. static void cBitOr() {
  319. cBitXor();
  320. while(cConsumeTokenIf(T_BIT_OR)) {
  321. cBitXor();
  322. cAddOperation(OP_BIT_OR);
  323. }
  324. }
  325. static void cAnd() {
  326. cBitOr();
  327. while(cConsumeTokenIf(T_AND)) {
  328. cAddOperation(OP_DUPLICATE);
  329. cAddOperation(OP_IF_GOTO);
  330. int p = cReserveInt();
  331. cBitOr();
  332. cAddOperation(OP_AND);
  333. cSetInt(p, code->length);
  334. }
  335. }
  336. static void cOr() {
  337. cAnd();
  338. while(cConsumeTokenIf(T_OR)) {
  339. cAddOperation(OP_DUPLICATE);
  340. cAddOperation(OP_NOT);
  341. cAddOperation(OP_IF_GOTO);
  342. int p = cReserveInt();
  343. cAnd();
  344. cAddOperation(OP_OR);
  345. cSetInt(p, code->length);
  346. }
  347. }
  348. static void cExpression() {
  349. cOr();
  350. }
  351. static void cSetVar(const char* literal) {
  352. cExpression();
  353. cAddOperation(OP_SET);
  354. cAddInt(cAddVar(literal));
  355. }
  356. static void cOperationSetVar(const char* literal, Operation op) {
  357. cGetVar(literal);
  358. cExpression();
  359. cAddOperation(op);
  360. cAddOperation(OP_SET);
  361. cAddInt(cAddVar(literal));
  362. }
  363. static void cLineLiteral() {
  364. const char* literal = cReadString();
  365. Token t = cReadTokenAndLine();
  366. switch(t) {
  367. case T_SET: cSetVar(literal); break;
  368. case T_ADD_SET: cOperationSetVar(literal, OP_ADD); break;
  369. case T_SUB_SET: cOperationSetVar(literal, OP_SUB); break;
  370. case T_MUL_SET: cOperationSetVar(literal, OP_MUL); break;
  371. case T_DIV_SET: cOperationSetVar(literal, OP_DIV); break;
  372. case T_MOD_SET: cOperationSetVar(literal, OP_MOD); break;
  373. case T_BIT_AND_SET: cOperationSetVar(literal, OP_BIT_AND); break;
  374. case T_BIT_OR_SET: cOperationSetVar(literal, OP_BIT_OR); break;
  375. case T_BIT_XOR_SET: cOperationSetVar(literal, OP_BIT_XOR); break;
  376. case T_LEFT_SHIFT_SET: cOperationSetVar(literal, OP_LEFT_SHIFT); break;
  377. case T_RIGHT_SHIFT_SET: cOperationSetVar(literal, OP_RIGHT_SHIFT); break;
  378. case T_OPEN_BRACKET: cCallFunction(literal, true); break;
  379. case T_INCREMENT:
  380. cPostIncrement(literal);
  381. cAddOperation(OP_POP);
  382. break;
  383. case T_DECREMENT:
  384. cPostDecrement(literal);
  385. cAddOperation(OP_POP);
  386. break;
  387. default: cUnexpectedToken(t);
  388. }
  389. }
  390. static int cFunctionArguments() {
  391. int arguments = 0;
  392. while(!cConsumeTokenIf(T_CLOSE_BRACKET)) {
  393. cConsumeToken(T_LITERAL);
  394. arguments++;
  395. cAddVar(cReadString());
  396. if(cConsumeTokenIf(T_COMMA) && tPeekToken() != T_LITERAL) {
  397. cUnexpectedToken(tPeekToken());
  398. }
  399. }
  400. return arguments;
  401. }
  402. static void cLine(Token t);
  403. static void cConsumeBody() {
  404. cConsumeToken(T_OPEN_CURVED_BRACKET);
  405. int oldLine = line;
  406. while(!cConsumeTokenIf(T_CLOSE_CURVED_BRACKET)) {
  407. Token t = cReadTokenAndLine();
  408. if(t == T_END) {
  409. cError("unexpected end of file: non closed curved bracket on line %d", oldLine);
  410. }
  411. cLine(t);
  412. }
  413. }
  414. static void cLinkReturns() {
  415. for(int i = 0; i < returnIndex; i++) {
  416. cSetInt(returns[i], vars[1].entries);
  417. }
  418. returnIndex = 0;
  419. }
  420. static void cFunctionBody(const char* name, int arguments) {
  421. int oldLine = line;
  422. cAddOperation(OP_GOTO);
  423. int gotoIndex = cReserveInt();
  424. int address = code->length;
  425. returnState = 0;
  426. int p = cAddPush(arguments);
  427. cConsumeBody();
  428. cAddPop(p, vars[1].entries);
  429. cLinkReturns();
  430. if(!fmAdd(&functions, name, arguments, address, returnState == 2)) {
  431. cError("function registered twice on line %d", oldLine);
  432. }
  433. cAddOperation(OP_RETURN);
  434. cSetInt(gotoIndex, code->length);
  435. }
  436. static void cFunction() {
  437. if(varIndex == 1) {
  438. cError("function inside function on line %d", line);
  439. }
  440. cConsumeToken(T_LITERAL);
  441. const char* name = cReadString();
  442. cConsumeToken(T_OPEN_BRACKET);
  443. varIndex = 1;
  444. vars[1].entries = 0;
  445. cFunctionBody(name, cFunctionArguments());
  446. varIndex = 0;
  447. }
  448. static void cAddReturn() {
  449. cAddOperation(OP_POP_VARS);
  450. returns[returnIndex++] = cReserveInt(vars);
  451. cAddOperation(OP_RETURN);
  452. }
  453. static void cReturn() {
  454. if(varIndex == 0) {
  455. cError("return without a function on line %d", line);
  456. } else if(returnIndex >= RETURN_BUFFER) {
  457. cError("too much returns in function around line %d", line);
  458. }
  459. if(cConsumeTokenIf(T_SEMICOLON)) {
  460. if(returnState == 2) {
  461. cError("mixed return type on line %d", line);
  462. }
  463. returnState = 1;
  464. cAddReturn();
  465. } else {
  466. if(returnState == 1) {
  467. cError("mixed return type on line %d", line);
  468. }
  469. returnState = 2;
  470. cExpression();
  471. cAddOperation(OP_SET_RETURN);
  472. cAddReturn();
  473. cConsumeToken(T_SEMICOLON);
  474. }
  475. }
  476. static void cPrint() {
  477. cExpression();
  478. cConsumeToken(T_SEMICOLON);
  479. cAddOperation(OP_PRINT);
  480. }
  481. static void cIf() {
  482. cConsumeToken(T_OPEN_BRACKET);
  483. cExpression();
  484. cConsumeToken(T_CLOSE_BRACKET);
  485. cAddOperation(OP_IF_GOTO);
  486. int ifP = cReserveInt();
  487. cConsumeBody();
  488. cSetInt(ifP, code->length);
  489. if(cConsumeTokenIf(T_ELSE)) {
  490. cAddOperation(OP_GOTO);
  491. int elseP = cReserveInt();
  492. cSetInt(ifP, code->length);
  493. if(cConsumeTokenIf(T_IF)) {
  494. cIf();
  495. } else {
  496. cConsumeBody();
  497. }
  498. cSetInt(elseP, code->length);
  499. }
  500. }
  501. static void cConsumeBreaks(int start, int address) {
  502. for(int i = start; i < breakIndex; i++) {
  503. cSetInt(breaks[i], address);
  504. }
  505. breakIndex = start;
  506. }
  507. static void cWhile() {
  508. int start = code->length;
  509. cConsumeToken(T_OPEN_BRACKET);
  510. cExpression();
  511. cConsumeToken(T_CLOSE_BRACKET);
  512. cAddOperation(OP_IF_GOTO);
  513. int ifP = cReserveInt();
  514. int breakStart = breakIndex;
  515. forWhileStack++;
  516. int oldContinue = continueAt;
  517. continueAt = start;
  518. cConsumeBody();
  519. continueAt = oldContinue;
  520. forWhileStack--;
  521. cAddOperation(OP_GOTO);
  522. cAddInt(start);
  523. cSetInt(ifP, code->length);
  524. cConsumeBreaks(breakStart, code->length);
  525. }
  526. static void cLineExpression(Token t) {
  527. switch(t) {
  528. case T_LITERAL: cLineLiteral(); break;
  529. case T_INCREMENT:
  530. cPreIncrement();
  531. cAddOperation(OP_POP);
  532. break;
  533. case T_DECREMENT:
  534. cPreDecrement();
  535. cAddOperation(OP_POP);
  536. break;
  537. default: cUnexpectedToken(t);
  538. }
  539. }
  540. static void cFor() {
  541. cConsumeToken(T_OPEN_BRACKET);
  542. cLineExpression(cReadTokenAndLine());
  543. cConsumeToken(T_SEMICOLON);
  544. int startCheck = code->length;
  545. cExpression();
  546. cConsumeToken(T_SEMICOLON);
  547. cAddOperation(OP_IF_GOTO);
  548. int end = cReserveInt();
  549. cAddOperation(OP_GOTO);
  550. int beginBody = cReserveInt();
  551. int startPerLoop = code->length;
  552. cLineExpression(cReadTokenAndLine());
  553. cAddOperation(OP_GOTO);
  554. cAddInt(startCheck);
  555. cConsumeToken(T_CLOSE_BRACKET);
  556. cSetInt(beginBody, code->length);
  557. int breakStart = breakIndex;
  558. forWhileStack++;
  559. int oldContinue = continueAt;
  560. continueAt = startPerLoop;
  561. cConsumeBody();
  562. continueAt = oldContinue;
  563. forWhileStack--;
  564. cAddOperation(OP_GOTO);
  565. cAddInt(startPerLoop);
  566. cSetInt(end, code->length);
  567. cConsumeBreaks(breakStart, code->length);
  568. }
  569. static void cBreak() {
  570. if(forWhileStack == 0) {
  571. cError("break without for or while on line %d", line);
  572. } else if(breakIndex >= BREAK_BUFFER) {
  573. cError("too much breaks around line %d", line);
  574. }
  575. cAddOperation(OP_GOTO);
  576. breaks[breakIndex++] = cReserveInt();
  577. cConsumeToken(T_SEMICOLON);
  578. }
  579. static void cContinue() {
  580. if(forWhileStack == 0) {
  581. cError("continue without for or while on line %d", line);
  582. }
  583. cAddOperation(OP_GOTO);
  584. cAddInt(continueAt);
  585. cConsumeToken(T_SEMICOLON);
  586. }
  587. static void cLine(Token t) {
  588. cAddOperation(OP_LINE);
  589. cAddInt16(line);
  590. switch(t) {
  591. case T_PRINT: cPrint(); break;
  592. case T_FUNCTION: cFunction(); break;
  593. case T_RETURN: cReturn(); break;
  594. case T_IF: cIf(); break;
  595. case T_WHILE: cWhile(); break;
  596. case T_FOR: cFor(); break;
  597. case T_BREAK: cBreak(); break;
  598. case T_CONTINUE: cContinue(); break;
  599. default: cLineExpression(t); cConsumeToken(T_SEMICOLON);
  600. }
  601. }
  602. static void cForEachLine() {
  603. Token t = cReadTokenAndLine();
  604. while(t != T_END) {
  605. cLine(t);
  606. t = cReadTokenAndLine();
  607. }
  608. }
  609. static void cLinkQueuedFunctions() {
  610. for(int i = 0; i < functions.queueEntries; i++) {
  611. Function* f = fmSearch(&functions, functions.queue[i].name, functions.queue[i].arguments);
  612. if(f == NULL) {
  613. cError("unknown function on line %d", functions.queue[i].line);
  614. } else if(!functions.queue[i].noReturn && !f->returns) {
  615. cError("function '%s' needs a return value on line %d", f->name, functions.queue[i].line);
  616. }
  617. cSetInt(functions.queue[i].reserved, f->address);
  618. if(functions.queue[i].noReturn && f->returns) {
  619. code->code[functions.queue[i].reserved + sizeof(int) * 2] = OP_POP;
  620. }
  621. }
  622. }
  623. static void cAllocAndCompile() {
  624. varIndex = 0;
  625. returnIndex = 0;
  626. returnState = 0;
  627. forWhileStack = 0;
  628. breakIndex = 0;
  629. simInit(vars);
  630. simInit(vars + 1);
  631. fmInit(&functions);
  632. if(!setjmp(errorJump)) {
  633. int p = cAddPush(0);
  634. cForEachLine();
  635. cAddPop(p, vars[varIndex].entries);
  636. cLinkQueuedFunctions();
  637. }
  638. fmDelete(&functions);
  639. simDelete(vars + 1);
  640. simDelete(vars);
  641. }
  642. ByteCode* cCompile() {
  643. error[0] = '\0';
  644. code = bcInit();
  645. cAllocAndCompile();
  646. if(error[0] != '\0') {
  647. bcDelete(code);
  648. return NULL;
  649. }
  650. return code;
  651. }
  652. const char* cGetError() {
  653. return error;
  654. }