From 2f0d4681bac66a682223b31bf35caa5a36a07687 Mon Sep 17 00:00:00 2001
From: Anton Salikhmetov
Date: Sun, 29 Jan 2017 01:21:12 +0200
Subject: [PATCH 01/27] Initial commit
---
Makefile | 8 +
README | 1 +
bundle.js | 3439 ++++++++++++++++++++++++++++++++++++++++++++++++++
entry.js | 9 +
fact.mlc | 30 +
index.html | 361 ++++++
package.json | 8 +
7 files changed, 3856 insertions(+)
create mode 100644 Makefile
create mode 100644 README
create mode 100644 bundle.js
create mode 100644 entry.js
create mode 100644 fact.mlc
create mode 100644 index.html
create mode 100644 package.json
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..13afe64
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,8 @@
+BROWSERIFY = node_modules/.bin/browserify
+
+all:
+ npm install
+ $(BROWSERIFY) -g brfs -o bundle.js entry.js
+
+clean:
+ -rm -fr node_modules
diff --git a/README b/README
new file mode 100644
index 0000000..c18156a
--- /dev/null
+++ b/README
@@ -0,0 +1 @@
+Call-by-need Lambda Calculus for Web using Interaction Nets
diff --git a/bundle.js b/bundle.js
new file mode 100644
index 0000000..9480670
--- /dev/null
+++ b/bundle.js
@@ -0,0 +1,3439 @@
+(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o number},
+ terminals_: {associative list: number ==> name},
+ productions_: [...],
+ performAction: function anonymous(yytext, yyleng, yylineno, yy, yystate, $$, _$),
+ table: [...],
+ defaultActions: {...},
+ parseError: function(str, hash),
+ parse: function(input),
+
+ lexer: {
+ EOF: 1,
+ parseError: function(str, hash),
+ setInput: function(input),
+ input: function(),
+ unput: function(str),
+ more: function(),
+ less: function(n),
+ pastInput: function(),
+ upcomingInput: function(),
+ showPosition: function(),
+ test_match: function(regex_match_array, rule_index),
+ next: function(),
+ lex: function(),
+ begin: function(condition),
+ popState: function(),
+ _currentRules: function(),
+ topState: function(),
+ pushState: function(condition),
+
+ options: {
+ ranges: boolean (optional: true ==> token location info will include a .range[] member)
+ flex: boolean (optional: true ==> flex-like lexing behaviour where the rules are tested exhaustively to find the longest match)
+ backtrack_lexer: boolean (optional: true ==> lexer regexes are tested in order and for each matching regex the action code is invoked; the lexer terminates the scan when a token is returned by the action code)
+ },
+
+ performAction: function(yy, yy_, $avoiding_name_collisions, YY_START),
+ rules: [...],
+ conditions: {associative list: name ==> set},
+ }
+ }
+
+
+ token location info (@$, _$, etc.): {
+ first_line: n,
+ last_line: n,
+ first_column: n,
+ last_column: n,
+ range: [start_number, end_number] (where the numbers are indexes into the input string, regular zero-based)
+ }
+
+
+ the parseError function receives a 'hash' object with these members for lexer and parser errors: {
+ text: (matched text)
+ token: (the produced terminal token, if any)
+ line: (yylineno)
+ }
+ while parser (grammar) errors will also provide these members, i.e. parser errors deliver a superset of attributes: {
+ loc: (yylloc)
+ expected: (string describing the set of expected tokens)
+ recoverable: (boolean: TRUE when the parser has a error recovery rule available for this particular error)
+ }
+*/
+var parser = (function(){
+var o=function(k,v,o,l){for(o=o||{},l=k.length;l--;o[k[l]]=v);return o},$V0=[6,14],$V1=[1,8],$V2=[2,11],$V3=[1,10],$V4=[1,11],$V5=[1,8,15],$V6=[1,6,8,14,15],$V7=[1,15];
+var parser = {trace: function trace() { },
+yy: {},
+symbols_: {"error":2,"text":3,"defs":4,"term":5,"NAME":6,"=":7,";":8,"appl":9,"abst":10,",":11,":":12,"atom":13,"(":14,")":15,"$accept":0,"$end":1},
+terminals_: {2:"error",6:"NAME",7:"=",8:";",11:",",12:":",14:"(",15:")"},
+productions_: [0,[3,2],[4,0],[4,5],[5,1],[5,1],[10,3],[10,3],[9,1],[9,2],[13,3],[13,1]],
+performAction: function anonymous(yytext, yyleng, yylineno, yy, yystate /* action[1] */, $$ /* vstack */, _$ /* lstack */) {
+/* this == yyval */
+
+var $0 = $$.length - 1;
+switch (yystate) {
+case 1:
+return {macros: $$[$0-1], term: $$[$0]};
+break;
+case 2:
+this.$ = [];
+break;
+case 3:
+$$[$0-4].unshift({id: $$[$0-3], def: $$[$0-1]}); this.$ = $$[$0-4];
+break;
+case 6: case 7:
+this.$ = {node: "abst", var: $$[$0-2], body: $$[$0]};
+break;
+case 9:
+this.$ = {node: "appl", left: $$[$0-1], right: $$[$0]};
+break;
+case 10:
+this.$ = $$[$0-1];
+break;
+case 11:
+this.$ = {node: "atom", name: yytext};
+break;
+}
+},
+table: [o($V0,[2,2],{3:1,4:2}),{1:[3]},{5:3,6:[1,4],9:5,10:6,13:7,14:$V1},{1:[2,1]},o([1,6,14],$V2,{7:[1,9],11:$V3,12:$V4}),o($V5,[2,4],{13:12,6:[1,13],14:$V1}),o($V5,[2,5]),o($V6,[2,8]),{5:14,6:$V7,9:5,10:6,13:7,14:$V1},{5:16,6:$V7,9:5,10:6,13:7,14:$V1},{6:[1,18],10:17},{5:19,6:$V7,9:5,10:6,13:7,14:$V1},o($V6,[2,9]),o($V6,$V2),{15:[1,20]},o($V6,$V2,{11:$V3,12:$V4}),{8:[1,21]},o($V5,[2,6]),{11:$V3,12:$V4},o($V5,[2,7]),o($V6,[2,10]),o($V0,[2,3])],
+defaultActions: {3:[2,1]},
+parseError: function parseError(str, hash) {
+ if (hash.recoverable) {
+ this.trace(str);
+ } else {
+ throw new Error(str);
+ }
+},
+parse: function parse(input) {
+ var self = this, stack = [0], tstack = [], vstack = [null], lstack = [], table = this.table, yytext = '', yylineno = 0, yyleng = 0, recovering = 0, TERROR = 2, EOF = 1;
+ var args = lstack.slice.call(arguments, 1);
+ var lexer = Object.create(this.lexer);
+ var sharedState = { yy: {} };
+ for (var k in this.yy) {
+ if (Object.prototype.hasOwnProperty.call(this.yy, k)) {
+ sharedState.yy[k] = this.yy[k];
+ }
+ }
+ lexer.setInput(input, sharedState.yy);
+ sharedState.yy.lexer = lexer;
+ sharedState.yy.parser = this;
+ if (typeof lexer.yylloc == 'undefined') {
+ lexer.yylloc = {};
+ }
+ var yyloc = lexer.yylloc;
+ lstack.push(yyloc);
+ var ranges = lexer.options && lexer.options.ranges;
+ if (typeof sharedState.yy.parseError === 'function') {
+ this.parseError = sharedState.yy.parseError;
+ } else {
+ this.parseError = Object.getPrototypeOf(this).parseError;
+ }
+ function popStack(n) {
+ stack.length = stack.length - 2 * n;
+ vstack.length = vstack.length - n;
+ lstack.length = lstack.length - n;
+ }
+ _token_stack:
+ function lex() {
+ var token;
+ token = lexer.lex() || EOF;
+ if (typeof token !== 'number') {
+ token = self.symbols_[token] || token;
+ }
+ return token;
+ }
+ var symbol, preErrorSymbol, state, action, a, r, yyval = {}, p, len, newState, expected;
+ while (true) {
+ state = stack[stack.length - 1];
+ if (this.defaultActions[state]) {
+ action = this.defaultActions[state];
+ } else {
+ if (symbol === null || typeof symbol == 'undefined') {
+ symbol = lex();
+ }
+ action = table[state] && table[state][symbol];
+ }
+ if (typeof action === 'undefined' || !action.length || !action[0]) {
+ var errStr = '';
+ expected = [];
+ for (p in table[state]) {
+ if (this.terminals_[p] && p > TERROR) {
+ expected.push('\'' + this.terminals_[p] + '\'');
+ }
+ }
+ if (lexer.showPosition) {
+ errStr = 'Parse error on line ' + (yylineno + 1) + ':\n' + lexer.showPosition() + '\nExpecting ' + expected.join(', ') + ', got \'' + (this.terminals_[symbol] || symbol) + '\'';
+ } else {
+ errStr = 'Parse error on line ' + (yylineno + 1) + ': Unexpected ' + (symbol == EOF ? 'end of input' : '\'' + (this.terminals_[symbol] || symbol) + '\'');
+ }
+ this.parseError(errStr, {
+ text: lexer.match,
+ token: this.terminals_[symbol] || symbol,
+ line: lexer.yylineno,
+ loc: yyloc,
+ expected: expected
+ });
+ }
+ if (action[0] instanceof Array && action.length > 1) {
+ throw new Error('Parse Error: multiple actions possible at state: ' + state + ', token: ' + symbol);
+ }
+ switch (action[0]) {
+ case 1:
+ stack.push(symbol);
+ vstack.push(lexer.yytext);
+ lstack.push(lexer.yylloc);
+ stack.push(action[1]);
+ symbol = null;
+ if (!preErrorSymbol) {
+ yyleng = lexer.yyleng;
+ yytext = lexer.yytext;
+ yylineno = lexer.yylineno;
+ yyloc = lexer.yylloc;
+ if (recovering > 0) {
+ recovering--;
+ }
+ } else {
+ symbol = preErrorSymbol;
+ preErrorSymbol = null;
+ }
+ break;
+ case 2:
+ len = this.productions_[action[1]][1];
+ yyval.$ = vstack[vstack.length - len];
+ yyval._$ = {
+ first_line: lstack[lstack.length - (len || 1)].first_line,
+ last_line: lstack[lstack.length - 1].last_line,
+ first_column: lstack[lstack.length - (len || 1)].first_column,
+ last_column: lstack[lstack.length - 1].last_column
+ };
+ if (ranges) {
+ yyval._$.range = [
+ lstack[lstack.length - (len || 1)].range[0],
+ lstack[lstack.length - 1].range[1]
+ ];
+ }
+ r = this.performAction.apply(yyval, [
+ yytext,
+ yyleng,
+ yylineno,
+ sharedState.yy,
+ action[1],
+ vstack,
+ lstack
+ ].concat(args));
+ if (typeof r !== 'undefined') {
+ return r;
+ }
+ if (len) {
+ stack = stack.slice(0, -1 * len * 2);
+ vstack = vstack.slice(0, -1 * len);
+ lstack = lstack.slice(0, -1 * len);
+ }
+ stack.push(this.productions_[action[1]][0]);
+ vstack.push(yyval.$);
+ lstack.push(yyval._$);
+ newState = table[stack[stack.length - 2]][stack[stack.length - 1]];
+ stack.push(newState);
+ break;
+ case 3:
+ return true;
+ }
+ }
+ return true;
+}};
+/* generated by jison-lex 0.3.4 */
+var lexer = (function(){
+var lexer = ({
+
+EOF:1,
+
+parseError:function parseError(str, hash) {
+ if (this.yy.parser) {
+ this.yy.parser.parseError(str, hash);
+ } else {
+ throw new Error(str);
+ }
+ },
+
+// resets the lexer, sets new input
+setInput:function (input, yy) {
+ this.yy = yy || this.yy || {};
+ this._input = input;
+ this._more = this._backtrack = this.done = false;
+ this.yylineno = this.yyleng = 0;
+ this.yytext = this.matched = this.match = '';
+ this.conditionStack = ['INITIAL'];
+ this.yylloc = {
+ first_line: 1,
+ first_column: 0,
+ last_line: 1,
+ last_column: 0
+ };
+ if (this.options.ranges) {
+ this.yylloc.range = [0,0];
+ }
+ this.offset = 0;
+ return this;
+ },
+
+// consumes and returns one char from the input
+input:function () {
+ var ch = this._input[0];
+ this.yytext += ch;
+ this.yyleng++;
+ this.offset++;
+ this.match += ch;
+ this.matched += ch;
+ var lines = ch.match(/(?:\r\n?|\n).*/g);
+ if (lines) {
+ this.yylineno++;
+ this.yylloc.last_line++;
+ } else {
+ this.yylloc.last_column++;
+ }
+ if (this.options.ranges) {
+ this.yylloc.range[1]++;
+ }
+
+ this._input = this._input.slice(1);
+ return ch;
+ },
+
+// unshifts one char (or a string) into the input
+unput:function (ch) {
+ var len = ch.length;
+ var lines = ch.split(/(?:\r\n?|\n)/g);
+
+ this._input = ch + this._input;
+ this.yytext = this.yytext.substr(0, this.yytext.length - len);
+ //this.yyleng -= len;
+ this.offset -= len;
+ var oldLines = this.match.split(/(?:\r\n?|\n)/g);
+ this.match = this.match.substr(0, this.match.length - 1);
+ this.matched = this.matched.substr(0, this.matched.length - 1);
+
+ if (lines.length - 1) {
+ this.yylineno -= lines.length - 1;
+ }
+ var r = this.yylloc.range;
+
+ this.yylloc = {
+ first_line: this.yylloc.first_line,
+ last_line: this.yylineno + 1,
+ first_column: this.yylloc.first_column,
+ last_column: lines ?
+ (lines.length === oldLines.length ? this.yylloc.first_column : 0)
+ + oldLines[oldLines.length - lines.length].length - lines[0].length :
+ this.yylloc.first_column - len
+ };
+
+ if (this.options.ranges) {
+ this.yylloc.range = [r[0], r[0] + this.yyleng - len];
+ }
+ this.yyleng = this.yytext.length;
+ return this;
+ },
+
+// When called from action, caches matched text and appends it on next action
+more:function () {
+ this._more = true;
+ return this;
+ },
+
+// When called from action, signals the lexer that this rule fails to match the input, so the next matching rule (regex) should be tested instead.
+reject:function () {
+ if (this.options.backtrack_lexer) {
+ this._backtrack = true;
+ } else {
+ return this.parseError('Lexical error on line ' + (this.yylineno + 1) + '. You can only invoke reject() in the lexer when the lexer is of the backtracking persuasion (options.backtrack_lexer = true).\n' + this.showPosition(), {
+ text: "",
+ token: null,
+ line: this.yylineno
+ });
+
+ }
+ return this;
+ },
+
+// retain first n characters of the match
+less:function (n) {
+ this.unput(this.match.slice(n));
+ },
+
+// displays already matched input, i.e. for error messages
+pastInput:function () {
+ var past = this.matched.substr(0, this.matched.length - this.match.length);
+ return (past.length > 20 ? '...':'') + past.substr(-20).replace(/\n/g, "");
+ },
+
+// displays upcoming input, i.e. for error messages
+upcomingInput:function () {
+ var next = this.match;
+ if (next.length < 20) {
+ next += this._input.substr(0, 20-next.length);
+ }
+ return (next.substr(0,20) + (next.length > 20 ? '...' : '')).replace(/\n/g, "");
+ },
+
+// displays the character position where the lexing error occurred, i.e. for error messages
+showPosition:function () {
+ var pre = this.pastInput();
+ var c = new Array(pre.length + 1).join("-");
+ return pre + this.upcomingInput() + "\n" + c + "^";
+ },
+
+// test the lexed token: return FALSE when not a match, otherwise return token
+test_match:function (match, indexed_rule) {
+ var token,
+ lines,
+ backup;
+
+ if (this.options.backtrack_lexer) {
+ // save context
+ backup = {
+ yylineno: this.yylineno,
+ yylloc: {
+ first_line: this.yylloc.first_line,
+ last_line: this.last_line,
+ first_column: this.yylloc.first_column,
+ last_column: this.yylloc.last_column
+ },
+ yytext: this.yytext,
+ match: this.match,
+ matches: this.matches,
+ matched: this.matched,
+ yyleng: this.yyleng,
+ offset: this.offset,
+ _more: this._more,
+ _input: this._input,
+ yy: this.yy,
+ conditionStack: this.conditionStack.slice(0),
+ done: this.done
+ };
+ if (this.options.ranges) {
+ backup.yylloc.range = this.yylloc.range.slice(0);
+ }
+ }
+
+ lines = match[0].match(/(?:\r\n?|\n).*/g);
+ if (lines) {
+ this.yylineno += lines.length;
+ }
+ this.yylloc = {
+ first_line: this.yylloc.last_line,
+ last_line: this.yylineno + 1,
+ first_column: this.yylloc.last_column,
+ last_column: lines ?
+ lines[lines.length - 1].length - lines[lines.length - 1].match(/\r?\n?/)[0].length :
+ this.yylloc.last_column + match[0].length
+ };
+ this.yytext += match[0];
+ this.match += match[0];
+ this.matches = match;
+ this.yyleng = this.yytext.length;
+ if (this.options.ranges) {
+ this.yylloc.range = [this.offset, this.offset += this.yyleng];
+ }
+ this._more = false;
+ this._backtrack = false;
+ this._input = this._input.slice(match[0].length);
+ this.matched += match[0];
+ token = this.performAction.call(this, this.yy, this, indexed_rule, this.conditionStack[this.conditionStack.length - 1]);
+ if (this.done && this._input) {
+ this.done = false;
+ }
+ if (token) {
+ return token;
+ } else if (this._backtrack) {
+ // recover context
+ for (var k in backup) {
+ this[k] = backup[k];
+ }
+ return false; // rule action called reject() implying the next rule should be tested instead.
+ }
+ return false;
+ },
+
+// return next match in input
+next:function () {
+ if (this.done) {
+ return this.EOF;
+ }
+ if (!this._input) {
+ this.done = true;
+ }
+
+ var token,
+ match,
+ tempMatch,
+ index;
+ if (!this._more) {
+ this.yytext = '';
+ this.match = '';
+ }
+ var rules = this._currentRules();
+ for (var i = 0; i < rules.length; i++) {
+ tempMatch = this._input.match(this.rules[rules[i]]);
+ if (tempMatch && (!match || tempMatch[0].length > match[0].length)) {
+ match = tempMatch;
+ index = i;
+ if (this.options.backtrack_lexer) {
+ token = this.test_match(tempMatch, rules[i]);
+ if (token !== false) {
+ return token;
+ } else if (this._backtrack) {
+ match = false;
+ continue; // rule action called reject() implying a rule MISmatch.
+ } else {
+ // else: this is a lexer rule which consumes input without producing a token (e.g. whitespace)
+ return false;
+ }
+ } else if (!this.options.flex) {
+ break;
+ }
+ }
+ }
+ if (match) {
+ token = this.test_match(match, rules[index]);
+ if (token !== false) {
+ return token;
+ }
+ // else: this is a lexer rule which consumes input without producing a token (e.g. whitespace)
+ return false;
+ }
+ if (this._input === "") {
+ return this.EOF;
+ } else {
+ return this.parseError('Lexical error on line ' + (this.yylineno + 1) + '. Unrecognized text.\n' + this.showPosition(), {
+ text: "",
+ token: null,
+ line: this.yylineno
+ });
+ }
+ },
+
+// return next match that has a token
+lex:function lex() {
+ var r = this.next();
+ if (r) {
+ return r;
+ } else {
+ return this.lex();
+ }
+ },
+
+// activates a new lexer condition state (pushes the new lexer condition state onto the condition stack)
+begin:function begin(condition) {
+ this.conditionStack.push(condition);
+ },
+
+// pop the previously active lexer condition state off the condition stack
+popState:function popState() {
+ var n = this.conditionStack.length - 1;
+ if (n > 0) {
+ return this.conditionStack.pop();
+ } else {
+ return this.conditionStack[0];
+ }
+ },
+
+// produce the lexer rule set which is active for the currently active lexer condition state
+_currentRules:function _currentRules() {
+ if (this.conditionStack.length && this.conditionStack[this.conditionStack.length - 1]) {
+ return this.conditions[this.conditionStack[this.conditionStack.length - 1]].rules;
+ } else {
+ return this.conditions["INITIAL"].rules;
+ }
+ },
+
+// return the currently active lexer condition state; when an index argument is provided it produces the N-th previous condition state, if available
+topState:function topState(n) {
+ n = this.conditionStack.length - 1 - Math.abs(n || 0);
+ if (n >= 0) {
+ return this.conditionStack[n];
+ } else {
+ return "INITIAL";
+ }
+ },
+
+// alias for begin(condition)
+pushState:function pushState(condition) {
+ this.begin(condition);
+ },
+
+// return the number of states currently on the stack
+stateStackSize:function stateStackSize() {
+ return this.conditionStack.length;
+ },
+options: {},
+performAction: function anonymous(yy,yy_,$avoiding_name_collisions,YY_START) {
+var YYSTATE=YY_START;
+switch($avoiding_name_collisions) {
+case 0:/* skip whitespace */
+break;
+case 1:return "NAME";
+break;
+case 2:return "=";
+break;
+case 3:return ";";
+break;
+case 4:return ",";
+break;
+case 5:return ":";
+break;
+case 6:return "(";
+break;
+case 7:return ")";
+break;
+}
+},
+rules: [/^(?:\s+)/,/^(?:[A-Za-z][A-Za-z0-9]*)/,/^(?:=)/,/^(?:;)/,/^(?:,)/,/^(?::)/,/^(?:\()/,/^(?:\))/],
+conditions: {"INITIAL":{"rules":[0,1,2,3,4,5,6,7],"inclusive":true}}
+});
+return lexer;
+})();
+parser.lexer = lexer;
+function Parser () {
+ this.yy = {};
+}
+Parser.prototype = parser;parser.Parser = Parser;
+return new Parser;
+})();
+module.exports = parser;
+
+},{}],3:[function(require,module,exports){
+"use strict";
+
+const generic = require("../generic");
+
+const path = require("path");
+
+const template = "\\apply[a, b] {\n\t/* Apply beta reduction. */\n\t++this.beta;\n\t++this.total;\n} \\lambda[\\wait(c, \\hold(c, a)), b];\n\n\\apply[\n\t\\fan_{[i[0], i[1] + 1]}(a, b),\n\t\\fan_{[i[0], i[1] + 1]}(c, d)\n] {\n\t/* Duplicate application. */\n\t++this.total;\n} \\fan_{i}[\\apply(a, c), \\apply(b, d)];\n\n\\fan_{i}[\\lambda(a, b), \\lambda(c, d)] {\n\t/* Duplicate abstraction. */\n\t++this.total;\n} \\lambda[\n\t\\fan_{[i[0], i[1] + 1]}(a, c),\n\t\\fan_{[i[0], i[1] + 1]}(b, d)\n];\n\n\\fan_{i}[\n\t\\fan_{[j[0], j[1] + 1]}(a, b),\n\t\\fan_{[j[0], j[1] + 1]}(c, d)\n] {\n\t/* Duplicate different fans. */\n\tif ((i[0] != j[0]) && (i[1] < j[1]))\n\t\t++this.total;\n\telse\n\t\treturn false;\n} \\fan_{j}[\n\t\\fan_{[this.plus(i[0], j[0]), i[1]]}(a, c),\n\t\\fan_{[this.minus(i[0], j[0]), i[1]]}(b, d)\n];\n\n\\fan_{i}[a, b] {\n\t/* Annihilate matching fans. */\n\tif ((i[0] == j[0]) || (i[1] == j[1]))\n\t\t++this.total;\n\telse\n\t\treturn false;\n} \\fan_{j}[a, b];\n\n\\print {\n\t/* Continue evaluation. */\n\t++this.wait;\n} \\wait[\\print, \\call];\n\n\\eval[\\fan_{i}(a, b)] {\n\t/* Postpone evaluation. */\n\t++this.wait;\n} \\fan_{i}[a, b];\n\n\\eval[a] {\n\t/* Continue evaluation. */\n\t++this.wait;\n} \\wait[\\eval(a), \\call];\n\n\\eval[\\atom_{M}] {\n\t/* Return an atom. */\n\t++this.wait;\n} \\atom_{M};\n\n\\eval[\\lambda(a, b)] {\n\t/* Return abstraction. */\n\t++this.wait;\n} \\lambda[a, b];\n\n\\read_{C}[\\fan_{i}(a, b)] {\n\t/* Duplicate context. */\n\t++this.read;\n} \\fan_{i}[\\read_{C}(a), \\read_{this.clone(C)}(b)];\n\n\\call {\n\t/* Erase late call. */\n\t++this.wait;\n} \\erase;\n\n\\fan_{i}[\\wait(a, \\amb(b, \\decide(c, d), d)), \\wait(e, b)] {\n\t/* Postpone duplication. */\n\t++this.wait;\n} \\wait[\\fan_{i}(a, e), c];\n\n\\call {\n\t/* Continue evaluation. */\n\t++this.wait;\n} \\decide[\\call, \\erase];\n\n\\erase {\n\t/* Erase reference. */\n\t++this.wait;\n} \\decide[a, a];\n\n\\call {\n\t/* Continue evaluation. */\n\t++this.wait;\n} \\hold[a, \\eval(a)];\n\n\\read_{C}[\\wait(a, b)] {\n\t/* Postpone readback. */\n\t++this.wait;\n} \\wait[\\read_{C}(a), b];\n\n\\erase {\n\t/* Erase holder. */\n\t++this.wait;\n} \\hold[\\erase, \\erase];\n\n\\erase {\n\t/* Erase reference. */\n\t++this.wait;\n} \\wait[\\erase, \\erase];\n\n\\apply[a, \\wait(b, \\hold(\\apply(a, b), \\wait(c, d)))] {\n\t/* Postpone application. */\n\t++this.wait;\n} \\wait[c, d];\n\n\\print {\n\t/* Output results of read-back. */\n\tthis.nf = M;\n\t++this.read;\n} \\atom_{M};\n\n\\read_{C}[a] {\n\t/* Read back abstraction. */\n\t++this.read;\n} \\lambda[\\atom_{this.mkid()}, \\read_{this.abst(C)}(a)];\n\n\\apply[\\read_{this.appl(M)}(a), a] {\n\t/* Read back application. */\n\t++this.read;\n} \\atom_{M};\n\n\\read_{C}[\\atom_{this.atom(C, M)}] {\n\t/* Read back an atom. */\n\t++this.read;\n} \\atom_{M};\n\n\\fan_{i}[\\atom_{M}, \\atom_{M}] {\n\t/* Duplicate an atom. */\n\t++this.read;\n} \\atom_{M};\n\n\\erase {\n\t/* Erase an atom. */\n\t++this.read;\n} \\atom_{M};\n\n\\erase {\n\t/* Erase application. */\n\t++this.total;\n} \\apply[\\erase, \\erase];\n\n\\erase {\n\t/* Erase abstraction. */\n\t++this.total;\n} \\lambda[\\erase, \\erase];\n\n\\erase {\n\t/* Erase duplicator. */\n\t++this.total;\n} \\fan_{i}[\\erase, \\erase];\n\n\\erase {\n\t/* Finish erasing. */\n\t++this.total;\n} \\erase;\n\n\\erase {\n\t/* Erase context. */\n\t++this.read;\n} \\read_{C}[\\erase];\n\n$$\n\nINCONFIG\n\n$$\n\nREADBACK\n\nconst table = [];\nlet last = 0;\n\nfunction uniq()\n{\n\tlet fresh = ++last;\n\n\tfresh = fresh.toString();\n\tfresh = hash(fresh);\n\treturn [fresh, 1];\n}\n\nfunction cons(s, a, b)\n{\n\treturn hash(a + s + b);\n}\n\nfunction mktable()\n{\n\tfor (let n = 0; n < 256; n++) {\n\t\tlet c = n;\n\n\t\tfor (let k = 0; k < 8; k++) {\n\t\t\tif (c & 1)\n\t\t\t\tc = 0xEDB88320 ^ (c >>> 1);\n\t\t\telse\n\t\t\t\tc = c >>> 1;\n\t\t}\n\n\t\ttable[n] = c;\n\t}\n}\n\nfunction hash(str)\n{\n\tconst n = str.length;\n\tlet crc = 0 ^ (-1);\n\n\tfor (let i = 0; i < n; i++) {\n\t\tconst b = str.charCodeAt(i);\n\n\t\tcrc = (crc >>> 8) ^ table[(crc ^ b) & 0xFF];\n\t}\n\n\treturn (crc ^ (-1)) >>> 0;\n}\n\nmktable();\n\nthis.plus = cons.bind(this, \"+\");\nthis.minus = cons.bind(this, \"-\");\nthis.uniq = uniq;\nthis.beta = 0;\nthis.total = 0;\nthis.wait = 0;\nthis.read = 0;\n";
+const system = template.replace("READBACK\n", generic.readback);
+const expand = generic.expand;
+const mkwire = generic.mkwire;
+const mktwins = generic.mktwins;
+const getfv = generic.getfv;
+
+function psi(shared, list)
+{
+ for (const atom in shared) {
+ const twins = shared[atom];
+ const wleft = twins.left;
+ const wright = twins.right;
+ let eqn = "%s = \\fan_{this.uniq()}(%s, %s)";
+
+ eqn = eqn.replace("%s", atom);
+ eqn = eqn.replace("%s", wright);
+ eqn = eqn.replace("%s", wleft);
+
+ list.push(eqn);
+ }
+}
+
+function mkscope(n)
+{
+ let s = "%s";
+
+ for (let i = 0; i < n; i++)
+ s = "\\scope_{0}(" + s + ")";
+
+ return s;
+}
+
+function gamma(obj, root, list)
+{
+ const node = obj.node;
+
+ if ("atom" == node) {
+ if (obj.free) {
+ let agent = "\\atom_{this.mkid(\"%s\")}";
+
+ agent = agent.replace("%s", obj.name);
+
+ list.push(root + " = " + agent);
+ } else {
+ let agent = mkscope(0);
+
+ agent = agent.replace("%s", root);
+
+ list.push(obj.name + " = " + agent);
+ }
+ } else if ("abst" == node) {
+ const id = obj.var;
+ const body = obj.body;
+ const fv = getfv(body);
+ const wire = mkwire();
+ let tree = "\\lambda(%s, %s)";
+ let agent;
+
+ if (id in fv)
+ agent = id;
+ else
+ agent = "\\erase";
+
+ tree = tree.replace("%s", agent);
+ tree = tree.replace("%s", wire);
+
+ list.push(root + " = " + tree);
+
+ gamma(body, wire, list);
+ } else if ("appl" == node) {
+ const wleft = mkwire();
+ const wright = mkwire();
+ const left = obj.left;
+ const right = obj.right;
+ const shared = mktwins(left, right);
+ let agent = "\\apply(%s, %s)";
+
+ agent = agent.replace("%s", wright);
+ agent = agent.replace("%s", root);
+
+ list.push(wleft + " = " + agent);
+
+ gamma(left, wleft, list);
+ gamma(right, wright, list);
+ psi(shared, list);
+ }
+}
+
+function encode(term)
+{
+ let inconfig = [
+ "\\eval(\\read_{this.mkhole()}(\\print)) = root"
+ ];
+
+ gamma(expand(term), "root", inconfig);
+ inconfig = inconfig.join(";\n") + ";";
+
+ return system.replace("INCONFIG", inconfig);
+}
+
+module.exports = encode;
+
+},{"../generic":5,"path":14}],4:[function(require,module,exports){
+"use strict";
+
+const generic = require("../generic");
+
+const path = require("path");
+
+const template = "\\copy[a, b] {\n\t/* Unshare variable. */\n\t++this.total;\n} \\share[\\copy(c, \\copy(a, b)), c];\n\n\\copy[a, b] {\n\t/* Initiate application. */\n\t++this.total;\n} \\outapp[\\apply(c, \\copy(a, b)), c];\n\n\\dup[a, b] {\n\t/* Unshare variable. */\n\t++this.total;\n} \\share[\\copy(c, \\dup(a, b)), c];\n\n\\dup[a, b] {\n\t/* Initiate application. */\n\t++this.total;\n} \\outapp[\\apply(c, \\dup(a, b)), c];\n\n\\apply[a, b] {\n\t/* Unshare variable. */\n\t++this.total;\n} \\share[\\copy(c, \\apply(a, b)), c];\n\n\\apply[a, b] {\n\t/* Initiate application. */\n\t++this.total;\n} \\outapp[\\apply(c, \\apply(a, b)), c];\n\n\\bind[a, \\outapp(b, c), d] {\n\t/* Inject application. */\n\t++this.total;\n} \\outapp[\\bind(e, b, d), \\bind(a, c, e)];\n\n\\erase {\n\t/* Erase sharing. */\n\t++this.total;\n} \\share[a, a];\n\n\\erase {\n\t/* Erase application. */\n\t++this.total;\n} \\outapp[\\erase, \\erase];\n\n\\bind[a, \\amb(b, \\share(c, d), d), e] {\n\t/* Inject sharing. */\n\t++this.total;\n} \\share[\\bind(a, c, e), b];\n\n\\read_{C}[a] {\n\t/* Initiate application. */\n\t++this.total;\n} \\outapp[\\apply(b, \\read_{C}(a)), b];\n\n\\print {\n\t/* Output results of read-back. */\n\tthis.nf = M;\n\t++this.total;\n} \\atom_{M};\n\n\\bind[a, \\erase, a] {\n\t/* Erase FV. */\n\t++this.total;\n} \\erase;\n\n\\bind[a, \\atom_{M}, a] {\n\t/* Bind an atom. */\n\t++this.total;\n} \\atom_{M};\n\n\\bind[a, \\lambda(b, c), a] {\n\t/* Bind a closed abstraction. */\n\t++this.total;\n} \\lambda[b, c];\n\n\\bind[\\dup(a, b), \\dup(c, d), \\dup(e, f)] {\n\t/* Duplicate FV. */\n\t++this.total;\n} \\dup[\\bind(a, c, e), \\bind(b, d, f)];\n\n\\read_{C}[\\dup(a, b)] {\n\t/* Duplicate context. */\n\t++this.total;\n} \\dup[\\read_{C}(a), \\read_{this.clone(C)}(b)];\n\n\\dup[a, b] {\n\t/* Duplicate sharing. */\n\t++this.total;\n} \\copy[\\dup(\\amb(c, \\share(a, d), d), \\amb(e, \\share(b, f), f)),\n\t\\dup(c, e)];\n\n\\read_{C}[a] {\n\t/* Read back abstraction. */\n\t++this.total;\n} \\lambda[\\atom_{this.mkid()}, \\read_{this.abst(C)}(a)];\n\n\\apply[\\read_{this.appl(M)}(a), a] {\n\t/* Read back application. */\n\t++this.total;\n} \\atom_{M};\n\n\\read_{C}[\\atom_{this.atom(C, M)}] {\n\t/* Read back an atom. */\n\t++this.total;\n} \\atom_{M};\n\n\\copy[\\atom_{M}, \\atom_{M}] {\n\t/* Copy an atom. */\n\t++this.total;\n} \\atom_{M};\n\n\\dup[\\atom_{M}, \\atom_{M}] {\n\t/* Duplicate an atom. */\n\t++this.total;\n} \\atom_{M};\n\n\\apply[a, b] {\n\t/* Apply a closed term. */\n\t++this.beta;\n\t++this.total;\n} \\lambda[a, b];\n\n\\copy[\\lambda(a, b), \\lambda(c, d)] {\n\t/* Initiate copy of a closed term. */\n\t++this.total;\n} \\lambda[\\dup(a, c), \\dup(b, d)];\n\n\\apply[\\dup(a, b), \\dup(\\outapp(c, a), \\outapp(d, b))] {\n\t/* Duplicate application. */\n\t++this.total;\n} \\dup[c, d];\n\n\\dup[\\lambda(a, b), \\lambda(c, d)] {\n\t/* Duplicate abstraction. */\n\t++this.total;\n} \\lambda[\\dup(a, c), \\dup(b, d)];\n\n\\dup[a, b] {\n\t/* Finish duplication. */\n\t++this.total;\n} \\dup[a, b];\n\n\\erase {\n\t/* Erase an atom. */\n\t++this.total;\n} \\atom_{M};\n\n\\erase {\n\t/* Erase application. */\n\t++this.total;\n} \\apply[\\erase, \\erase];\n\n\\erase {\n\t/* Erase abstraction. */\n\t++this.total;\n} \\lambda[\\erase, \\erase];\n\n\\erase {\n\t/* Erase copy initiator. */\n\t++this.total;\n} \\copy[\\erase, \\erase];\n\n\\erase {\n\t/* Erase duplicator. */\n\t++this.total;\n} \\dup[\\erase, \\erase];\n\n\\erase {\n\t/* Finish erasing. */\n\t++this.total;\n} \\erase;\n\n$$\n\nINCONFIG\n\n$$\n\nREADBACK\n\nthis.beta = 0;\nthis.total = 0;\n";
+const system = template.replace("READBACK\n", generic.readback);
+const expand = generic.expand;
+const mkwire = generic.mkwire;
+const mktwins = generic.mktwins;
+const getfv = generic.getfv;
+const subst = generic.subst;
+
+function psi(shared, list)
+{
+ for (const atom in shared) {
+ const twins = shared[atom];
+ const wleft = twins.left;
+ const wright = twins.right;
+ const wire = mkwire();
+ let eqn = "%s = \\amb(%s, \\share(%s, %s), %s)";
+
+ eqn = eqn.replace("%s", wleft);
+ eqn = eqn.replace("%s", wright);
+ eqn = eqn.replace("%s", atom);
+ eqn = eqn.replace("%s", wire);
+ eqn = eqn.replace("%s", wire);
+
+ list.push(eqn);
+ }
+}
+
+function rho(fv, root, end, list)
+{
+ for (const atom in fv) {
+ const ref = fv[atom].ref;
+ const next = mkwire();
+ let head = "%s = \\bind(%s, %s, %s)";
+
+ head = head.replace("%s", atom);
+ head = head.replace("%s", next);
+ head = head.replace("%s", ref);
+ head = head.replace("%s", root);
+
+ list.push(head);
+
+ root = next;
+ }
+
+ list.push(root + " = " + end);
+}
+
+function gamma(obj, root, list)
+{
+ const node = obj.node;
+
+ if ("atom" == node) {
+ let agent = "\\atom_{this.mkid(\"%s\")}";
+
+ if (obj.free)
+ agent = agent.replace("%s", obj.name);
+ else
+ agent = obj.name;
+
+ list.push(root + " = " + agent);
+ } else if ("abst" == node) {
+ const id = obj.var;
+ const body = obj.body;
+ const fv = getfv(body);
+ const wire = mkwire();
+ let tree = "\\lambda(%s, %s)";
+ let agent;
+
+ if (id in fv)
+ agent = id;
+ else
+ agent = "\\erase";
+
+ tree = tree.replace("%s", agent);
+ tree = tree.replace("%s", wire);
+
+ delete fv[id];
+
+ for (const atom in fv) {
+ var wref = mkwire();
+
+ fv[atom] = {
+ ref: wref
+ };
+ }
+
+ subst(body, fv, "ref");
+
+ rho(fv, root, tree, list);
+ gamma(body, wire, list);
+ } else if ("appl" == node) {
+ const wleft = mkwire();
+ const wright = mkwire();
+ const left = obj.left;
+ const right = obj.right;
+ const shared = mktwins(left, right);
+ let agent = "\\outapp(%s, %s)";
+
+ agent = agent.replace("%s", wleft);
+ agent = agent.replace("%s", wright);
+
+ list.push(root + " = " + agent);
+
+ gamma(left, wleft, list);
+ gamma(right, wright, list);
+ psi(shared, list);
+ }
+}
+
+function encode(term)
+{
+ let inconfig = [
+ "\\read_{this.mkhole()}(\\print) = root"
+ ];
+
+ gamma(expand(term), "root", inconfig);
+ inconfig = inconfig.join(";\n") + ";";
+
+ return system.replace("INCONFIG", inconfig);
+}
+
+module.exports = encode;
+
+},{"../generic":5,"path":14}],5:[function(require,module,exports){
+"use strict";
+
+
+const path = require("path");
+
+const readback = "const gfv = [];\nlet id = 0;\n\nfunction mkvar(fresh)\n{\n\tif (fresh)\n\t\t++id;\n\n\treturn \"v\" + id.toFixed(0);\n}\n\nfunction mkid(name)\n{\n\tconst fv = {};\n\tconst obj = {\n\t\tnode: \"atom\",\n\t\tname: name,\n\t\tfv: fv\n\t};\n\n\tif (name) {\n\t\tgfv[name] = true;\n\t\treturn obj;\n\t}\n\n\tdo {\n\t\tname = mkvar(true);\n\t} while (gfv[name]);\n\n\tobj.name = name;\n\tfv[name] = true;\n\treturn obj;\n}\n\nfunction mkhole()\n{\n\tconst obj = {};\n\n\tobj.fv = {};\n\tobj.bv = {};\n\tobj.hole = obj;\n\treturn obj;\n}\n\nfunction subst(hole, obj)\n{\n\tconst parent = hole.parent;\n\tconst body = obj.body;\n\tconst left = obj.left;\n\tconst right = obj.right;\n\n\tif (parent)\n\t\tobj.parent = hole.parent;\n\telse\n\t\tdelete obj.parent;\n\n\tObject.assign(hole, obj);\n\n\tif (body)\n\t\tbody.parent = hole;\n\tif (left)\n\t\tleft.parent = hole;\n\tif (right)\n\t\tright.parent = hole;\n}\n\nfunction eta(obj)\n{\n\tlet parent, left, right, name;\n\n\tif (\"appl\" != obj.node)\n\t\treturn;\n\n\tparent = obj.parent;\n\tif (!parent)\n\t\treturn;\n\tif (\"abst\" != parent.node)\n\t\treturn;\n\n\tright = obj.right;\n\tif (\"atom\" != right.node)\n\t\treturn;\n\n\tname = parent.var;\n\tif (name != right.name)\n\t\treturn;\n\n\tleft = obj.left;\n\tif (left.fv[name])\n\t\treturn;\n\n\tsubst(parent, left);\n\n\teta(parent);\n}\n\nfunction atom(context, obj, name)\n{\n\tconst ofv = obj.fv;\n\tconst cfv = context.fv;\n\tconst bv = context.bv;\n\tconst chole = context.hole;\n\tconst ohole = obj.hole;\n\n\tif (name)\n\t\tbv[name] = true;\n\n\tfor (const key in ofv)\n\t\tif (!(key in bv))\n\t\t\tcfv[key] = true;\n\n\tsubst(chole, obj);\n\n\tif (ohole) {\n\t\tdelete chole.hole;\n\t\tcontext.hole = ohole;\n\t} else {\n\t\tdelete context.hole;\n\t\teta(chole);\n\t}\n\n\treturn context;\n}\n\nfunction abst(context)\n{\n\tconst hole = mkhole();\n\tconst name = mkvar();\n\tconst obj = {\n\t\tnode: \"abst\",\n\t\tvar: name,\n\t\tbody: hole,\n\t\tfv: {},\n\t\thole: hole\n\t};\n\n\thole.parent = obj;\n\treturn atom(context, obj, name);\n}\n\nfunction appl(left)\n{\n\tconst context = mkhole();\n\tconst hole = mkhole();\n\tconst obj = {\n\t\tnode: \"appl\",\n\t\tleft: left,\n\t\tright: hole,\n\t\tfv: Object.assign({}, left.fv),\n\t\thole: hole\n\t};\n\n\tleft.parent = obj;\n\thole.parent = obj;\n\treturn atom(context, obj);\n}\n\nfunction clone(obj, root, hole, parent)\n{\n\tconst copy = {};\n\n\tif (!obj)\n\t\treturn;\n\n\tif (!root) {\n\t\troot = copy;\n\t\thole = obj.hole;\n\t}\n\n\tcopy.node = obj.node;\n\tcopy.var = obj.var;\n\tcopy.name = obj.name;\n\tcopy.parent = parent;\n\tcopy.body = clone(obj.body, root, hole, copy);\n\tcopy.left = clone(obj.left, root, hole, copy);\n\tcopy.right = clone(obj.right, root, hole, copy);\n\n\tcopy.fv = Object.assign({}, obj.fv);\n\tcopy.bv = Object.assign({}, obj.bv);\n\n\tif (obj === hole)\n\t\troot.hole = copy;\n\n\treturn copy;\n}\n\nthis.clone = clone;\nthis.mkid = mkid;\nthis.mkvar = mkvar;\nthis.mkhole = mkhole;\nthis.abst = abst;\nthis.appl = appl;\nthis.atom = atom;\n";
+let lastwire;
+
+function getcap(left, right)
+{
+ const dict = {};
+
+ for (const prop in left)
+ if (prop in right)
+ dict[prop] = left[prop];
+
+ return dict;
+}
+
+function merge(left, right)
+{
+ const dict = {};
+
+ for (const prop in left)
+ dict[prop] = left[prop];
+
+ for (const prop in right)
+ dict[prop] = right[prop];
+
+ return dict;
+}
+
+function getfv(obj)
+{
+ const node = obj.node;
+ let fv;
+
+ if ("atom" == node) {
+ fv = {};
+
+ if (!obj.free)
+ fv[obj.name] = true;
+ } else if ("abst" == node) {
+ fv = getfv(obj.body);
+
+ delete fv[obj.var];
+ } else if ("appl" == node) {
+ const left = getfv(obj.left);
+ const right = getfv(obj.right);
+
+ fv = merge(left, right);
+ }
+
+ return fv;
+}
+
+function mkwire()
+{
+ ++lastwire;
+ return "w" + lastwire.toFixed(0);
+}
+
+function subst(obj, shared, side)
+{
+ const node = obj.node;
+
+ if ("atom" == node) {
+ const name = obj.name;
+
+ if (name in shared) {
+ const entry = shared[name];
+
+ obj.name = entry[side];
+ }
+ } else if ("abst" == node) {
+ const body = obj.body;
+
+ subst(body, shared, side);
+ } else if ("appl" == node) {
+ subst(obj.left, shared, side);
+ subst(obj.right, shared, side);
+ }
+}
+
+function mktwins(left, right)
+{
+ const fvleft = getfv(left);
+ const fvright = getfv(right);
+ const shared = getcap(fvleft, fvright);
+
+ for (const atom in shared) {
+ const wleft = mkwire();
+ const wright = mkwire();
+
+ shared[atom] = {
+ left: wleft,
+ right: wright
+ };
+ }
+
+ subst(left, shared, "left");
+ subst(right, shared, "right");
+
+ return shared;
+}
+
+function alpha(obj, bv, lvl)
+{
+ const node = obj.node;
+ const aobj = {
+ node: node
+ };
+
+ if (!bv)
+ bv = {};
+
+ if (!lvl)
+ lvl = 0;
+
+ if ("atom" == node) {
+ const name = obj.name;
+ const id = bv[name];
+
+ if (id) {
+ aobj.name = id.name;
+ aobj.index = lvl - id.lvl;
+ } else {
+ aobj.name = name;
+ aobj.free = true;
+ }
+ } else if ("abst" == node) {
+ const id = obj.var;
+ const old = bv[id];
+ const wire = mkwire();
+
+ bv[id] = {
+ name: wire,
+ lvl: ++lvl
+ };
+
+ aobj.var = wire;
+ aobj.body = alpha(obj.body, bv, lvl);
+
+ if (old)
+ bv[id] = old;
+ else
+ delete bv[id];
+ } else if ("appl" == node) {
+ aobj.left = alpha(obj.left, bv, lvl);
+ aobj.right = alpha(obj.right, bv, lvl);
+ }
+
+ return aobj;
+}
+
+function expand(dict)
+{
+ const macros = dict.macros;
+ const mlen = macros.length;
+ let term = dict.term;
+ let fv = getfv(term);
+
+ for (let i = 0; i < mlen; i++) {
+ const macro = macros[i];
+ const id = macro.id;
+ const def = macro.def;
+
+ if (!fv[id])
+ continue;
+
+ delete fv[id];
+ fv = merge(fv, getfv(def));
+
+ term = {
+ node: "appl",
+ left: {
+ node: "abst",
+ var: id,
+ body: term
+ },
+ right: def
+ };
+ }
+
+ dict.expanded = term;
+ lastwire = 0;
+ return alpha(term);
+}
+
+exports.expand = expand;
+exports.mkwire = mkwire;
+exports.mktwins = mktwins;
+exports.getfv = getfv;
+exports.subst = subst;
+exports.readback = readback;
+
+},{"path":14}],6:[function(require,module,exports){
+"use strict";
+
+exports.abstract = require("./abstract");
+exports.closed = require("./closed");
+exports.normal = require("./normal");
+exports.optimal = require("./optimal");
+exports.turning = require("./turning");
+
+},{"./abstract":3,"./closed":4,"./normal":7,"./optimal":8,"./turning":9}],7:[function(require,module,exports){
+"use strict";
+
+const generic = require("../generic");
+
+const path = require("path");
+
+const template = "\\print {\n\t/* Output results of read-back. */\n\tthis.nf = M;\n\t++this.total;\n} \\atom_{M};\n\n\\read_{C}[a] {\n\t/* Unshare variable. */\n\t++this.total;\n} \\share[\\copy(b, \\read_{C}(a)), b];\n\n\\read_{C}[a] {\n\t/* Initiate application. */\n\t++this.total;\n} \\apply[\\lambda(b, \\read_{C}(a)), b];\n\n\\read_{C}[a] {\n\t/* Read back abstraction. */\n\t++this.total;\n} \\lambda[\\atom_{this.mkid()}, \\read_{this.abst(C)}(a)];\n\n\\lambda[\\read_{this.appl(M)}(a), a] {\n\t/* Read back application. */\n\t++this.total;\n} \\atom_{M};\n\n\\read_{C}[\\atom_{this.atom(C, M)}] {\n\t/* Read back an atom. */\n\t++this.total;\n} \\atom_{M};\n\n\\copy[\\atom_{M}, \\atom_{this.clone(M)}] {\n\t/* Copy an atom. */\n\t++this.total;\n} \\atom_{M};\n\n\\dup[\\atom_{M}, \\atom_{this.clone(M)}] {\n\t/* Duplicate an atom. */\n\t++this.total;\n} \\atom_{M};\n\n\\lambda[a, b] {\n\t/* Unshare variable. */\n\t++this.total;\n} \\share[\\copy(c, \\lambda(a, b)), c];\n\n\\lambda[a, b] {\n\t/* Initiate application. */\n\t++this.total;\n} \\apply[\\lambda(c, \\lambda(a, b)), c];\n\n\\lambda[a, b] {\n\t/* Apply a closed term. */\n\t++this.beta;\n\t++this.total;\n} \\lambda[a, b];\n\n\\copy[a, b] {\n\t/* Unshare variable. */\n\t++this.total;\n} \\share[\\copy(c, \\copy(a, b)), c];\n\n\\copy[a, b] {\n\t/* Initiate application. */\n\t++this.total;\n} \\apply[\\lambda(c, \\copy(a, b)), c];\n\n\\copy[\\lambda(a, b), \\lambda(c, d)] {\n\t/* Initiate copy of a closed term. */\n\t++this.total;\n} \\lambda[\\dup(a, c), \\dup(b, d)];\n\n\\dup[a, b] {\n\t/* Unshare variable. */\n\t++this.total;\n} \\share[\\copy(c, \\dup(a, b)), c];\n\n\\dup[a, b] {\n\t/* Duplicate sharing. */\n\t++this.total;\n} \\copy[\\dup(\\amb(c, \\share(a, d), d), \\amb(e, \\share(b, f), f)),\n\t\\dup(c, e)];\n\n\\dup[\\apply(a, b), \\apply(c, d)] {\n\t/* Duplicate application. */\n\t++this.total;\n} \\apply[\\dup(a, c), \\dup(b, d)];\n\n\\dup[\\lambda(a, b), \\lambda(c, d)] {\n\t/* Duplicate abstraction. */\n\t++this.total;\n} \\lambda[\\dup(a, c), \\dup(b, d)];\n\n\\dup[a, b] {\n\t/* Finish duplication. */\n\t++this.total;\n} \\dup[a, b];\n\n\\erase {\n\t/* Erase an atom. */\n\t++this.total;\n} \\atom_{M};\n\n\\erase {\n\t/* Erase sharing. */\n\t++this.total;\n} \\share[a, a];\n\n\\erase {\n\t/* Erase application. */\n\t++this.total;\n} \\apply[\\erase, \\erase];\n\n\\erase {\n\t/* Erase abstraction. */\n\t++this.total;\n} \\lambda[\\erase, \\erase];\n\n\\erase {\n\t/* Erase copy initiator. */\n\t++this.total;\n} \\copy[\\erase, \\erase];\n\n\\erase {\n\t/* Erase duplicator. */\n\t++this.total;\n} \\dup[\\erase, \\erase];\n\n\\erase {\n\t/* Finish erasing. */\n\t++this.total;\n} \\erase;\n\n$$\n\nINCONFIG\n\n$$\n\nREADBACK\n\nthis.beta = 0;\nthis.total = 0;\n";
+const system = template.replace("READBACK\n", generic.readback);
+const expand = generic.expand;
+const mkwire = generic.mkwire;
+const mktwins = generic.mktwins;
+const getfv = generic.getfv;
+
+function psi(shared, list)
+{
+ for (const atom in shared) {
+ const twins = shared[atom];
+ const wleft = twins.left;
+ const wright = twins.right;
+ const wire = mkwire();
+ let eqn = "%s = \\amb(%s, \\share(%s, %s), %s)";
+
+ eqn = eqn.replace("%s", wleft);
+ eqn = eqn.replace("%s", wright);
+ eqn = eqn.replace("%s", atom);
+ eqn = eqn.replace("%s", wire);
+ eqn = eqn.replace("%s", wire);
+
+ list.push(eqn);
+ }
+}
+
+function gamma(obj, root, list)
+{
+ const node = obj.node;
+
+ if ("atom" == node) {
+ let agent = "\\atom_{this.mkid(\"%s\")}";
+
+ if (obj.free)
+ agent = agent.replace("%s", obj.name);
+ else
+ agent = obj.name;
+
+ list.push(root + " = " + agent);
+ } else if ("abst" == node) {
+ const id = obj.var;
+ const body = obj.body;
+ const fv = getfv(body);
+ const wire = mkwire();
+ let tree = "\\lambda(%s, %s)";
+ let agent;
+
+ if (id in fv)
+ agent = id;
+ else
+ agent = "\\erase";
+
+ tree = tree.replace("%s", agent);
+ tree = tree.replace("%s", wire);
+
+ list.push(root + " = " + tree);
+
+ gamma(body, wire, list);
+ } else if ("appl" == node) {
+ const wleft = mkwire();
+ const wright = mkwire();
+ const left = obj.left;
+ const right = obj.right;
+ const shared = mktwins(left, right);
+ let agent = "\\apply(%s, %s)";
+
+ agent = agent.replace("%s", wleft);
+ agent = agent.replace("%s", wright);
+
+ list.push(root + " = " + agent);
+
+ gamma(left, wleft, list);
+ gamma(right, wright, list);
+ psi(shared, list);
+ }
+}
+
+function encode(term)
+{
+ let inconfig = [
+ "\\read_{this.mkhole()}(\\print) = root"
+ ];
+
+ gamma(expand(term), "root", inconfig);
+ inconfig = inconfig.join(";\n") + ";";
+
+ return system.replace("INCONFIG", inconfig);
+}
+
+module.exports = encode;
+
+},{"../generic":5,"path":14}],8:[function(require,module,exports){
+"use strict";
+
+const generic = require("../generic");
+
+const path = require("path");
+
+const template = "\\eval[\\fan_{i}(a, b)] {\n\t/* Postpone evaluation. */\n\t++this.total;\n} \\fan_{i}[a, b];\n\n\\eval[\\scope_{i}(a)] {\n\t/* Evaluate delimiter. */\n\t++this.total;\n} \\scope_{i}[\\eval(a)];\n\n\\eval[a] {\n\t/* Continue evaluation. */\n\t++this.total;\n} \\wait[\\eval(a), \\call];\n\n\\eval[\\atom_{M}] {\n\t/* Return an atom. */\n\t++this.total;\n} \\atom_{M};\n\n\\eval[\\lambda(a, b)] {\n\t/* Evaluate abstraction. */\n\t++this.total;\n} \\lambda[a, \\eval(b)];\n\n\\fan_{i}[\\scope_{j}(a), \\scope_{j}(b)] {\n\t/* Duplicate higher delimiter. */\n\tif (i < j)\n\t\t++this.total;\n\telse\n\t\treturn false;\n} \\scope_{j}[\\fan_{i}(a, b)];\n\n\\scope_{i}[\\fan_{j + 1}(a, b)] {\n\t/* Level up higher or matching fan. */\n\tif (i <= j)\n\t\t++this.total;\n\telse\n\t\treturn false;\n} \\fan_{j}[\\scope_{i}(a), \\scope_{i}(b)];\n\n\\scope_{i}[\\scope_{j + 1}(a)] {\n\t/* Level up higher delimiter. */\n\tif (i < j)\n\t\t++this.total;\n\telse\n\t\treturn false;\n} \\scope_{j}[\\scope_{i}(a)];\n\n\\print {\n\t/* Ignore delimiter. */\n\t++this.total;\n} \\scope_{i}[\\print];\n\n\\read_{C}[\\scope_{i}(a)] {\n\t/* Pass through context. */\n\t++this.total;\n} \\scope_{i}[\\read_{C}(a)];\n\n\\scope_{i}[a] {\n\t/* Annihilate matching delimiters. */\n\tif (i == j)\n\t\t++this.total;\n\telse\n\t\treturn false;\n} \\scope_{j}[a];\n\n\\scope_{i}[\\apply(a, b)] {\n\t/* Pass through application. */\n\t++this.total;\n} \\apply[\\scope_{i}(a), \\scope_{i}(b)];\n\n\\scope_{i}[\\lambda(a, b)] {\n\t/* Level up delimiter. */\n\t++this.total;\n} \\lambda[\\scope_{i + 1}(a), \\scope_{i + 1}(b)];\n\n\\erase {\n\t/* Erase delimiter. */\n\t++this.total;\n} \\scope_{i}[\\erase];\n\n\\scope_{i}[\\wait(a, b)] {\n\t/* Postpone delimiter. */\n\t++this.total;\n} \\wait[\\scope_{i}(a), b];\n\n\\scope_{i}[\\atom_{M}] {\n\t/* Return an atom. */\n\t++this.total;\n} \\atom_{M};\n\n\\read_{C}[\\fan_{i}(a, b)] {\n\t/* Duplicate context. */\n\t++this.total;\n} \\fan_{i}[\\read_{C}(a), \\read_{this.clone(C)}(b)];\n\n\\call {\n\t/* Erase late call. */\n\t++this.total;\n} \\erase;\n\n\\fan_{i}[\\wait(a, \\amb(b, \\decide(c, d), d)), \\wait(e, b)] {\n\t/* Postpone duplication. */\n\t++this.total;\n} \\wait[\\fan_{i}(a, e), c];\n\n\\call {\n\t/* Continue evaluation. */\n\t++this.total;\n} \\decide[\\call, \\erase];\n\n\\erase {\n\t/* Erase reference. */\n\t++this.total;\n} \\decide[a, a];\n\n\\call {\n\t/* Continue evaluation. */\n\t++this.total;\n} \\hold[a, \\eval(a)];\n\n\\read_{C}[\\wait(a, b)] {\n\t/* Postpone readback. */\n\t++this.total;\n} \\wait[\\read_{C}(a), b];\n\n\\erase {\n\t/* Erase holder. */\n\t++this.total;\n} \\hold[\\erase, \\erase];\n\n\\erase {\n\t/* Erase reference. */\n\t++this.total;\n} \\wait[\\erase, \\erase];\n\n\\apply[a, \\wait(b, \\hold(\\apply(a, b), \\wait(c, d)))] {\n\t/* Postpone application. */\n\t++this.total;\n} \\wait[c, d];\n\n\\print {\n\t/* Output results of read-back. */\n\tthis.nf = M;\n\t++this.total;\n} \\atom_{M};\n\n\\read_{C}[a] {\n\t/* Read back abstraction. */\n\t++this.total;\n} \\lambda[\\atom_{this.mkid()}, \\read_{this.abst(C)}(a)];\n\n\\apply[\\read_{this.appl(M)}(a), a] {\n\t/* Read back application. */\n\t++this.total;\n} \\atom_{M};\n\n\\read_{C}[\\atom_{this.atom(C, M)}] {\n\t/* Read back an atom. */\n\t++this.total;\n} \\atom_{M};\n\n\\fan_{i}[\\atom_{M}, \\atom_{M}] {\n\t/* Duplicate an atom. */\n\t++this.total;\n} \\atom_{M};\n\n\\apply[a, \\scope_{0}(b)] {\n\t/* Apply beta reduction. */\n\t++this.beta;\n} \\lambda[\\wait(c, \\hold(\\scope_{0}(c), a)), b];\n\n\\fan_{i}[\\apply(a, b), \\apply(c, d)] {\n\t/* Duplicate application. */\n\t++this.total;\n} \\apply[\\fan_{i}(a, c), \\fan_{i}(b, d)];\n\n\\fan_{i}[\\lambda(a, b), \\lambda(c, d)] {\n\t/* Level up fan. */\n\t++this.total;\n} \\lambda[\\fan_{i + 1}(a, c), \\fan_{i + 1}(b, d)];\n\n\\fan_{i}[a, b] {\n\t/* Annihilate matching fans. */\n\tif (i == j)\n\t\t++this.total;\n\telse\n\t\treturn false;\n} \\fan_{j}[a, b];\n\n\\fan_{i}[\\fan_{j}(a, b), \\fan_{j}(c, d)] {\n\t/* Duplicate higher fan. */\n\tif (i < j)\n\t\t++this.total;\n\telse\n\t\treturn false;\n} \\fan_{j}[\\fan_{i}(a, c), \\fan_{i}(b, d)];\n\n\\erase {\n\t/* Erase an atom. */\n\t++this.total;\n} \\atom_{M};\n\n\\erase {\n\t/* Erase application. */\n\t++this.total;\n} \\apply[\\erase, \\erase];\n\n\\erase {\n\t/* Erase abstraction. */\n\t++this.total;\n} \\lambda[\\erase, \\erase];\n\n\\erase {\n\t/* Erase duplicator. */\n\t++this.total;\n} \\fan_{i}[\\erase, \\erase];\n\n\\erase {\n\t/* Finish erasing. */\n\t++this.total;\n} \\erase;\n\n$$\n\nINCONFIG\n\n$$\n\nREADBACK\n\nthis.beta = 0;\nthis.total = 0;\n";
+const system = template.replace("READBACK\n", generic.readback);
+const expand = generic.expand;
+const mkwire = generic.mkwire;
+const mktwins = generic.mktwins;
+const getfv = generic.getfv;
+
+function psi(shared, list)
+{
+ for (const atom in shared) {
+ const twins = shared[atom];
+ const wleft = twins.left;
+ const wright = twins.right;
+ let eqn = "%s = \\fan_{0}(%s, %s)";
+
+ eqn = eqn.replace("%s", atom);
+ eqn = eqn.replace("%s", wright);
+ eqn = eqn.replace("%s", wleft);
+
+ list.push(eqn);
+ }
+}
+
+function mkscope(n)
+{
+ let s = "%s";
+
+ for (let i = 0; i < n; i++)
+ s = "\\scope_{0}(" + s + ")";
+
+ return s;
+}
+
+function gamma(obj, root, list)
+{
+ const node = obj.node;
+
+ if ("atom" == node) {
+ if (obj.free) {
+ let agent = "\\atom_{this.mkid(\"%s\")}";
+
+ agent = agent.replace("%s", obj.name);
+
+ list.push(root + " = " + agent);
+ } else {
+ let agent = mkscope(obj.index);
+
+ agent = agent.replace("%s", root);
+
+ list.push(obj.name + " = " + agent);
+ }
+ } else if ("abst" == node) {
+ const id = obj.var;
+ const body = obj.body;
+ const fv = getfv(body);
+ const wire = mkwire();
+ let tree = "\\lambda(%s, %s)";
+ let agent;
+
+ if (id in fv)
+ agent = id;
+ else
+ agent = "\\erase";
+
+ tree = tree.replace("%s", agent);
+ tree = tree.replace("%s", wire);
+
+ list.push(root + " = " + tree);
+
+ gamma(body, wire, list);
+ } else if ("appl" == node) {
+ const wleft = mkwire();
+ const wright = mkwire();
+ const left = obj.left;
+ const right = obj.right;
+ const shared = mktwins(left, right);
+ let agent = "\\apply(%s, %s)";
+
+ agent = agent.replace("%s", wright);
+ agent = agent.replace("%s", root);
+
+ list.push(wleft + " = " + agent);
+
+ gamma(left, wleft, list);
+ gamma(right, wright, list);
+ psi(shared, list);
+ }
+}
+
+function encode(term)
+{
+ let inconfig = [
+ "\\eval(\\read_{this.mkhole()}(\\print)) = root"
+ ];
+
+ gamma(expand(term), "root", inconfig);
+ inconfig = inconfig.join(";\n") + ";";
+
+ return system.replace("INCONFIG", inconfig);
+}
+
+module.exports = encode;
+
+},{"../generic":5,"path":14}],9:[function(require,module,exports){
+"use strict";
+
+const generic = require("../generic");
+
+const path = require("path");
+
+const template = "\\print {\n\t/* Continue evaluation. */\n\t++this.total;\n} \\wait[\\print, \\call];\n\n\\apply[a, \\outapp(\\outapp(b, c), a)] {\n\t/* Turn application. */\n\t++this.total;\n} \\outapp[b, c];\n\n\\fanin_{i}[a, b] {\n\t/* Duplicate application. */\n\t++this.total;\n} \\outapp[\\fanin_{i}(\\apply(c, a), \\apply(d, b)), \\fanin_{i}(c, d)];\n\n\\eval[\\outapp(a, b)] {\n\t/* Postpone evaluation. */\n\t++this.total;\n} \\outapp[a, b];\n\n\\eval[\\fanout_{i}(a, b)] {\n\t/* Postpone evaluation. */\n\t++this.total;\n} \\fanout_{i}[a, b];\n\n\\eval[a] {\n\t/* Continue evaluation. */\n\t++this.total;\n} \\wait[\\eval(a), \\call];\n\n\\eval[\\atom_{M}] {\n\t/* Return an atom. */\n\t++this.total;\n} \\atom_{M};\n\n\\eval[\\lambda(a, b)] {\n\t/* Return abstraction. */\n\t++this.total;\n} \\lambda[a, b];\n\n\\read_{C}[\\fanout_{i}(a, b)] {\n\t/* Duplicate context. */\n\t++this.total;\n} \\fanout_{i}[\\read_{C}(a), \\read_{this.clone(C)}(b)];\n\n\\call {\n\t/* Erase late call. */\n\t++this.total;\n} \\erase;\n\n\\fanin_{i}[\\wait(a, \\amb(b, \\decide(c, d), d)), \\wait(e, b)] {\n\t/* Postpone duplication. */\n\t++this.total;\n} \\wait[\\fanin_{i}(a, e), c];\n\n\\call {\n\t/* Continue evaluation. */\n\t++this.total;\n} \\decide[\\call, \\erase];\n\n\\erase {\n\t/* Erase reference. */\n\t++this.total;\n} \\decide[a, a];\n\n\\call {\n\t/* Continue evaluation. */\n\t++this.total;\n} \\hold[a, \\eval(a)];\n\n\\read_{C}[\\wait(a, b)] {\n\t/* Postpone readback. */\n\t++this.total;\n} \\wait[\\read_{C}(a), b];\n\n\\erase {\n\t/* Erase holder. */\n\t++this.total;\n} \\hold[\\erase, \\erase];\n\n\\erase {\n\t/* Erase reference. */\n\t++this.total;\n} \\wait[\\erase, \\erase];\n\n\\apply[a, \\wait(b, \\hold(\\apply(a, b), \\wait(c, d)))] {\n\t/* Postpone application. */\n\t++this.total;\n} \\wait[c, d];\n\n\\print {\n\t/* Output results of read-back. */\n\tthis.nf = M;\n\t++this.total;\n} \\atom_{M};\n\n\\read_{C}[a] {\n\t/* Read back abstraction. */\n\t++this.total;\n} \\lambda[\\atom_{this.mkid()}, \\read_{this.abst(C)}(a)];\n\n\\apply[\\read_{this.appl(M)}(a), a] {\n\t/* Read back application. */\n\t++this.total;\n} \\atom_{M};\n\n\\read_{C}[\\atom_{this.atom(C, M)}] {\n\t/* Read back an atom. */\n\t++this.total;\n} \\atom_{M};\n\n\\fanin_{i}[\\atom_{M}, \\atom_{M}] {\n\t/* Duplicate an atom. */\n\t++this.total;\n} \\atom_{M};\n\n\\apply[a, b] {\n\t/* Apply beta reduction. */\n\t++this.beta;\n} \\lambda[\\wait(c, \\hold(c, a)), b];\n\n\\apply[a, \\outapp(\\fanout_{i}(b, c), a)] {\n\t/* Turn application. */\n\t++this.total;\n} \\fanout_{i}[b, c];\n\n\\fanin_{i}[\\lambda(a, b), \\lambda(c, d)] {\n\t/* Duplicate abstraction. */\n\t++this.total;\n} \\lambda[\\fanout_{i}(a, c), \\fanin_{i}(b, d)];\n\n\\fanin_{i}[a, b] {\n\t/* Annihilate matching fans. */\n\tif (i == j)\n\t\t++this.total;\n\telse\n\t\treturn false;\n} \\fanout_{j}[a, b];\n\n\\fanin_{i}[\\fanout_{j}(a, b), \\fanout_{j}(c, d)] {\n\t/* Duplicate different fans. */\n\tif (i != j)\n\t\t++this.total;\n\telse\n\t\treturn false;\n} \\fanout_{j}[\\fanin_{++this.id}(a, c), \\fanin_{++this.id}(b, d)];\n\n\\erase {\n\t/* Erase an atom. */\n\t++this.total;\n} \\atom_{M};\n\n\\erase {\n\t/* Erase application. */\n\t++this.total;\n} \\apply[\\erase, \\erase];\n\n\\erase {\n\t/* Erase abstraction. */\n\t++this.total;\n} \\lambda[\\erase, \\erase];\n\n\\erase {\n\t/* Erase duplicator. */\n\t++this.total;\n} \\fanin_{i}[\\erase, \\erase];\n\n\\erase {\n\t/* Erase duplicator. */\n\t++this.total;\n} \\fanout_{j}[\\erase, \\erase];\n\n\\erase {\n\t/* Finish erasing. */\n\t++this.total;\n} \\erase;\n\n\\erase {\n\t/* Erase context. */\n\t++this.total;\n} \\read_{C}[\\erase];\n\n\\erase {\n\t/* Erase application. */\n\t++this.total;\n} \\outapp[\\erase, \\erase];\n\n$$\n\nINCONFIG\n\n$$\n\nREADBACK\n\nthis.id = 0;\nthis.beta = 0;\nthis.total = 0;\n";
+const system = template.replace("READBACK\n", generic.readback);
+const expand = generic.expand;
+const mkwire = generic.mkwire;
+const mktwins = generic.mktwins;
+const getfv = generic.getfv;
+
+function psi(shared, list)
+{
+ for (const atom in shared) {
+ const twins = shared[atom];
+ const wleft = twins.left;
+ const wright = twins.right;
+ let eqn = "%s = \\fanin_{++this.id}(%s, %s)";
+
+ eqn = eqn.replace("%s", atom);
+ eqn = eqn.replace("%s", wright);
+ eqn = eqn.replace("%s", wleft);
+
+ list.push(eqn);
+ }
+}
+
+function mkscope(n)
+{
+ let s = "%s";
+
+ for (let i = 0; i < n; i++)
+ s = "\\scope_{0}(" + s + ")";
+
+ return s;
+}
+
+function gamma(obj, root, list)
+{
+ const node = obj.node;
+
+ if ("atom" == node) {
+ if (obj.free) {
+ let agent = "\\atom_{this.mkid(\"%s\")}";
+
+ agent = agent.replace("%s", obj.name);
+
+ list.push(root + " = " + agent);
+ } else {
+ let agent = mkscope(0);
+
+ agent = agent.replace("%s", root);
+
+ list.push(obj.name + " = " + agent);
+ }
+ } else if ("abst" == node) {
+ const id = obj.var;
+ const body = obj.body;
+ const fv = getfv(body);
+ const wire = mkwire();
+ let tree = "\\lambda(%s, %s)";
+ let agent;
+
+ if (id in fv)
+ agent = id;
+ else
+ agent = "\\erase";
+
+ tree = tree.replace("%s", agent);
+ tree = tree.replace("%s", wire);
+
+ list.push(root + " = " + tree);
+
+ gamma(body, wire, list);
+ } else if ("appl" == node) {
+ const wleft = mkwire();
+ const wright = mkwire();
+ const left = obj.left;
+ const right = obj.right;
+ const shared = mktwins(left, right);
+ let agent = "\\apply(%s, %s)";
+
+ agent = agent.replace("%s", wright);
+ agent = agent.replace("%s", root);
+
+ list.push(wleft + " = " + agent);
+
+ gamma(left, wleft, list);
+ gamma(right, wright, list);
+ psi(shared, list);
+ }
+}
+
+function encode(term)
+{
+ let inconfig = [
+ "\\eval(\\read_{this.mkhole()}(\\print)) = root"
+ ];
+
+ gamma(expand(term), "root", inconfig);
+ inconfig = inconfig.join(";\n") + ";";
+
+ return system.replace("INCONFIG", inconfig);
+}
+
+module.exports = encode;
+
+},{"../generic":5,"path":14}],10:[function(require,module,exports){
+"use strict";
+
+const encoding = require("./encoding");
+const compile = require("./compile");
+const samples = require("./samples");
+const inet = require("inet-lib");
+
+const parser = new compile.Parser();
+let expanded;
+
+function obj2mlc(obj)
+{
+ const node = obj.node;
+
+ if ("atom" == node)
+ return obj.name;
+
+ if ("abst" == node) {
+ const body = obj.body;
+ let sep;
+
+ if ("abst" == body.node)
+ sep = ", ";
+ else
+ sep = ": ";
+
+ return obj.var + sep + obj2mlc(body);
+ }
+
+ if ("appl" == node) {
+ const left = obj.left;
+ const right = obj.right;
+ const rnode = right.node;
+ let lmlc = obj2mlc(left);
+ let rmlc = obj2mlc(right);
+
+ if ("abst" == left.node)
+ lmlc = "(" + lmlc + ")";
+
+ if (("abst" == rnode) || ("appl" == rnode))
+ rmlc = "(" + rmlc + ")";
+
+ return lmlc + " " + rmlc;
+ }
+
+ return "[ ]";
+}
+
+function mlc2in(mlc, algo)
+{
+ const encode = encoding[algo ? algo : "normal"];
+ let insrc;
+
+ if (!encode)
+ throw `${algo}: Unknown algorithm`;
+
+ mlc = parser.parse(mlc);
+ insrc = encode(mlc);
+ expanded = mlc.expanded;
+
+ return insrc;
+}
+
+function format(data)
+{
+ if (Array.isArray(data))
+ return data.toString();
+ else if ("object" == typeof data)
+ return obj2mlc(data);
+ else if ("number" == typeof data)
+ return data.toString();
+ else
+ return data;
+}
+
+function prepare(mlc, algo)
+{
+ const src = mlc2in(mlc, algo);
+
+ inet.prepare(src, format);
+}
+
+function debug()
+{
+ return inet.debug();
+}
+
+function debug0()
+{
+ return inet.debug0();
+}
+
+function debug1()
+{
+ return inet.debug1();
+}
+
+function run(mlc, algo)
+{
+ const src = mlc2in(mlc, algo);
+ const output = inet(src);
+
+ output.term = obj2mlc(expanded);
+
+ if (output.nf)
+ output.nf = obj2mlc(output.nf);
+ else
+ output.nf = output.term;
+
+ return output;
+}
+
+run.prepare = prepare;
+run.debug = debug;
+run.debug0 = debug0;
+run.debug1 = debug1;
+run.mlc2in = mlc2in;
+run.example = samples.fact.replace(/\n*$/, "");
+run.samples = samples;
+
+module.exports = run;
+
+},{"./compile":2,"./encoding":6,"./samples":11,"inet-lib":13}],11:[function(require,module,exports){
+"use strict";
+
+
+const path = require("path");
+
+exports.asperti = "(x: x x) (x, y: (z: z (z y)) (w: x w))\n";
+exports.debug = "x: (x: x) v1 x\n";
+exports.exp = "C10 C2 C2 I I\n";
+exports.fact = "FACT = Y (self, n: (ZERO n) C1 (MULT n (self (PRED n))));\n\nMINUS (C3 C3) (FACT C4)\n";
+exports.helper = "I = x: x;\nK = x, y: x;\nS = x, y, z: x z (y z);\nT = K;\nF = K I;\nAND = p, q: p q F;\nOR = p, q: p T q;\nNOT = p: (a, b: p b a);\nC0 = f, x: x;\nC1 = f, x: f x;\nC2 = f, x: f (f x);\nC3 = f, x: f (f (f x));\nC4 = f, x: f (f (f (f x)));\nC5 = f, x: f (f (f (f (f x))));\nC6 = f, x: f (f (f (f (f (f x)))));\nC7 = f, x: f (f (f (f (f (f (f x))))));\nC8 = f, x: f (f (f (f (f (f (f (f x)))))));\nC9 = f, x: f (f (f (f (f (f (f (f (f x))))))));\nC10 = f, x: f (f (f (f (f (f (f (f (f (f x)))))))));\nSUCC = n: (f, x: f (n f x));\nPLUS = m, n: (f, x: m f (n f x));\nMULT = m, n: (f: m (n f));\nEXP = m, n: n m;\nPRED = n: (f, x: n (g, h: h (g f)) (K x) I);\nMINUS = m, n: n PRED m;\nZERO = n: n (K F) T;\nY = (a: a a) (self, f: f (self self f));\n";
+exports.larger = "FACT = Y (self, n: (ZERO n) C1 (MULT n (self (PRED n))));\n\nMINUS (C3 C5) (FACT C5)\n";
+exports.test = "(f, x: x f f) (x: (y: y y) (y: y x))\n";
+
+},{"path":14}],12:[function(require,module,exports){
+/* parser generated by jison 0.4.15 */
+/*
+ Returns a Parser object of the following structure:
+
+ Parser: {
+ yy: {}
+ }
+
+ Parser.prototype: {
+ yy: {},
+ trace: function(),
+ symbols_: {associative list: name ==> number},
+ terminals_: {associative list: number ==> name},
+ productions_: [...],
+ performAction: function anonymous(yytext, yyleng, yylineno, yy, yystate, $$, _$),
+ table: [...],
+ defaultActions: {...},
+ parseError: function(str, hash),
+ parse: function(input),
+
+ lexer: {
+ EOF: 1,
+ parseError: function(str, hash),
+ setInput: function(input),
+ input: function(),
+ unput: function(str),
+ more: function(),
+ less: function(n),
+ pastInput: function(),
+ upcomingInput: function(),
+ showPosition: function(),
+ test_match: function(regex_match_array, rule_index),
+ next: function(),
+ lex: function(),
+ begin: function(condition),
+ popState: function(),
+ _currentRules: function(),
+ topState: function(),
+ pushState: function(condition),
+
+ options: {
+ ranges: boolean (optional: true ==> token location info will include a .range[] member)
+ flex: boolean (optional: true ==> flex-like lexing behaviour where the rules are tested exhaustively to find the longest match)
+ backtrack_lexer: boolean (optional: true ==> lexer regexes are tested in order and for each matching regex the action code is invoked; the lexer terminates the scan when a token is returned by the action code)
+ },
+
+ performAction: function(yy, yy_, $avoiding_name_collisions, YY_START),
+ rules: [...],
+ conditions: {associative list: name ==> set},
+ }
+ }
+
+
+ token location info (@$, _$, etc.): {
+ first_line: n,
+ last_line: n,
+ first_column: n,
+ last_column: n,
+ range: [start_number, end_number] (where the numbers are indexes into the input string, regular zero-based)
+ }
+
+
+ the parseError function receives a 'hash' object with these members for lexer and parser errors: {
+ text: (matched text)
+ token: (the produced terminal token, if any)
+ line: (yylineno)
+ }
+ while parser (grammar) errors will also provide these members, i.e. parser errors deliver a superset of attributes: {
+ loc: (yylloc)
+ expected: (string describing the set of expected tokens)
+ recoverable: (boolean: TRUE when the parser has a error recovery rule available for this particular error)
+ }
+*/
+var parser = (function(){
+var o=function(k,v,o,l){for(o=o||{},l=k.length;l--;o[k[l]]=v);return o},$V0=[5,21],$V1=[1,6],$V2=[1,5,20,21],$V3=[9,10],$V4=[1,16],$V5=[9,10,12,14,17,18,19,23],$V6=[10,14,18,19,23],$V7=[1,26],$V8=[14,18,19];
+var parser = {trace: function trace() { },
+yy: {},
+symbols_: {"error":2,"prog":3,"rset":4,"MARK":5,"init":6,"tail":7,"side":8,"CODE":9,";":10,"cell":11,"[":12,"list":13,"]":14,"tree":15,"leaf":16,"(":17,")":18,",":19,"NAME":20,"\\":21,"_":22,"=":23,"$accept":0,"$end":1},
+terminals_: {2:"error",5:"MARK",9:"CODE",10:";",12:"[",14:"]",17:"(",18:")",19:",",20:"NAME",21:"\\",22:"_",23:"="},
+productions_: [0,[3,4],[4,0],[4,5],[8,1],[8,4],[15,1],[15,4],[13,1],[13,3],[16,1],[16,1],[11,2],[11,4],[6,0],[6,5],[7,0],[7,2]],
+performAction: function anonymous(yytext, yyleng, yylineno, yy, yystate /* action[1] */, $$ /* vstack */, _$ /* lstack */) {
+/* this == yyval */
+
+var $0 = $$.length - 1;
+switch (yystate) {
+case 1:
+return {rules: $$[$0-3], conf: $$[$0-1], code: $$[$0]};
+break;
+case 2: case 14:
+this.$ = [];
+break;
+case 3:
+$$[$0-4].push({left: $$[$0-3], right: $$[$0-1], code: $$[$0-2]}); this.$ = $$[$0-4];
+break;
+case 4: case 6:
+this.$ = {node: $$[$0], pax: []};
+break;
+case 5: case 7:
+this.$ = {node: $$[$0-3], pax: $$[$0-1]};
+break;
+case 8:
+this.$ = [$$[$0]];
+break;
+case 9:
+$$[$0-2].push($$[$0]); this.$ = $$[$0-2];
+break;
+case 11:
+this.$ = {agent: "wire", name: $$[$0]};
+break;
+case 12:
+this.$ = {agent: $$[$0], code: ""};
+break;
+case 13:
+this.$ = {agent: $$[$0-2], code: $$[$0].slice(1, -1)};
+break;
+case 15:
+$$[$0-4].push({left: $$[$0-3], right: $$[$0-1]}); this.$ = $$[$0-4];
+break;
+case 16:
+this.$ = "";
+break;
+case 17:
+this.$ = $$[$0];
+break;
+}
+},
+table: [o($V0,[2,2],{3:1,4:2}),{1:[3]},{5:[1,3],8:4,11:5,21:$V1},o($V2,[2,14],{6:7}),{9:[1,8]},o($V3,[2,4],{12:[1,9]}),{20:[1,10]},{1:[2,16],5:[1,13],7:11,11:15,15:12,16:14,20:$V4,21:$V1},{8:17,11:5,21:$V1},{11:15,13:18,15:19,16:14,20:$V4,21:$V1},o($V5,[2,12],{22:[1,20]}),{1:[2,1]},{23:[1,21]},{9:[1,22]},o($V6,[2,6]),o($V6,[2,10],{17:[1,23]}),o($V6,[2,11]),{10:[1,24]},{14:[1,25],19:$V7},o($V8,[2,8]),{9:[1,27]},{11:15,15:28,16:14,20:$V4,21:$V1},{1:[2,17]},{11:15,13:29,15:19,16:14,20:$V4,21:$V1},o($V0,[2,3]),o($V3,[2,5]),{11:15,15:30,16:14,20:$V4,21:$V1},o($V5,[2,13]),{10:[1,31]},{18:[1,32],19:$V7},o($V8,[2,9]),o($V2,[2,15]),o($V6,[2,7])],
+defaultActions: {11:[2,1],22:[2,17]},
+parseError: function parseError(str, hash) {
+ if (hash.recoverable) {
+ this.trace(str);
+ } else {
+ throw new Error(str);
+ }
+},
+parse: function parse(input) {
+ var self = this, stack = [0], tstack = [], vstack = [null], lstack = [], table = this.table, yytext = '', yylineno = 0, yyleng = 0, recovering = 0, TERROR = 2, EOF = 1;
+ var args = lstack.slice.call(arguments, 1);
+ var lexer = Object.create(this.lexer);
+ var sharedState = { yy: {} };
+ for (var k in this.yy) {
+ if (Object.prototype.hasOwnProperty.call(this.yy, k)) {
+ sharedState.yy[k] = this.yy[k];
+ }
+ }
+ lexer.setInput(input, sharedState.yy);
+ sharedState.yy.lexer = lexer;
+ sharedState.yy.parser = this;
+ if (typeof lexer.yylloc == 'undefined') {
+ lexer.yylloc = {};
+ }
+ var yyloc = lexer.yylloc;
+ lstack.push(yyloc);
+ var ranges = lexer.options && lexer.options.ranges;
+ if (typeof sharedState.yy.parseError === 'function') {
+ this.parseError = sharedState.yy.parseError;
+ } else {
+ this.parseError = Object.getPrototypeOf(this).parseError;
+ }
+ function popStack(n) {
+ stack.length = stack.length - 2 * n;
+ vstack.length = vstack.length - n;
+ lstack.length = lstack.length - n;
+ }
+ _token_stack:
+ function lex() {
+ var token;
+ token = lexer.lex() || EOF;
+ if (typeof token !== 'number') {
+ token = self.symbols_[token] || token;
+ }
+ return token;
+ }
+ var symbol, preErrorSymbol, state, action, a, r, yyval = {}, p, len, newState, expected;
+ while (true) {
+ state = stack[stack.length - 1];
+ if (this.defaultActions[state]) {
+ action = this.defaultActions[state];
+ } else {
+ if (symbol === null || typeof symbol == 'undefined') {
+ symbol = lex();
+ }
+ action = table[state] && table[state][symbol];
+ }
+ if (typeof action === 'undefined' || !action.length || !action[0]) {
+ var errStr = '';
+ expected = [];
+ for (p in table[state]) {
+ if (this.terminals_[p] && p > TERROR) {
+ expected.push('\'' + this.terminals_[p] + '\'');
+ }
+ }
+ if (lexer.showPosition) {
+ errStr = 'Parse error on line ' + (yylineno + 1) + ':\n' + lexer.showPosition() + '\nExpecting ' + expected.join(', ') + ', got \'' + (this.terminals_[symbol] || symbol) + '\'';
+ } else {
+ errStr = 'Parse error on line ' + (yylineno + 1) + ': Unexpected ' + (symbol == EOF ? 'end of input' : '\'' + (this.terminals_[symbol] || symbol) + '\'');
+ }
+ this.parseError(errStr, {
+ text: lexer.match,
+ token: this.terminals_[symbol] || symbol,
+ line: lexer.yylineno,
+ loc: yyloc,
+ expected: expected
+ });
+ }
+ if (action[0] instanceof Array && action.length > 1) {
+ throw new Error('Parse Error: multiple actions possible at state: ' + state + ', token: ' + symbol);
+ }
+ switch (action[0]) {
+ case 1:
+ stack.push(symbol);
+ vstack.push(lexer.yytext);
+ lstack.push(lexer.yylloc);
+ stack.push(action[1]);
+ symbol = null;
+ if (!preErrorSymbol) {
+ yyleng = lexer.yyleng;
+ yytext = lexer.yytext;
+ yylineno = lexer.yylineno;
+ yyloc = lexer.yylloc;
+ if (recovering > 0) {
+ recovering--;
+ }
+ } else {
+ symbol = preErrorSymbol;
+ preErrorSymbol = null;
+ }
+ break;
+ case 2:
+ len = this.productions_[action[1]][1];
+ yyval.$ = vstack[vstack.length - len];
+ yyval._$ = {
+ first_line: lstack[lstack.length - (len || 1)].first_line,
+ last_line: lstack[lstack.length - 1].last_line,
+ first_column: lstack[lstack.length - (len || 1)].first_column,
+ last_column: lstack[lstack.length - 1].last_column
+ };
+ if (ranges) {
+ yyval._$.range = [
+ lstack[lstack.length - (len || 1)].range[0],
+ lstack[lstack.length - 1].range[1]
+ ];
+ }
+ r = this.performAction.apply(yyval, [
+ yytext,
+ yyleng,
+ yylineno,
+ sharedState.yy,
+ action[1],
+ vstack,
+ lstack
+ ].concat(args));
+ if (typeof r !== 'undefined') {
+ return r;
+ }
+ if (len) {
+ stack = stack.slice(0, -1 * len * 2);
+ vstack = vstack.slice(0, -1 * len);
+ lstack = lstack.slice(0, -1 * len);
+ }
+ stack.push(this.productions_[action[1]][0]);
+ vstack.push(yyval.$);
+ lstack.push(yyval._$);
+ newState = table[stack[stack.length - 2]][stack[stack.length - 1]];
+ stack.push(newState);
+ break;
+ case 3:
+ return true;
+ }
+ }
+ return true;
+}};
+/* generated by jison-lex 0.3.4 */
+var lexer = (function(){
+var lexer = ({
+
+EOF:1,
+
+parseError:function parseError(str, hash) {
+ if (this.yy.parser) {
+ this.yy.parser.parseError(str, hash);
+ } else {
+ throw new Error(str);
+ }
+ },
+
+// resets the lexer, sets new input
+setInput:function (input, yy) {
+ this.yy = yy || this.yy || {};
+ this._input = input;
+ this._more = this._backtrack = this.done = false;
+ this.yylineno = this.yyleng = 0;
+ this.yytext = this.matched = this.match = '';
+ this.conditionStack = ['INITIAL'];
+ this.yylloc = {
+ first_line: 1,
+ first_column: 0,
+ last_line: 1,
+ last_column: 0
+ };
+ if (this.options.ranges) {
+ this.yylloc.range = [0,0];
+ }
+ this.offset = 0;
+ return this;
+ },
+
+// consumes and returns one char from the input
+input:function () {
+ var ch = this._input[0];
+ this.yytext += ch;
+ this.yyleng++;
+ this.offset++;
+ this.match += ch;
+ this.matched += ch;
+ var lines = ch.match(/(?:\r\n?|\n).*/g);
+ if (lines) {
+ this.yylineno++;
+ this.yylloc.last_line++;
+ } else {
+ this.yylloc.last_column++;
+ }
+ if (this.options.ranges) {
+ this.yylloc.range[1]++;
+ }
+
+ this._input = this._input.slice(1);
+ return ch;
+ },
+
+// unshifts one char (or a string) into the input
+unput:function (ch) {
+ var len = ch.length;
+ var lines = ch.split(/(?:\r\n?|\n)/g);
+
+ this._input = ch + this._input;
+ this.yytext = this.yytext.substr(0, this.yytext.length - len);
+ //this.yyleng -= len;
+ this.offset -= len;
+ var oldLines = this.match.split(/(?:\r\n?|\n)/g);
+ this.match = this.match.substr(0, this.match.length - 1);
+ this.matched = this.matched.substr(0, this.matched.length - 1);
+
+ if (lines.length - 1) {
+ this.yylineno -= lines.length - 1;
+ }
+ var r = this.yylloc.range;
+
+ this.yylloc = {
+ first_line: this.yylloc.first_line,
+ last_line: this.yylineno + 1,
+ first_column: this.yylloc.first_column,
+ last_column: lines ?
+ (lines.length === oldLines.length ? this.yylloc.first_column : 0)
+ + oldLines[oldLines.length - lines.length].length - lines[0].length :
+ this.yylloc.first_column - len
+ };
+
+ if (this.options.ranges) {
+ this.yylloc.range = [r[0], r[0] + this.yyleng - len];
+ }
+ this.yyleng = this.yytext.length;
+ return this;
+ },
+
+// When called from action, caches matched text and appends it on next action
+more:function () {
+ this._more = true;
+ return this;
+ },
+
+// When called from action, signals the lexer that this rule fails to match the input, so the next matching rule (regex) should be tested instead.
+reject:function () {
+ if (this.options.backtrack_lexer) {
+ this._backtrack = true;
+ } else {
+ return this.parseError('Lexical error on line ' + (this.yylineno + 1) + '. You can only invoke reject() in the lexer when the lexer is of the backtracking persuasion (options.backtrack_lexer = true).\n' + this.showPosition(), {
+ text: "",
+ token: null,
+ line: this.yylineno
+ });
+
+ }
+ return this;
+ },
+
+// retain first n characters of the match
+less:function (n) {
+ this.unput(this.match.slice(n));
+ },
+
+// displays already matched input, i.e. for error messages
+pastInput:function () {
+ var past = this.matched.substr(0, this.matched.length - this.match.length);
+ return (past.length > 20 ? '...':'') + past.substr(-20).replace(/\n/g, "");
+ },
+
+// displays upcoming input, i.e. for error messages
+upcomingInput:function () {
+ var next = this.match;
+ if (next.length < 20) {
+ next += this._input.substr(0, 20-next.length);
+ }
+ return (next.substr(0,20) + (next.length > 20 ? '...' : '')).replace(/\n/g, "");
+ },
+
+// displays the character position where the lexing error occurred, i.e. for error messages
+showPosition:function () {
+ var pre = this.pastInput();
+ var c = new Array(pre.length + 1).join("-");
+ return pre + this.upcomingInput() + "\n" + c + "^";
+ },
+
+// test the lexed token: return FALSE when not a match, otherwise return token
+test_match:function (match, indexed_rule) {
+ var token,
+ lines,
+ backup;
+
+ if (this.options.backtrack_lexer) {
+ // save context
+ backup = {
+ yylineno: this.yylineno,
+ yylloc: {
+ first_line: this.yylloc.first_line,
+ last_line: this.last_line,
+ first_column: this.yylloc.first_column,
+ last_column: this.yylloc.last_column
+ },
+ yytext: this.yytext,
+ match: this.match,
+ matches: this.matches,
+ matched: this.matched,
+ yyleng: this.yyleng,
+ offset: this.offset,
+ _more: this._more,
+ _input: this._input,
+ yy: this.yy,
+ conditionStack: this.conditionStack.slice(0),
+ done: this.done
+ };
+ if (this.options.ranges) {
+ backup.yylloc.range = this.yylloc.range.slice(0);
+ }
+ }
+
+ lines = match[0].match(/(?:\r\n?|\n).*/g);
+ if (lines) {
+ this.yylineno += lines.length;
+ }
+ this.yylloc = {
+ first_line: this.yylloc.last_line,
+ last_line: this.yylineno + 1,
+ first_column: this.yylloc.last_column,
+ last_column: lines ?
+ lines[lines.length - 1].length - lines[lines.length - 1].match(/\r?\n?/)[0].length :
+ this.yylloc.last_column + match[0].length
+ };
+ this.yytext += match[0];
+ this.match += match[0];
+ this.matches = match;
+ this.yyleng = this.yytext.length;
+ if (this.options.ranges) {
+ this.yylloc.range = [this.offset, this.offset += this.yyleng];
+ }
+ this._more = false;
+ this._backtrack = false;
+ this._input = this._input.slice(match[0].length);
+ this.matched += match[0];
+ token = this.performAction.call(this, this.yy, this, indexed_rule, this.conditionStack[this.conditionStack.length - 1]);
+ if (this.done && this._input) {
+ this.done = false;
+ }
+ if (token) {
+ return token;
+ } else if (this._backtrack) {
+ // recover context
+ for (var k in backup) {
+ this[k] = backup[k];
+ }
+ return false; // rule action called reject() implying the next rule should be tested instead.
+ }
+ return false;
+ },
+
+// return next match in input
+next:function () {
+ if (this.done) {
+ return this.EOF;
+ }
+ if (!this._input) {
+ this.done = true;
+ }
+
+ var token,
+ match,
+ tempMatch,
+ index;
+ if (!this._more) {
+ this.yytext = '';
+ this.match = '';
+ }
+ var rules = this._currentRules();
+ for (var i = 0; i < rules.length; i++) {
+ tempMatch = this._input.match(this.rules[rules[i]]);
+ if (tempMatch && (!match || tempMatch[0].length > match[0].length)) {
+ match = tempMatch;
+ index = i;
+ if (this.options.backtrack_lexer) {
+ token = this.test_match(tempMatch, rules[i]);
+ if (token !== false) {
+ return token;
+ } else if (this._backtrack) {
+ match = false;
+ continue; // rule action called reject() implying a rule MISmatch.
+ } else {
+ // else: this is a lexer rule which consumes input without producing a token (e.g. whitespace)
+ return false;
+ }
+ } else if (!this.options.flex) {
+ break;
+ }
+ }
+ }
+ if (match) {
+ token = this.test_match(match, rules[index]);
+ if (token !== false) {
+ return token;
+ }
+ // else: this is a lexer rule which consumes input without producing a token (e.g. whitespace)
+ return false;
+ }
+ if (this._input === "") {
+ return this.EOF;
+ } else {
+ return this.parseError('Lexical error on line ' + (this.yylineno + 1) + '. Unrecognized text.\n' + this.showPosition(), {
+ text: "",
+ token: null,
+ line: this.yylineno
+ });
+ }
+ },
+
+// return next match that has a token
+lex:function lex() {
+ var r = this.next();
+ if (r) {
+ return r;
+ } else {
+ return this.lex();
+ }
+ },
+
+// activates a new lexer condition state (pushes the new lexer condition state onto the condition stack)
+begin:function begin(condition) {
+ this.conditionStack.push(condition);
+ },
+
+// pop the previously active lexer condition state off the condition stack
+popState:function popState() {
+ var n = this.conditionStack.length - 1;
+ if (n > 0) {
+ return this.conditionStack.pop();
+ } else {
+ return this.conditionStack[0];
+ }
+ },
+
+// produce the lexer rule set which is active for the currently active lexer condition state
+_currentRules:function _currentRules() {
+ if (this.conditionStack.length && this.conditionStack[this.conditionStack.length - 1]) {
+ return this.conditions[this.conditionStack[this.conditionStack.length - 1]].rules;
+ } else {
+ return this.conditions["INITIAL"].rules;
+ }
+ },
+
+// return the currently active lexer condition state; when an index argument is provided it produces the N-th previous condition state, if available
+topState:function topState(n) {
+ n = this.conditionStack.length - 1 - Math.abs(n || 0);
+ if (n >= 0) {
+ return this.conditionStack[n];
+ } else {
+ return "INITIAL";
+ }
+ },
+
+// alias for begin(condition)
+pushState:function pushState(condition) {
+ this.begin(condition);
+ },
+
+// return the number of states currently on the stack
+stateStackSize:function stateStackSize() {
+ return this.conditionStack.length;
+ },
+options: {},
+performAction: function anonymous(yy,yy_,$avoiding_name_collisions,YY_START) {
+var YYSTATE=YY_START;
+switch($avoiding_name_collisions) {
+case 0:return "CODE";
+break;
+case 1:/* skip whitespace */
+break;
+case 2:return "CODE";
+break;
+case 3:return "NAME";
+break;
+case 4: this.begin("TAIL"); return "MARK";
+break;
+case 5: this.begin("CONF"); return "MARK";
+break;
+case 6:return ";";
+break;
+case 7:return "[";
+break;
+case 8:return "]";
+break;
+case 9:return "(";
+break;
+case 10:return ")";
+break;
+case 11:return ",";
+break;
+case 12:return "\\";
+break;
+case 13:return "_";
+break;
+case 14:return "=";
+break;
+}
+},
+rules: [/^(?:(.|\n)*$)/,/^(?:\s+)/,/^(?:\{[^}]+\})/,/^(?:[A-Za-z][A-Za-z0-9]*)/,/^(?:\$\$)/,/^(?:\$\$)/,/^(?:;)/,/^(?:\[)/,/^(?:\])/,/^(?:\()/,/^(?:\))/,/^(?:,)/,/^(?:\\)/,/^(?:_\b)/,/^(?:=)/],
+conditions: {"CONF":{"rules":[1,2,3,4,5,6,9,10,11,12,13,14],"inclusive":true},"TAIL":{"rules":[0,1,2,3,5,6,9,10,11,12,13],"inclusive":true},"INITIAL":{"rules":[1,2,3,5,6,7,8,9,10,11,12,13],"inclusive":true}}
+});
+return lexer;
+})();
+parser.lexer = lexer;
+function Parser () {
+ this.yy = {};
+}
+Parser.prototype = parser;parser.Parser = Parser;
+return new Parser;
+})();
+module.exports = parser;
+
+},{}],13:[function(require,module,exports){
+"use strict";
+
+const compile = require("./compile");
+
+const parser = new compile.Parser();
+
+let inverb, inrules, inconf, inenv, inqueue, nwires, nambs;
+let typelist, types, ntypes, wiretype, ambtype, table;
+let lpaxtype, rpaxtype, format, ndebug;
+
+function addtypes(tree)
+{
+ const agent = tree.node.agent;
+ const pax = tree.pax;
+ const plen = pax.length;
+
+ if ("wire" == agent)
+ return;
+
+ if (!types[agent]) {
+ types[agent] = ntypes;
+ ++ntypes;
+ }
+
+ for (let i = 0; i < plen; i++)
+ addtypes(pax[i]);
+}
+
+function norules(lagent, ragent)
+{
+ const eqn = geteqn({
+ left: lagent,
+ right: ragent
+ });
+
+ throw "NO RULES: " + eqn;
+}
+
+function ischild(wire, agent)
+{
+ const type = agent.type;
+
+ if (wiretype == type) {
+ if (wire === agent)
+ return true;
+ } else if (ambtype == type) {
+ if (ischild(wire, agent.main))
+ return true;
+
+ if (ischild(wire, agent.aux))
+ return true;
+ } else {
+ const pax = agent.pax;
+ const plen = pax.length;
+
+ for (let i = 0; i < plen; i++)
+ if (ischild(wire, pax[i]))
+ return true;
+ }
+
+ return false;
+}
+
+function detect(wire, agent)
+{
+ if (ndebug)
+ return;
+
+ if (ischild(wire, agent)) {
+ const eqn = geteqn({
+ left: wire,
+ right: agent
+ });
+
+ throw "DEADLOCK: " + eqn;
+ }
+}
+
+function indwire(wire, agent)
+{
+ const dst = wire.twin;
+ const twin = agent.twin;
+
+ dst.twin = twin;
+ twin.twin = dst;
+}
+
+function inderiw(agent, wire)
+{
+ indwire(wire, agent);
+}
+
+function indamb(wire, agent)
+{
+ const dst = wire.twin;
+ const twin = agent.twin;
+
+ detect(dst, agent);
+
+ dst.twin = twin;
+ twin.twin = dst;
+
+ dst.type = ambtype;
+ dst.main = agent.main;
+ dst.aux = agent.aux;
+}
+
+function indbma(agent, wire)
+{
+ indamb(wire, agent);
+}
+
+function indagent(wire, agent)
+{
+ const dst = wire.twin;
+
+ detect(dst, agent);
+
+ dst.type = agent.type;
+ dst.pax = agent.pax;
+ dst.data = agent.data;
+}
+
+function indtnega(agent, wire)
+{
+ indagent(wire, agent);
+}
+
+function getindir(type)
+{
+ if ("wire" == type)
+ return indwire;
+ else if ("amb" == type)
+ return indamb;
+ else
+ return indagent;
+}
+
+function getridni(type)
+{
+ if ("wire" == type)
+ return inderiw;
+ else if ("amb" == type)
+ return indbma;
+ else
+ return indtnega;
+}
+
+function determ(amb, agent)
+{
+ const dst = amb.twin;
+ const aux = amb.aux;
+ const type = aux.type;
+
+ if (wiretype == type) {
+ const twin = aux.twin;
+
+ dst.twin = twin;
+ twin.twin = dst;
+
+ dst.type = type;
+ } else if (ambtype == type) {
+ const twin = aux.twin;
+
+ dst.twin = twin;
+ twin.twin = dst;
+
+ dst.main = aux.main;
+ dst.aux = aux.aux;
+ } else {
+ dst.type = type;
+ dst.pax = aux.pax;
+ dst.data = aux.data;
+ }
+
+ flush([{
+ left: amb.main,
+ right: agent
+ }]);
+}
+
+function mreted(agent, amb)
+{
+ determ(amb, agent);
+}
+
+function mkeffect(lval, rval, code, expr)
+{
+ let body = expr ? "return (%s);" : "%s\n\treturn true;";
+
+ if (!lval)
+ lval = "LVAL";
+ if (!rval)
+ rval = "RVAL";
+ if (!code && expr)
+ code = "void(0)";
+
+ body = body.replace("%s", code);
+ return new Function(lval, rval, body);
+}
+
+function prequeue(queue, side, lval, rval, pax, wires)
+{
+ const plen = pax.length;
+
+ for (let i = 0; i < plen; i++) {
+ const img = encode(lval, rval, pax[i], wires);
+
+ queue.push({
+ left: {
+ type: side,
+ id: i
+ },
+ right: img
+ });
+ }
+}
+
+function optimize(queue)
+{
+ const needed = [];
+ const qlen = queue.length;
+
+ for (let i = 0; i < qlen; i++) {
+ const pair = queue[i];
+ const pax = pair.left;
+ const wire = pair.right;
+ const twin = wire.twin;
+
+ if (wiretype != wire.type) {
+ needed.push(pair);
+ continue;
+ }
+
+ twin.type = pax.type;
+ twin.id = pax.id;
+
+ wire.junk = true;
+ twin.junk = true;
+ }
+
+ return needed;
+}
+
+function geneff(effect)
+{
+ effect = "(" + effect.toString() + ")";
+ return effect + ".call(this, lval, rval)";
+}
+
+function gentwins(wlist, alist)
+{
+ const wlen = wlist.length;
+ const alen = alist.length;
+ let head = "";
+ let tail = "";
+
+ if (!wlist.length)
+ return "";
+
+ for (let i = 0; i < wlen; i++) {
+ const wire = wlist[i];
+ const type = wire.type;
+ const twin = wire.twin.id;
+
+ head = head.concat("\
+ const wire" + i + " = {type: " + type + "};\n");
+
+ tail = tail.concat("\
+ wire" + i + ".twin = wire" + twin + ";\n");
+ }
+
+ for (let i = 0; i < alen; i++) {
+ const tree = alist[i];
+
+ head = head.concat("\
+ const tree" + i + " = " + genclone(tree) + ";\n");
+ }
+
+ for (let i = 0; i < wlen; i++) {
+ const wire = wlist[i];
+
+ if (ambtype == wire.type) {
+ const main = wire.main;
+ const aux = wire.aux;
+
+ tail = tail.concat("\
+ wire" + i + ".main = tree" + main + ";\n\
+ wire" + i + ".aux = tree" + aux + ";\n");
+ }
+ }
+
+ return head.concat("\n", tail, "\n");
+}
+
+function genclone(img)
+{
+ const type = img.type;
+ const imgpax = img.pax;
+ const pax = [];
+ let iplen;
+
+ if (lpaxtype == type)
+ return "lpax[" + img.id + "]";
+
+ if (rpaxtype == type)
+ return "rpax[" + img.id + "]";
+
+ if (wiretype == type)
+ return "wire" + img.id;
+
+ if (ambtype == type)
+ return "wire" + img.id;
+
+ iplen = imgpax.length;
+ for (let i = 0; i < iplen; i++)
+ pax[i] = genclone(imgpax[i]);
+
+ return "{\n\
+ type: " + type + ",\n\
+ pax: [" + pax.join(", ") + "],\n\
+ data: " + geneff(img.effect) + "\n\
+ }";
+}
+
+function genqueue(img)
+{
+ const queue = [];
+ const ilen = img.length;
+
+ for (let i = 0; i < ilen; i++) {
+ const pair = img[i];
+ const left = pair.left;
+ const right = pair.right;
+
+ queue.push("{\n\
+ left: " + genclone(left) + ",\n\
+ right: " + genclone(right) + "\n\
+ }");
+ }
+
+ return "[" + queue.join(", ") + "]";
+}
+
+function generate(img, wlist, alist, effect, rl)
+{
+ const left = rl ? "right" : "left";
+ const right = rl ? "left" : "right";
+ const body = "\
+ const lval = " + left + ".data;\n\
+ const rval = " + right + ".data;\n\n\
+ if (!(" + geneff(effect) + "))\n\
+ return;\n\n\
+ const lpax = left.pax;\n\
+ const rpax = right.pax;\n\n\
+ " + gentwins(wlist, alist) + "\
+ return " + genqueue(img) + ";";
+
+ return new Function("left", "right", body);
+}
+
+function apply(left, right, code, rl)
+{
+ const lnode = left.node;
+ const rnode = right.node;
+ const human = lnode.agent + "><" + rnode.agent;
+ const lval = rl ? rnode.code : lnode.code;
+ const rval = rl ? lnode.code : rnode.code;
+ const effect = mkeffect(lval, rval, code);
+ const img = [];
+ const wires = {};
+ const wlist = [];
+ const alist = [];
+ let oimg, interact;
+
+ prequeue(img, lpaxtype, lval, rval, left.pax, wires);
+ prequeue(img, rpaxtype, lval, rval, right.pax, wires);
+
+ oimg = optimize(img);
+
+ for (const name in wires) {
+ const wire = wires[name];
+ const twin = wire.twin;
+
+ if (wire.junk)
+ continue;
+
+ wire.id = wlist.length;
+ wlist.push(wire);
+
+ twin.id = wlist.length;
+ wlist.push(twin);
+
+ if (ambtype == wire.type) {
+ const main = wire.main;
+ const aux = wire.aux;
+
+ wire.main = alist.length;
+ twin.main = alist.length;
+ alist.push(main);
+
+ wire.aux = alist.length;
+ twin.aux = alist.length;
+ alist.push(aux);
+ }
+ }
+
+ interact = generate(oimg, wlist, alist, effect, rl);
+ interact.human = human;
+ interact.count = 0;
+ return interact;
+}
+
+function addrule(dict, rule)
+{
+ const human = rule.human;
+ const entry = dict[human];
+
+ if (entry)
+ entry.push(rule);
+ else
+ dict[human] = [rule];
+}
+
+function gettable()
+{
+ const tab = [];
+ const custom = {};
+ const rlen = inrules.length;
+ const clen = inconf.length;
+
+ for (let i = 0; i < rlen; i++) {
+ const rule = inrules[i];
+ const left = rule.left;
+ const right = rule.right;
+ const code = rule.code;
+ let lrfunc, rlfunc;
+
+ addtypes(left);
+ addtypes(right);
+
+ lrfunc = apply(left, right, code);
+ addrule(custom, lrfunc);
+
+ rlfunc = apply(right, left, code, true);
+ addrule(custom, rlfunc);
+ }
+
+ for (let i = 0; i < clen; i++) {
+ const eqn = inconf[i];
+ const left = eqn.left;
+ const right = eqn.right;
+
+ addtypes(left);
+ addtypes(right);
+ }
+
+ for (const left in types) {
+ const row = [];
+
+ for (const right in types) {
+ let rules = custom[left + "><" + right];
+
+ if (!rules) {
+ if ("wire" == left)
+ rules = getindir(right);
+ else if ("wire" == right)
+ rules = getridni(left);
+ else if ("amb" == left)
+ rules = determ;
+ else if ("amb" == right)
+ rules = mreted;
+ else
+ rules = norules;
+ }
+
+ row[types[right]] = rules;
+ }
+
+ tab[types[left]] = row;
+
+ typelist[types[left]] = left;
+ }
+
+ return tab;
+}
+
+function traverse(pair)
+{
+ const left = pair.left;
+ const right = pair.right;
+ const rules = pair.rules;
+ const rlen = rules.length;
+
+ for (let i = 0; i < rlen; i++) {
+ const rule = rules[i];
+ const queue = rule.call(inenv, left, right);
+
+ if (queue) {
+ ++rule.count;
+ flush(queue);
+ return;
+ }
+ }
+
+ norules(left, right);
+}
+
+function reduce(max)
+{
+ if (!max)
+ max = 1e7;
+
+ for (let i = 0; i < max; i++) {
+ const pair = inqueue.shift();
+
+ if (!pair)
+ break;
+
+ traverse(pair);
+ }
+}
+
+function flush(queue)
+{
+ const qlen = queue.length;
+
+ for (let i = 0; i < qlen; i++) {
+ const pair = queue[i];
+ const left = pair.left;
+ const right = pair.right;
+ const row = table[left.type];
+ const rules = row[right.type];
+
+ pair.rules = rules;
+
+ if (rules.pseudo)
+ rules(left, right);
+ else
+ inqueue.push(pair);
+ }
+}
+
+function encode(lval, rval, tree, wires, rt)
+{
+ const node = tree.node;
+ const code = node.code;
+ const agent = node.agent;
+ const type = types[agent];
+ const pax = tree.pax;
+ const plen = pax.length;
+ const imgpax = [];
+
+ for (let i = 0; i < plen; i++) {
+ const sub = pax[i];
+
+ imgpax[i] = encode(lval, rval, sub, wires, rt);
+ }
+
+ tree = {
+ type: type,
+ pax: imgpax
+ };
+
+ if (wiretype == type) {
+ const name = node.name;
+ const wire = wires[name];
+
+ if (wire) {
+ wire.twin = tree;
+ tree.twin = wire;
+
+ tree.type = wire.type;
+ tree.main = wire.main;
+ tree.aux = wire.aux;
+ }
+
+ delete tree.pax;
+
+ wires[name] = tree;
+ } else if (ambtype == type) {
+ const wire = imgpax.shift();
+ const twin = wire.twin;
+ const main = imgpax.shift();
+ const aux = imgpax.shift();
+
+ wire.type = type;
+ wire.main = main;
+ wire.aux = aux;
+
+ if (twin) {
+ twin.type = type;
+ twin.main = main;
+ twin.aux = aux;
+ }
+
+ return wire;
+ } else {
+ const effect = mkeffect(lval, rval, code, true);
+
+ if (rt)
+ tree.data = effect.call(inenv);
+ else
+ tree.effect = effect;
+ }
+
+ return tree;
+}
+
+function init()
+{
+ const wires = {};
+ const queue = [];
+ const effect = mkeffect(0, 0, inverb);
+ const clen = inconf.length;
+
+ effect.call(inenv);
+
+ for (let i = 0; i < clen; i++) {
+ const eqn = inconf[i];
+ const left = eqn.left;
+ const right = eqn.right;
+
+ queue.push({
+ left: encode(0, 0, left, wires, true),
+ right: encode(0, 0, right, wires, true)
+ });
+ }
+
+ flush(queue);
+}
+
+function prepare(src, fmt, deadlock)
+{
+ const system = parser.parse(src);
+
+ if (fmt)
+ format = fmt;
+ else
+ format = noformat;
+
+ ndebug = !deadlock;
+ inverb = system.code;
+ inrules = system.rules;
+ inconf = system.conf;
+ inenv = {};
+ inqueue = [];
+ typelist = [];
+ types = {
+ wire: 0,
+ amb: 1
+ };
+ ntypes = 2;
+ nwires = 0;
+ nambs = 0;
+
+ norules.pseudo = true;
+ determ.pseudo = true;
+ mreted.pseudo = true;
+ indwire.pseudo = true;
+ inderiw.pseudo = true;
+ indamb.pseudo = true;
+ indbma.pseudo = true;
+ indagent.pseudo = true;
+ indtnega.pseudo = true;
+
+ wiretype = types["wire"];
+ ambtype = types["amb"];
+ lpaxtype = -1;
+ rpaxtype = -2;
+
+ table = gettable();
+
+ init();
+
+ return inenv;
+}
+
+function getlist(pax)
+{
+ const list = pax.map(gettree);
+
+ if (list.length)
+ return "(" + list.join(", ") + ")";
+ else
+ return "";
+}
+
+function noformat(data)
+{
+ return data;
+}
+
+function gettree(agent)
+{
+ const type = agent.type;
+ let human;
+
+ if (wiretype == type) {
+ human = agent.human;
+
+ if (!human) {
+ ++nwires;
+ human = "w" + nwires;
+ agent.human = human;
+ }
+
+ agent.twin.human = human;
+ } else if (ambtype == type) {
+ let index = agent.index;
+ let list = "";
+
+ if (!index || (nambs < index)) {
+ ++nambs;
+ index = nambs;
+ agent.twin.index = nambs;
+
+ list = getlist([
+ agent.main,
+ agent.aux
+ ]);
+ }
+
+ human = "\\amb#" + index + list;
+ } else {
+ let data = format(agent.data);
+ let cell;
+
+ if (void(0) == data)
+ data = "";
+ else
+ data = "_{" + data + "}";
+
+ cell = typelist[type] + data;
+
+ human = "\\" + cell + getlist(agent.pax);
+ }
+
+ return human;
+}
+
+function geteqn(pair)
+{
+ const left = gettree(pair.left);
+ const right = gettree(pair.right);
+
+ return left + " = " + right + ";";
+}
+
+function getconf()
+{
+ nambs = 0;
+ return inqueue.map(geteqn).join("\n");
+}
+
+function debug()
+{
+ const conf = getconf();
+ const pair = inqueue.shift();
+
+ if (pair)
+ traverse(pair);
+
+ return conf;
+}
+
+function debug0()
+{
+ const pair = inqueue.shift();
+
+ if (pair) {
+ traverse(pair);
+ return true;
+ }
+
+ return false;
+}
+
+function debug1()
+{
+ const pair = inqueue.shift();
+
+ if (pair) {
+ const eqn = geteqn(pair);
+
+ traverse(pair);
+ return eqn;
+ }
+}
+
+function getstats()
+{
+ const stats = {};
+ const tlen = table.length;
+
+ for (let i = 0; i < tlen; i++) {
+ const row = table[i];
+ const rlen = row.length;
+
+ for (let j = 0; j < rlen; j++) {
+ const cell = row[j];
+ const clen = cell.length;
+
+ if (cell.pseudo)
+ continue;
+
+ for (let k = 0; k < clen; k++) {
+ const rule = cell[k];
+ const count = rule.count;
+ let human = rule.human;
+
+ if (!count)
+ continue;
+
+ human = human.split("><");
+ human = human.sort();
+ human = human.join("><");
+
+ if (stats[human])
+ stats[human] += count;
+ else
+ stats[human] = count;
+ }
+ }
+ }
+
+ return stats;
+}
+
+function run(src, max)
+{
+ let t0, t1;
+
+ prepare(src);
+
+ t0 = Date.now();
+ reduce(max);
+ t1 = Date.now();
+
+ inenv.redtime = t1 - t0;
+ inenv.stats = getstats();
+ return inenv;
+}
+
+run.prepare = prepare;
+run.debug = debug;
+run.debug0 = debug0;
+run.debug1 = debug1;
+
+module.exports = run;
+
+},{"./compile":12}],14:[function(require,module,exports){
+(function (process){
+// Copyright Joyent, Inc. and other Node contributors.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a
+// copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to permit
+// persons to whom the Software is furnished to do so, subject to the
+// following conditions:
+//
+// The above copyright notice and this permission notice shall be included
+// in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
+// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+// USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+// resolves . and .. elements in a path array with directory names there
+// must be no slashes, empty elements, or device names (c:\) in the array
+// (so also no leading and trailing slashes - it does not distinguish
+// relative and absolute paths)
+function normalizeArray(parts, allowAboveRoot) {
+ // if the path tries to go above the root, `up` ends up > 0
+ var up = 0;
+ for (var i = parts.length - 1; i >= 0; i--) {
+ var last = parts[i];
+ if (last === '.') {
+ parts.splice(i, 1);
+ } else if (last === '..') {
+ parts.splice(i, 1);
+ up++;
+ } else if (up) {
+ parts.splice(i, 1);
+ up--;
+ }
+ }
+
+ // if the path is allowed to go above the root, restore leading ..s
+ if (allowAboveRoot) {
+ for (; up--; up) {
+ parts.unshift('..');
+ }
+ }
+
+ return parts;
+}
+
+// Split a filename into [root, dir, basename, ext], unix version
+// 'root' is just a slash, or nothing.
+var splitPathRe =
+ /^(\/?|)([\s\S]*?)((?:\.{1,2}|[^\/]+?|)(\.[^.\/]*|))(?:[\/]*)$/;
+var splitPath = function(filename) {
+ return splitPathRe.exec(filename).slice(1);
+};
+
+// path.resolve([from ...], to)
+// posix version
+exports.resolve = function() {
+ var resolvedPath = '',
+ resolvedAbsolute = false;
+
+ for (var i = arguments.length - 1; i >= -1 && !resolvedAbsolute; i--) {
+ var path = (i >= 0) ? arguments[i] : process.cwd();
+
+ // Skip empty and invalid entries
+ if (typeof path !== 'string') {
+ throw new TypeError('Arguments to path.resolve must be strings');
+ } else if (!path) {
+ continue;
+ }
+
+ resolvedPath = path + '/' + resolvedPath;
+ resolvedAbsolute = path.charAt(0) === '/';
+ }
+
+ // At this point the path should be resolved to a full absolute path, but
+ // handle relative paths to be safe (might happen when process.cwd() fails)
+
+ // Normalize the path
+ resolvedPath = normalizeArray(filter(resolvedPath.split('/'), function(p) {
+ return !!p;
+ }), !resolvedAbsolute).join('/');
+
+ return ((resolvedAbsolute ? '/' : '') + resolvedPath) || '.';
+};
+
+// path.normalize(path)
+// posix version
+exports.normalize = function(path) {
+ var isAbsolute = exports.isAbsolute(path),
+ trailingSlash = substr(path, -1) === '/';
+
+ // Normalize the path
+ path = normalizeArray(filter(path.split('/'), function(p) {
+ return !!p;
+ }), !isAbsolute).join('/');
+
+ if (!path && !isAbsolute) {
+ path = '.';
+ }
+ if (path && trailingSlash) {
+ path += '/';
+ }
+
+ return (isAbsolute ? '/' : '') + path;
+};
+
+// posix version
+exports.isAbsolute = function(path) {
+ return path.charAt(0) === '/';
+};
+
+// posix version
+exports.join = function() {
+ var paths = Array.prototype.slice.call(arguments, 0);
+ return exports.normalize(filter(paths, function(p, index) {
+ if (typeof p !== 'string') {
+ throw new TypeError('Arguments to path.join must be strings');
+ }
+ return p;
+ }).join('/'));
+};
+
+
+// path.relative(from, to)
+// posix version
+exports.relative = function(from, to) {
+ from = exports.resolve(from).substr(1);
+ to = exports.resolve(to).substr(1);
+
+ function trim(arr) {
+ var start = 0;
+ for (; start < arr.length; start++) {
+ if (arr[start] !== '') break;
+ }
+
+ var end = arr.length - 1;
+ for (; end >= 0; end--) {
+ if (arr[end] !== '') break;
+ }
+
+ if (start > end) return [];
+ return arr.slice(start, end - start + 1);
+ }
+
+ var fromParts = trim(from.split('/'));
+ var toParts = trim(to.split('/'));
+
+ var length = Math.min(fromParts.length, toParts.length);
+ var samePartsLength = length;
+ for (var i = 0; i < length; i++) {
+ if (fromParts[i] !== toParts[i]) {
+ samePartsLength = i;
+ break;
+ }
+ }
+
+ var outputParts = [];
+ for (var i = samePartsLength; i < fromParts.length; i++) {
+ outputParts.push('..');
+ }
+
+ outputParts = outputParts.concat(toParts.slice(samePartsLength));
+
+ return outputParts.join('/');
+};
+
+exports.sep = '/';
+exports.delimiter = ':';
+
+exports.dirname = function(path) {
+ var result = splitPath(path),
+ root = result[0],
+ dir = result[1];
+
+ if (!root && !dir) {
+ // No dirname whatsoever
+ return '.';
+ }
+
+ if (dir) {
+ // It has a dirname, strip trailing slash
+ dir = dir.substr(0, dir.length - 1);
+ }
+
+ return root + dir;
+};
+
+
+exports.basename = function(path, ext) {
+ var f = splitPath(path)[2];
+ // TODO: make this comparison case-insensitive on windows?
+ if (ext && f.substr(-1 * ext.length) === ext) {
+ f = f.substr(0, f.length - ext.length);
+ }
+ return f;
+};
+
+
+exports.extname = function(path) {
+ return splitPath(path)[3];
+};
+
+function filter (xs, f) {
+ if (xs.filter) return xs.filter(f);
+ var res = [];
+ for (var i = 0; i < xs.length; i++) {
+ if (f(xs[i], i, xs)) res.push(xs[i]);
+ }
+ return res;
+}
+
+// String.prototype.substr - negative index don't work in IE8
+var substr = 'ab'.substr(-1) === 'b'
+ ? function (str, start, len) { return str.substr(start, len) }
+ : function (str, start, len) {
+ if (start < 0) start = str.length + start;
+ return str.substr(start, len);
+ }
+;
+
+}).call(this,require('_process'))
+},{"_process":15}],15:[function(require,module,exports){
+// shim for using process in browser
+var process = module.exports = {};
+
+// cached from whatever global is present so that test runners that stub it
+// don't break things. But we need to wrap it in a try catch in case it is
+// wrapped in strict mode code which doesn't define any globals. It's inside a
+// function because try/catches deoptimize in certain engines.
+
+var cachedSetTimeout;
+var cachedClearTimeout;
+
+function defaultSetTimout() {
+ throw new Error('setTimeout has not been defined');
+}
+function defaultClearTimeout () {
+ throw new Error('clearTimeout has not been defined');
+}
+(function () {
+ try {
+ if (typeof setTimeout === 'function') {
+ cachedSetTimeout = setTimeout;
+ } else {
+ cachedSetTimeout = defaultSetTimout;
+ }
+ } catch (e) {
+ cachedSetTimeout = defaultSetTimout;
+ }
+ try {
+ if (typeof clearTimeout === 'function') {
+ cachedClearTimeout = clearTimeout;
+ } else {
+ cachedClearTimeout = defaultClearTimeout;
+ }
+ } catch (e) {
+ cachedClearTimeout = defaultClearTimeout;
+ }
+} ())
+function runTimeout(fun) {
+ if (cachedSetTimeout === setTimeout) {
+ //normal enviroments in sane situations
+ return setTimeout(fun, 0);
+ }
+ // if setTimeout wasn't available but was latter defined
+ if ((cachedSetTimeout === defaultSetTimout || !cachedSetTimeout) && setTimeout) {
+ cachedSetTimeout = setTimeout;
+ return setTimeout(fun, 0);
+ }
+ try {
+ // when when somebody has screwed with setTimeout but no I.E. maddness
+ return cachedSetTimeout(fun, 0);
+ } catch(e){
+ try {
+ // When we are in I.E. but the script has been evaled so I.E. doesn't trust the global object when called normally
+ return cachedSetTimeout.call(null, fun, 0);
+ } catch(e){
+ // same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error
+ return cachedSetTimeout.call(this, fun, 0);
+ }
+ }
+
+
+}
+function runClearTimeout(marker) {
+ if (cachedClearTimeout === clearTimeout) {
+ //normal enviroments in sane situations
+ return clearTimeout(marker);
+ }
+ // if clearTimeout wasn't available but was latter defined
+ if ((cachedClearTimeout === defaultClearTimeout || !cachedClearTimeout) && clearTimeout) {
+ cachedClearTimeout = clearTimeout;
+ return clearTimeout(marker);
+ }
+ try {
+ // when when somebody has screwed with setTimeout but no I.E. maddness
+ return cachedClearTimeout(marker);
+ } catch (e){
+ try {
+ // When we are in I.E. but the script has been evaled so I.E. doesn't trust the global object when called normally
+ return cachedClearTimeout.call(null, marker);
+ } catch (e){
+ // same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error.
+ // Some versions of I.E. have different rules for clearTimeout vs setTimeout
+ return cachedClearTimeout.call(this, marker);
+ }
+ }
+
+
+
+}
+var queue = [];
+var draining = false;
+var currentQueue;
+var queueIndex = -1;
+
+function cleanUpNextTick() {
+ if (!draining || !currentQueue) {
+ return;
+ }
+ draining = false;
+ if (currentQueue.length) {
+ queue = currentQueue.concat(queue);
+ } else {
+ queueIndex = -1;
+ }
+ if (queue.length) {
+ drainQueue();
+ }
+}
+
+function drainQueue() {
+ if (draining) {
+ return;
+ }
+ var timeout = runTimeout(cleanUpNextTick);
+ draining = true;
+
+ var len = queue.length;
+ while(len) {
+ currentQueue = queue;
+ queue = [];
+ while (++queueIndex < len) {
+ if (currentQueue) {
+ currentQueue[queueIndex].run();
+ }
+ }
+ queueIndex = -1;
+ len = queue.length;
+ }
+ currentQueue = null;
+ draining = false;
+ runClearTimeout(timeout);
+}
+
+process.nextTick = function (fun) {
+ var args = new Array(arguments.length - 1);
+ if (arguments.length > 1) {
+ for (var i = 1; i < arguments.length; i++) {
+ args[i - 1] = arguments[i];
+ }
+ }
+ queue.push(new Item(fun, args));
+ if (queue.length === 1 && !draining) {
+ runTimeout(drainQueue);
+ }
+};
+
+// v8 likes predictible objects
+function Item(fun, array) {
+ this.fun = fun;
+ this.array = array;
+}
+Item.prototype.run = function () {
+ this.fun.apply(null, this.array);
+};
+process.title = 'browser';
+process.browser = true;
+process.env = {};
+process.argv = [];
+process.version = ''; // empty string to avoid regexp issues
+process.versions = {};
+
+function noop() {}
+
+process.on = noop;
+process.addListener = noop;
+process.once = noop;
+process.off = noop;
+process.removeListener = noop;
+process.removeAllListeners = noop;
+process.emit = noop;
+
+process.binding = function (name) {
+ throw new Error('process.binding is not supported');
+};
+
+process.cwd = function () { return '/' };
+process.chdir = function (dir) {
+ throw new Error('process.chdir is not supported');
+};
+process.umask = function() { return 0; };
+
+},{}]},{},[1]);
diff --git a/entry.js b/entry.js
new file mode 100644
index 0000000..37468cb
--- /dev/null
+++ b/entry.js
@@ -0,0 +1,9 @@
+"use strict";
+
+const mlcjs = require("@alexo/lambda");
+const fs = require("fs");
+const example = fs.readFileSync("fact.mlc", "utf8");
+
+mlcjs.example = example.replace(/\n$/, "");
+
+global.mlcjs = mlcjs;
diff --git a/fact.mlc b/fact.mlc
new file mode 100644
index 0000000..633d3f5
--- /dev/null
+++ b/fact.mlc
@@ -0,0 +1,30 @@
+I = x: x;
+K = x, y: x;
+S = x, y, z: x z (y z);
+
+T = K;
+F = x, y: y;
+AND = p, q: p q F;
+OR = p, q: p T q;
+NOT = p: (a, b: p b a);
+
+C0 = f, x: x;
+C1 = f, x: f x;
+C2 = f, x: f (f x);
+C3 = f, x: f (f (f x));
+SUCC = n: (f, x: f (n f x));
+PLUS = m, n: (f, x: m f (n f x));
+MULT = m, n: (f: m (n f));
+EXP = m, n: n m;
+PRED = n: (f, x: n (g, h: h (g f)) (K x) I);
+MINUS = m, n: n PRED m;
+ZERO = n: n (K F) T;
+
+A = self, f: f (self self f);
+Y = A A;
+FACTR = self, n: (ZERO n) C1 (MULT n (self (PRED n)));
+FACT = Y FACTR;
+
+C24 = FACT (PLUS C2 C2);
+C27 = EXP C3 C3;
+MINUS C27 C24
diff --git a/index.html b/index.html
new file mode 100644
index 0000000..a68385a
--- /dev/null
+++ b/index.html
@@ -0,0 +1,361 @@
+
+
+
+
+
+MLC
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Macro Lambda Calculus
+
+Call-by-need Lambda Calculus for Web using Interaction Nets
+
+
+
+
+
+
+
Implementation
+
+
+This is implementation of
+Lambda Calculus
+that works in your Web browser.
+Terms are defined in a variant of Lambda Calculus called
+Macro Lambda Calculus (MLC), and their normal form (if any)
+will be printed in MLC, too.
+The language allows macro definitions that make it easier
+to input complex expressions.
+The last term in the input is the term whose normal form
+is to be found.
+Give it a try.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Interaction Net Reduction
+
+
+
+
+Here you can see step-by-step reduction of the interaction net.
+For each step, the current state of the interaction net will be
+printed using format similar to initial configuration
+in the INC programming language.
+
+
+
+
+
+The interaction net has reached its normal form.
+No more active pairs left.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Generated Interaction Net
+
+
+
+
+The specified lambda term is automatically encoded into an interaction net.
+Below is the generated source in the INC language that consists of three parts:
+interaction rules, initial configuration,
+and initial side effect.
+
+
+
+
+
+You may notice side effects written in JavaScript.
+They are executed during reduction of the interaction net.
+
+
+
+
+
+
+
+
+
It may take a while... or forever!
+
+
+
+
+
+
+
+
+
+
How It Works
+
+
+Implementation is based on Interaction Nets with non-deterministic extension.
+The interaction system behind (agent types and interaction rules) performs
+call-by-need reduction and also has a readback machanism embedded.
+Since
+the interaction rules
+are defined using notation similar to Yves Lafont's, it is easy to experiment with
+different evaluation techniques.
+
+
+
+To find normal form, the algorithm goes through
+the following steps.
+
+From the bottom up, abstract each macro's name as a variable in the main term,
+then apply this abstraction to the macro's definition.
+It may sound complicated but
+the corresponding source code
+is quite simple.
+
+
+
+Encode the resulting stand-alone term into an interaction net
+as described in
+arXiv:1304.2290v8.
+More specifically, define interaction rules and initial configuration
+in a language called Interaction Nets Compiler (INC).
+Based on Interaction Nets, INC implicitly extends interaction systems
+with non-deterministic agent amb and
+also allows side effects.
+
+
+
+Parse the produced definition according to
+the INC grammar.
+
+
+
+Enter the main loop and keep applying interaction rules to all active pairs
+in the net until its normal form has been reached.
+At that point, readback should be finished, its result being
+the normal form of
+the initial lambda term.
+
+Software was first adapted for
+Node.js
+from the C programming language
+(mlc and
+inet).
+The JavaScript version uses
+Jison
+to generate parsers from grammar.
+Then, a JavaScript bundle suitable for a Web browser
+is produced by
+Browserify (with its
+brfs
+plugin enabled).
+Finally, Twitter's
+Bootstrap
+gives this page its look.
+
+
+
Feedback
+
+
+Any feedback is highly appreciated, including comments and
+collaboration in software development.
+It would be great to make this page self-explanatory in an interactive way,
+while making the JavaScript library behind it
+as efficient as possible.
+
Implementation is based on Interaction Nets with non-deterministic extension.
The interaction system behind (agent types and interaction rules) performs
call-by-need reduction and also has a readback machanism embedded.
-Since
-the interaction rules
-are defined using notation similar to Yves Lafont's, it is easy to experiment with
-different evaluation techniques.
+Since the interaction rules are defined using notation similar to Yves Lafont's,
+it is easy to experiment with different evaluation techniques.
-From the bottom up, abstract each macro's name as a variable in the main term,
-then apply this abstraction to the macro's definition.
-It may sound complicated but
-the corresponding source code
-is quite simple.
+From the bottom up, substitute each referenced macro using β-expansion.
Macro Lambda Calculus
-
-Call-by-need Lambda Calculus for Web using Interaction Nets
-
-
+
Macro Lambda Calculus
-
-
-
Implementation
-
-
-This is implementation of
-Lambda Calculus
-that works in your Web browser.
-Terms are defined in a variant of Lambda Calculus called
-Macro Lambda Calculus (MLC), and their normal form (if any)
-will be printed in MLC, too.
-The language allows macro definitions that make it easier
-to input complex expressions.
-The last term in the input is the term whose normal form
-is to be found.
-Give it a try.
-
-
-
-
-
-
How It Works
-
-
-Implementation is based on Interaction Nets with non-deterministic extension.
-The interaction system behind (agent types and interaction rules) performs
-call-by-need reduction and also has a readback machanism embedded.
-Since the interaction rules are defined using notation similar to Yves Lafont's,
-it is easy to experiment with different evaluation techniques.
-
-
-
-To find normal form, the algorithm goes through
-the following steps.
-
-From the bottom up, substitute each macro using β-expansion.
-
-
-
-Encode the resulting stand-alone term into an interaction net
-as described in
-arXiv:1304.2290v8.
-More specifically, define interaction rules and initial configuration
-in a language called Interaction Nets Compiler (INC).
-Based on Interaction Nets, INC implicitly extends interaction systems
-with non-deterministic agent amb and
-also allows side effects.
-
-
-
-Parse the produced definition according to
-the INC grammar.
-
-
-
-Enter the main loop and keep applying interaction rules to all active pairs
-in the net until its normal form has been reached.
-At that point, readback should be finished, its result being
-the normal form of
-the initial lambda term.
-
-Software was first adapted for
-Node.js
-from the C programming language.
-The JavaScript version uses
-Jison
-to generate parsers from grammar.
-Then, a JavaScript bundle suitable for a Web browser
-is produced by
-Browserify (with its
-brfs
-plugin enabled).
-Finally, Twitter's
-Bootstrap
-gives this page its look.
-
-
-
Feedback
-
-
-Any feedback is highly appreciated, including comments and
-collaboration in software development.
-It would be great to make this page self-explanatory in an interactive way,
-while making the JavaScript library behind it
-as efficient as possible.
-
-Here you can see step-by-step reduction of the interaction net.
-For each step, the current state of the interaction net will be
-printed using format similar to initial configuration
-in the INC programming language.
-
-
-
-
-
-The interaction net has reached its normal form.
-No more active pairs left.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
Generated Interaction Net
-
-
-
-
-The specified lambda term is automatically encoded into an interaction net.
-Below is the generated source in the INC language that consists of three parts:
-interaction rules, initial configuration,
-and initial side effect.
-
-
-
-
-
-You may notice side effects written in JavaScript.
-They are executed during reduction of the interaction net.
-
-
-
-
-
-
-
It may take a while... or forever!
-
-
Define a lambda term
From 149467f890ca09bfa645eef3c31b174b6c55dc47 Mon Sep 17 00:00:00 2001
From: Anton Salikhmetov
Date: Thu, 9 Mar 2017 14:50:01 +0200
Subject: [PATCH 11/27] Print results to a
element
---
bundle.js | 2 +-
fact.mlc | 4 ----
index.html | 37 ++++++++++++++++++++++++++-----------
3 files changed, 27 insertions(+), 16 deletions(-)
diff --git a/bundle.js b/bundle.js
index 4b89fa3..39e95cb 100644
--- a/bundle.js
+++ b/bundle.js
@@ -4,7 +4,7 @@
const mlcjs = require("@alexo/lambda");
-const example = "I = x: x;\nK = x, y: x;\nS = x, y, z: x z (y z);\n\nT = K;\nF = K I;\nAND = p, q: p q F;\nOR = p, q: p T q;\nNOT = p: (a, b: p b a);\n\nC0 = f, x: x;\nC1 = f, x: f x;\nC2 = f, x: f (f x);\nC3 = f, x: f (f (f x));\nSUCC = n: (f, x: f (n f x));\nPLUS = m, n: (f, x: m f (n f x));\nMULT = m, n: (f: m (n f));\nEXP = m, n: n m;\nPRED = n: (f, x: n (g, h: h (g f)) (K x) I);\nMINUS = m, n: n PRED m;\nZERO = n: n (K F) T;\n\nY = (a: a a) (self, f: f (self self f));\nFACT = Y (self, n: (ZERO n) C1 (MULT n (self (PRED n))));\n\nC24 = FACT (PLUS C2 C2);\nC27 = EXP C3 C3;\nMINUS C27 C24\n";
+const example = "I = x: x;\nK = x, y: x;\nS = x, y, z: x z (y z);\nT = K;\nF = K I;\nAND = p, q: p q F;\nOR = p, q: p T q;\nNOT = p: (a, b: p b a);\nC0 = f, x: x;\nC1 = f, x: f x;\nC2 = f, x: f (f x);\nC3 = f, x: f (f (f x));\nSUCC = n: (f, x: f (n f x));\nPLUS = m, n: (f, x: m f (n f x));\nMULT = m, n: (f: m (n f));\nEXP = m, n: n m;\nPRED = n: (f, x: n (g, h: h (g f)) (K x) I);\nMINUS = m, n: n PRED m;\nZERO = n: n (K F) T;\nY = (a: a a) (self, f: f (self self f));\nFACT = Y (self, n: (ZERO n) C1 (MULT n (self (PRED n))));\nC24 = FACT (PLUS C2 C2);\nC27 = EXP C3 C3;\nMINUS C27 C24\n";
mlcjs.example = example.replace(/\n$/, "");
diff --git a/fact.mlc b/fact.mlc
index 02e23ea..5dc1458 100644
--- a/fact.mlc
+++ b/fact.mlc
@@ -1,13 +1,11 @@
I = x: x;
K = x, y: x;
S = x, y, z: x z (y z);
-
T = K;
F = K I;
AND = p, q: p q F;
OR = p, q: p T q;
NOT = p: (a, b: p b a);
-
C0 = f, x: x;
C1 = f, x: f x;
C2 = f, x: f (f x);
@@ -19,10 +17,8 @@ EXP = m, n: n m;
PRED = n: (f, x: n (g, h: h (g f)) (K x) I);
MINUS = m, n: n PRED m;
ZERO = n: n (K F) T;
-
Y = (a: a a) (self, f: f (self self f));
FACT = Y (self, n: (ZERO n) C1 (MULT n (self (PRED n))));
-
C24 = FACT (PLUS C2 C2);
C27 = EXP C3 C3;
MINUS C27 C24
diff --git a/index.html b/index.html
index d848610..9279534 100644
--- a/index.html
+++ b/index.html
@@ -63,14 +63,16 @@
function find()
{
- var mlc = textarea.val();
+ let mlc = textarea.val();
mlc = mlcjs(mlc);
+ mlc = [
+ mlc.term,
+ `${mlc.total}(${mlc.beta}), ${mlc.redtime} ms`,
+ mlc.nf
+ ];
- console.info("%s(%s)", mlc.total, mlc.beta);
-
- result.attr("title", mlc.term);
- result.text(mlc.nf);
+ result.text(mlc.join("\n"));
}
function allow()
@@ -106,7 +108,7 @@
config = $("#config");
config.hide();
- result = $("abbr");
+ result = $("#result");
pre = $("#incsrc");
final = $("#final");
@@ -121,7 +123,22 @@