@@ -1,717 +0,0 @@
1−import noun from './noun.js';
2−import { NounMap } from './hamt.js';
3−import list from './list.js';
4−var Noun = noun.Noun, Atom = noun.Atom.Atom, Cell = noun.Cell, MEMO = noun.dwim("memo"), SLOG = noun.dwim("slog"), FAST = noun.dwim("fast"), SPOT = noun.dwim("spot"), MEAN = noun.dwim("mean"), HUNK = noun.dwim("hunk"), LOSE = noun.dwim("lose");
10− Statement.call(this);
11− this.statements = [];
13−Block.prototype = Object.create(Statement.prototype);
14−Block.prototype.constructor = Block;
16−Block.prototype.append = function(st) {
17− this.statements.push(st);
20−Block.prototype.toJs = function() {
21− var sts = this.statements;
22− var parts = new Array(sts.length);
23− for ( var i = 0; i < sts.length; ++i) {
24− parts[i] = sts[i].toJs();
26− return parts.join('');
29−function Assignment(name, expr) {
30− Statement.call(this);
34−Assignment.prototype = Object.create(Statement.prototype);
35−Assignment.prototype.constructor = Assignment;
37−Assignment.prototype.toJs = function() {
38− return "var " + this.name + " = " + this.expr.toJs() + ";";
41−function Expression() {
44−function Cons(head, tail) {
45− Expression.call(this);
49−Cons.prototype = Object.create(Expression.prototype);
50−Cons.prototype.constructor = Cons;
52−Cons.prototype.toJs = function() {
53− return "context.cons(" + this.head + ", " + this.tail + ")";
56−function Frag(axis, name) {
57− Expression.call(this);
61−Frag.prototype = Object.create(Expression.prototype);
62−Frag.prototype.constructor = Frag;
64−Frag.prototype.toJs = function() {
65− var parts = [this.name];
66− for ( var ax = this.axis; ax > 1; ax = ax.mas() ) {
67− parts.push( ( 2 === ax.cap().valueOf() ) ? "head" : "tail" );
69− return parts.join(".");
73− Statement.call(this);
75−Bail.prototype = Object.create(Statement.prototype);
76−Bail.prototype.constructor = Bail;
78−Bail.prototype.toJs = function() {
79− return "throw new Error(\"Bail\")";
82−function Identity(name) {
83− Expression.call(this);
86−Identity.prototype = Object.create(Expression.prototype);
87−Identity.prototype.constructor = Identity;
89−Identity.prototype.toJs = function() {
93−function Constant(index) {
94− Expression.call(this);
97−Constant.prototype = Object.create(Expression.prototype);
98−Constant.prototype.constructor = Constant;
100−Constant.prototype.toJs = function() {
101− return "constants[" + this.index + "]";
104−function Nock(subject, formula, tail) {
105− Expression.call(this);
106− this.subject = subject;
107− this.formula = formula;
110−Nock.prototype = Object.create(Expression.prototype);
111−Nock.prototype.constructor = Nock;
113−Nock.prototype.toJs = function() {
114− var f = this.formula;
115− var targetCode = "(" + f + ".hasOwnProperty('target') ? " + f +
116− ".target : (" + f + ".target = context.compile(" + this.formula + ")))";
118− "context.trampoline(" + targetCode + ", " + this.subject + ")" :
119− targetCode + "(" + this.subject + ")";
122−function Deep(name) {
123− Expression.call(this);
126−Deep.prototype = Object.create(Expression.prototype);
127−Deep.prototype.constructor = Deep;
129−Deep.prototype.toJs = function() {
130− return this.name +".deep ? context.yes : context.no";
133−function Bump(name) {
134− Expression.call(this);
137−Bump.prototype = Object.create(Expression.prototype);
138−Bump.prototype.constructor = Bump;
140−Bump.prototype.toJs = function() {
141− return this.name + ".bump()";
144−function Same(one, two) {
145− Expression.call(this);
149−Same.prototype = Object.create(Expression.prototype);
150−Same.prototype.constructor = Same;
152−Same.prototype.toJs = function() {
153− return "(" + this.one + ".equals(" + this.two + ")" + " ? context.yes : context.no)";
156−function If(test, yes, no) {
157− Statement.call(this);
162−If.prototype = Object.create(Statement.prototype);
163−If.prototype.constructor = If;
165−If.prototype.toJs = function() {
166− return "if(" + this.test + ".loob()){" +
167− this.yes.toJs() + "}else{" + this.no.toJs() + "}";
170−function Kick(axis, core, tail) {
171− Expression.call(this)
176−Kick.prototype = Object.create(Expression.prototype);
177−Kick.prototype.constructor = Kick;
179−Kick.prototype.toJs = function() {
180− var axis = this.axis.shortCode();
182− return "(function (cor) {" +
183− "var pro, tgt, bus, arms, bat = cor.head, has = false;" +
184− "if ( bat.hasOwnProperty('loc') && (tgt = bat.loc.jets[" + axis + "]) && bat.loc.fine(cor) ) {" +
185− "return tgt(cor);" +
187− "if ( bat.hasOwnProperty('arms') ) {" +
188− "arms = bat.arms;" +
189− "has = arms.hasOwnProperty('" + axis + "');" +
191− "else arms = bat.arms = {};" +
192− "tgt = (has ? arms['" + axis + "'] : (arms['" + axis + "'] = context.compile(" +
193− new Frag(this.axis, "bat").toJs() + ")));" +
195− (this.tail ? "pro = context.trampoline(tgt, bus);" :
198− "if ( context.isTrampoline(pro) ) {" +
199− "tgt = pro.target;" +
200− "bus = pro.subject;" +
205− "})(" + this.core + ")";
208−function GetMemo(name) {
209− Expression.call(this);
212−GetMemo.prototype = Object.create(Expression.prototype);
213−GetMemo.prototype.constructor = GetMemo;
215−GetMemo.prototype.toJs = function() {
216− return "context.getMemo(" + this.name + ")";
219−function PutMemo(key, val) {
220− Statement.call(this);
224−PutMemo.prototype = Object.create(Statement.prototype);
225−PutMemo.prototype.constructor = PutMemo;
227−function Push(name) {
228− Statement.call(this);
231−Push.prototype = Object.create(Statement.prototype);
232−Push.prototype.constructor = Push;
234−Push.prototype.toJs = function() {
235− return "context.stackPush(" + this.name + ");";
239− Statement.call(this);
241−Pop.prototype = Object.create(Statement.prototype);
242−Pop.prototype.constructor = Pop;
244−Pop.prototype.toJs = function() {
245− return "context.stackPop()";
248−function Fast(clue, core) {
249− Statement.call(this);
254−Fast.prototype.toJs = function() {
255− return "context.register(" + this.core + ", " + this.clue + ");";
258−function Slog(name) {
259− Statement.call(this);
263−Slog.prototype.toJs = function() {
264− return "context.slog(" + this.name + ")";
267−function compile(formula, subject, product, fresh, constants, block, tail) {
268− var op, arg, one, two, odd;
269− if ( !(formula instanceof Cell )) {
270− throw new Error("invalid formula");
274− if ( op instanceof Cell ) {
277− compile(op, subject, one, fresh, constants, block, false);
278− compile(arg, subject, two, fresh, constants, block, false);
279− block.append(new Assignment(product, new Cons(one, two)));
281− else switch ( op.valueOf() ) {
284− block.append(new Bail());
286− else if ( 1 === arg ) {
287− block.append(new Identity(subject));
290− block.append(new Assignment(product, new Frag(arg, subject)));
294− constants.push(arg);
295− block.append(new Assignment(product, new Constant(constants.length - 1)));
300− compile(arg.head, subject, one, fresh, constants, block, false);
301− compile(arg.tail, subject, two, fresh, constants, block, false);
302− block.append(new Assignment(product, new Nock(one, two, tail)));
306− compile(arg, subject, one, fresh, constants, block, false);
307− block.append(new Assignment(product, new Deep(one)));
311− compile(arg, subject, one, fresh, constants, block, false);
312− block.append(new Assignment(product, new Bump(one)));
317− compile(arg.head, subject, one, fresh, constants, block, false);
318− compile(arg.tail, subject, two, fresh, constants, block, false);
319− block.append(new Assignment(product, new Same(one, two)));
325− compile(arg.head, subject, odd, fresh, constants, block, false);
326− compile(arg.tail.head, subject, product, fresh, constants, one, tail);
327− compile(arg.tail.tail, subject, product, fresh, constants, two, tail);
328− block.append(new If(odd, one, two));
332− compile(arg.head, subject, one, fresh, constants, block, false);
333− compile(arg.tail, one, product, fresh, constants, block, tail);
338− compile(arg.head, subject, one, fresh, constants, block, false);
339− block.append(new Assignment(two, new Cons(one, subject)));
340− compile(arg.tail, two, product, fresh, constants, block, tail);
344− if ( 2 === odd.cap().valueOf() ) {
347− compile(arg.tail, subject, one, fresh, constants, block, false);
348− block.append(new Assignment(product, new Kick(two, one, tail)));
351− compile(noun.dwim([7, arg.tail, 2, [0, 1], 0, odd]),
352− subject, product, fresh, constants, block, tail);
356− var hint = arg.head;
357− if ( !(arg.head instanceof Cell) ) {
358− // no recognized static hints
359− compile(arg.tail, subject, product, fresh, constants, block, tail);
362− var zep = hint.head;
364− compile(hint.tail, subject, clu, fresh, constants, block, false);
365− if ( zep.equals(MEMO) ) {
371− var konst = fresh();
372− block.append(new Assignment(konst, new Constant(hint.tail)));
373− block.append(new Assignment(key, new Cons(subject, konst)));
374− block.append(new Assignment(got, new GetMemo(two)));
375− block.append(new Assignment(odd, new Deep(got)));
376− one.append(new Assignment(product, new Frag(noun.dwim(3), got)));
377− compile(arg.tail, subject, product, fresh, two, false);
378− two.append(new PutMemo(key, product));
379− block.append(new If(odd, one, two));
381− else if ( zep.equals(SLOG) ) {
382− block.append(new Slog(clu));
383− compile(arg.tail, subject, product, fresh, constants, block, tail);
385− else if ( zep.equals(FAST) ) {
386− compile(arg.tail, subject, product, fresh, constants, block, false);
387− block.append(new Fast(clu, product));
389− else if ( zep.equals(SPOT) ||
392− zep.equals(LOSE) ) {
395− block.append(new Assignment(one, new Constant(zep)));
396− block.append(new Assignment(two, new Cons(one, clu)));
397− block.append(new Push(two));
398− compile(arg.tail, subject, product, fresh, constants, block, false);
399− block.append(new Pop());
403− compile(arg.tail, subject, product, fresh, constants, block, tail);
410− compile(arg.head, subject, one, fresh, constants, block, false);
411− compile(arg.tail, subject, two, fresh, constants, block, false);
412− block.append(new Assignment(product, new Esc(one, two)));
415− throw new Error("invalid opcode");
419−function Trampoline(target, subject) {
420− this.target = target;
421− this.subject = subject;
424−function genFine(loc) {
425− var constants = [], out = [], i;
426− for ( i = 0; !loc.isStatic; ++i ) {
427− out.push("if(!constants[" + i + "].equals(a.head)){return false;}");
428− constants.push(loc.noun);
429− out.push("a=" + new Frag(loc.axisToParent, "a").toJs() + ";");
430− loc = loc.parentLoc;
432− out.push("return constants[" + i + "].equals(a);");
433− constants.push(loc.noun);
434− var body = 'return function(a){' + out.join('') + 'return true;};';
435− var builder = new Function('constants', body);
436− return builder(constants);
439−var three = noun.dwim(3);
440−function Location(context, name, label, axisToParent, hooks, noun, parentLoc) {
443− this.parentLoc = parentLoc;
444− this.axisToParent = axisToParent;
445− this.fragToParent = Noun.fragmenter(axisToParent);
446− this.nameToAxis = hooks;
447− this.axisToName = {};
448− this.isStatic = ( null === parentLoc || (three.equals(axisToParent) && parentLoc.isStatic) );
449− if ( this.isStatic ) {
453− this.noun = noun.head;
456− for ( var k in hooks ) {
457− if ( hooks.hasOwnProperty(k) ) {
458− this.axisToName[hooks[k].shortCode()] = k;
462− var drivers = context.drivers[label];
463− if ( drivers && drivers.length > 0 ) {
464− for ( var i = 0; i < drivers.length; ++i ) {
466− if ( d instanceof AxisArm ) {
467− this.jets[d.axis.mas().shortCode()] = d.fn;
470− this.jets[nameToAxis[d.name].mas().shortCode()] = d.fn;
474− this.fine = genFine(this);
477−function Clue(name, parentAxis, hooks) {
479− this.parentAxis = parentAxis;
483−function JetDriver(label, fn) {
488−function AxisArm(label, axis, fn) {
489− JetDriver.call(this, label, fn);
492−AxisArm.prototype = Object.create(JetDriver.prototype);
493−AxisArm.prototype.constructor = AxisArm;
495−function NamedArm(label, name, fn) {
496− JetDriver.call(this, label, fn);
499−NamedArm.prototype = Object.create(JetDriver.prototype);
500−NamedArm.prototype.constructor = NamedArm;
502−var two = noun.dwim(2);
503−function collectFromCore(prefix, spec, out) {
504− var name = spec[0], arms = spec[1], children = spec[2],
505− labl = prefix + "/" + name;
506− if ( arms instanceof Function ) {
507− out[labl] = [new AxisArm(labl, two, arms)];
511− for ( var k in arms ) {
512− if ( arms.hasOwnProperty(k) ) {
513− all.push(( 'number' === typeof(k) ) ?
514− new AxisArm(labl, noun.dwim(k), arms[k]) :
515− new NamedArm(labl, k, arms[k]));
521− for ( var i = 0; i < children.length; ++i ) {
522− collectFromCore(labl, children[i], out);
527−function Context(drivers) {
528− this.memo = new NounMap();
529− this.clues = new NounMap();
530− this.dash = new NounMap();
531− this.tax = noun.Atom.yes;
534− collectFromCore('', drivers, this.drivers);
538−Context.prototype.yes = noun.Atom.yes;
539−Context.prototype.no = noun.Atom.no;
540−Context.prototype.cons = function (h, t) {
541− return new Cell(h, t);
544−Context.prototype.trampoline = function(tgt, bus) {
545− return new Trampoline(tgt, bus);
548−Context.prototype.isTrampoline = function(a) {
549− return (a instanceof Trampoline);
552−Context.prototype.compile = function(cell) {
554− var fresh = function() {
557− var body = new Block();
559− compile(cell, "subject", "product", fresh, constants, body, true);
560− var text = "return function(subject){" + body.toJs() + "return product;}";
561− var builder = new Function("context", "constants", text);
562− return cell.target = builder(this, constants);
565−Context.prototype.nock = function(subject, formula) {
566− var product, target;
567− if ( !formula.hasOwnProperty("target") ) {
568− this.compile(formula);
570− target = formula.target;
572− product = target(subject);
573− if ( product instanceof Trampoline ) {
574− subject = product.subject;
575− target = product.target;
583−Context.prototype.getMemo = function(key) {
584− return this.memo.get(key);
587−Context.prototype.putMemo = function(key, val) {
588− this.memo.insert(key, val);
591−Context.prototype.stackPush = function(item) {
592− this.tax = new Cell(item, this.tax);
595−Context.prototype.stackPop = function() {
596− this.tax = this.tax.tail;
599−Context.prototype.slog = function(item) {
600− // TODO: don't rewrite ++wash again, just call the kernel
606− return Atom.cordToString(n.head) + n.tail.number.shortValue().toString(10);
609− return Atom.cordToString(n);
613−var ten = noun.dwim(10);
614−function skipHints(formula) {
616− if ( formula.deep ) {
617− if ( ten.equals(formula.head) ) {
618− formula = formula.tail.tail;
626−var zero = noun.dwim(0), constant_zero = noun.dwim(1,0);
627−function parseParentAxis(noun) {
628− var f = skipHints(noun);
629− if ( constant_zero.equals(f) ) {
632− else if ( !zero.equals(f.head) ) {
633− throw new Error("weird formula head");
635− else if ( 3 != f.tail.cap().valueOf() ) {
636− throw new Error("weird parent axis");
641−var nine = noun.dwim(9), constant_frag = noun.dwim(0,1);
642−function parseHookAxis(nock) {
643− var f = skipHints(nock),
646− if ( zero.equals(op) ) {
647− if ( !f.tail.deep ) {
651− else if ( nine.equals(op) ) {
653− if ( !rest.head.deep && constant_frag.equals(rest.tail) ) {
661−function parseHooks(noun) {
663− list.forEach(noun, function(c) {
664− var term = Atom.cordToString(c.head),
665− axis = parseHookAxis(c.tail);
666− if ( null != axis ) {
673−Context.prototype.parseClue = function(raw) {
674− var clue = this.clues.get(raw);
675− if ( clue === undefined ) {
676− var name = chum(raw.head),
677− parentAxis = parseParentAxis(raw.tail.head),
678− hooks = parseHooks(raw.tail.tail);
679− clue = new Clue(name, parentAxis, hooks);
680− this.clues.insert(raw, clue);
685−Context.prototype.register = function(core, raw) {
686− var bat = core.head;
687− var loc = this.dash.get(bat);
688− if ( undefined === loc ) {
690− var clue = this.parseClue(raw);
691− if ( zero.equals(clue.parentAxis) ) {
692− loc = new Location(this, clue.name, '/' + clue.name, zero, clue.hooks, core, null);
695− var parentCore = core.at(clue.parentAxis),
696− parentBattery = parentCore.head,
697− parentLoc = this.dash.get(parentBattery);
698− if ( undefined === parentLoc ) {
699− console.log('register: invalid parent for ' + clue.name);
702− var label = parentLoc.label + "/" + clue.name;
703− loc = new Location(this, clue.name, label, clue.parentAxis, clue.hooks, core, parentLoc);
707− this.dash.insert(bat, loc);