inet-lib
Version:
JavaScript Engine for Interaction Nets
566 lines (481 loc) • 10.8 kB
Plain Text
\print {
/* Continue evaluation. */
++this.total;
} \wait[!print, \call];
\eval[\fan_{i}(a, b)] {
/* Postpone evaluation. */
++this.total;
} \fan_{i}[a, b];
\eval[\scope_{i}(a)] {
/* Evaluate delimiter. */
++this.total;
} \scope_{i}[\eval(a)];
\eval[a] {
/* Continue evaluation. */
++this.total;
} \wait[\eval(a), \call];
\eval[\atom_{M}] {
/* Return an atom. */
++this.total;
} \atom_{M};
\eval[\lambda(a, b)] {
/* Evaluate abstraction. */
++this.total;
} \lambda[a, b];
\fan_{i}[\scope_{j}(a), \scope_{j}(b)] {
/* Duplicate higher delimiter. */
if (i < j)
++this.total;
else
return false;
} \scope_{j}[\fan_{i}(a, b)];
\scope_{i}[\fan_{j + 1}(a, b)] {
/* Level up higher or matching fan. */
if (i <= j)
++this.total;
else
return false;
} \fan_{j}[\scope_{i}(a), \scope_{i}(b)];
\scope_{i}[\scope_{j + 1}(a)] {
/* Level up higher delimiter. */
if (i < j)
++this.total;
else
return false;
} \scope_{j}[\scope_{i}(a)];
\print {
/* Ignore delimiter. */
++this.total;
} \scope_{i}[!print];
\read_{C}[\scope_{i}(a)] {
/* Pass through context. */
++this.total;
} \scope_{i}[\read_{C}(a)];
\scope_{i}[a] {
/* Annihilate matching delimiters. */
if (i == j)
++this.total;
else
return false;
} \scope_{j}[a];
\scope_{i}[\apply(a, b)] {
/* Pass through application. */
++this.total;
} \apply[\scope_{i}(a), \scope_{i}(b)];
\scope_{i}[\lambda(a, b)] {
/* Level up delimiter. */
++this.total;
} \lambda[\scope_{i + 1}(a), \scope_{i + 1}(b)];
\erase {
/* Erase delimiter. */
++this.total;
} \scope_{i}[\erase];
\scope_{i}[\wait(a, b)] {
/* Postpone delimiter. */
++this.total;
} \wait[\scope_{i}(a), b];
\scope_{i}[\atom_{M}] {
/* Return an atom. */
++this.total;
} \atom_{M};
\read_{C}[\fan_{i}(a, b)] {
/* Duplicate context. */
++this.total;
} \fan_{i}[\read_{C}(a), \read_{this.clone(C)}(b)];
\call {
/* Erase late call. */
++this.total;
} \erase;
\fan_{i}[\wait(a, \amb(b, \decide(c, d), d)), \wait(e, b)] {
/* Postpone duplication. */
++this.total;
} \wait[\fan_{i}(a, e), c];
\call {
/* Continue evaluation. */
++this.total;
} \decide[\call, \erase];
\erase {
/* Erase reference. */
++this.total;
} \decide[a, a];
\call {
/* Continue evaluation. */
++this.total;
} \hold[a, \eval(a)];
\read_{C}[\wait(a, b)] {
/* Postpone readback. */
++this.total;
} \wait[\read_{C}(a), b];
\erase {
/* Erase holder. */
++this.total;
} \hold[\erase, \erase];
\erase {
/* Erase reference. */
++this.total;
} \wait[\erase, \erase];
\apply[a, \wait(b, \hold(\apply(a, b), \wait(c, d)))] {
/* Postpone application. */
++this.total;
} \wait[c, d];
\print {
/* Output results of read-back. */
this.nf = M;
++this.total;
} \atom_{M};
\read_{C}[a] {
/* Read back abstraction. */
++this.total;
} \lambda[\atom_{this.mkid()}, \read_{this.abst(C)}(a)];
\apply[\read_{this.appl(M)}(a), a] {
/* Read back application. */
++this.total;
} \atom_{M};
\read_{C}[\atom_{this.atom(C, M)}] {
/* Read back an atom. */
++this.total;
} \atom_{M};
\fan_{i}[\atom_{M}, \atom_{M}] {
/* Duplicate an atom. */
++this.total;
} \atom_{M};
\apply[a, \scope_{0}(b)] {
/* Apply beta reduction. */
++this.beta;
++this.total;
} \lambda[\wait(c, \hold(\scope_{0}(c), a)), b];
\fan_{i}[\apply(a, b), \apply(c, d)] {
/* Duplicate application. */
++this.total;
} \apply[\fan_{i}(a, c), \fan_{i}(b, d)];
\fan_{i}[\lambda(a, b), \lambda(c, d)] {
/* Level up fan. */
++this.total;
} \lambda[\fan_{i + 1}(a, c), \fan_{i + 1}(b, d)];
\fan_{i}[a, b] {
/* Annihilate matching fans. */
if (i == j)
++this.total;
else
return false;
} \fan_{j}[a, b];
\fan_{i}[\fan_{j}(a, b), \fan_{j}(c, d)] {
/* Duplicate higher fan. */
if (i < j)
++this.total;
else
return false;
} \fan_{j}[\fan_{i}(a, c), \fan_{i}(b, d)];
\erase {
/* Erase an atom. */
++this.total;
} \atom_{M};
\erase {
/* Erase application. */
++this.total;
} \apply[\erase, \erase];
\erase {
/* Erase abstraction. */
++this.total;
} \lambda[\erase, \erase];
\erase {
/* Erase duplicator. */
++this.total;
} \fan_{i}[\erase, \erase];
\erase {
/* Finish erasing. */
++this.total;
} \erase;
$$
\eval(\read_{this.mkhole()}(!print)) = root;
w37 = \apply(w38, root);
w37 = \lambda(w1, w39);
w40 = \apply(w41, w39);
w40 = \lambda(w2, w42);
w43 = \apply(w44, w42);
w43 = \lambda(w3, w45);
w46 = \apply(w47, w45);
w46 = \lambda(w4, w48);
w49 = \apply(w50, w48);
w49 = \lambda(w5, w51);
w52 = \apply(w53, w51);
w52 = \lambda(w6, w54);
w55 = \apply(w56, w54);
w55 = \lambda(w7, w57);
w58 = \apply(w59, w57);
w58 = \lambda(w8, w60);
w61 = \apply(w62, w60);
w61 = \lambda(w9, w63);
w64 = \apply(w65, w63);
w64 = \lambda(w10, w66);
w67 = \apply(w68, w66);
w71 = \apply(w72, w67);
w9 = \scope_{0}(w71);
w73 = \apply(w74, w72);
w4 = \scope_{0}(\scope_{0}(\scope_{0}(\scope_{0}(\scope_{0}(\scope_{0}(w73))))));
w69 = \scope_{0}(\scope_{0}(\scope_{0}(\scope_{0}(\scope_{0}(w74)))));
w75 = \apply(w76, w68);
w10 = w75;
w70 = \scope_{0}(\scope_{0}(\scope_{0}(\scope_{0}(\scope_{0}(w76)))));
w5 = \fan_{0}(w70, w69);
w65 = \lambda(w11, w77);
w78 = \apply(w79, w77);
w82 = \apply(w83, w78);
w84 = \apply(w85, w82);
w11 = w84;
w85 = \lambda(w12, w86);
w86 = \lambda(w13, w87);
w88 = \apply(w89, w87);
w92 = \apply(w93, w88);
w7 = \scope_{0}(\scope_{0}(\scope_{0}(\scope_{0}(\scope_{0}(w92)))));
w90 = w93;
w94 = \apply(w95, w89);
w12 = \scope_{0}(w94);
w96 = \apply(w97, w95);
w6 = \scope_{0}(\scope_{0}(\scope_{0}(\scope_{0}(\scope_{0}(\scope_{0}(w96))))));
w91 = w97;
w13 = \fan_{0}(w91, w90);
w83 = \lambda(\erase, w98);
w80 = \scope_{0}(\scope_{0}(\scope_{0}(\scope_{0}(\scope_{0}(\scope_{0}(\scope_{0}(\scope_{0}(w98))))))));
w81 = \scope_{0}(\scope_{0}(\scope_{0}(\scope_{0}(\scope_{0}(\scope_{0}(\scope_{0}(w79)))))));
w3 = \fan_{0}(w81, w80);
w62 = \lambda(w15, w99);
w99 = \lambda(w16, w100);
w101 = \apply(w102, w100);
w103 = \apply(w104, w101);
w16 = w103;
w8 = \scope_{0}(\scope_{0}(w104));
w15 = \scope_{0}(w102);
w59 = \lambda(w17, w105);
w105 = \lambda(w18, w106);
w106 = \lambda(w19, w107);
w108 = \apply(w109, w107);
w110 = \apply(w111, w108);
w112 = \apply(w113, w110);
w17 = \scope_{0}(\scope_{0}(w112));
w113 = \lambda(w20, w114);
w114 = \lambda(w21, w115);
w116 = \apply(w117, w115);
w21 = w116;
w118 = \apply(w119, w117);
w20 = \scope_{0}(w118);
w18 = \scope_{0}(\scope_{0}(\scope_{0}(w119)));
w120 = \apply(w121, w111);
w2 = \scope_{0}(\scope_{0}(\scope_{0}(\scope_{0}(\scope_{0}(\scope_{0}(\scope_{0}(\scope_{0}(w120))))))));
w19 = w121;
w1 = \scope_{0}(\scope_{0}(\scope_{0}(\scope_{0}(\scope_{0}(\scope_{0}(\scope_{0}(\scope_{0}(\scope_{0}(w109)))))))));
w56 = \lambda(w22, w122);
w122 = \lambda(w23, w123);
w123 = \lambda(w24, w124);
w125 = \apply(w126, w124);
w22 = \scope_{0}(\scope_{0}(w125));
w127 = \apply(w128, w126);
w23 = \scope_{0}(w127);
w24 = w128;
w53 = \lambda(w25, w129);
w129 = \lambda(w26, w130);
w130 = \lambda(w27, w131);
w132 = \apply(w133, w131);
w134 = \scope_{0}(w132);
w136 = \apply(w137, w133);
w138 = \apply(w139, w136);
w25 = \scope_{0}(\scope_{0}(w138));
w135 = \scope_{0}(w139);
w27 = w137;
w26 = \fan_{0}(w135, w134);
w50 = \lambda(w28, w140);
w140 = \lambda(w29, w141);
w142 = \apply(w143, w141);
w144 = \scope_{0}(w142);
w146 = \apply(w147, w143);
w148 = \scope_{0}(w146);
w150 = \apply(w151, w147);
w152 = \scope_{0}(w150);
w154 = \apply(w155, w151);
w156 = \scope_{0}(w154);
w158 = \apply(w159, w155);
w157 = \scope_{0}(w158);
w29 = w159;
w153 = \fan_{0}(w157, w156);
w149 = \fan_{0}(w153, w152);
w145 = \fan_{0}(w149, w148);
w28 = \fan_{0}(w145, w144);
w47 = \lambda(w30, w160);
w160 = \lambda(w31, w161);
w162 = \apply(w163, w161);
w164 = \scope_{0}(w162);
w166 = \apply(w167, w163);
w168 = \scope_{0}(w166);
w170 = \apply(w171, w167);
w169 = \scope_{0}(w170);
w31 = w171;
w165 = \fan_{0}(w169, w168);
w30 = \fan_{0}(w165, w164);
w44 = \lambda(w32, w172);
w172 = \lambda(w33, w173);
w174 = \apply(w175, w173);
w32 = \scope_{0}(w174);
w33 = w175;
w41 = \lambda(w34, w176);
w176 = \lambda(\erase, w177);
w34 = \scope_{0}(w177);
w38 = \lambda(w36, w178);
w36 = w178;
$$
const gfv = [];
let id = 0;
function mkvar(fresh)
{
if (fresh)
++id;
return "v" + id.toFixed(0);
}
function mkid(name)
{
const fv = {};
const obj = {
node: "atom",
name: name,
fv: fv
};
if (name) {
gfv[name] = true;
return obj;
}
do {
name = mkvar(true);
} while (gfv[name]);
obj.name = name;
fv[name] = true;
return obj;
}
function mkhole()
{
const obj = {};
obj.fv = {};
obj.bv = {};
obj.hole = obj;
return obj;
}
function subst(hole, obj)
{
const parent = hole.parent;
const body = obj.body;
const left = obj.left;
const right = obj.right;
if (parent)
obj.parent = hole.parent;
else
delete obj.parent;
Object.assign(hole, obj);
if (body)
body.parent = hole;
if (left)
left.parent = hole;
if (right)
right.parent = hole;
}
function eta(obj)
{
let parent, left, right, name;
if ("appl" != obj.node)
return;
parent = obj.parent;
if (!parent)
return;
if ("abst" != parent.node)
return;
right = obj.right;
if ("atom" != right.node)
return;
name = parent.var;
if (name != right.name)
return;
left = obj.left;
if (left.fv[name])
return;
subst(parent, left);
eta(parent);
}
function atom(context, obj, name)
{
const ofv = obj.fv;
const cfv = context.fv;
const bv = context.bv;
const chole = context.hole;
const ohole = obj.hole;
if (name)
bv[name] = true;
for (const key in ofv)
if (!(key in bv))
cfv[key] = true;
subst(chole, obj);
if (ohole) {
delete chole.hole;
context.hole = ohole;
} else {
delete context.hole;
eta(chole);
}
return context;
}
function abst(context)
{
const hole = mkhole();
const name = mkvar();
const obj = {
node: "abst",
var: name,
body: hole,
fv: {},
hole: hole
};
hole.parent = obj;
return atom(context, obj, name);
}
function appl(left)
{
const context = mkhole();
const hole = mkhole();
const obj = {
node: "appl",
left: left,
right: hole,
fv: Object.assign({}, left.fv),
hole: hole
};
left.parent = obj;
hole.parent = obj;
return atom(context, obj);
}
function clone(obj, root, hole, parent)
{
const copy = {};
if (!obj)
return;
if (!root) {
root = copy;
hole = obj.hole;
}
copy.node = obj.node;
copy.var = obj.var;
copy.name = obj.name;
copy.parent = parent;
copy.body = clone(obj.body, root, hole, copy);
copy.left = clone(obj.left, root, hole, copy);
copy.right = clone(obj.right, root, hole, copy);
copy.fv = Object.assign({}, obj.fv);
copy.bv = Object.assign({}, obj.bv);
if (obj === hole)
root.hole = copy;
return copy;
}
this.clone = clone;
this.mkid = mkid;
this.mkvar = mkvar;
this.mkhole = mkhole;
this.abst = abst;
this.appl = appl;
this.atom = atom;
this.beta = 0;
this.total = 0;