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 + + + + + + + + + + + + + +
+ + +
+
+

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. +

+ +
+
+ +
+ + + + + + + + + +

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. +

+ +
    +
  1. +Parse input according to +the MLC grammar. +
  2. + +
  3. +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. +
  4. + +
  5. +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. +
  6. + +
  7. +Parse the produced definition according to +the INC grammar. +
  8. + +
  9. +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. +
  10. +
+ +

+This algorithm was inspired by the work of François-Régis Sinot, namely +Token-Passing Nets: Call-by-Need for Free. +In particular, the eval and return agents and their +interaction rules became the basis for +the embedded readback machanism. +

+ +

+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. +

+ +

+ + +

+
+
+ +
+
+ + +
+
+ +Fork me on GitHub + + + + diff --git a/package.json b/package.json new file mode 100644 index 0000000..e982e66 --- /dev/null +++ b/package.json @@ -0,0 +1,8 @@ +{ + "dependencies": { + "@alexo/lambda": "0.0.9", + "browserify": "14.0.0", + "brfs": "1.4.3" + }, + "private": true +} From f7eb41dea48a414fe2e67c0b9823e6a68ce87e6f Mon Sep 17 00:00:00 2001 From: Anton Salikhmetov Date: Sun, 29 Jan 2017 02:08:56 +0200 Subject: [PATCH 02/27] Correct links in index.html --- index.html | 16 +++++----------- 1 file changed, 5 insertions(+), 11 deletions(-) diff --git a/index.html b/index.html index a68385a..41f31ef 100644 --- a/index.html +++ b/index.html @@ -233,10 +233,8 @@

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. +Since the interaction rules are defined using notation similar to Yves Lafont's, +it is easy to experiment with different evaluation techniques.

@@ -247,15 +245,11 @@

How It Works

  1. Parse input according to -the MLC grammar. +the MLC grammar.
  2. -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.
  3. @@ -271,7 +265,7 @@

    How It Works

  4. Parse the produced definition according to -the INC grammar. +the INC grammar.
  5. From 9c20b6825c8c65a3ee6892fb7a866cb372312dc7 Mon Sep 17 00:00:00 2001 From: Anton Salikhmetov Date: Sun, 29 Jan 2017 04:19:44 +0200 Subject: [PATCH 03/27] Switch to @alexo/lambda@0.1.0 --- bundle.js | 45 ++++++++++++++------------------------------- fact.mlc | 8 +++----- index.html | 2 +- package.json | 2 +- 4 files changed, 19 insertions(+), 38 deletions(-) diff --git a/bundle.js b/bundle.js index 9480670..0a77668 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 = x, y: y;\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\nA = self, f: f (self self f);\nY = A A;\nFACTR = self, n: (ZERO n) C1 (MULT n (self (PRED n)));\nFACT = Y FACTR;\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);\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"; mlcjs.example = example.replace(/\n$/, ""); @@ -633,7 +633,7 @@ 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 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.total;\n} \\wait[\\print, \\call];\n\n\\eval[\\fan_{i}(a, b)] {\n\t/* Postpone evaluation. */\n\t++this.total;\n} \\fan_{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}[\\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\\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\\erase {\n\t/* Erase context. */\n\t++this.total;\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;\n"; const system = template.replace("READBACK\n", generic.readback); const expand = generic.expand; const mkwire = generic.mkwire; @@ -736,7 +736,7 @@ function encode(term) module.exports = encode; -},{"../generic":5,"path":14}],4:[function(require,module,exports){ +},{"../generic":5,"path":13}],4:[function(require,module,exports){ "use strict"; const generic = require("../generic"); @@ -866,7 +866,7 @@ function encode(term) module.exports = encode; -},{"../generic":5,"path":14}],5:[function(require,module,exports){ +},{"../generic":5,"path":13}],5:[function(require,module,exports){ "use strict"; @@ -1063,7 +1063,7 @@ exports.getfv = getfv; exports.subst = subst; exports.readback = readback; -},{"path":14}],6:[function(require,module,exports){ +},{"path":13}],6:[function(require,module,exports){ "use strict"; exports.abstract = require("./abstract"); @@ -1170,14 +1170,14 @@ function encode(term) module.exports = encode; -},{"../generic":5,"path":14}],8:[function(require,module,exports){ +},{"../generic":5,"path":13}],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 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\t++this.total;\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; @@ -1280,14 +1280,14 @@ function encode(term) module.exports = encode; -},{"../generic":5,"path":14}],9:[function(require,module,exports){ +},{"../generic":5,"path":13}],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 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\t++this.total;\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; @@ -1390,12 +1390,11 @@ function encode(term) module.exports = encode; -},{"../generic":5,"path":14}],10:[function(require,module,exports){ +},{"../generic":5,"path":13}],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(); @@ -1508,26 +1507,10 @@ 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){ +},{"./compile":2,"./encoding":6,"inet-lib":12}],11:[function(require,module,exports){ /* parser generated by jison 0.4.15 */ /* Returns a Parser object of the following structure: @@ -2174,7 +2157,7 @@ return new Parser; })(); module.exports = parser; -},{}],13:[function(require,module,exports){ +},{}],12:[function(require,module,exports){ "use strict"; const compile = require("./compile"); @@ -3026,7 +3009,7 @@ run.debug1 = debug1; module.exports = run; -},{"./compile":12}],14:[function(require,module,exports){ +},{"./compile":11}],13:[function(require,module,exports){ (function (process){ // Copyright Joyent, Inc. and other Node contributors. // @@ -3254,7 +3237,7 @@ var substr = 'ab'.substr(-1) === 'b' ; }).call(this,require('_process')) -},{"_process":15}],15:[function(require,module,exports){ +},{"_process":14}],14:[function(require,module,exports){ // shim for using process in browser var process = module.exports = {}; diff --git a/fact.mlc b/fact.mlc index 633d3f5..02e23ea 100644 --- a/fact.mlc +++ b/fact.mlc @@ -3,7 +3,7 @@ K = x, y: x; S = x, y, z: x z (y z); T = K; -F = x, y: y; +F = K I; AND = p, q: p q F; OR = p, q: p T q; NOT = p: (a, b: p b a); @@ -20,10 +20,8 @@ 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; +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; diff --git a/index.html b/index.html index 41f31ef..59555df 100644 --- a/index.html +++ b/index.html @@ -249,7 +249,7 @@

    How It Works

  6. -From the bottom up, substitute each referenced macro using β-expansion. +From the bottom up, substitute each macro using β-expansion.
  7. diff --git a/package.json b/package.json index e982e66..6cbb1e8 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "dependencies": { - "@alexo/lambda": "0.0.9", + "@alexo/lambda": "0.1.0", "browserify": "14.0.0", "brfs": "1.4.3" }, From b4f400a6fcf6b0f37a81b4b3915b5a941cc80dc9 Mon Sep 17 00:00:00 2001 From: Anton Salikhmetov Date: Sun, 29 Jan 2017 12:35:23 +0200 Subject: [PATCH 04/27] Switch to @alexo/lambda@0.1.1 --- bundle.js | 4 +++- package.json | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/bundle.js b/bundle.js index 0a77668..ff0493d 100644 --- a/bundle.js +++ b/bundle.js @@ -1449,6 +1449,7 @@ function mlc2in(mlc, algo) mlc = parser.parse(mlc); insrc = encode(mlc); expanded = mlc.expanded; + inet.inenv = {}; return insrc; } @@ -2803,7 +2804,7 @@ function prepare(src, fmt, deadlock) inverb = system.code; inrules = system.rules; inconf = system.conf; - inenv = {}; + inenv = run.inenv; inqueue = []; typelist = []; types = { @@ -3002,6 +3003,7 @@ function run(src, max) return inenv; } +run.inenv = {}; run.prepare = prepare; run.debug = debug; run.debug0 = debug0; diff --git a/package.json b/package.json index 6cbb1e8..91d9c4b 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "dependencies": { - "@alexo/lambda": "0.1.0", + "@alexo/lambda": "0.1.1", "browserify": "14.0.0", "brfs": "1.4.3" }, From fe71ca40081f22d8c8dd04f6ffae4286b3aa70c5 Mon Sep 17 00:00:00 2001 From: Anton Salikhmetov Date: Mon, 30 Jan 2017 01:40:55 +0200 Subject: [PATCH 05/27] Switch to @alexo/lambda@0.1.2 --- bundle.js | 8 +++----- package.json | 2 +- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/bundle.js b/bundle.js index ff0493d..3f63442 100644 --- a/bundle.js +++ b/bundle.js @@ -743,7 +743,7 @@ 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 template = "\\read_{C}[a] {\n\t/* Unshare variable. */\n\t++this.total;\n} \\share[\\copy(b, \\read_{C}(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} \\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)), \\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; @@ -1079,7 +1079,7 @@ 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 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)), \\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; @@ -1177,7 +1177,7 @@ 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\t++this.total;\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 template = "\\print {\n\t/* Continue evaluation. */\n\t++this.total;\n} \\wait[\\print, \\call];\n\n\\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, 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\t++this.total;\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; @@ -1497,8 +1497,6 @@ function run(mlc, algo) if (output.nf) output.nf = obj2mlc(output.nf); - else - output.nf = output.term; return output; } diff --git a/package.json b/package.json index 91d9c4b..95f4286 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "dependencies": { - "@alexo/lambda": "0.1.1", + "@alexo/lambda": "0.1.2", "browserify": "14.0.0", "brfs": "1.4.3" }, From d80177f1825a87a2e9f9a9328a8e544bcdf43725 Mon Sep 17 00:00:00 2001 From: Anton Salikhmetov Date: Wed, 1 Feb 2017 01:39:34 +0200 Subject: [PATCH 06/27] Switch to @alexo/lambda@0.1.6 --- bundle.js | 51 +++++++++++++++++++++++++++++++++++++++++++++------ package.json | 2 +- 2 files changed, 46 insertions(+), 7 deletions(-) diff --git a/bundle.js b/bundle.js index 3f63442..355eb6f 100644 --- a/bundle.js +++ b/bundle.js @@ -633,12 +633,20 @@ const generic = require("../generic"); const path = require("path"); +const lambdai = "\\apply[a, b] {\n\t/* Apply beta reduction. */\n\t++this.beta;\n\t++this.total;\n} \\lambda[a, b];\n"; 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.total;\n} \\wait[\\print, \\call];\n\n\\eval[\\fan_{i}(a, b)] {\n\t/* Postpone evaluation. */\n\t++this.total;\n} \\fan_{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}[\\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\\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\\erase {\n\t/* Erase context. */\n\t++this.total;\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;\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; +let lambdak; + +function kill() +{ + lambdak = true; + return "\\erase"; +} function psi(shared, list) { @@ -695,7 +703,7 @@ function gamma(obj, root, list) if (id in fv) agent = id; else - agent = "\\erase"; + agent = kill(); tree = tree.replace("%s", agent); tree = tree.replace("%s", wire); @@ -727,11 +735,16 @@ function encode(term) let inconfig = [ "\\eval(\\read_{this.mkhole()}(\\print)) = root" ]; + let inet = system; + lambdak = false; gamma(expand(term), "root", inconfig); inconfig = inconfig.join(";\n") + ";"; - return system.replace("INCONFIG", inconfig); + if (!lambdak) + inet = lambdai.concat("\n", inet); + + return inet.replace("INCONFIG", inconfig); } module.exports = encode; @@ -1177,12 +1190,20 @@ const generic = require("../generic"); const path = require("path"); +const lambdai = "\\apply[\\scope_{0}(a), \\scope_{0}(b)] {\n\t/* Apply beta reduction. */\n\t++this.beta;\n\t++this.total;\n} \\lambda[a, b];\n"; const template = "\\print {\n\t/* Continue evaluation. */\n\t++this.total;\n} \\wait[\\print, \\call];\n\n\\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, 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\t++this.total;\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; +let lambdak; + +function kill() +{ + lambdak = true; + return "\\erase"; +} function psi(shared, list) { @@ -1239,7 +1260,7 @@ function gamma(obj, root, list) if (id in fv) agent = id; else - agent = "\\erase"; + agent = kill(); tree = tree.replace("%s", agent); tree = tree.replace("%s", wire); @@ -1271,11 +1292,16 @@ function encode(term) let inconfig = [ "\\eval(\\read_{this.mkhole()}(\\print)) = root" ]; + let inet = system; + lambdak = false; gamma(expand(term), "root", inconfig); inconfig = inconfig.join(";\n") + ";"; - return system.replace("INCONFIG", inconfig); + if (!lambdak) + inet = lambdai.concat("\n", inet); + + return inet.replace("INCONFIG", inconfig); } module.exports = encode; @@ -1287,12 +1313,20 @@ const generic = require("../generic"); const path = require("path"); +const lambdai = "\\apply[a, b] {\n\t/* Apply beta reduction. */\n\t++this.beta;\n\t++this.total;\n} \\lambda[a, b];\n"; 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\t++this.total;\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; +let lambdak; + +function kill() +{ + lambdak = true; + return "\\erase"; +} function psi(shared, list) { @@ -1349,7 +1383,7 @@ function gamma(obj, root, list) if (id in fv) agent = id; else - agent = "\\erase"; + agent = kill(); tree = tree.replace("%s", agent); tree = tree.replace("%s", wire); @@ -1381,11 +1415,16 @@ function encode(term) let inconfig = [ "\\eval(\\read_{this.mkhole()}(\\print)) = root" ]; + let inet = system; + lambdak = false; gamma(expand(term), "root", inconfig); inconfig = inconfig.join(";\n") + ";"; - return system.replace("INCONFIG", inconfig); + if (!lambdak) + inet = lambdai.concat("\n", inet); + + return inet.replace("INCONFIG", inconfig); } module.exports = encode; diff --git a/package.json b/package.json index 95f4286..9850a85 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "dependencies": { - "@alexo/lambda": "0.1.2", + "@alexo/lambda": "0.1.6", "browserify": "14.0.0", "brfs": "1.4.3" }, From e0af7d94f49c6313ba03b60b44fd61d72e03a6a6 Mon Sep 17 00:00:00 2001 From: Anton Salikhmetov Date: Mon, 27 Feb 2017 23:09:06 +0200 Subject: [PATCH 07/27] Remove links to mlc and inet --- index.html | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/index.html b/index.html index 59555df..4ce2771 100644 --- a/index.html +++ b/index.html @@ -288,9 +288,7 @@

    How It Works

    Software was first adapted for Node.js -from the C programming language -(mlc and -inet). +from the C programming language. The JavaScript version uses Jison to generate parsers from grammar. From 38472237bf5449cf794488fd1eaa22fa9f38b594 Mon Sep 17 00:00:00 2001 From: Anton Salikhmetov Date: Fri, 3 Mar 2017 04:38:48 +0200 Subject: [PATCH 08/27] Switch to @alexo/lambda@0.1.8 --- bundle.js | 826 +++++++++++++++++++++++++-------------------------- package.json | 2 +- 2 files changed, 410 insertions(+), 418 deletions(-) diff --git a/bundle.js b/bundle.js index 355eb6f..c43571f 100644 --- a/bundle.js +++ b/bundle.js @@ -749,7 +749,7 @@ function encode(term) module.exports = encode; -},{"../generic":5,"path":13}],4:[function(require,module,exports){ +},{"../generic":5,"path":15}],4:[function(require,module,exports){ "use strict"; const generic = require("../generic"); @@ -879,7 +879,7 @@ function encode(term) module.exports = encode; -},{"../generic":5,"path":13}],5:[function(require,module,exports){ +},{"../generic":5,"path":15}],5:[function(require,module,exports){ "use strict"; @@ -1076,7 +1076,7 @@ exports.getfv = getfv; exports.subst = subst; exports.readback = readback; -},{"path":13}],6:[function(require,module,exports){ +},{"path":15}],6:[function(require,module,exports){ "use strict"; exports.abstract = require("./abstract"); @@ -1183,7 +1183,7 @@ function encode(term) module.exports = encode; -},{"../generic":5,"path":13}],8:[function(require,module,exports){ +},{"../generic":5,"path":15}],8:[function(require,module,exports){ "use strict"; const generic = require("../generic"); @@ -1306,7 +1306,7 @@ function encode(term) module.exports = encode; -},{"../generic":5,"path":13}],9:[function(require,module,exports){ +},{"../generic":5,"path":15}],9:[function(require,module,exports){ "use strict"; const generic = require("../generic"); @@ -1429,7 +1429,7 @@ function encode(term) module.exports = encode; -},{"../generic":5,"path":13}],10:[function(require,module,exports){ +},{"../generic":5,"path":15}],10:[function(require,module,exports){ "use strict"; const encoding = require("./encoding"); @@ -1548,7 +1548,7 @@ run.mlc2in = mlc2in; module.exports = run; -},{"./compile":2,"./encoding":6,"inet-lib":12}],11:[function(require,module,exports){ +},{"./compile":2,"./encoding":6,"inet-lib":13}],11:[function(require,module,exports){ /* parser generated by jison 0.4.15 */ /* Returns a Parser object of the following structure: @@ -1623,12 +1623,12 @@ module.exports = run; } */ 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 o=function(k,v,o,l){for(o=o||{},l=k.length;l--;o[k[l]]=v);return o},$V0=[5,23,24],$V1=[1,7],$V2=[1,8],$V3=[1,5,20,23,24],$V4=[9,10],$V5=[1,18],$V6=[9,10,12,14,17,18,19,25],$V7=[10,14,18,19,25],$V8=[1,28],$V9=[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]], +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,"need":21,"_":22,"!":23,"\\":24,"=":25,"$accept":0,"$end":1}, +terminals_: {2:"error",5:"MARK",9:"CODE",10:";",12:"[",14:"]",17:"(",18:")",19:",",20:"NAME",22:"_",23:"!",24:"\\",25:"="}, +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],[21,1],[21,1],[6,0],[6,5],[7,0],[7,2]], performAction: function anonymous(yytext, yyleng, yylineno, yy, yystate /* action[1] */, $$ /* vstack */, _$ /* lstack */) { /* this == yyval */ @@ -1637,7 +1637,7 @@ switch (yystate) { case 1: return {rules: $$[$0-3], conf: $$[$0-1], code: $$[$0]}; break; -case 2: case 14: +case 2: case 16: this.$ = []; break; case 3: @@ -1659,24 +1659,30 @@ case 11: this.$ = {agent: "wire", name: $$[$0]}; break; case 12: -this.$ = {agent: $$[$0], code: ""}; +this.$ = {agent: $$[$0], need: $$[$0-1], code: ""}; break; case 13: -this.$ = {agent: $$[$0-2], code: $$[$0].slice(1, -1)}; +this.$ = {agent: $$[$0-2], need: $$[$0-3], code: $$[$0].slice(1, -1)}; +break; +case 14: +this.$ = true; break; case 15: +this.$ = false; +break; +case 17: $$[$0-4].push({left: $$[$0-3], right: $$[$0-1]}); this.$ = $$[$0-4]; break; -case 16: +case 18: this.$ = ""; break; -case 17: +case 19: 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]}, +table: [o($V0,[2,2],{3:1,4:2}),{1:[3]},{5:[1,3],8:4,11:5,21:6,23:$V1,24:$V2},o($V3,[2,16],{6:9}),{9:[1,10]},o($V4,[2,4],{12:[1,11]}),{20:[1,12]},{20:[2,14]},{20:[2,15]},{1:[2,18],5:[1,15],7:13,11:17,15:14,16:16,20:$V5,21:6,23:$V1,24:$V2},{8:19,11:5,21:6,23:$V1,24:$V2},{11:17,13:20,15:21,16:16,20:$V5,21:6,23:$V1,24:$V2},o($V6,[2,12],{22:[1,22]}),{1:[2,1]},{25:[1,23]},{9:[1,24]},o($V7,[2,6]),o($V7,[2,10],{17:[1,25]}),o($V7,[2,11]),{10:[1,26]},{14:[1,27],19:$V8},o($V9,[2,8]),{9:[1,29]},{11:17,15:30,16:16,20:$V5,21:6,23:$V1,24:$V2},{1:[2,19]},{11:17,13:31,15:21,16:16,20:$V5,21:6,23:$V1,24:$V2},o($V0,[2,3]),o($V4,[2,5]),{11:17,15:32,16:16,20:$V5,21:6,23:$V1,24:$V2},o($V6,[2,13]),{10:[1,33]},{18:[1,34],19:$V8},o($V9,[2,9]),o($V3,[2,17]),o($V7,[2,7])], +defaultActions: {7:[2,14],8:[2,15],13:[2,1],24:[2,19]}, parseError: function parseError(str, hash) { if (hash.recoverable) { this.trace(str); @@ -2173,16 +2179,18 @@ case 10:return ")"; break; case 11:return ","; break; -case 12:return "\\"; +case 12:return "!"; break; -case 13:return "_"; +case 13:return "\\"; break; -case 14:return "="; +case 14:return "_"; +break; +case 15: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}} +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,15],"inclusive":true},"TAIL":{"rules":[0,1,2,3,5,6,9,10,11,12,13,14],"inclusive":true},"INITIAL":{"rules":[1,2,3,5,6,7,8,9,10,11,12,13,14],"inclusive":true}} }); return lexer; })(); @@ -2198,80 +2206,276 @@ module.exports = parser; },{}],12:[function(require,module,exports){ "use strict"; -const compile = require("./compile"); +const ambtype = 1; +const wiretype = 0; -const parser = new compile.Parser(); +let nwires, nambs, typelist, infmt; -let inverb, inrules, inconf, inenv, inqueue, nwires, nambs; -let typelist, types, ntypes, wiretype, ambtype, table; -let lpaxtype, rpaxtype, format, ndebug; +function getlist(pax) +{ + const list = pax.map(gettree); -function addtypes(tree) + if (list.length) + return "(" + list.join(", ") + ")"; + else + return ""; +} + +function gettree(agent) { - const agent = tree.node.agent; - const pax = tree.pax; - const plen = pax.length; + const type = agent.type; + let human; - if ("wire" == agent) - return; + if (wiretype == type) { + human = agent.human; - if (!types[agent]) { - types[agent] = ntypes; - ++ntypes; + if (!human) { + ++nwires; + human = "w" + nwires; + agent.human = human; + } + + agent.twin.human = human; + } else if (ambtype == type) { + const need = agent.need ? "!" : "\\"; + let index = agent.index; + let list = ""; + + if (!index || (nambs < index)) { + ++nambs; + index = nambs; + agent.twin.index = nambs; + + list = getlist([ + agent.main, + agent.aux + ]); + } + + human = need + "amb#" + index + list; + } else { + const need = agent.need ? "!" : "\\"; + let data = infmt(agent.data); + let cell; + + if (void(0) == data) + data = ""; + else + data = "_{" + data + "}"; + + cell = typelist[type] + data; + + human = need + cell + getlist(agent.pax); } - for (let i = 0; i < plen; i++) - addtypes(pax[i]); + return human; } -function norules(lagent, ragent) +function geteqn(pair) { - const eqn = geteqn({ - left: lagent, - right: ragent - }); + const left = gettree(pair.left); + const right = gettree(pair.right); - throw "NO RULES: " + eqn; + return left + " = " + right + ";"; } -function ischild(wire, agent) +function getconf(queue) { - const type = agent.type; + nambs = 0; + return queue.map(geteqn).join("\n"); +} - if (wiretype == type) { - if (wire === agent) - return true; - } else if (ambtype == type) { - if (ischild(wire, agent.main)) - return true; +function nofmt(data) +{ + return data; +} - if (ischild(wire, agent.aux)) - return true; - } else { - const pax = agent.pax; - const plen = pax.length; +function reset(fmt, types) +{ + if (fmt) + infmt = fmt; + else + infmt = nofmt; - for (let i = 0; i < plen; i++) - if (ischild(wire, pax[i])) - return true; + nwires = 0; + nambs = 0; + typelist = []; + + for (const type in types) + typelist[types[type]] = type; +} + +exports.reset = reset; +exports.geteqn = geteqn; +exports.getconf = getconf; + +},{}],13:[function(require,module,exports){ +"use strict"; + +const setup = require("./setup"); +const format = require("./format"); + +const reset = format.reset; +const geteqn = format.geteqn; +const getconf = format.getconf; + +let inenv, inqueue, table; + +function reduce(pair) +{ + const left = pair.left; + const right = pair.right; + const rule = pair.rule; + + if (!rule(left, right)) + throw "NO RULES: " + geteqn(pair); + + ++rule.count; +} + +function prepare(src, fmt) +{ + let system; + + inenv = run.inenv; + + system = setup(src, inenv); + table = system.rules; + inqueue = system.queue; + reset(fmt, system.types); + + return inenv; +} + +function debug() +{ + const conf = getconf(inqueue); + const pair = inqueue.pop(); + + if (pair) + reduce(pair); + + return conf; +} + +function debug0() +{ + const pair = inqueue.pop(); + + if (pair) { + reduce(pair); + return true; } return false; } -function detect(wire, agent) +function debug1() { - if (ndebug) - return; + const pair = inqueue.pop(); - if (ischild(wire, agent)) { - const eqn = geteqn({ - left: wire, - right: agent - }); + if (pair) { + const eqn = geteqn(pair); + + reduce(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 rule = row[j]; + const count = rule.count; + let human = rule.human; + + if (!human) + continue; + + 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 perform(max) +{ + const t0 = Date.now(); + + for (let i = 0; i < max; i++) { + if (!inqueue.length) + break; - throw "DEADLOCK: " + eqn; + reduce(inqueue.pop()); } + + return Date.now() - t0; +} + +function run(src, max) +{ + prepare(src); + inenv.redtime = perform(max ? max : 1e7); + inenv.stats = getstats(); + return inenv; +} + +run.inenv = {}; +run.prepare = prepare; +run.debug = debug; +run.debug0 = debug0; +run.debug1 = debug1; + +module.exports = run; + +},{"./format":12,"./setup":14}],14:[function(require,module,exports){ +"use strict"; + +const compile = require("./compile"); + +const parser = new compile.Parser(); + +const ambtype = 1; +const wiretype = 0; +const lpaxtype = -1; +const rpaxtype = -2; + +let inqueue, inenv, ntypes, types, table; + +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 indwire(wire, agent) @@ -2281,11 +2485,13 @@ function indwire(wire, agent) dst.twin = twin; twin.twin = dst; + + return true; } function inderiw(agent, wire) { - indwire(wire, agent); + return indwire(wire, agent); } function indamb(wire, agent) @@ -2293,35 +2499,35 @@ 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; + + return true; } function indbma(agent, wire) { - indamb(wire, agent); + return 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; + + return true; } function indtnega(agent, wire) { - indagent(wire, agent); + return indagent(wire, agent); } function getindir(type) @@ -2371,15 +2577,14 @@ function determ(amb, agent) dst.data = aux.data; } - flush([{ - left: amb.main, - right: agent - }]); + flush(amb.main, agent); + + return true; } function mreted(agent, amb) { - determ(amb, agent); + return determ(amb, agent); } function mkeffect(lval, rval, code, expr) @@ -2528,16 +2733,13 @@ function genqueue(img) for (let i = 0; i < ilen; i++) { const pair = img[i]; - const left = pair.left; - const right = pair.right; + const left = genclone(pair.left); + const right = genclone(pair.right); - queue.push("{\n\ - left: " + genclone(left) + ",\n\ - right: " + genclone(right) + "\n\ - }"); + queue.push("flush(" + left + "," + right + ");"); } - return "[" + queue.join(", ") + "]"; + return queue.join("\n"); } function generate(img, wlist, alist, effect, rl) @@ -2552,9 +2754,10 @@ function generate(img, wlist, alist, effect, rl) const lpax = left.pax;\n\ const rpax = right.pax;\n\n\ " + gentwins(wlist, alist) + "\ - return " + genqueue(img) + ";"; + " + genqueue(img) + "\n\ + return true;"; - return new Function("left", "right", body); + return new Function("flush", "left", "right", body); } function apply(left, right, code, rl) @@ -2604,11 +2807,28 @@ function apply(left, right, code, rl) } interact = generate(oimg, wlist, alist, effect, rl); + interact = interact.bind(inenv, flush); interact.human = human; - interact.count = 0; return interact; } +function flush(left, right) +{ + const row = table[left.type]; + const rule = row[right.type]; + + if (rule.pseudo) { + rule(left, right); + return; + } + + inqueue.push({ + left: left, + right: right, + rule: rule + }); +} + function addrule(dict, rule) { const human = rule.human; @@ -2620,125 +2840,6 @@ function addrule(dict, rule) 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; @@ -2805,250 +2906,141 @@ function encode(lval, rval, tree, wires, rt) return tree; } -function init() +function traverse(list, pair) { - const wires = {}; - const queue = []; - const effect = mkeffect(0, 0, inverb); - const clen = inconf.length; + const n = list.length; - effect.call(inenv); + function compound(left, right) + { + for (let i = 0; i < n; i++) { + const rule = list[i]; - for (let i = 0; i < clen; i++) { - const eqn = inconf[i]; - const left = eqn.left; - const right = eqn.right; + if (rule(left, right)) + return true; + } - queue.push({ - left: encode(0, 0, left, wires, true), - right: encode(0, 0, right, wires, true) - }); + return false; } - flush(queue); + compound.human = pair; + compound.count = 0; + return compound; } -function prepare(src, fmt, deadlock) +function setup(src, env) { const system = parser.parse(src); + const inrules = system.rules; + const inconf = system.conf; + const rlen = inrules.length; + const clen = inconf.length; + const custom = {}; + const wires = {}; + const queue = []; + const effect = mkeffect(0, 0, system.code); - if (fmt) - format = fmt; - else - format = noformat; - - ndebug = !deadlock; - inverb = system.code; - inrules = system.rules; - inconf = system.conf; - inenv = run.inenv; + table = []; inqueue = []; - typelist = []; + inenv = env; + ntypes = 2; types = { - wire: 0, - amb: 1 + wire: wiretype, + amb: ambtype }; - 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); + 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; - return conf; -} + addtypes(left); + addtypes(right); -function debug0() -{ - const pair = inqueue.shift(); + lrfunc = apply(left, right, code); + addrule(custom, lrfunc); - if (pair) { - traverse(pair); - return true; + rlfunc = apply(right, left, code, true); + addrule(custom, rlfunc); } - return false; -} - -function debug1() -{ - const pair = inqueue.shift(); + for (const pair in custom) + custom[pair] = traverse(custom[pair], pair); - if (pair) { - const eqn = geteqn(pair); + for (let i = 0; i < clen; i++) { + const eqn = inconf[i]; + const left = eqn.left; + const right = eqn.right; - traverse(pair); - return eqn; + addtypes(left); + addtypes(right); } -} - -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; + for (const left in types) { + const row = []; - human = human.split("><"); - human = human.sort(); - human = human.join("><"); + for (const right in types) { + let rule = custom[left + "><" + right]; - if (stats[human]) - stats[human] += count; + if (!rule) { + if ("wire" == left) + rule = getindir(right); + else if ("wire" == right) + rule = getridni(left); + else if ("amb" == left) + rule = determ; + else if ("amb" == right) + rule = mreted; else - stats[human] = count; + rule = () => {}; } + + row[types[right]] = rule; } + + table[types[left]] = row; } - return stats; -} + effect.call(inenv); -function run(src, max) -{ - let t0, t1; + for (let i = 0; i < clen; i++) { + const eqn = inconf[i]; + const left = eqn.left; + const right = eqn.right; - prepare(src); + queue.push({ + left: encode(0, 0, left, wires, true), + right: encode(0, 0, right, wires, true) + }); + } + + queue.forEach(pair => { + const left = pair.left; + const right = pair.right; - t0 = Date.now(); - reduce(max); - t1 = Date.now(); + flush(left, right); + }); - inenv.redtime = t1 - t0; - inenv.stats = getstats(); - return inenv; + return { + queue: inqueue, + rules: table, + types: types + }; } -run.inenv = {}; -run.prepare = prepare; -run.debug = debug; -run.debug0 = debug0; -run.debug1 = debug1; +determ.pseudo = true; +mreted.pseudo = true; +indwire.pseudo = true; +inderiw.pseudo = true; +indamb.pseudo = true; +indbma.pseudo = true; +indagent.pseudo = true; +indtnega.pseudo = true; -module.exports = run; +module.exports = setup; -},{"./compile":11}],13:[function(require,module,exports){ +},{"./compile":11}],15:[function(require,module,exports){ (function (process){ // Copyright Joyent, Inc. and other Node contributors. // @@ -3276,7 +3268,7 @@ var substr = 'ab'.substr(-1) === 'b' ; }).call(this,require('_process')) -},{"_process":14}],14:[function(require,module,exports){ +},{"_process":16}],16:[function(require,module,exports){ // shim for using process in browser var process = module.exports = {}; diff --git a/package.json b/package.json index 9850a85..e700730 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "dependencies": { - "@alexo/lambda": "0.1.6", + "@alexo/lambda": "0.1.8", "browserify": "14.0.0", "brfs": "1.4.3" }, From 0b2a3d24a1249a49f8171972fa2f87364f441713 Mon Sep 17 00:00:00 2001 From: Anton Salikhmetov Date: Thu, 9 Mar 2017 02:51:40 +0200 Subject: [PATCH 09/27] Switch to @alexo/lambda@0.2.1 --- bundle.js | 918 ++++++++++++++++++++++++--------------------------- index.html | 140 +------- package.json | 2 +- 3 files changed, 438 insertions(+), 622 deletions(-) diff --git a/bundle.js b/bundle.js index c43571f..4b89fa3 100644 --- a/bundle.js +++ b/bundle.js @@ -11,7 +11,7 @@ mlcjs.example = example.replace(/\n$/, ""); global.mlcjs = mlcjs; }).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) -},{"@alexo/lambda":10}],2:[function(require,module,exports){ +},{"@alexo/lambda":9}],2:[function(require,module,exports){ /* parser generated by jison 0.4.15 */ /* Returns a Parser object of the following structure: @@ -629,24 +629,12 @@ module.exports = parser; },{}],3:[function(require,module,exports){ "use strict"; -const generic = require("../generic"); const path = require("path"); -const lambdai = "\\apply[a, b] {\n\t/* Apply beta reduction. */\n\t++this.beta;\n\t++this.total;\n} \\lambda[a, b];\n"; -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.total;\n} \\wait[\\print, \\call];\n\n\\eval[\\fan_{i}(a, b)] {\n\t/* Postpone evaluation. */\n\t++this.total;\n} \\fan_{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}[\\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\\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\\erase {\n\t/* Erase context. */\n\t++this.total;\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;\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; -let lambdak; +const template = "\\apply[a, b] {\n\t/* Apply beta reduction. */\n\t++this.beta;\n\t++this.total;\n} \\lambda[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\\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\\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\\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\\erase {\n\t/* Erase context. */\n\t++this.total;\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;\n"; -function kill() -{ - lambdak = true; - return "\\erase"; -} +let mkwire, mktwins, getfv; function psi(shared, list) { @@ -703,7 +691,7 @@ function gamma(obj, root, list) if (id in fv) agent = id; else - agent = kill(); + agent = "\\erase"; tree = tree.replace("%s", agent); tree = tree.replace("%s", wire); @@ -730,39 +718,33 @@ function gamma(obj, root, list) } } -function encode(term) +function encode(generic, term) { - let inconfig = [ - "\\eval(\\read_{this.mkhole()}(\\print)) = root" + const inconfig = [ + "\\read_{this.mkhole()}(!print) = root" ]; - let inet = system; - lambdak = false; - gamma(expand(term), "root", inconfig); - inconfig = inconfig.join(";\n") + ";"; + mkwire = generic.mkwire; + mktwins = generic.mktwins; + getfv = generic.getfv; - if (!lambdak) - inet = lambdai.concat("\n", inet); + gamma(term, "root", inconfig); - return inet.replace("INCONFIG", inconfig); + inconfig.inet = template; + return inconfig; } module.exports = encode; -},{"../generic":5,"path":15}],4:[function(require,module,exports){ +},{"path":15}],4:[function(require,module,exports){ "use strict"; -const generic = require("../generic"); const path = require("path"); const template = "\\read_{C}[a] {\n\t/* Unshare variable. */\n\t++this.total;\n} \\share[\\copy(b, \\read_{C}(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} \\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)), \\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; + +let mkwire, mktwins, getfv, subst; function psi(shared, list) { @@ -865,21 +847,26 @@ function gamma(obj, root, list) } } -function encode(term) +function encode(generic, term) { - let inconfig = [ - "\\read_{this.mkhole()}(\\print) = root" + const inconfig = [ + "\\read_{this.mkhole()}(!print) = root" ]; - gamma(expand(term), "root", inconfig); - inconfig = inconfig.join(";\n") + ";"; + mkwire = generic.mkwire; + mktwins = generic.mktwins; + getfv = generic.getfv; + subst = generic.subst; - return system.replace("INCONFIG", inconfig); + gamma(term, "root", inconfig); + + inconfig.inet = template; + return inconfig; } module.exports = encode; -},{"../generic":5,"path":15}],5:[function(require,module,exports){ +},{"path":15}],5:[function(require,module,exports){ "use strict"; @@ -1079,131 +1066,48 @@ exports.readback = readback; },{"path":15}],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 generic = require("./generic"); +const abstract = require("./abstract"); +const closed = require("./closed"); +const optimal = require("./optimal"); +const turning = require("./turning"); -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)), \\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); +const readback = generic.readback; - list.push(eqn); - } -} - -function gamma(obj, root, list) +function addalgo(name, algo) { - 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); + function encode(term) + { + let conf, inet; - list.push(root + " = " + agent); + term = expand(term); + conf = algo(generic, term); + inet = conf.inet; - gamma(left, wleft, list); - gamma(right, wright, list); - psi(shared, list); + conf = conf.join(";\n") + ";"; + inet = inet.replace("INCONFIG", conf); + inet = inet.replace("READBACK\n", readback); + return inet; } -} - -function encode(term) -{ - let inconfig = [ - "\\read_{this.mkhole()}(\\print) = root" - ]; - - gamma(expand(term), "root", inconfig); - inconfig = inconfig.join(";\n") + ";"; - return system.replace("INCONFIG", inconfig); + exports[name] = encode; } -module.exports = encode; +addalgo("abstract", abstract); +addalgo("closed", closed); +addalgo("optimal", optimal); +addalgo("turning", turning); -},{"../generic":5,"path":15}],8:[function(require,module,exports){ +},{"./abstract":3,"./closed":4,"./generic":5,"./optimal":7,"./turning":8}],7:[function(require,module,exports){ "use strict"; -const generic = require("../generic"); const path = require("path"); -const lambdai = "\\apply[\\scope_{0}(a), \\scope_{0}(b)] {\n\t/* Apply beta reduction. */\n\t++this.beta;\n\t++this.total;\n} \\lambda[a, b];\n"; -const template = "\\print {\n\t/* Continue evaluation. */\n\t++this.total;\n} \\wait[\\print, \\call];\n\n\\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, 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\t++this.total;\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; -let lambdak; +const template = "\\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}[\\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\\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[\\scope_{0}(a), \\scope_{0}(b)] {\n\t/* Apply beta reduction. */\n\t++this.beta;\n\t++this.total;\n} \\lambda[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"; -function kill() -{ - lambdak = true; - return "\\erase"; -} +let mkwire, mktwins, getfv; function psi(shared, list) { @@ -1260,7 +1164,7 @@ function gamma(obj, root, list) if (id in fv) agent = id; else - agent = kill(); + agent = "\\erase"; tree = tree.replace("%s", agent); tree = tree.replace("%s", wire); @@ -1287,46 +1191,33 @@ function gamma(obj, root, list) } } -function encode(term) +function encode(generic, term) { - let inconfig = [ - "\\eval(\\read_{this.mkhole()}(\\print)) = root" + const inconfig = [ + "\\read_{this.mkhole()}(!print) = root" ]; - let inet = system; - lambdak = false; - gamma(expand(term), "root", inconfig); - inconfig = inconfig.join(";\n") + ";"; + mkwire = generic.mkwire; + mktwins = generic.mktwins; + getfv = generic.getfv; - if (!lambdak) - inet = lambdai.concat("\n", inet); + gamma(term, "root", inconfig); - return inet.replace("INCONFIG", inconfig); + inconfig.inet = template; + return inconfig; } module.exports = encode; -},{"../generic":5,"path":15}],9:[function(require,module,exports){ +},{"path":15}],8:[function(require,module,exports){ "use strict"; -const generic = require("../generic"); const path = require("path"); -const lambdai = "\\apply[a, b] {\n\t/* Apply beta reduction. */\n\t++this.beta;\n\t++this.total;\n} \\lambda[a, b];\n"; -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\t++this.total;\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; -let lambdak; +const template = "\\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\\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\\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\t++this.total;\n} \\lambda[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"; -function kill() -{ - lambdak = true; - return "\\erase"; -} +let mkwire, mktwins, getfv; function psi(shared, list) { @@ -1383,7 +1274,7 @@ function gamma(obj, root, list) if (id in fv) agent = id; else - agent = kill(); + agent = "\\erase"; tree = tree.replace("%s", agent); tree = tree.replace("%s", wire); @@ -1410,26 +1301,25 @@ function gamma(obj, root, list) } } -function encode(term) +function encode(generic, term) { - let inconfig = [ - "\\eval(\\read_{this.mkhole()}(\\print)) = root" + const inconfig = [ + "\\read_{this.mkhole()}(!print) = root" ]; - let inet = system; - lambdak = false; - gamma(expand(term), "root", inconfig); - inconfig = inconfig.join(";\n") + ";"; + mkwire = generic.mkwire; + mktwins = generic.mktwins; + getfv = generic.getfv; - if (!lambdak) - inet = lambdai.concat("\n", inet); + gamma(term, "root", inconfig); - return inet.replace("INCONFIG", inconfig); + inconfig.inet = template; + return inconfig; } module.exports = encode; -},{"../generic":5,"path":15}],10:[function(require,module,exports){ +},{"path":15}],9:[function(require,module,exports){ "use strict"; const encoding = require("./encoding"); @@ -1479,7 +1369,7 @@ function obj2mlc(obj) function mlc2in(mlc, algo) { - const encode = encoding[algo ? algo : "normal"]; + const encode = encoding[algo ? algo : "closed"]; let insrc; if (!encode) @@ -1548,7 +1438,7 @@ run.mlc2in = mlc2in; module.exports = run; -},{"./compile":2,"./encoding":6,"inet-lib":13}],11:[function(require,module,exports){ +},{"./compile":2,"./encoding":6,"inet-lib":12}],10:[function(require,module,exports){ /* parser generated by jison 0.4.15 */ /* Returns a Parser object of the following structure: @@ -2203,7 +2093,7 @@ return new Parser; })(); module.exports = parser; -},{}],12:[function(require,module,exports){ +},{}],11:[function(require,module,exports){ "use strict"; const ambtype = 1; @@ -2309,7 +2199,7 @@ exports.reset = reset; exports.geteqn = geteqn; exports.getconf = getconf; -},{}],13:[function(require,module,exports){ +},{}],12:[function(require,module,exports){ "use strict"; const setup = require("./setup"); @@ -2331,6 +2221,9 @@ function reduce(pair) throw "NO RULES: " + geteqn(pair); ++rule.count; + + pair.left = void(0); + pair.right = void(0); } function prepare(src, fmt) @@ -2366,8 +2259,6 @@ function debug0() reduce(pair); return true; } - - return false; } function debug1() @@ -2385,22 +2276,14 @@ function debug1() 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 rule = row[j]; + table.forEach(row => { + row.forEach(rule => { const count = rule.count; let human = rule.human; - if (!human) - continue; - - if (!count) - continue; + if (!human || !count) + return; human = human.split("><"); human = human.sort(); @@ -2410,8 +2293,8 @@ function getstats() stats[human] += count; else stats[human] = count; - } - } + }); + }); return stats; } @@ -2446,25 +2329,27 @@ run.debug1 = debug1; module.exports = run; -},{"./format":12,"./setup":14}],14:[function(require,module,exports){ +},{"./format":11,"./setup":13}],13:[function(require,module,exports){ "use strict"; const compile = require("./compile"); +const verbatim = require("./verbatim"); const parser = new compile.Parser(); +const generate = verbatim.generate; +const mkeffect = verbatim.mkeffect; const ambtype = 1; const wiretype = 0; const lpaxtype = -1; const rpaxtype = -2; +const eqntype = -3; let inqueue, inenv, ntypes, types, table; function addtypes(tree) { const agent = tree.node.agent; - const pax = tree.pax; - const plen = pax.length; if ("wire" == agent) return; @@ -2474,8 +2359,9 @@ function addtypes(tree) ++ntypes; } - for (let i = 0; i < plen; i++) - addtypes(pax[i]); + tree.pax.forEach(sub => { + addtypes(sub); + }); } function indwire(wire, agent) @@ -2486,7 +2372,10 @@ function indwire(wire, agent) dst.twin = twin; twin.twin = dst; - return true; + wire.parent = void(0); + wire.twin = void(0); + agent.parent = void(0); + agent.twin = void(0); } function inderiw(agent, wire) @@ -2498,15 +2387,28 @@ function indamb(wire, agent) { const dst = wire.twin; const twin = agent.twin; + const main = agent.main; + const aux = agent.aux; dst.twin = twin; twin.twin = dst; dst.type = ambtype; - dst.main = agent.main; - dst.aux = agent.aux; + dst.main = main; + dst.aux = aux; - return true; + main.parent = dst; + aux.parent = dst; + + if (agent.need) + delegate(dst); + + wire.parent = void(0); + wire.twin = void(0); + agent.parent = void(0); + agent.twin = void(0); + agent.main = void(0); + agent.aux = void(0); } function indbma(agent, wire) @@ -2517,12 +2419,24 @@ function indbma(agent, wire) function indagent(wire, agent) { const dst = wire.twin; + const pax = agent.pax; + const plen = pax.length; dst.type = agent.type; - dst.pax = agent.pax; dst.data = agent.data; + dst.pax = pax; + + for (let i = 0; i < plen; i++) + pax[i].parent = dst; - return true; + if (agent.need) + delegate(dst); + + wire.parent = void(0); + wire.twin = void(0); + agent.parent = void(0); + agent.data = void(0); + agent.pax = void(0); } function indtnega(agent, wire) @@ -2530,6 +2444,30 @@ function indtnega(agent, wire) return indagent(wire, agent); } +function delegate(node) +{ + do { + const type = node.type; + + node.need = true; + + if (eqntype == type) { + inqueue.push(node); + return; + } + + if (ambtype == type) { + const twin = node.twin; + + twin.need = true; + + delegate(twin.parent); + } + + node = node.parent; + } while (node && !node.need); +} + function getindir(type) { if ("wire" == type) @@ -2552,34 +2490,19 @@ function getridni(type) function determ(amb, agent) { - const dst = amb.twin; + const twin = amb.twin; + const main = amb.main; 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(amb.main, agent); + amb.type = wiretype; + amb.main = void(0); + amb.aux = void(0); + twin.type = wiretype; + twin.main = void(0); + twin.aux = void(0); - return true; + flush(amb, aux); + flush(main, agent); } function mreted(agent, amb) @@ -2587,177 +2510,25 @@ function mreted(agent, amb) return determ(amb, agent); } -function mkeffect(lval, rval, code, expr) +function getqueue(lval, rval, left, right, wires) { - 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); -} + const getpair = type => (tree, i) => { + tree = encode(lval, rval, tree, wires); -function prequeue(queue, side, lval, rval, pax, wires) -{ - const plen = pax.length; + adopt(tree); - for (let i = 0; i < plen; i++) { - const img = encode(lval, rval, pax[i], wires); - - queue.push({ + return { left: { - type: side, + type: type, 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 = genclone(pair.left); - const right = genclone(pair.right); - - queue.push("flush(" + left + "," + right + ");"); - } - - return queue.join("\n"); -} - -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) + "\ - " + genqueue(img) + "\n\ - return true;"; + right: tree + }; + }; - return new Function("flush", "left", "right", body); + left = left.pax.map(getpair(lpaxtype)); + right = right.pax.map(getpair(rpaxtype)); + return left.concat(right); } function apply(left, right, code, rl) @@ -2768,24 +2539,16 @@ function apply(left, right, code, rl) 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); + const img = getqueue(lval, rval, left, right, wires); + let interact; for (const name in wires) { const wire = wires[name]; const twin = wire.twin; - if (wire.junk) - continue; - wire.id = wlist.length; wlist.push(wire); @@ -2806,27 +2569,63 @@ function apply(left, right, code, rl) } } - interact = generate(oimg, wlist, alist, effect, rl); + interact = generate(img, wlist, alist, effect, rl); interact = interact.bind(inenv, flush); interact.human = human; return interact; } -function flush(left, right) +function adopt(agent, parent) { - const row = table[left.type]; - const rule = row[right.type]; - - if (rule.pseudo) { - rule(left, right); - return; + const type = agent.type; + let need = agent.need; + + if (ambtype == type) { + if (adopt(agent.main, agent)) + need = true; + + if (adopt(agent.aux, agent)) + need = true; + } else if (wiretype != type) { + agent.pax.forEach(tree => { + if (adopt(tree, agent)) + need = true; + }); } - inqueue.push({ + agent.parent = parent; + + agent.need = need; + return need; +} + +function addpair(left, right, rule) +{ + const need = left.need || right.need; + const pair = { + need: need, + type: eqntype, left: left, right: right, rule: rule - }); + }; + + left.parent = pair; + right.parent = pair; + + if (need) + inqueue.push(pair); +} + +function flush(left, right) +{ + const row = table[left.type]; + const rule = row[right.type]; + + if (rule.pseudo) + rule(left, right); + else + addpair(left, right, rule); } function addrule(dict, rule) @@ -2840,70 +2639,74 @@ function addrule(dict, rule) dict[human] = [rule]; } -function encode(lval, rval, tree, wires, rt) +function copyamb(dst, src) { - 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); - } + dst.need = src.need; + dst.type = src.type; + dst.main = src.main; + dst.aux = src.aux; +} - tree = { - type: type, - pax: imgpax - }; +function encode(lval, rval, root, wires, rt) +{ + const node = root.node; + const need = node.need; + const type = types[node.agent]; + const pax = root.pax.map(sub => { + return encode(lval, rval, sub, wires, rt); + }); if (wiretype == type) { const name = node.name; const wire = wires[name]; + const tree = { + type: type + }; if (wire) { wire.twin = tree; tree.twin = wire; - tree.type = wire.type; - tree.main = wire.main; - tree.aux = wire.aux; + copyamb(tree, wire); } - delete tree.pax; - wires[name] = tree; + + return tree; } else if (ambtype == type) { - const wire = imgpax.shift(); + const wire = pax.shift(); + const main = pax.shift(); + const aux = pax.shift(); const twin = wire.twin; - const main = imgpax.shift(); - const aux = imgpax.shift(); + const tree = { + need: need, + type: type, + main: main, + aux: aux + }; - wire.type = type; - wire.main = main; - wire.aux = aux; + copyamb(wire, tree); - if (twin) { - twin.type = type; - twin.main = main; - twin.aux = aux; - } + if (twin) + copyamb(twin, tree); return wire; } else { + const code = node.code; const effect = mkeffect(lval, rval, code, true); + const tree = { + need: need, + type: type, + pax: pax + }; if (rt) tree.data = effect.call(inenv); else tree.effect = effect; - } - return tree; + return tree; + } } function traverse(list, pair) @@ -2918,8 +2721,6 @@ function traverse(list, pair) if (rule(left, right)) return true; } - - return false; } compound.human = pair; @@ -2930,13 +2731,9 @@ function traverse(list, pair) function setup(src, env) { const system = parser.parse(src); - const inrules = system.rules; const inconf = system.conf; - const rlen = inrules.length; - const clen = inconf.length; const custom = {}; const wires = {}; - const queue = []; const effect = mkeffect(0, 0, system.code); table = []; @@ -2948,8 +2745,7 @@ function setup(src, env) amb: ambtype }; - for (let i = 0; i < rlen; i++) { - const rule = inrules[i]; + system.rules.forEach(rule => { const left = rule.left; const right = rule.right; const code = rule.code; @@ -2963,19 +2759,15 @@ function setup(src, env) rlfunc = apply(right, left, code, true); addrule(custom, rlfunc); - } + }); for (const pair in custom) custom[pair] = traverse(custom[pair], pair); - for (let i = 0; i < clen; i++) { - const eqn = inconf[i]; - const left = eqn.left; - const right = eqn.right; - - addtypes(left); - addtypes(right); - } + inconf.forEach(eqn => { + addtypes(eqn.left); + addtypes(eqn.right); + }); for (const left in types) { const row = []; @@ -3004,21 +2796,21 @@ function setup(src, env) effect.call(inenv); - for (let i = 0; i < clen; i++) { - const eqn = inconf[i]; + inconf.map(eqn => { const left = eqn.left; const right = eqn.right; - queue.push({ + return { left: encode(0, 0, left, wires, true), right: encode(0, 0, right, wires, true) - }); - } - - queue.forEach(pair => { + }; + }).forEach(pair => { const left = pair.left; const right = pair.right; + adopt(left); + adopt(right); + flush(left, right); }); @@ -3040,7 +2832,157 @@ indtnega.pseudo = true; module.exports = setup; -},{"./compile":11}],15:[function(require,module,exports){ +},{"./compile":10,"./verbatim":14}],14:[function(require,module,exports){ +"use strict"; + +const ambtype = 1; +const wiretype = 0; +const lpaxtype = -1; +const rpaxtype = -2; + +function geneff(effect) +{ + return `(${effect.toString()}).call(this, lval, rval)`; +} + +function gentwins(body, wlist, alist) +{ + if (!wlist.length) + return; + + wlist.forEach((wire, i) => { + const type = wire.type; + + body.push(`const wire${i} = {type: ${type}};`); + }); + + alist.forEach((amb, i) => { + const tree = genclone(body, amb); + + body.push(`const tree${i} = ${tree};`); + }); + + wlist.forEach((wire, i) => { + const twin = wire.twin.id; + + body.push(`wire${i}.twin = wire${twin};`); + + if (ambtype != wire.type) + return; + + body.push(`wire${i}.main = tree${wire.main};`); + body.push(`tree${wire.main}.parent = wire${i};`); + + body.push(`wire${i}.aux = tree${wire.aux};`); + body.push(`tree${wire.aux}.parent = wire${i};`); + }); +} + +function genclone(body, img) +{ + const type = img.type; + let pax, node; + + if (lpaxtype == type) + return `lpax[${img.id}]`; + + if (rpaxtype == type) + return `rpax[${img.id}]`; + + if (wiretype == type) + return `wire${img.id}`; + + if (ambtype == type) { + if (img.need) + body.push(`wire${img.id}.need = true;`); + + return `wire${img.id}`; + } + + node = `node${body.nnodes}`; + body.push(`const ${node} = { + type: ${type}, + data: ${geneff(img.effect)} + };`); + ++body.nnodes; + + pax = img.pax.map(child => { + child = genclone(body, child); + + body.push(`${child}.parent = ${node};`); + + return child; + }); + + body.push(`${node}.pax = [${pax.join(", ")}];`); + + if (img.need) + body.push(`${node}.need = true;`); + + return node; +} + +function genqueue(body, img) +{ + img.forEach(pair => { + pair.left = genclone(body, pair.left); + pair.right = genclone(body, pair.right); + }); + + img.forEach(pair => { + body.push(`flush(${pair.left}, ${pair.right});`); + }); +} + +function generate(img, wlist, alist, effect, rl) +{ + const left = rl ? "right" : "left"; + const right = rl ? "left" : "right"; + const body = ["/* Generated code below. */"]; + + body.nnodes = 0; + gentwins(body, wlist, alist); + genqueue(body, img); + + return new Function("flush", "left", "right", ` + const lval = ${left}.data; + const rval = ${right}.data; + + if (!${geneff(effect)}) + return; + + const lpax = left.pax; + const rpax = right.pax; + + left.parent = void(0); + left.data = void(0); + left.pax = void(0); + right.parent = void(0); + right.data = void(0); + right.pax = void(0); + + ${body.join("\n")} + + return true; + `); +} + +function mkeffect(lval, rval, code, expr) +{ + const left = lval ? lval : "LVAL"; + const right = rval ? rval : "RVAL"; + + return new Function(left, right, expr ? ` + return ${code ? code : "void(0)"}; + ` : `${code} + return true; + `); +} + +exports.generate = generate; +exports.mkeffect = mkeffect; + +},{}],15:[function(require,module,exports){ (function (process){ // Copyright Joyent, Inc. and other Node contributors. // diff --git a/index.html b/index.html index 4ce2771..794ac0e 100644 --- a/index.html +++ b/index.html @@ -1,6 +1,6 @@ - + MLC @@ -9,8 +9,13 @@ @@ -117,31 +122,9 @@

    -
    -
    -

    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. -

    - -
      -
    1. -Parse input according to -the MLC grammar. -
    2. - -
    3. -From the bottom up, substitute each macro using β-expansion. -
    4. - -
    5. -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. -
    6. - -
    7. -Parse the produced definition according to -the INC grammar. -
    8. - -
    9. -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. -
    10. -
    - -

    -This algorithm was inspired by the work of François-Régis Sinot, namely -Token-Passing Nets: Call-by-Need for Free. -In particular, the eval and return agents and their -interaction rules became the basis for -the embedded readback machanism. -

    - -

    -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. -

    - -

    - - -

    -
    -
    -
    - -
    diff --git a/package.json b/package.json index e700730..421cc5b 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "dependencies": { - "@alexo/lambda": "0.1.8", + "@alexo/lambda": "0.2.1", "browserify": "14.0.0", "brfs": "1.4.3" }, From b8944a4684d303485f38dac07c45331fc5cd15ea Mon Sep 17 00:00:00 2001 From: Anton Salikhmetov Date: Thu, 9 Mar 2017 14:08:12 +0200 Subject: [PATCH 10/27] Remove modal elements --- index.html | 69 ------------------------------------------------------ 1 file changed, 69 deletions(-) diff --git a/index.html b/index.html index 794ac0e..d848610 100644 --- a/index.html +++ b/index.html @@ -121,9 +121,7 @@
    -
    @@ -134,76 +132,9 @@

    Macro Lambda Calculus

    - - - - - -

    It may take a while... or forever!

    -
    -
    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 @@
     
     
     
    -

    Macro Lambda Calculus

    +
    +
    + + +
    + + +
    @@ -134,12 +151,10 @@

    Macro Lambda Calculus

    It may take a while... or forever!

    - - -
    -
    +
    Results will be printed here.
    +
    From 0e438885682d863afc6fbfdf3af13711ee307728 Mon Sep 17 00:00:00 2001 From: Anton Salikhmetov Date: Thu, 9 Mar 2017 21:34:51 +0200 Subject: [PATCH 12/27] Add more control elements --- README | 1 - README.md | 3 ++ index.html | 150 +++++++++++++++++++++++------------------------------ 3 files changed, 69 insertions(+), 85 deletions(-) delete mode 100644 README create mode 100644 README.md diff --git a/README b/README deleted file mode 100644 index c18156a..0000000 --- a/README +++ /dev/null @@ -1 +0,0 @@ -Call-by-need Lambda Calculus for Web using Interaction Nets diff --git a/README.md b/README.md new file mode 100644 index 0000000..3bddd5a --- /dev/null +++ b/README.md @@ -0,0 +1,3 @@ +Browserified version of [@alexo/lambda][1] + +[1]: https://www.npmjs.com/package/@alexo/lambda diff --git a/index.html b/index.html index 9279534..b59446c 100644 --- a/index.html +++ b/index.html @@ -8,12 +8,11 @@ @@ -23,98 +22,60 @@ diff --git a/package.json b/package.json index 421cc5b..bd4e546 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "dependencies": { - "@alexo/lambda": "0.2.1", + "@alexo/lambda": "0.2.2", "browserify": "14.0.0", "brfs": "1.4.3" }, From 689e9f50974fbd6a746888c9bcf3487edb8a85fe Mon Sep 17 00:00:00 2001 From: Anton Salikhmetov Date: Fri, 10 Mar 2017 01:24:37 +0200 Subject: [PATCH 14/27] Implement step-by-step evaluation --- index.html | 147 ++++++++++++++++++++++++++++++++++++----------------- 1 file changed, 99 insertions(+), 48 deletions(-) diff --git a/index.html b/index.html index 464790f..4eee76e 100644 --- a/index.html +++ b/index.html @@ -19,71 +19,124 @@ -