alang.js 35 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681
  1. let flags = globalThis.flags;
  2. if (flags == null) {
  3. flags = {};
  4. flags.alang_source = null;
  5. flags.alang_output = "./test.c";
  6. }
  7. // ██████╗ █████╗ ██████╗ ███████╗ ███████╗
  8. // ██╔══██╗ ██╔══██╗ ██╔══██╗ ██╔════╝ ██╔════╝
  9. // ██████╔╝ ███████║ ██████╔╝ ███████╗ █████╗
  10. // ██╔═══╝ ██╔══██║ ██╔══██╗ ╚════██║ ██╔══╝
  11. // ██║ ██║ ██║ ██║ ██║ ███████║ ███████╗
  12. // ╚═╝ ╚═╝ ╚═╝ ╚═╝ ╚═╝ ╚══════╝ ╚══════╝
  13. let specials = [":", ";", ",", "(", ")", "[", "]", "{", "}", "<", ">", "!"];
  14. let is_comment = false;
  15. let is_string = false;
  16. let pos = 0;
  17. let tokens = [];
  18. let header = "";
  19. function is_alpha_numeric(code) {
  20. return (code > 47 && code < 58) || // 0-9
  21. (code === 45) || // -
  22. (code === 43) || // +
  23. (code === 95) || // _
  24. (code === 46) || // .
  25. (code > 64 && code < 91) || // A-Z
  26. (code > 96 && code < 123); // a-z
  27. }
  28. function is_alpha(code) {
  29. return (code > 96 && code < 123) || // a-z
  30. (code > 64 && code < 91) || // A-Z
  31. (code === 95); // _
  32. }
  33. function is_numeric(code) {
  34. return (code > 47 && code < 58); // 0-9
  35. }
  36. function is_white_space(code) {
  37. return code === 32 || // " "
  38. code === 9 || // "\t"
  39. code === 13 || // "\r"
  40. code === 10; // "\n"
  41. }
  42. function read_token() {
  43. // Skip white space
  44. while (is_white_space(flags.alang_source.charCodeAt(pos))) {
  45. pos++;
  46. }
  47. let token = "";
  48. let first = true;
  49. let is_anum = false;
  50. while (pos < flags.alang_source.length) {
  51. let c = flags.alang_source.charAt(pos);
  52. // Comment start
  53. if (token === "//") {
  54. is_comment = true;
  55. }
  56. if (is_comment) {
  57. token += c;
  58. pos++;
  59. // Comment end
  60. if (c === "\n") {
  61. is_comment = false;
  62. if (token.startsWith("///include") || token.startsWith("///define")) {
  63. header += "#" + token.substring(3, token.length);
  64. }
  65. // Remove comments
  66. return null;
  67. }
  68. // Prevent parsing of comments
  69. continue;
  70. }
  71. // String start / end
  72. if (c === "\"") {
  73. // Escaped \"
  74. let last = token.length > 0 ? token.charAt(token.length - 1) : "";
  75. let last_last = token.length > 1 ? token.charAt(token.length - 2) : "";
  76. let is_escaped = last === "\\" && last_last != "\\";
  77. if (!is_escaped) {
  78. is_string = !is_string;
  79. }
  80. // Token end - string end
  81. if (!is_string) {
  82. token += c;
  83. pos++;
  84. break;
  85. }
  86. }
  87. if (is_string) {
  88. if (c == "\r") {
  89. pos++;
  90. continue;
  91. }
  92. token += c;
  93. pos++;
  94. // Prevent parsing of strings
  95. continue;
  96. }
  97. // Token end
  98. if (is_white_space(flags.alang_source.charCodeAt(pos))) {
  99. break;
  100. }
  101. // Parsing an alphanumeric token
  102. if (first) {
  103. first = false;
  104. is_anum = is_alpha_numeric(c.charCodeAt(0));
  105. }
  106. // Token end
  107. let is_special = specials.indexOf(c) > -1;
  108. if (is_anum && is_special) {
  109. break;
  110. }
  111. // Add char to token and advance pos
  112. token += c;
  113. pos++;
  114. // Token end, got special
  115. if (is_special) {
  116. break;
  117. }
  118. }
  119. return token;
  120. }
  121. function alang_parse() {
  122. tokens = [];
  123. pos = 0;
  124. while (true) {
  125. let token = read_token();
  126. if (token === "") { // No more tokens
  127. break;
  128. }
  129. if (token === "=" && tokens[tokens.length - 1] === "!") { // Merge "!" and "=" into "!=" token
  130. tokens[tokens.length - 1] = "!=";
  131. continue;
  132. }
  133. if (token == null) { // Throw away this token
  134. continue;
  135. }
  136. tokens.push(token);
  137. }
  138. }
  139. // ██╗ ██╗ ██████╗
  140. // ██║ ██║ ██╔══██╗
  141. // ██║ ██║ ██████╔╝
  142. // ██║ ██║ ██╔══██╗
  143. // ███████╗ ██║ ██████╔╝
  144. // ╚══════╝ ╚═╝ ╚═════╝
  145. let fhandle;
  146. let strings = [];
  147. let tabs = 0;
  148. let new_line = false;
  149. let basic_types = ["i8", "u8", "i16", "u16", "i32", "u32", "f32", "i64", "u64", "f64", "bool"];
  150. let pass_by_value_types = ["vec4_t", "vec3_t", "vec2_t", "quat_t", "mat4_t", "mat3_t"];
  151. let enums = [];
  152. let value_types = new Map();
  153. let struct_types = new Map();
  154. let fn_declarations = new Map();
  155. let fn_default_params = new Map();
  156. let fn_call_stack = [];
  157. let param_pos_stack = [];
  158. let is_for_loop = false;
  159. let global_inits = [];
  160. let global_ptrs = [];
  161. function handle_tabs(token) {
  162. // Entering block, add tab
  163. if (token === "{") {
  164. tabs++;
  165. }
  166. else if (token === "}") {
  167. tabs--;
  168. }
  169. if (is_for_loop) {
  170. return;
  171. }
  172. // New line, add tabs
  173. if (new_line) {
  174. for (let i = 0; i < tabs; ++i) {
  175. out("\t");
  176. }
  177. }
  178. }
  179. function handle_new_line(token) {
  180. if (is_for_loop) {
  181. return;
  182. }
  183. // Insert new line
  184. new_line = token === ";" || token === "{" || token === "}";
  185. if (new_line) {
  186. out("\n");
  187. }
  188. }
  189. let add_space_keywords = ["return", "else"];
  190. function handle_spaces(token) {
  191. // Add space to separate keywords
  192. if (add_space_keywords.indexOf(token) > -1) {
  193. out(" ");
  194. }
  195. }
  196. function get_token(off = 0) {
  197. // if (pos + off < tokens.length) {
  198. return tokens[pos + off];
  199. // }
  200. // return "";
  201. }
  202. function get_token_after_piece() {
  203. let _pos = pos;
  204. skip_piece();
  205. let t = get_token(1);
  206. pos = _pos;
  207. return t;
  208. }
  209. function skip_until(s) {
  210. while (true) {
  211. let token = get_token();
  212. if (token === s) {
  213. break;
  214. }
  215. pos++;
  216. }
  217. }
  218. function skip_block() { // { ... }
  219. pos++; // {
  220. let nested = 1;
  221. while (true) {
  222. let token = get_token();
  223. if (token === "}") {
  224. nested--;
  225. if (nested === 0) {
  226. break;
  227. }
  228. }
  229. else if (token === "{") {
  230. nested++;
  231. }
  232. pos++;
  233. }
  234. }
  235. function function_return_type() {
  236. let _pos = pos;
  237. skip_until("{");
  238. let t = get_token(-1);
  239. if (t === "]") { // ): i32[]
  240. pos -= 2;
  241. }
  242. else if (t === ">") { // ): map_t<a, b>
  243. pos -= 5;
  244. }
  245. pos -= 2; // ): i32 {
  246. let result = get_token() === ":" ? read_type() : "void";
  247. pos = _pos;
  248. return result;
  249. }
  250. function join_type_name(type, name) {
  251. value_types.set(name, type);
  252. if (type.indexOf("(*NAME)(") > 0) { // Function pointer
  253. return type.replace("NAME", name);
  254. }
  255. return type + " " + name;
  256. }
  257. function read_type() { // Cursor at ":"
  258. pos++;
  259. let type = get_token();
  260. if (type === "(" && get_token(1) === "(") { // (()=>void)[]
  261. pos++;
  262. }
  263. if (get_token(1) === ")" && get_token(2) === "[") { // (()=>void)[]
  264. pos++;
  265. }
  266. if (type === "(") { // ()=>void
  267. let params = "(";
  268. if (get_token(1) != ")") { // Has params
  269. while (true) {
  270. skip_until(":");
  271. params += read_type();
  272. pos++;
  273. if (get_token() === ")") { // End of params
  274. break;
  275. }
  276. params += ",";
  277. }
  278. }
  279. else {
  280. params += "void";
  281. }
  282. params += ")";
  283. skip_until("=>");
  284. let ret = read_type();
  285. type = ret + "(*NAME)" + params;
  286. }
  287. if (type === "color_t") {
  288. type = "i32";
  289. }
  290. else if (type === "string") {
  291. type = "string_t";
  292. }
  293. if (get_token(1) === "[") { // Array
  294. if (is_struct(type)) {
  295. type = type + "_array_t";
  296. }
  297. else if (type === "bool") {
  298. type = "u8_array_t";
  299. }
  300. else {
  301. type = type + "_array_t";
  302. }
  303. pos += 2; // Skip "[]"
  304. }
  305. if (is_struct(type) && pass_by_value_types.indexOf(type) === -1) {
  306. type += " *";
  307. }
  308. if (type === "map_t *" && get_token(1) === "<") { // Map
  309. let mv = get_token(4);
  310. if (mv === "f32") {
  311. type = "f32_" + type;
  312. }
  313. else if (basic_types.indexOf(mv) > -1) {
  314. let mk = get_token(2);
  315. if (mk === "i32") {
  316. type = "i32_i" + type;
  317. }
  318. else {
  319. type = "i32_" + type;
  320. }
  321. }
  322. else {
  323. let mk = get_token(2);
  324. if (mk === "i32") {
  325. type = "any_i" + type;
  326. }
  327. else {
  328. type = "any_" + type;
  329. }
  330. }
  331. skip_until(">"); // Skip <a, b>
  332. }
  333. return type;
  334. }
  335. function enum_access(s) {
  336. // Turn enum_t.VALUE into enum_t_VALUE
  337. if (s.indexOf("_t.") > -1) {
  338. for (let e of enums) {
  339. if (s.indexOf(e) > -1) {
  340. s = s.replaceAll(".", "_");
  341. break;
  342. }
  343. }
  344. }
  345. return s;
  346. }
  347. function struct_access(s) {
  348. // Turn a.b into a->b
  349. let dot = s.indexOf(".");
  350. if (dot === -1) {
  351. return s;
  352. }
  353. if (is_numeric(s.charCodeAt(dot + 1))) {
  354. return s;
  355. }
  356. if (s.indexOf("\"") > -1) {
  357. return s;
  358. }
  359. if (s.startsWith("GC_ALLOC_INIT")) {
  360. return s;
  361. }
  362. // Accessing pass_by_value_types struct like vec4.x
  363. let has_minus = s.startsWith("-");
  364. let base = s.substring(has_minus ? 1 : 0, dot);
  365. let type = value_types.get(base);
  366. if (type != null) {
  367. let dot_last = s.lastIndexOf(".");
  368. if (dot != dot_last) { // a.vec4.x
  369. let parts = s.split(".");
  370. for (let i = 1; i < parts.length - 1; ++i) {
  371. let struct_value_types = struct_types.get(type);
  372. if (struct_value_types != null) {
  373. type = struct_value_types.get(parts[i]);
  374. // struct my_struct -> my_struct_t
  375. // my_struct * -> my_struct
  376. if (type.startsWith("struct ") && type.endsWith(" *")) {
  377. type = type.substring(0, type.length - 2);
  378. type = type.substring(7, type.length) + "_t *";
  379. }
  380. }
  381. }
  382. if (!type.endsWith(" *")) { // vec4_t
  383. let first = s.substring(0, dot_last).replaceAll(".", "->");
  384. let last = s.substring(dot_last, s.length);
  385. return first + last; // a->vec4.x
  386. }
  387. }
  388. else if (!type.endsWith(" *")) { // vec4.x
  389. return s;
  390. }
  391. }
  392. return s.replaceAll(".", "->");
  393. }
  394. function struct_alloc(token, type = null) {
  395. // "= { a: b, ... }" -> GC_ALLOC_INIT
  396. if ((get_token(-1) === "=" && token === "{" && get_token(-3) != "type") || type != null) {
  397. if (type == null) {
  398. // let a: b = {, a = {, a.b = {
  399. let i = get_token(-3) === ":" ? -4 : -2;
  400. let t = struct_access(get_token(i));
  401. type = value_type(t);
  402. if (type.endsWith(" *")) { // my_struct * -> my_struct
  403. type = type.substring(0, type.length - 2);
  404. }
  405. if (type.startsWith("struct ")) { // struct my_struct -> my_struct_t
  406. type = type.substring(7, type.length) + "_t";
  407. }
  408. }
  409. token = "GC_ALLOC_INIT(" + type + ", {";
  410. pos++; // {
  411. let ternary = 0;
  412. while (true) {
  413. let t = get_token();
  414. if (t == "}") {
  415. break;
  416. }
  417. let tc = get_token_c();
  418. tc = string_ops(tc);
  419. if (get_token(1) === ":" && !ternary) {
  420. tc = "." + tc; // a: b -> .a = b
  421. }
  422. if (t === ":") {
  423. if (ternary > 0) {
  424. ternary--;
  425. }
  426. else {
  427. tc = "=";
  428. }
  429. }
  430. else if (t === "?") {
  431. ternary++;
  432. }
  433. else if (t === "[" && get_token(-1) === ":") {
  434. let member = get_token(-2);
  435. let types = struct_types.get(type + " *");
  436. let content_type = types.get(member);
  437. content_type = content_type.substring(7, content_type.length - 8); // struct my_struct_array_t * -> my_struct
  438. tc = array_create("[", "", content_type);
  439. }
  440. token += tc;
  441. pos++;
  442. }
  443. // "= {}" -> "= {0}", otherwise msvc refuses to init members to zero
  444. if (get_token(-1) === "{") {
  445. token += "0";
  446. }
  447. token += get_token(); // "}"
  448. token += ")";
  449. tabs--;
  450. }
  451. return token;
  452. }
  453. function array_type(name) {
  454. let type = value_type(name);
  455. if (type == null) {
  456. return "any";
  457. }
  458. if (type.startsWith("struct ")) { // struct u8_array * -> u8_array_t *
  459. type = type.substring(7, type.length - 2) + "_t *";
  460. }
  461. type = strip(type, 10); // Strip _array_t *
  462. if (basic_types.indexOf(type) > -1) { // u8
  463. return type;
  464. }
  465. return "any";
  466. }
  467. function array_contents(type) {
  468. // [1, 2, ..] or [{a:b}, {a:b}, ..] or [a(), b(), ..]
  469. let contents = [];
  470. let content = "";
  471. while (true) {
  472. pos++;
  473. let token = get_token();
  474. if (token === "]") {
  475. if (content != "") {
  476. contents.push(content);
  477. }
  478. break;
  479. }
  480. if (token === ",") {
  481. contents.push(content);
  482. content = "";
  483. continue;
  484. }
  485. if (token === "{") {
  486. token = struct_alloc(token, type);
  487. tabs++; // Undo tabs-- in struct_alloc
  488. }
  489. if (get_token(1) === "(") {
  490. // Function call
  491. while (true) {
  492. pos++;
  493. token += get_token();
  494. token = fill_default_params(token);
  495. if (token.endsWith(")")) {
  496. break;
  497. }
  498. }
  499. }
  500. // a / b - > a / (float)b
  501. if (token === "/") {
  502. token = "/(float)";
  503. }
  504. token = struct_access(token);
  505. token = string_ops(token);
  506. content += token;
  507. }
  508. return contents;
  509. }
  510. function member_name(name) {
  511. let i = name.lastIndexOf(".");
  512. if (i > -1) {
  513. name = name.substring(i + 1, name.length);
  514. }
  515. return name;
  516. }
  517. function array_create(token, name, content_type = null) {
  518. if ((get_token(-1) === "=" && token === "[") || content_type != null) {
  519. if (name === "]") {
  520. name = get_token(-6); // ar: i32[] = [
  521. }
  522. let member = member_name(name);
  523. let type = array_type(member);
  524. // = [], = [1, 2, ..] -> any/i32/.._array_create_from_raw
  525. if (content_type == null) {
  526. name = struct_access(name);
  527. content_type = value_type(name);
  528. if (content_type != null) {
  529. content_type = content_type.substring(0, content_type.length - 10);
  530. }
  531. }
  532. let contents = array_contents(content_type);
  533. token = type + "_array_create_from_raw((" + type + "[]){";
  534. for (let e of contents) {
  535. token += e + ",";
  536. }
  537. token += "}," + contents.length + ")";
  538. }
  539. return token;
  540. }
  541. function array_access(token) {
  542. // array[0] -> array->buffer[0]
  543. if (token === "[" && get_token(-1) != "=") {
  544. return "->buffer[";
  545. }
  546. return token;
  547. }
  548. function is_struct(type) {
  549. // Ends with _t and is not an enum
  550. return type.endsWith("_t") && enums.indexOf(type) === -1;
  551. }
  552. function strip(name, len) {
  553. return name.substring(0, name.length - len);
  554. }
  555. function strip_optional(name) {
  556. if (name.endsWith("?")) {
  557. return strip(name, 1); // :val? -> :val
  558. }
  559. return name;
  560. }
  561. function param_pos() {
  562. return param_pos_stack[param_pos_stack.length - 1];
  563. }
  564. function param_pos_add() {
  565. param_pos_stack[param_pos_stack.length - 1]++;
  566. }
  567. function fn_call() {
  568. return fn_call_stack[fn_call_stack.length - 1];
  569. }
  570. function fill_fn_params(token) {
  571. if (token === "(") {
  572. // Function is being called to init this variable
  573. fn_call_stack.push(get_token(-1));
  574. param_pos_stack.push(0);
  575. }
  576. else if (token === ",") {
  577. // Param has beed passed manually
  578. param_pos_add();
  579. }
  580. else if (token === ")") {
  581. // Fill in default parameters if needed
  582. if (get_token(-1) != "(") {
  583. // Param has beed passed manually
  584. param_pos_add();
  585. }
  586. // If default param exists, fill it
  587. let res = "";
  588. while (fn_default_params.has(fn_call() + param_pos())) {
  589. if (param_pos() > 0) {
  590. res += ",";
  591. }
  592. res += fn_default_params.get(fn_call() + param_pos());
  593. param_pos_add();
  594. }
  595. fn_call_stack.pop();
  596. param_pos_stack.pop();
  597. token = res + token;
  598. }
  599. return token;
  600. }
  601. function get_token_c() {
  602. let t = get_token();
  603. t = enum_access(t);
  604. t = struct_access(t);
  605. t = array_access(t);
  606. return t;
  607. }
  608. function fill_default_params(piece) {
  609. // fn(a, 1, ..)
  610. if (get_token(1) === ")") {
  611. let fn_name = "";
  612. let params = 0;
  613. let i = 0;
  614. let nested = 1;
  615. while (true) {
  616. let ti = get_token(i);
  617. if (ti === ")") {
  618. nested++;
  619. }
  620. else if (ti === "(") {
  621. if (get_token(i - 1) === ":") { // : ()=>void
  622. return piece;
  623. }
  624. nested--;
  625. if (nested === 0) {
  626. fn_name = get_token(i - 1);
  627. if (get_token(i + 1) != ")") {
  628. params++;
  629. }
  630. break;
  631. }
  632. }
  633. else if (ti === ",") {
  634. params++;
  635. }
  636. i--;
  637. }
  638. while (fn_default_params.has(fn_name + params)) {
  639. if (params > 0) {
  640. piece += ",";
  641. }
  642. piece += fn_default_params.get(fn_name + params);
  643. params++;
  644. }
  645. }
  646. return piece;
  647. }
  648. function skip_piece(nested = 0) {
  649. let t1 = get_token(1);
  650. if (t1 === "(" || t1 === "[") {
  651. nested++;
  652. pos++;
  653. skip_piece(nested);
  654. return;
  655. }
  656. if (t1 === ")" || t1 === "]") {
  657. nested--;
  658. if (nested < 0) {
  659. return;
  660. }
  661. pos++;
  662. skip_piece(nested);
  663. return;
  664. }
  665. if (nested > 0) {
  666. pos++;
  667. skip_piece(nested);
  668. return;
  669. }
  670. if (t1.startsWith(".")) {
  671. pos++;
  672. skip_piece();
  673. return;
  674. }
  675. }
  676. function read_piece(nested = 0) {
  677. // call(a, b, c), a[b + c]
  678. let piece = get_token_c();
  679. piece = string_length(piece);
  680. piece = map_ops(piece);
  681. let t1 = get_token(1);
  682. if (t1 === "(" || t1 === "[") {
  683. nested++;
  684. pos++;
  685. return piece + read_piece(nested);
  686. }
  687. if (t1 === ")" || t1 === "]") {
  688. nested--;
  689. if (nested < 0) {
  690. return piece;
  691. }
  692. piece = fill_default_params(piece);
  693. pos++;
  694. return piece + read_piece(nested);
  695. }
  696. if (nested > 0) {
  697. pos++;
  698. return piece + read_piece(nested);
  699. }
  700. if (t1.startsWith(".")) {
  701. pos++;
  702. return piece + read_piece();
  703. }
  704. return piece;
  705. }
  706. function string_length(token) {
  707. // "str->length" -> "string_length(str)"
  708. if (!token.endsWith("->length")) {
  709. return token;
  710. }
  711. let base = strip(token, 8); // ->length
  712. let type = value_type(base);
  713. if (type === "string_t *" || type === "struct string *") {
  714. token = "string_length(" + base + ")";
  715. }
  716. return token;
  717. }
  718. function value_type(value) {
  719. let arrow = value.indexOf("->");
  720. if (arrow > -1) {
  721. let base = value.substring(0, arrow);
  722. let type = value_types.get(base);
  723. let member = value.substring(arrow + 2, value.length);
  724. let struct_value_types = struct_types.get(type);
  725. if (struct_value_types != null) {
  726. return struct_value_types.get(member);
  727. }
  728. }
  729. return value_types.get(value);
  730. }
  731. function set_fn_param_types() {
  732. pos++; // (
  733. while (true) {
  734. pos++;
  735. let t = get_token(); // Param name, ) or ,
  736. if (t === ")") { // Params end
  737. break;
  738. }
  739. if (t === ",") { // Next param
  740. continue;
  741. }
  742. pos++; // :
  743. let type = read_type();
  744. value_types.set(t, type);
  745. if (get_token(1) === "=") { // Skip default value
  746. pos += 2;
  747. }
  748. }
  749. }
  750. function number_to_string(token) {
  751. let type = value_type(token);
  752. if (type === "i32") {
  753. return "i32_to_string(" + token + ")";
  754. }
  755. if (type === "f32") {
  756. return "f32_to_string(" + token + ")";
  757. }
  758. return token;
  759. }
  760. function token_is_string(token) {
  761. let is_string = token.startsWith("\"") || value_type(token) === "string_t *";
  762. if (!is_string) {
  763. let _pos = pos;
  764. skip_piece();
  765. let t1 = get_token(1);
  766. if (t1 === "+" || t1 === "+=" || t1 === "==" || t1 === "!=") {
  767. let t2 = get_token(2);
  768. if (t2.startsWith("\"") || value_type(t2) === "string_t *") {
  769. is_string = true;
  770. }
  771. }
  772. pos = _pos;
  773. }
  774. if (is_string && get_token(2) === "null") {
  775. is_string = false;
  776. }
  777. return is_string;
  778. }
  779. function string_add(token) {
  780. token = "string_join(" + token + ",";
  781. pos++;
  782. let token_b = read_piece();
  783. token_b = number_to_string(token_b);
  784. token += token_b;
  785. token += ")";
  786. return token;
  787. }
  788. function string_ops(token) {
  789. // "str" + str + 1 + ...
  790. if (!token_is_string(token)) {
  791. return token;
  792. }
  793. let first = true;
  794. while (get_token_after_piece() === "+") {
  795. if (first) {
  796. first = false;
  797. token = read_piece();
  798. token = number_to_string(token);
  799. }
  800. pos++;
  801. token = string_add(token);
  802. }
  803. // "str" += str + str2
  804. let p1 = get_token_after_piece();
  805. if (p1 === "+=") {
  806. token = read_piece();
  807. pos++;
  808. token = token + "=string_join(" + token + ",";
  809. pos++;
  810. if (get_token_after_piece() === "+") {
  811. let token_b = read_piece();
  812. token_b = number_to_string(token_b);
  813. while (get_token_after_piece() === "+") {
  814. pos++;
  815. token_b = string_add(token_b);
  816. }
  817. token += token_b;
  818. }
  819. else {
  820. token += read_piece();
  821. }
  822. token += ")";
  823. }
  824. // str = str
  825. else if (p1 === "=") {
  826. let _pos = pos;
  827. let t1 = read_piece();
  828. pos++;
  829. pos++; // =
  830. let t2 = read_piece();
  831. if (get_token(1) === ";" && !t2.startsWith("\"")) { // str = str;
  832. token = t1 + "=string_copy(" + t2 + ")"; // Copy string
  833. }
  834. else {
  835. pos = _pos;
  836. }
  837. }
  838. // "str" === str
  839. else if (p1 === "==") {
  840. token = read_piece();
  841. pos++;
  842. token = "string_equals(" + token + ",";
  843. pos++;
  844. token += read_piece();
  845. token += ")";
  846. }
  847. // "str" != str
  848. else if (p1 === "!=") {
  849. token = read_piece();
  850. pos++;
  851. token = "!string_equals(" + token + ",";
  852. pos++;
  853. token += read_piece();
  854. token += ")";
  855. }
  856. return token;
  857. }
  858. function array_ops(token) {
  859. // array_push -> i32_array_push/any_array_push
  860. if (token === "array_push") {
  861. let value = get_token(2);
  862. if (get_token(3) === "[") { // raws[i].value
  863. value = get_token(6).substring(1); // .value
  864. }
  865. if (value.lastIndexOf(".") > -1) {
  866. value = value.substring(value.lastIndexOf(".") + 1, value.length);
  867. }
  868. let type = array_type(value);
  869. token = type + "_array_push";
  870. }
  871. // array_remove -> i32_array_remove / char_ptr_array_remove
  872. else if (token === "array_remove") {
  873. let value = get_token(2);
  874. value = struct_access(value);
  875. let type = value_type(value);
  876. if (type != null && type.startsWith("struct ")) { // struct u8_array * -> u8_array_t *
  877. type = type.substring(7, type.length - 2) + "_t *";
  878. }
  879. if (type === "i32_array_t *") {
  880. token = "i32_array_remove";
  881. }
  882. else if (type === "string_t_array_t *") {
  883. token = "char_ptr_array_remove";
  884. }
  885. }
  886. // array_index_of -> i32_array_index_of / char_ptr_array_index_of
  887. else if (token === "array_index_of") {
  888. let value = get_token(2);
  889. value = struct_access(value);
  890. let type = value_type(value);
  891. if (type != null && type.startsWith("struct ")) { // struct u8_array * -> u8_array_t *
  892. type = type.substring(7, type.length - 2) + "_t *";
  893. }
  894. if (type === "i32_array_t *") {
  895. token = "i32_array_index_of";
  896. }
  897. else if (type === "string_t_array_t *") {
  898. token = "char_ptr_array_index_of";
  899. }
  900. else {
  901. let fn = fn_declarations.get(value);
  902. if (fn != null && fn.startsWith("string_t_array_t *")) {
  903. token = "char_ptr_array_index_of";
  904. }
  905. }
  906. }
  907. return token;
  908. }
  909. function map_ops(token) {
  910. if (token === "map_create") {
  911. let t = value_type(get_token(-2));
  912. if (t === "i32_map_t *") {
  913. token = "i32_map_create";
  914. }
  915. else if (t === "i32_imap_t *") {
  916. token = "i32_imap_create";
  917. }
  918. else if (t === "any_imap_t *") {
  919. token = "any_imap_create";
  920. }
  921. else {
  922. token = "any_map_create";
  923. }
  924. }
  925. else if (token === "map_set") {
  926. let t = value_type(get_token(2));
  927. if (t === "i32_map_t *") {
  928. token = "i32_map_set";
  929. }
  930. else if (t === "i32_imap_t *") {
  931. token = "i32_imap_set";
  932. }
  933. else if (t === "any_imap_t *") {
  934. token = "any_imap_set";
  935. }
  936. else {
  937. token = "any_map_set";
  938. }
  939. }
  940. else if (token === "map_get") {
  941. let t = value_type(get_token(2));
  942. if (t === "i32_map_t *") {
  943. token = "i32_map_get";
  944. }
  945. else if (t === "i32_imap_t *") {
  946. token = "i32_imap_get";
  947. }
  948. else if (t === "any_imap_t *") {
  949. token = "any_imap_get";
  950. }
  951. else {
  952. token = "any_map_get";
  953. }
  954. }
  955. else if (token === "map_delete") {
  956. let t = value_type(get_token(2));
  957. if (t === "any_imap_t *") {
  958. token = "imap_delete";
  959. }
  960. }
  961. return token;
  962. }
  963. function _t_to_struct(type) {
  964. // type_t * -> struct type *
  965. if (type.endsWith("_t *") && type != "string_t *") {
  966. let type_short = strip(type, 4); // _t *
  967. if (type_short.endsWith("_array")) { // tex_format_t_array -> i32_array
  968. for (let e of enums) {
  969. if (type_short.startsWith(e)) {
  970. type_short = "i32_array";
  971. break;
  972. }
  973. }
  974. }
  975. type = "struct " + type_short + " *";
  976. }
  977. return type;
  978. }
  979. // ██╗ ██╗ ██████╗ ██╗ ████████╗ ███████╗ ██████╗
  980. // ██║ ██║ ██╔══██╗ ██║ ╚══██╔══╝ ██╔════╝ ██╔════╝
  981. // ██║ █╗ ██║ ██████╔╝ ██║ ██║ █████╗ ██║
  982. // ██║███╗██║ ██╔══██╗ ██║ ██║ ██╔══╝ ██║
  983. // ╚███╔███╔╝ ██║ ██║ ██║ ██║ ███████╗ ╚██████╗
  984. // ╚══╝╚══╝ ╚═╝ ╚═╝ ╚═╝ ╚═╝ ╚══════╝ ╚═════╝
  985. function stream_write(token) {
  986. fhandle.puts(token);
  987. }
  988. function string_write(token) {
  989. strings[strings.length - 1] += token;
  990. }
  991. function null_write(token) {
  992. return;
  993. }
  994. let out = stream_write;
  995. function write_enums() {
  996. enums = [];
  997. for (pos = 0; pos < tokens.length; ++pos) {
  998. let token = get_token();
  999. // Turn "enum name {}" into "typedef enum {} name;"
  1000. if (token === "enum") {
  1001. out = get_token(-1) === "declare" ? null_write : stream_write;
  1002. pos++;
  1003. let enum_name = get_token();
  1004. enums.push(enum_name);
  1005. out("typedef enum{\n");
  1006. pos++; // {
  1007. while (true) {
  1008. // Enum contents
  1009. pos++;
  1010. token = get_token(); // Item name
  1011. if (token === "}") { // Enum end
  1012. out("}" + enum_name + ";\n");
  1013. break;
  1014. }
  1015. out("\t" + enum_name + "_" + token);
  1016. pos++; // = or ,
  1017. token = get_token();
  1018. if (token === "=") { // Enum value
  1019. pos++; // n
  1020. token = get_token();
  1021. out("=" + token);
  1022. pos++; // ,
  1023. }
  1024. out(",\n");
  1025. }
  1026. out("\n");
  1027. continue;
  1028. }
  1029. }
  1030. out = stream_write;
  1031. }
  1032. function write_types() {
  1033. for (pos = 0; pos < tokens.length; ++pos) {
  1034. let token = get_token();
  1035. // Turn "type x = {};" into "typedef struct {} x;"
  1036. // Turn "type x = y;" into "typedef x y;"
  1037. if (token === "type") {
  1038. out = get_token(-1) === "declare" ? null_write : stream_write;
  1039. pos++;
  1040. let struct_name = get_token();
  1041. let stuct_name_short = strip(struct_name, 2); // _t
  1042. pos++;
  1043. token = get_token(); // =
  1044. if (token != "=") {
  1045. continue;
  1046. }
  1047. pos++;
  1048. token = get_token();
  1049. // "type x = y;"
  1050. if (token != "{") {
  1051. pos--;
  1052. let type = read_type();
  1053. type = _t_to_struct(type);
  1054. out("typedef " + type + " " + struct_name + ";\n\n");
  1055. skip_until(";");
  1056. continue;
  1057. }
  1058. // "type x = {};"
  1059. out("typedef struct " + stuct_name_short + "{\n");
  1060. let struct_value_types = new Map();
  1061. struct_types.set(struct_name + " *", struct_value_types);
  1062. while (true) {
  1063. // Struct contents
  1064. pos++;
  1065. let name = get_token();
  1066. if (name === "}") { // Struct end
  1067. out("}" + struct_name + ";\n");
  1068. break;
  1069. }
  1070. // val?: i32 -> val: i32
  1071. name = strip_optional(name);
  1072. pos++;
  1073. // :
  1074. let type = read_type();
  1075. // type_t * -> struct type *
  1076. type = _t_to_struct(type);
  1077. // my_struct_t*(*NAME)(my_struct_t *) -> struct my_struct*(*NAME)(struct my_struct*)
  1078. if (type.indexOf("(*NAME)") > -1) {
  1079. let args = type.substring(type.indexOf(")(") + 2, type.lastIndexOf(")"));
  1080. args = args.split(",");
  1081. type = type.substring(0, type.indexOf("(*NAME)"));
  1082. type = _t_to_struct(type);
  1083. type += "(*NAME)(";
  1084. for (let i = 0; i < args.length; ++i) {
  1085. let arg = args[i];
  1086. arg = _t_to_struct(arg);
  1087. if (i > 0) {
  1088. type += ",";
  1089. }
  1090. type += arg;
  1091. }
  1092. type += ")";
  1093. }
  1094. skip_until(";");
  1095. out("\t" + join_type_name(type, name) + ";\n");
  1096. struct_value_types.set(name, type);
  1097. }
  1098. out("\n");
  1099. continue;
  1100. }
  1101. }
  1102. out = stream_write;
  1103. }
  1104. function write_array_types() {
  1105. // Array structs (any_array_t -> scene_t_array_t)
  1106. let array_structs = new Map();
  1107. for (pos = 0; pos < tokens.length; ++pos) {
  1108. let token = get_token();
  1109. if (get_token(1) === "[") {
  1110. let type = token;
  1111. if (type === "string") {
  1112. type = "string_t";
  1113. }
  1114. if (is_struct(type)) {
  1115. if (!array_structs.has(type)) {
  1116. let as = "typedef struct " + type + "_array{" +
  1117. type + "**buffer;int length;int capacity;}" +
  1118. type + "_array_t;";
  1119. array_structs.set(type, as);
  1120. }
  1121. }
  1122. pos += 2; // Skip "[]"
  1123. }
  1124. }
  1125. for (let as of array_structs.values()) {
  1126. out(as);
  1127. out("\n");
  1128. }
  1129. out("\n");
  1130. }
  1131. function write_fn_declarations() {
  1132. fn_declarations = new Map();
  1133. fn_default_params = new Map();
  1134. let last_fn_name = "";
  1135. for (pos = 0; pos < tokens.length; ++pos) {
  1136. let token = get_token();
  1137. if (token === "function") {
  1138. out = get_token(-1) === "declare" ? null_write : stream_write;
  1139. // Return type + name
  1140. pos++;
  1141. let fn_name = get_token();
  1142. let ret = function_return_type();
  1143. if (fn_name === "(") { // Anonymous function
  1144. fn_name = last_fn_name + "_" + (pos - 1);
  1145. pos--;
  1146. }
  1147. else {
  1148. if (fn_name === "main") {
  1149. fn_name = "_main";
  1150. }
  1151. last_fn_name = fn_name;
  1152. }
  1153. // Params
  1154. let _param_pos = 0;
  1155. let params = "(";
  1156. pos++; // (
  1157. while (true) {
  1158. pos++;
  1159. token = get_token(); // Param name, ) or ,
  1160. if (token === ")") { // Params end
  1161. break;
  1162. }
  1163. if (token === ",") { // Next param
  1164. params += ",";
  1165. _param_pos++;
  1166. continue;
  1167. }
  1168. pos++; // :
  1169. let type = read_type();
  1170. params += join_type_name(type, token);
  1171. // Store param default
  1172. if (get_token(1) === "=") {
  1173. let param = get_token(2);
  1174. param = enum_access(param);
  1175. fn_default_params.set(fn_name + _param_pos, param);
  1176. pos += 2;
  1177. }
  1178. }
  1179. params += ")";
  1180. let fn_decl = ret + " " + fn_name + params;
  1181. out(fn_decl + ";\n");
  1182. fn_declarations.set(fn_name, fn_decl);
  1183. }
  1184. }
  1185. out("\n");
  1186. out = stream_write;
  1187. }
  1188. function write_globals() {
  1189. global_inits = [];
  1190. global_ptrs = [];
  1191. for (pos = 0; pos < tokens.length; ++pos) {
  1192. let token = get_token();
  1193. if (token === "let") {
  1194. out = get_token(-1) === "declare" ? null_write : stream_write;
  1195. pos++;
  1196. let name = get_token();
  1197. pos++; // :
  1198. let type = read_type();
  1199. if (basic_types.indexOf(type) === -1 &&
  1200. pass_by_value_types.indexOf(type) === -1 &&
  1201. enums.indexOf(type) === -1) {
  1202. global_ptrs.push(name);
  1203. }
  1204. out(join_type_name(type, name) + ";");
  1205. // Init this var in _kickstart()
  1206. let is_initialized = get_token(1) === "=";
  1207. if (is_initialized) {
  1208. let init = name;
  1209. tabs = 1;
  1210. while (true) {
  1211. pos++;
  1212. token = get_token();
  1213. token = enum_access(token);
  1214. token = array_access(token);
  1215. token = struct_alloc(token);
  1216. if (token === ";") {
  1217. break;
  1218. }
  1219. token = fill_fn_params(token);
  1220. // [] -> _array_create
  1221. token = array_create(token, name);
  1222. if (token === "map_create") {
  1223. let t = value_type(name);
  1224. if (t === "i32_map_t *") {
  1225. token = "i32_map_create";
  1226. }
  1227. else if (t === "i32_imap_t *") {
  1228. token = "i32_imap_create";
  1229. }
  1230. else if (t === "any_imap_t *") {
  1231. token = "any_imap_create";
  1232. }
  1233. else {
  1234. token = "any_map_create";
  1235. }
  1236. }
  1237. init += token;
  1238. }
  1239. global_inits.push(init);
  1240. }
  1241. out("\n");
  1242. }
  1243. // Skip function blocks
  1244. if (token === "function" && get_token(-1) != "declare") {
  1245. skip_until("{");
  1246. skip_block();
  1247. }
  1248. }
  1249. out = stream_write;
  1250. }
  1251. function write_kickstart() {
  1252. // Start function
  1253. out("\nvoid _kickstart() {\n");
  1254. // Init globals
  1255. for (let val of global_inits) {
  1256. out("\t");
  1257. let name = val.split("=")[0];
  1258. let global_alloc = global_ptrs.indexOf(name) > -1 && !val.endsWith("=null") && !val.endsWith("\"");
  1259. if (global_alloc) {
  1260. out("gc_unroot(" + name + ");");
  1261. }
  1262. out(val + ";");
  1263. if (global_alloc) {
  1264. out("gc_root(" + name + ");");
  1265. }
  1266. out("\n");
  1267. }
  1268. out("\t_main();\n");
  1269. out("\t#ifndef NO_IRON_START\n");
  1270. out("\tiron_start();\n");
  1271. out("\t#endif\n");
  1272. out("}\n\n");
  1273. }
  1274. function write_function() {
  1275. // Function declaration
  1276. let fn_name = get_token();
  1277. if (fn_name === "main") {
  1278. fn_name = "_main";
  1279. }
  1280. let fn_decl = fn_declarations.get(fn_name);
  1281. out(fn_decl + "{\n");
  1282. // Function body
  1283. // Re-set function param types into value_types map
  1284. set_fn_param_types();
  1285. skip_until("{");
  1286. tabs = 1;
  1287. new_line = true;
  1288. let mark_as_root = null;
  1289. let nested = [];
  1290. while (true) {
  1291. pos++;
  1292. let token = get_token();
  1293. if (token === "function") { // Begin nested function
  1294. let anon_fn = fn_name + "_" + pos;
  1295. out("&" + anon_fn);
  1296. if (get_token(-1) === "=") {
  1297. out(";\n");
  1298. }
  1299. skip_until("{");
  1300. out = string_write;
  1301. strings.push("");
  1302. let fn_decl = fn_declarations.get(anon_fn);
  1303. out(fn_decl + "{\n");
  1304. let find = fn_decl.substring(0, fn_decl.indexOf("("));
  1305. let fn_pos = parseInt(find.substring(find.lastIndexOf("_") + 1, find.length));
  1306. let _pos = pos;
  1307. pos = fn_pos;
  1308. set_fn_param_types();
  1309. pos = _pos;
  1310. nested.push(1);
  1311. continue;
  1312. }
  1313. if (nested.length > 0) {
  1314. if (token === "{") {
  1315. nested[nested.length - 1]++;
  1316. }
  1317. else if (token === "}") { // End nested function
  1318. nested[nested.length - 1]--;
  1319. if (nested[nested.length - 1] === 0) {
  1320. nested.pop();
  1321. out("}\n\n");
  1322. if (strings.length > 1) {
  1323. let s = strings.pop();
  1324. strings[strings.length - 1] = s + strings[strings.length - 1];
  1325. }
  1326. if (nested.length === 0) {
  1327. out = stream_write;
  1328. }
  1329. continue;
  1330. }
  1331. }
  1332. }
  1333. // Function end
  1334. if (token === "}" && tabs === 1) {
  1335. out("}\n\n");
  1336. break;
  1337. }
  1338. handle_tabs(token);
  1339. if (token === "for") { // Skip new lines in for (;;) loop
  1340. is_for_loop = true;
  1341. }
  1342. else if (token === "{") {
  1343. is_for_loop = false;
  1344. }
  1345. // Write type and name
  1346. else if (token === "let") {
  1347. pos++;
  1348. let name = get_token();
  1349. pos++; // :
  1350. let type = read_type();
  1351. out(join_type_name(type, name));
  1352. // = or ;
  1353. pos++;
  1354. token = get_token();
  1355. }
  1356. // Turn val.a into val_a or val->a
  1357. token = enum_access(token);
  1358. token = struct_access(token);
  1359. // array[0] -> array->buffer[0]
  1360. token = array_access(token);
  1361. // Use static alloc for global pointers
  1362. let is_assign = get_token(1) === "=" || get_token(1) === "+="; // += for string_join
  1363. if (is_assign && token != ":") {
  1364. if (global_ptrs.indexOf(token) > -1) {
  1365. out("gc_unroot(" + token + ");");
  1366. if (get_token(2) != "null") {
  1367. mark_as_root = token;
  1368. }
  1369. }
  1370. }
  1371. if (token === ";" && mark_as_root != null) {
  1372. out(";gc_root(" + mark_as_root + ")");
  1373. mark_as_root = null;
  1374. }
  1375. // "= { ... }" -> GC_ALLOC_INIT
  1376. token = struct_alloc(token);
  1377. // [] -> _array_create
  1378. token = array_create(token, get_token(-2));
  1379. token = array_ops(token);
  1380. // Maps
  1381. token = map_ops(token);
  1382. // Strings
  1383. token = string_ops(token);
  1384. // "str->length" -> "string_length(str)"
  1385. token = string_length(token);
  1386. // a / b - > a / (float)b
  1387. if (token === "/") {
  1388. token = "/(float)";
  1389. }
  1390. // a(1) -> a(1, 2) // a(x: i32, y: i32 = 2)
  1391. token = fill_fn_params(token);
  1392. // Write token
  1393. out(token);
  1394. handle_spaces(token);
  1395. handle_new_line(token);
  1396. }
  1397. }
  1398. function write_functions() {
  1399. for (pos = 0; pos < tokens.length; ++pos) {
  1400. let token = get_token();
  1401. if (token === "function") {
  1402. pos++;
  1403. if (get_token(-2) === "declare") {
  1404. continue;
  1405. }
  1406. write_function();
  1407. }
  1408. // Write anonymous function body
  1409. while (strings.length > 0) {
  1410. let s = strings.pop();
  1411. out(s);
  1412. }
  1413. }
  1414. }
  1415. function write_iron_c() {
  1416. out("#include <iron.h>\n\n");
  1417. out(header);
  1418. write_enums();
  1419. write_types();
  1420. write_array_types();
  1421. write_fn_declarations();
  1422. write_globals();
  1423. write_kickstart();
  1424. write_functions();
  1425. }
  1426. // ██╗ ██╗ ██╗ ██████╗ ██╗ ██╗ ███████╗ ████████╗ █████╗ ██████╗ ████████╗
  1427. // ██║ ██╔╝ ██║ ██╔════╝ ██║ ██╔╝ ██╔════╝ ╚══██╔══╝ ██╔══██╗ ██╔══██╗ ╚══██╔══╝
  1428. // █████╔╝ ██║ ██║ █████╔╝ ███████╗ ██║ ███████║ ██████╔╝ ██║
  1429. // ██╔═██╗ ██║ ██║ ██╔═██╗ ╚════██║ ██║ ██╔══██║ ██╔══██╗ ██║
  1430. // ██║ ██╗ ██║ ╚██████╗ ██║ ██╗ ███████║ ██║ ██║ ██║ ██║ ██║ ██║
  1431. // ╚═╝ ╚═╝ ╚═╝ ╚═════╝ ╚═╝ ╚═╝ ╚══════╝ ╚═╝ ╚═╝ ╚═╝ ╚═╝ ╚═╝ ╚═╝
  1432. function alang() {
  1433. alang_parse();
  1434. fhandle = std.open(flags.alang_output, "w");
  1435. write_iron_c();
  1436. fhandle.close();
  1437. }
  1438. let t = Date.now();
  1439. alang();
  1440. console.log("alang took " + (Date.now() - t) + "ms.");