Compiler.c 19 KB

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