abstract-algorithm
Advanced tools
Comparing version 0.1.18 to 0.1.19
{ | ||
"name": "abstract-algorithm", | ||
"version": "0.1.18", | ||
"version": "0.1.19", | ||
"description": "Abstract-algorithm for optional reduction of stratifiable lambda terms", | ||
@@ -5,0 +5,0 @@ "main": "src/lambda-calculus.js", |
# Lamping's Abstract Algorithm | ||
A cleaned up adaptation of [Lamping's abstract algorithm](http://dl.acm.org/citation.cfm?id=96711). It evaluates functions optimally by encoding a λ-term as ([symmetric](https://scholar.google.com.br/scholar?q=symmetric+interaction+combinators&hl=en&as_sdt=0&as_vis=1&oi=scholart&sa=X&ved=0ahUKEwjNgZbO7aTVAhUEkZAKHYyTAFgQgQMIJjAA)) [interaction combinators](http://www.sciencedirect.com/science/article/pii/S0890540197926432), normalizing the resulting graph, and decoding it back. It asymptotically beats all usual evaluators of functional programs, including Haskell's GHC, Scheme compilers, Google's V8 and so on. Moreover, it is capable of automatically exploiting any inherent parallelizability of your program, since interaction nets are a naturally concurrent model of computation. This implementation consists of two files, [a 121-loc reducer](src/interaction-combinators.js) for interaction combinators and [a 71-loc conversor](https://github.com/MaiaVictor/abstract-algorithm/blob/master/src/lambda-encoder.js) of λ-terms to and from those. It isn't parallel, but is completely lazy: it doesn't perform any work that won't influence on the normal form. There is an inherent tradeoff between those. | ||
A cleaned up adaptation of [Lamping's abstract algorithm](http://dl.acm.org/citation.cfm?id=96711). It evaluates functions optimally by encoding a λ-term as ([symmetric](https://scholar.google.com.br/scholar?q=symmetric+interaction+combinators&hl=en&as_sdt=0&as_vis=1&oi=scholart&sa=X&ved=0ahUKEwjNgZbO7aTVAhUEkZAKHYyTAFgQgQMIJjAA)) [interaction combinators](http://www.sciencedirect.com/science/article/pii/S0890540197926432), normalizing the resulting graph, and decoding it back. It asymptotically beats all usual evaluators of functional programs, including Haskell's GHC, Scheme compilers, Google's V8 and so on. Moreover, it is capable of automatically exploiting any inherent parallelizability of your program, since interaction nets are a naturally concurrent model of computation. This implementation consists of two files, [a 100-LOC reducer](src/abstract-combinators.js) for interaction combinators and [a 71-loc conversor](https://github.com/MaiaVictor/abstract-algorithm/blob/master/src/lambda-encoder.js) of λ-terms to and from those. It isn't parallel, but is completely lazy: it doesn't perform any work that won't influence on the normal form. There is an inherent tradeoff between those. | ||
@@ -5,0 +5,0 @@ ![combinator_rules](images/combinators_rules.png) |
@@ -1,2 +0,2 @@ | ||
const I = require("./interaction-combinators.js"); | ||
const I = require("./abstract-combinators.js"); | ||
@@ -82,29 +82,29 @@ const Var = (idx) => ({tag: "Var", idx}); | ||
var kind = 1; | ||
var mem = [0, 1, 2, 0]; | ||
var net = I.newNet([0, 1, 2, 0]); | ||
var ptr = (function encode(term, scope){ | ||
switch (term.tag){ | ||
case "Lam": | ||
var fun = I.newNode(mem,1); | ||
var era = I.newNode(mem,0); | ||
I.link(mem, I.port(fun,1), I.port(era,0)); | ||
I.link(mem, I.port(era,1), I.port(era,2)); | ||
var fun = I.newNode(net,1); | ||
var era = I.newNode(net,0); | ||
I.link(net, I.port(fun,1), I.port(era,0)); | ||
I.link(net, I.port(era,1), I.port(era,2)); | ||
var bod = encode(term.bod, [fun].concat(scope)); | ||
I.link(mem, I.port(fun,2), bod); | ||
I.link(net, I.port(fun,2), bod); | ||
return I.port(fun,0); | ||
case "App": | ||
var app = I.newNode(mem,1); | ||
var app = I.newNode(net,1); | ||
var fun = encode(term.fun, scope); | ||
I.link(mem, I.port(app,0), fun); | ||
I.link(net, I.port(app,0), fun); | ||
var arg = encode(term.arg, scope); | ||
I.link(mem, I.port(app,1), arg); | ||
I.link(net, I.port(app,1), arg); | ||
return I.port(app,2); | ||
case "Var": | ||
var lam = scope[term.idx]; | ||
if (I.getNodeKind(mem,I.getPortNode(I.enterPort(mem,I.port(lam,1)))) === 0) { | ||
if (I.getNodeKind(net,I.getPortNode(I.enterPort(net,I.port(lam,1)))) === 0) { | ||
return I.port(lam,1); | ||
} else { | ||
var dup = I.newNode(mem, ++kind); | ||
var arg = I.enterPort(mem, I.port(lam,1)); | ||
I.link(mem, I.port(dup,1), I.enterPort(mem,I.port(lam,1))); | ||
I.link(mem, I.port(dup,0), I.port(lam,1)); | ||
var dup = I.newNode(net, ++kind); | ||
var arg = I.enterPort(net, I.port(lam,1)); | ||
I.link(net, I.port(dup,1), I.enterPort(net,I.port(lam,1))); | ||
I.link(net, I.port(dup,0), I.port(lam,1)); | ||
return I.port(dup,2); | ||
@@ -114,13 +114,13 @@ } | ||
})(term, []); | ||
I.link(mem, 0, ptr); | ||
return mem; | ||
I.link(net, 0, ptr); | ||
return net; | ||
}; | ||
const fromNet = mem => { | ||
const fromNet = net => { | ||
var nodeDepth = {}; | ||
return (function go(next, exit, depth){ | ||
var prev = I.enterPort(mem, next); | ||
var prev = I.enterPort(net, next); | ||
var prevPort = I.getPortSlot(prev); | ||
var prevNode = I.getPortNode(prev); | ||
if (I.getNodeKind(mem, prevNode) === 1) { | ||
if (I.getNodeKind(net, prevNode) === 1) { | ||
switch (prevPort) { | ||
@@ -142,3 +142,3 @@ case 0: | ||
} | ||
})(mem[1], null, 0); | ||
})(0, null, 0); | ||
}; | ||
@@ -145,0 +145,0 @@ |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is too big to display
Long strings
Supply chain riskContains long string literals, which may be a sign of obfuscated or packed code.
Found 1 instance in 1 package
5440646
2642
4