UNPKG

inet-lib

Version:

JavaScript Engine for Interaction Nets

566 lines (481 loc) 10.8 kB
\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;