Advertisement
rak235711

Untitled

Nov 30th, 2017
74
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 22.89 KB | None | 0 0
  1. ----- BEGIN KAOS v0.3 -----
  2. <!DOCTYPE HTML>
  3.  
  4. <!--
  5. KAOS v0.3
  6. -->
  7.  
  8. <html>
  9. <head>
  10. <meta charset="utf-8">
  11. <title>KAOS v0.3</title>
  12.  
  13. <style>
  14. canvas {
  15. position: absolute;
  16. top: 0;
  17. left: 0;
  18. width: 100%;
  19. height: 100%;
  20. }
  21. </style>
  22.  
  23. <script src="https://cdn.jsdelivr.net/processing.js/1.4.8/processing.min.js"></script>
  24. <script>
  25. var fcon;
  26.  
  27. // Nim based module system for importing and installing applications and .nim "binaries"
  28. // Heavily draws inspiration and snippets from Ben Burrill's acclaimed BMS, go give him an upvote! https://www.khanacademy.org/computer-programming/bens-module-system-version-2/6070976254115840
  29. var modules = {
  30. loadProgram: function (id, callback) {
  31. document.loadProgram = callback;
  32.  
  33. var scr = document.createElement("script");
  34. scr.src = "https://www.khanacademy.org/api/labs/scratchpads/" + id + "?callback=document.loadProgram";
  35.  
  36. document.head.appendChild(scr);
  37. },
  38.  
  39. downloadProgram: function (id, path, callback) {
  40. modules.loadProgram(id, function (data) {
  41. var f = new fcon("f", path);
  42. f.write(data.revision.code);
  43. f.init();
  44.  
  45. callback();
  46. });
  47. }
  48. }
  49. </script>
  50. </head>
  51. <body>
  52. <canvas id="kaos_canvas"></canvas>
  53.  
  54. <script>
  55. modules.loadProgram("5871784009596928", function (data) {
  56. eval(data.revision.code);
  57.  
  58. fcon = fs.File;
  59.  
  60. new Processing(document.getElementById("kaos_canvas"), function (processing) {
  61. with (processing) {
  62. init(modules, processing);
  63. }
  64. });
  65. });
  66. </script>
  67. </body>
  68. </html>
  69. ----- END KAOS v0.3 -----
  70. ----- BEGIN KAOS v0.3 BACKEND -----
  71. // jshint ignore:start
  72.  
  73. // The filesystem object.
  74. // Each entry's key is its path array, and entries are unordered.
  75. var filesystem = {};
  76.  
  77. // User constructor. Makes a user.
  78. var User = function (name, password) {
  79. this.name = name;
  80. this.password = password;
  81.  
  82. this.home = "/home/" + name;
  83. };
  84.  
  85. // Current user.
  86. var user = new User("guest");
  87.  
  88. // Users. Each element is the name of a user.
  89. var users = ["guest", "root"];
  90.  
  91. // Groups. Each group is simply a named array of usernames.
  92. var groups = {};
  93.  
  94. // Utility functions
  95. util: {
  96.  
  97. // Represents a KAOS error.
  98. var KAOSError = function (message) {
  99. this.message = message;
  100. };
  101.  
  102. // If first argument is undefined, return second argument. Otherwise return first.
  103. // Used for default parameters in functions.
  104. var def = function (first, second) {
  105. return first === undefined ? second : first;
  106. };
  107.  
  108. // Get a specific digit from an octal number.
  109. // Digit numbers are 0-indexed and big-endian.
  110. var getOctalDigit = function (number, digit) {
  111. // Binary magic
  112. return (number & (7 << (3 * digit))) >> (3 * digit);
  113. };
  114.  
  115. // readable(), writable(), and executable() return a truthy value if you can read/write/execute a file, and a falsy value if you can't.
  116.  
  117. var readable = function (file) {
  118. return (file.permissions & 4) ||
  119. (groups[file.group].indexOf(user.name) > -1 && (file.permissions & 32)) ||
  120. ((file.owner === user.name) && (file.permissions & 256)) ||
  121. user.name === "root";
  122. };
  123.  
  124. var writable = function (file) {
  125. return (file.permissions & 2) ||
  126. (groups[file.group].indexOf(user.name) > -1 && (file.permissions & 16)) ||
  127. (file.owner === user.name && (file.permissions & 128)) ||
  128. user.name === "root";
  129. };
  130.  
  131. var executable = function (file) {
  132. return (file.permissions & 1) ||
  133. (groups[file.group].indexOf(user.name) > -1 && (file.permissions & 8)) ||
  134. (file.owner === user.name && (file.permissions & 64)) ||
  135. user.name === "root";
  136. };
  137.  
  138. // Turns a path array (normal parameters) into a displayable path string.
  139. // Optional: appendix, an element to be added to the end of path.
  140. var getPathString = function (path, appendix) {
  141. return ("/" + path.concat(appendix ? [appendix] : []).join("/")).replace(new RegExp("^" + user.home), "~");
  142. };
  143.  
  144. // Turns a displayable path string into a path array (normal parameters).
  145. var getPathArray = function (pathString) {
  146. return pathString.replace(/^\//, "").replace(/^~/, user.home.slice(1)).split("/");
  147. };
  148.  
  149. }
  150.  
  151. // File constructor
  152. file: {
  153.  
  154. /*
  155. Represents a file in the filesystem. Can be either a classical file or a directory.
  156.  
  157. `type`: The type of the file. Either "f" or "d". Defaults to "f".
  158. `name`: The name of the file. Defaults to "untitled.txt" if type is "f" and "untitled" if type is "d".
  159. `parent`: The path of the parent directory.
  160. `permissions`: The octal permissions of the file. Defaults to 0[o]666 for type "f" and 0[o]777 for type "d".
  161. `owner`: The user who owns the file.
  162. `group`: The group which has group access to the file.
  163. */
  164.  
  165. var File = function (type, name, parent, permissions, owner, group) {
  166. this.type = def(type, "f");
  167. this.parent = def(parent, []);
  168.  
  169. if (this.parent.length && filesystem[this.parent].type !== "d") {
  170. throw new KAOSError(getPathString(this.parent) + ": Not a directory");
  171. }
  172.  
  173. this.owner = owner;
  174. this.group = group;
  175.  
  176. this.path = this.parent.concat([name]);
  177. this.pathString = getPathString(this.parent, name);
  178.  
  179. if (this.type === "f") {
  180. this.name = name;
  181. this.permissions = def(permissions, 0666); // 0b110110110
  182.  
  183. this.text = "";
  184. } else if (this.type === "d") {
  185. this.name = name;
  186. this.permissions = def(permissions, 0777); // 0b111111111
  187.  
  188. this.children = [];
  189. } else {
  190. throw new KAOSError(this.pathString + ": Invalid file type: `" + type + "`");
  191. }
  192. };
  193.  
  194. File.prototype.init = function () {
  195. filesystem[this.path] = this;
  196. };
  197.  
  198. File.prototype.read = function () {
  199. if (this.type !== "f") {
  200. throw new KAOSError("You cannot read a directory");
  201. }
  202.  
  203. if (!readable(this)) {
  204. throw new KAOSError("User " + user.name + " does not have read access to " + this.pathString);
  205. }
  206.  
  207. return this.text;
  208. };
  209.  
  210. File.prototype.write = function (text) {
  211. if (this.type !== "f") {
  212. throw new KAOSError("You cannot write to a directory");
  213. }
  214.  
  215. if (!writable(this)) {
  216. throw new KAOSError("User " + user.name + " does not have write access to " + this.pathString);
  217. }
  218.  
  219. this.text = text;
  220. };
  221.  
  222. File.prototype.chmod = function (permissions) {
  223. if (this.type !== "f") {
  224. throw new KAOSError("You cannot write to a directory");
  225. }
  226.  
  227. if (user.name !== this.owner) {
  228. throw new KAOSError("User " + user.name + " does not own " + this.pathString);
  229. }
  230.  
  231. this.permissions = permissions;
  232. };
  233.  
  234. File.prototype.ls = function () {
  235. if (!readable(this)) {
  236. throw new KAOSError("User " + user.name + " does not have read access to " + this.pathString);
  237. }
  238.  
  239. if (this.type === "f") {
  240. return [this];
  241. }
  242.  
  243. return this.children;
  244. };
  245.  
  246. }
  247.  
  248. // Nim language, transpiled from es6 using babel and customized to the above filesystem
  249. nim: {
  250.  
  251. var defaultFunctions = {
  252. "print": {
  253. args: 1,
  254. type: "string",
  255. run: function (a, o) {
  256. return [a[0], a[0]];
  257. }
  258. },
  259. "epoch": {
  260. args: 0,
  261. type: "number",
  262. run: function (a, o) {
  263. return ["", Date.now()];
  264. }
  265. }
  266. };
  267.  
  268. // Utility functions that need to be taken outside of constructors, maybe recursive stuff
  269. var utils = {
  270. // Get responses for HTTP error codes
  271. getErrorResponse: function (code) {
  272. return code.toString();
  273. },
  274.  
  275. // Split partially tokenized block into more blocks on subs/sube
  276. splitIntoBlocks: function (tokens) {
  277. var s = 0;
  278. var t = [];
  279. var k = false;
  280.  
  281. for (var i = 0; i < tokens.length; i++) {
  282. if (tokens[i][1] == "subs") {
  283. s++;
  284.  
  285. k = true;
  286. } else if (tokens[i][1] == "sube" && ! --s) {
  287. tokens = tokens.slice(0, i - t.length).concat([[utils.splitIntoBlocks(t.slice(1)), "block"]]).concat(tokens.slice(i + 1));
  288.  
  289. i -= t.length;
  290.  
  291. t = [];
  292. k = false;
  293. }
  294.  
  295. if (k) {
  296. t.push(tokens[i]);
  297. }
  298. }
  299.  
  300. return tokens;
  301. },
  302.  
  303. // Split partially tokenized block into statements on EOL (;)
  304. splitIntoStatements: function (tokens, file) {
  305. var t = [];
  306.  
  307. for (var i = 0; i < tokens.length; i++) {
  308. t.push([]);
  309.  
  310. while (tokens[i][1] != "eol") {
  311. if (tokens[i][1] == "block") {
  312. tokens[i][0] = utils.splitIntoStatements(tokens[i][0], file);
  313. }
  314.  
  315. t[t.length - 1].push(tokens[i++]);
  316.  
  317. if (i >= tokens.length) {
  318. throw new NimError("Code block does not end in semicolon.", file, tokens[tokens.length - 1][2]);
  319. }
  320. }
  321. }
  322.  
  323. return t;
  324. }
  325. };
  326.  
  327. // Nim custom errors
  328. // Stolen from SO
  329. var NimError = function (msg, file, char) {
  330. this.message = msg;
  331.  
  332. this.name = this.constructor.name;
  333.  
  334. this.file = file.replace(/\/+/g, "/");
  335. this.fileText = filesystem[getPathArray(file)].read();
  336.  
  337. var leadingText = this.fileText.slice(0, char);
  338.  
  339. this.line = leadingText.match(/\n/g) ? leadingText.match(/\n/g).length + 1 : 1;
  340. this.char = char - leadingText.lastIndexOf("\n");
  341.  
  342. //Error.captureStackTrace(this, this.constructor);
  343. }
  344.  
  345. NimError.prototype = Object.create(Error.prototype);
  346.  
  347. NimError.prototype.print = function () {
  348. return [
  349. this.file + ":" + this.line + ":" + this.char,
  350. "\t\t" + this.fileText.split("\n")[this.line - 1],
  351. "\t\t" + " ".repeat(this.char) + "^",
  352. this.name + ": " + this.message,
  353. " at " + this.file + ":" + this.line + ":" + this.char
  354. ].join("\n");
  355. };
  356.  
  357. // Level -1 Level 0 Level 1 Level 2 Level 3
  358.  
  359. // REQUEST -----> Server.process Parser.process Parser.parse -----> CLIENT-READY
  360. // | ^ | ^
  361. // |-----> Server.processURI -----| |-----> Tokenizer.tokenize -----|
  362.  
  363. // Tokenizer constructor
  364. var Tokenizer = function () {
  365. var _this = this;
  366.  
  367. // Tokenizes (lexes, lexemizes, lexically analyzes, whatever) Nim-coded HTML, level 2
  368. this.tokenize = function (text, file) {
  369. _this.reset();
  370.  
  371. _this.raw = text;
  372. _this.file = file;
  373.  
  374. // Array of blocks of pure Nim code
  375. var re = /<!--{\s*([\W\w]+?)\s*}-->/g;
  376. var blocks = [],
  377. indices = [],
  378. match;
  379.  
  380. while (match = re.exec(text)) {
  381. blocks.push(match[1]);
  382.  
  383. for (var i = match.index + 5; /\s/.test(text[i]); i++) {}
  384.  
  385. indices.push(i);
  386. }
  387.  
  388. // Plain HTML surrounding Nim blocks, to be interleaved with Nim output
  389. _this.plain = text.match(/(^|}-->)([\W\w]*?)(<!--{|$)/g).map(function (e) {
  390. return e.replace(/(<!--{\s*|\s*}-->)/g, "");
  391. });
  392.  
  393. for (var i = 0; i < blocks.length; i++) {
  394. _this.tokens.push(_this.tokenizeBlock(blocks[i], indices[i]));
  395. }
  396.  
  397. return _this;
  398. };
  399.  
  400. this.tokenizeBlock = function (block, index) {
  401. var tokens = [];
  402.  
  403. for (var i = 0; i < block.length;) {
  404. var value = block[i];
  405. var type;
  406.  
  407. // Hello, future me.
  408. // If you're reading this, this tokenizer has probably broken and you probably still remember writing this comment.
  409. // Don't try to understand the increments. Please.
  410. // They work. Maybe.
  411.  
  412. // Sincerely, past you.
  413.  
  414. // https://xkcd.com/1421/
  415.  
  416. if (value == "#") {
  417. type = "comment";
  418.  
  419. // While no newline, keep adding to the comment
  420. while (!/[\r\n]/.test(block[i])) {
  421. value += block[i++];
  422. }
  423. } else if (value == "{") {
  424. type = "subs";
  425. } else if (value == "}") {
  426. type = "sube";
  427. } else if (value == ";") {
  428. type = "eol";
  429. } else if (value == "=") {
  430. if (block[i + 1] == "=") {
  431. type = "equality";
  432. i++;
  433. } else {
  434. type = "equals";
  435. }
  436. } else if (value == "+") {
  437. type = "plus";
  438. } else if (value == "-") {
  439. type = "minus";
  440. } else if (value == "*") {
  441. type = "times";
  442. } else if (value == "/") {
  443. type = "div";
  444. } else if (value == "%") {
  445. // %/ is intdiv, % is mod, distinguish
  446. if (block[i + 1] == "/") {
  447. type = "intdiv";
  448. i++;
  449. } else {
  450. type = "mod";
  451. }
  452. } else if (value == ">" || value == "<") {
  453. type = (value == ">" ? "g" : "l") + "t";
  454.  
  455. if (block[i + 1] == "=") {
  456. type += "e";
  457. i++;
  458. }
  459. } else if (value == "$") {
  460. // If there is no alphanumeric character in front of the $, error
  461. if (!/[A-Za-z0-9]/.test(block[++i])) {
  462. throw new NimError("Expected variable identifier", _this.file, index + i);
  463. }
  464.  
  465. // Keep adding to the identifier until identifier runs out
  466. while (/[A-Za-z0-9]/.test(block[i])) {
  467. value += block[i++];
  468. }
  469.  
  470. while (/\s/.test(block[i])) {
  471. i++;
  472. }
  473.  
  474. if (block[i] == "=" && block[i + 1] != "=") {
  475. type = "variableSet";
  476. } else {
  477. type = "variableGet";
  478. i--;
  479. }
  480.  
  481. value = value.slice(1);
  482. } else if (/\d/.test(value)) {
  483. type = "number";
  484.  
  485. var hex = false;
  486.  
  487. if (!+value) {
  488. if (block[++i] != "." && block[i] != "b" && block[i] != "o" && block[i] != "x" && /\D/.test(block[i])) {
  489. throw new NimError("Expected numerical radix, got " + value + block[i], _this.file, index + i);
  490. } else {
  491. if (block[i] == "x") {
  492. hex = true;
  493. }
  494.  
  495. value += block[i];
  496. }
  497. }
  498.  
  499. while ((hex ? /[\dA-Fa-f]/ : /[\d\.]/).test(block[i + 1])) {
  500. value += block[++i];
  501. }
  502.  
  503. value = Number(value);
  504. } else if (value == "\"" || value == "'") {
  505. type = "string";
  506.  
  507. var delim = value,
  508. bs = false; // Backslashes indicate BS string endings
  509.  
  510. while (block[++i] != delim || bs) {
  511. if (!block[i]) {
  512. throw new NimError("String without ending", _this.file, index + i);
  513. }
  514.  
  515. if (block[i] == "\\") {
  516. bs = true;
  517. } else {
  518. if (bs && block[i] == "n") {
  519. value += "\n";
  520. bs = false;
  521. } else {
  522. value += block[i];
  523. }
  524.  
  525. bs = false;
  526. }
  527. }
  528.  
  529. value = value.slice(1);
  530. } else if (/[A-Za-z0-9]/.test(value)) {
  531. // Identifier time! (ouch)
  532. while (/[A-Za-z0-9]/.test(block[i + 1])) {
  533. value += block[++i];
  534. }
  535.  
  536. if (value == "true" || value == "false") {
  537. type = "bool";
  538. value = value == "true";
  539. } else if (block[i + 1] + block[i + 2] == "()") {
  540. i += 2;
  541. type = "function";
  542. } else if (_this.keywords.indexOf(value) > -1) {
  543. type = value;
  544. }
  545. } else {
  546. throw new NimError("Invalid character: " + value, _this.file, index + i);
  547. }
  548.  
  549. tokens.push([value, type, index + i]);
  550.  
  551. while (/\s/.test(block[++i])) {}
  552. }
  553.  
  554. tokens = utils.splitIntoStatements(utils.splitIntoBlocks(tokens), _this.file);
  555.  
  556. return tokens;
  557. };
  558.  
  559. // Reset tokenizer, we don't want to create new objects every request
  560. this.reset = function () {
  561. _this.tokens = [];
  562.  
  563. _this.raw = "";
  564. _this.plain = [];
  565.  
  566. _this.file = "";
  567.  
  568. return _this;
  569. };
  570.  
  571. // List of straight identifier keywords, ex. if, elseif, else, def, ...
  572. this.keywords = ["if", "elseif", "else", "def"];
  573.  
  574. // Tokens array, Array of arrays of arrays of tuples
  575. // Each tuple is a token
  576. // Each array of tuples is a statement ...;
  577. // Each array of statements is a Nim block <!--{...}-->
  578. // The array of Nim blocks is this.tokens
  579. this.tokens = [];
  580.  
  581. this.raw = "";
  582. this.plain = [];
  583.  
  584. this.file = "";
  585. };
  586.  
  587. // Parser constructor
  588. var Parser = function () {
  589. var _this = this;
  590.  
  591. // Interprets Nim-coded HTML, level 1
  592. this.process = function (text, file) {
  593. _this.functions = defaultFunctions;
  594. _this.variables = {};
  595.  
  596. _this.file = file;
  597.  
  598. return _this.parse(_this.tokenizer.tokenize(text, file))[0];
  599. };
  600.  
  601. // Parses tokenized Nim, level 3
  602. this.parse = function (tokenizer) {
  603. var tokens = tokenizer.tokens;
  604. var plain = tokenizer.plain;
  605.  
  606. // output[0] is text printed to page
  607. // output[1] is returned value
  608. var output = [plain[0]];
  609.  
  610. for (var i = 0; i < tokens.length; i++) {
  611. for (var j = 0; j < tokens[i].length; j++) {
  612. var statement = _this.parseStatement(tokens[i][j]);
  613.  
  614. output[0] += statement[0];
  615. output[1] = statement[1];
  616. }
  617.  
  618. output[0] += plain[i + 1];
  619. }
  620.  
  621. return output;
  622. };
  623.  
  624. // Parse individual statements
  625. // VALID STATEMENTS:
  626. // <comment>
  627. // <function> [arg1] [arg2] [...]
  628. // <variable> <equals> <data>
  629. // <data> <operation> <data>
  630. // <data>
  631. // <if> <boolean> <block>
  632. // <elseif> <boolean> <block>
  633. // <else> <block>
  634. // <def> <string> <string(type)> <string...> <block>
  635. this.parseStatement = function (statement) {
  636. var output = "",
  637. ret,
  638. rettype,
  639. k;
  640.  
  641. var f = function (e) {
  642. // If type is variableGet and statement isn't one that requires variable-type expressions not to be evaluated beforehand, evaluate variable
  643. if (e[1] == "variableGet" && !(["def"].indexOf(statement[0][1]) > -1)) {
  644. return [_this.variables[e[0]], "variableGet"];
  645. } else if (e[1] == "block") {
  646. return [e[0].map(f), e[1]];
  647. } else {
  648. return e;
  649. }
  650. };
  651.  
  652. statement = statement.map(function (e, i) {
  653. // If type is block and statement isn't one that requires blocks not to be evaluated beforehand, evaluate block
  654. if (e[1] == "block" && !(["if", "elseif", "else", "def"].indexOf(statement[0][1]) > -1 && i == statement.length - 1)) {
  655. var k = e[0].map(_this.parseStatement).reduce(function (a, b) {
  656. return [a[0] + b[0], b[1], b[2], b[3]];
  657. });
  658. output += k[0];
  659.  
  660. return [k[1], k[2]];
  661. } else {
  662. return e;
  663. }
  664. }).map(f);
  665.  
  666. var lastLooked = 0;
  667.  
  668. switch (statement[0][1]) {
  669. case "comment":
  670.  
  671. break;case "function":
  672. var name = statement[0][0];
  673. var func = _this.functions[name];
  674.  
  675. if (func) {
  676. var args = statement.slice(1);
  677.  
  678. if (args.length != func.args) {
  679. throw new NimError("Incorrect number of arguments: Expected " + func.args.length + " arguments for function `" + name + "` but got " + args.length, _this.file, statement[statement.length - 1][2]);
  680. }
  681.  
  682. var res = func.run(args.map(function (e) {
  683. return e[0];
  684. }));
  685.  
  686. output += res[0];
  687. ret = res[1];
  688. rettype = func.type;
  689.  
  690. lastLooked = statement.length - 1;
  691. } else {
  692. throw new NimError("Undefined function: " + name, _this.file, statement[0][2]);
  693. }
  694. break;case "variableSet":
  695. _this.variables[statement[0][0]] = statement[1][0];
  696.  
  697. ret = statement[1][0];
  698. rettype = statement[1][1];
  699.  
  700. lastLooked = 1;
  701. break;case "number":
  702. case "string":
  703. case "bool":
  704. case "variableGet":
  705. switch (statement[1][1]) {
  706. case "plus":
  707. ret = statement[0][0] + statement[2][0];
  708. break;case "minus":
  709. ret = statement[0][0] - statement[2][0];
  710. break;case "times":
  711. ret = statement[0][0] * statement[2][0];
  712. break;case "div":
  713. ret = statement[0][0] / statement[2][0];
  714. break;case "mod":
  715. ret = statement[0][0] % statement[2][0];
  716. break;case "intdiv":
  717. ret = Math.floor(statement[0][0] / statement[2][0]);
  718. break;case "equality":
  719. ret = statement[0][0] == statement[2][0];
  720. break;case "gt":
  721. ret = statement[0][0] > statement[2][0];
  722. break;case "gte":
  723. ret = statement[0][0] >= statement[2][0];
  724. break;case "lt":
  725. ret = statement[0][0] < statement[2][0];
  726. break;case "lte":
  727. ret = statement[0][0] <= statement[2][0];
  728. break;case undefined:
  729. ret = statement[0];
  730. break;default:
  731. throw new NimError("Expected operation on " + statement[0][1], _this.file, statement[0][2]);
  732. }
  733.  
  734. rettype = "" + ret === ret ? "string" : ret == true || ret == false ? "bool" : "number";
  735.  
  736. lastLooked = 2;
  737. break;case "if":
  738. _this.conditions = [statement[1][0]];
  739.  
  740. if (statement[1][0]) {
  741. var r = statement[2][0].map(_this.parseStatement).reduce(function (a, b) {
  742. return [a[0] + b[0], b[1], b[2], b[3]];
  743. });
  744.  
  745. output = r[0];
  746. ret = r[1];
  747. rettype = r[2];
  748. }
  749.  
  750. lastLooked = 2;
  751. break;case "elseif":
  752. if (!_this.conditions.length) {
  753. throw new NimError("elseif after no if or elseif", _this.file, statement[0][2]);
  754. }
  755.  
  756. if (!_this.conditions.reduce(function (a, b) {
  757. return a || b;
  758. }) && statement[1][0]) {
  759. var r = statement[2][0].map(_this.parseStatement).reduce(function (a, b) {
  760. return [a[0] + b[0], b[1], b[2], b[3]];
  761. });
  762.  
  763. output = r[0];
  764. ret = r[1];
  765. rettype = r[2];
  766. }
  767.  
  768. _this.conditions.push(statement[1][0]);
  769.  
  770. lastLooked = 2;
  771. break;case "else":
  772. if (!_this.conditions.length) {
  773. throw new NimError("else after no if or elseif", _this.file, statement[0][2]);
  774. }
  775.  
  776. if (!_this.conditions.reduce(function (a, b) {
  777. return a || b;
  778. })) {
  779. var r = statement[1][0].map(_this.parseStatement).reduce(function (a, b) {
  780. return [a[0] + b[0], b[1], b[2], b[3]];
  781. });
  782.  
  783. output = r[0];
  784. ret = r[1];
  785. rettype = r[2];
  786. }
  787.  
  788. lastLooked = 1;
  789. break;case "def":
  790. var args = statement.slice(3, statement.length - 1);
  791. var code = statement[statement.length - 1][0];
  792.  
  793. _this.functions[statement[1][0]] = {
  794. args: args.length,
  795. type: statement[2],
  796. run: function (a, o) {
  797. var parser2 = Object.assign(new Parser(), _this);
  798.  
  799. for (var i = 0; i < args.length; i++) {
  800. parser2.variables[args[i][0]] = a[i];
  801. }
  802.  
  803. var k = code.map(parser2.parseStatement).reduce(function (a, b) {
  804. return [a[0] + b[0], b[1], b[2], b[3]];
  805. });
  806.  
  807. return [k[0], k[1]];
  808. }
  809. };
  810.  
  811. lastLooked = statement.length - 1;
  812. break;default:
  813. throw new NimError("Invalid statement beginning: " + statement[0][0] + " (" + statement[0][1] + ")", _this.file, statement[0][2]);
  814. }
  815.  
  816. if (statement.length - 1 > lastLooked) {
  817. throw new NimError("Unexpected token: `" + statement[lastLooked + 1] + "`", _this.file, statement[lastLooked + 1][2]);
  818. }
  819.  
  820. return [output, ret, rettype, statement[statement.length - 1][2]];
  821. };
  822.  
  823. // Functions
  824. this.functions = defaultFunctions;
  825.  
  826. // Variables
  827. this.variables = {};
  828.  
  829. // Condition of previous if/elseif/else, if needed
  830. this.conditions = [];
  831.  
  832. // Moving on to level 2...
  833. this.tokenizer = new Tokenizer();
  834. };
  835.  
  836. }
  837.  
  838. // The module system is disallowed per guildelines in PJS, so we use this callback.
  839. var init = function (modules, p) {
  840. var parser = new Parser();
  841.  
  842. modules.downloadProgram("4548198515802112", "t.nim", function () {
  843. var res;
  844.  
  845. try {
  846. res = parser.process(filesystem[getPathArray("/t.nim")].read(), "/t.nim");
  847. } catch (e) {
  848. if (e instanceof NimError) {
  849. res = e.print();
  850. } else {
  851. throw e;
  852. }
  853. }
  854.  
  855. p.size(600, 600);
  856. p.frameRate(30);
  857.  
  858. p.background(255);
  859.  
  860. p.fill(0);
  861. p.textSize(12);
  862. p.text(res, 10, 10, 580, 580);
  863. });
  864. };
  865.  
  866. var fs = { File: File };
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement