@@ -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");
5−
6−function Statement() {
7−}
8−
9−function Block() {
10− Statement.call(this);
11− this.statements = [];
12−}
13−Block.prototype = Object.create(Statement.prototype);
14−Block.prototype.constructor = Block;
15−
16−Block.prototype.append = function(st) {
17− this.statements.push(st);
18−}
19−
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();
25− }
26− return parts.join('');
27−};
28−
29−function Assignment(name, expr) {
30− Statement.call(this);
31− this.name = name;
32− this.expr = expr;
33−}
34−Assignment.prototype = Object.create(Statement.prototype);
35−Assignment.prototype.constructor = Assignment;
36−
37−Assignment.prototype.toJs = function() {
38− return "var " + this.name + " = " + this.expr.toJs() + ";";
39−}
40−
41−function Expression() {
42−}
43−
44−function Cons(head, tail) {
45− Expression.call(this);
46− this.head = head;
47− this.tail = tail;
48−}
49−Cons.prototype = Object.create(Expression.prototype);
50−Cons.prototype.constructor = Cons;
51−
52−Cons.prototype.toJs = function() {
53− return "context.cons(" + this.head + ", " + this.tail + ")";
54−};
55−
56−function Frag(axis, name) {
57− Expression.call(this);
58− this.axis = axis;
59− this.name = name;
60−}
61−Frag.prototype = Object.create(Expression.prototype);
62−Frag.prototype.constructor = Frag;
63−
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" );
68− }
69− return parts.join(".");
70−};
71−
72−function Bail() {
73− Statement.call(this);
74−}
75−Bail.prototype = Object.create(Statement.prototype);
76−Bail.prototype.constructor = Bail;
77−
78−Bail.prototype.toJs = function() {
79− return "throw new Error(\"Bail\")";
80−};
81−
82−function Identity(name) {
83− Expression.call(this);
84− this.name = name;
85−}
86−Identity.prototype = Object.create(Expression.prototype);
87−Identity.prototype.constructor = Identity;
88−
89−Identity.prototype.toJs = function() {
90− return this.name;
91−};
92−
93−function Constant(index) {
94− Expression.call(this);
95− this.index = index;
96−}
97−Constant.prototype = Object.create(Expression.prototype);
98−Constant.prototype.constructor = Constant;
99−
100−Constant.prototype.toJs = function() {
101− return "constants[" + this.index + "]";
102−};
103−
104−function Nock(subject, formula, tail) {
105− Expression.call(this);
106− this.subject = subject;
107− this.formula = formula;
108− this.tail = tail;
109−}
110−Nock.prototype = Object.create(Expression.prototype);
111−Nock.prototype.constructor = Nock;
112−
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 + ")))";
117− return this.tail ?
118− "context.trampoline(" + targetCode + ", " + this.subject + ")" :
119− targetCode + "(" + this.subject + ")";
120−};
121−
122−function Deep(name) {
123− Expression.call(this);
124− this.name = name;
125−}
126−Deep.prototype = Object.create(Expression.prototype);
127−Deep.prototype.constructor = Deep;
128−
129−Deep.prototype.toJs = function() {
130− return this.name +".deep ? context.yes : context.no";
131−};
132−
133−function Bump(name) {
134− Expression.call(this);
135− this.name = name;
136−}
137−Bump.prototype = Object.create(Expression.prototype);
138−Bump.prototype.constructor = Bump;
139−
140−Bump.prototype.toJs = function() {
141− return this.name + ".bump()";
142−};
143−
144−function Same(one, two) {
145− Expression.call(this);
146− this.one = one;
147− this.two = two;
148−}
149−Same.prototype = Object.create(Expression.prototype);
150−Same.prototype.constructor = Same;
151−
152−Same.prototype.toJs = function() {
153− return "(" + this.one + ".equals(" + this.two + ")" + " ? context.yes : context.no)";
154−};
155−
156−function If(test, yes, no) {
157− Statement.call(this);
158− this.test = test;
159− this.yes = yes;
160− this.no = no;
161−}
162−If.prototype = Object.create(Statement.prototype);
163−If.prototype.constructor = If;
164−
165−If.prototype.toJs = function() {
166− return "if(" + this.test + ".loob()){" +
167− this.yes.toJs() + "}else{" + this.no.toJs() + "}";
168−};
169−
170−function Kick(axis, core, tail) {
171− Expression.call(this)
172− this.axis = axis;
173− this.core = core;
174− this.tail = tail;
175−}
176−Kick.prototype = Object.create(Expression.prototype);
177−Kick.prototype.constructor = Kick;
178−
179−Kick.prototype.toJs = function() {
180− var axis = this.axis.shortCode();
181−
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);" +
186− "}" +
187− "if ( bat.hasOwnProperty('arms') ) {" +
188− "arms = bat.arms;" +
189− "has = arms.hasOwnProperty('" + axis + "');" +
190− "}" +
191− "else arms = bat.arms = {};" +
192− "tgt = (has ? arms['" + axis + "'] : (arms['" + axis + "'] = context.compile(" +
193− new Frag(this.axis, "bat").toJs() + ")));" +
194− "bus = cor;" +
195− (this.tail ? "pro = context.trampoline(tgt, bus);" :
196− "while (true) {" +
197− "pro = tgt(bus);" +
198− "if ( context.isTrampoline(pro) ) {" +
199− "tgt = pro.target;" +
200− "bus = pro.subject;" +
201− "}" +
202− "else break;" +
203− "}") +
204− "return pro;" +
205− "})(" + this.core + ")";
206−};
207−
208−function GetMemo(name) {
209− Expression.call(this);
210− this.name = name;
211−}
212−GetMemo.prototype = Object.create(Expression.prototype);
213−GetMemo.prototype.constructor = GetMemo;
214−
215−GetMemo.prototype.toJs = function() {
216− return "context.getMemo(" + this.name + ")";
217−};
218−
219−function PutMemo(key, val) {
220− Statement.call(this);
221− this.key = key;
222− this.val = val;
223−}
224−PutMemo.prototype = Object.create(Statement.prototype);
225−PutMemo.prototype.constructor = PutMemo;
226−
227−function Push(name) {
228− Statement.call(this);
229− this.name = name;
230−}
231−Push.prototype = Object.create(Statement.prototype);
232−Push.prototype.constructor = Push;
233−
234−Push.prototype.toJs = function() {
235− return "context.stackPush(" + this.name + ");";
236−};
237−
238−function Pop() {
239− Statement.call(this);
240−}
241−Pop.prototype = Object.create(Statement.prototype);
242−Pop.prototype.constructor = Pop;
243−
244−Pop.prototype.toJs = function() {
245− return "context.stackPop()";
246−};
247−
248−function Fast(clue, core) {
249− Statement.call(this);
250− this.clue = clue;
251− this.core = core;
252−}
253−
254−Fast.prototype.toJs = function() {
255− return "context.register(" + this.core + ", " + this.clue + ");";
256−}
257−
258−function Slog(name) {
259− Statement.call(this);
260− this.name = name;
261−}
262−
263−Slog.prototype.toJs = function() {
264− return "context.slog(" + this.name + ")";
265−};
266−
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");
271− }
272− op = formula.head;
273− arg = formula.tail;
274− if ( op instanceof Cell ) {
275− one = fresh();
276− two = fresh();
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)));
280− }
281− else switch ( op.valueOf() ) {
282− case 0:
283− if ( 0 === arg ) {
284− block.append(new Bail());
285− }
286− else if ( 1 === arg ) {
287− block.append(new Identity(subject));
288− }
289− else {
290− block.append(new Assignment(product, new Frag(arg, subject)));
291− }
292− break;
293− case 1:
294− constants.push(arg);
295− block.append(new Assignment(product, new Constant(constants.length - 1)));
296− break;
297− case 2:
298− one = fresh();
299− two = fresh();
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)));
303− break;
304− case 3:
305− one = fresh();
306− compile(arg, subject, one, fresh, constants, block, false);
307− block.append(new Assignment(product, new Deep(one)));
308− break;
309− case 4:
310− one = fresh();
311− compile(arg, subject, one, fresh, constants, block, false);
312− block.append(new Assignment(product, new Bump(one)));
313− break;
314− case 5:
315− one = fresh();
316− two = fresh();
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)));
320− break;
321− case 6:
322− odd = fresh();
323− one = new Block();
324− two = new Block();
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));
329− break;
330− case 7:
331− one = fresh();
332− compile(arg.head, subject, one, fresh, constants, block, false);
333− compile(arg.tail, one, product, fresh, constants, block, tail);
334− break;
335− case 8:
336− one = fresh();
337− two = fresh();
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);
341− break;
342− case 9:
343− odd = arg.head;
344− if ( 2 === odd.cap().valueOf() ) {
345− one = fresh();
346− two = odd.mas();
347− compile(arg.tail, subject, one, fresh, constants, block, false);
348− block.append(new Assignment(product, new Kick(two, one, tail)));
349− }
350− else {
351− compile(noun.dwim([7, arg.tail, 2, [0, 1], 0, odd]),
352− subject, product, fresh, constants, block, tail);
353− }
354− break;
355− case 10:
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);
360− }
361− else {
362− var zep = hint.head;
363− var clu = fresh();
364− compile(hint.tail, subject, clu, fresh, constants, block, false);
365− if ( zep.equals(MEMO) ) {
366− var key = fresh();
367− var got = fresh();
368− odd = fresh();
369− one = new Block();
370− two = new Block();
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));
380− }
381− else if ( zep.equals(SLOG) ) {
382− block.append(new Slog(clu));
383− compile(arg.tail, subject, product, fresh, constants, block, tail);
384− }
385− else if ( zep.equals(FAST) ) {
386− compile(arg.tail, subject, product, fresh, constants, block, false);
387− block.append(new Fast(clu, product));
388− }
389− else if ( zep.equals(SPOT) ||
390− zep.equals(MEAN) ||
391− zep.equals(HUNK) ||
392− zep.equals(LOSE) ) {
393− one = fresh();
394− two = fresh();
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());
400− }
401− else {
402− // unrecognized
403− compile(arg.tail, subject, product, fresh, constants, block, tail);
404− }
405− }
406− break;
407− case 11:
408− one = fresh();
409− two = fresh();
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)));
413− break;
414− default:
415− throw new Error("invalid opcode");
416− }
417−}
418−
419−function Trampoline(target, subject) {
420− this.target = target;
421− this.subject = subject;
422−}
423−
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;
431− }
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);
437−}
438−
439−var three = noun.dwim(3);
440−function Location(context, name, label, axisToParent, hooks, noun, parentLoc) {
441− this.name = name;
442− this.label = label;
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 ) {
450− this.noun = noun;
451− }
452− else {
453− this.noun = noun.head;
454− this.noun.mug();
455− }
456− for ( var k in hooks ) {
457− if ( hooks.hasOwnProperty(k) ) {
458− this.axisToName[hooks[k].shortCode()] = k;
459− }
460− }
461− this.jets = {};
462− var drivers = context.drivers[label];
463− if ( drivers && drivers.length > 0 ) {
464− for ( var i = 0; i < drivers.length; ++i ) {
465− var d = drivers[i];
466− if ( d instanceof AxisArm ) {
467− this.jets[d.axis.mas().shortCode()] = d.fn;
468− }
469− else {
470− this.jets[nameToAxis[d.name].mas().shortCode()] = d.fn;
471− }
472− }
473− }
474− this.fine = genFine(this);
475−}
476−
477−function Clue(name, parentAxis, hooks) {
478− this.name = name;
479− this.parentAxis = parentAxis;
480− this.hooks = hooks;
481−}
482−
483−function JetDriver(label, fn) {
484− this.label = label;
485− this.fn = fn;
486−}
487−
488−function AxisArm(label, axis, fn) {
489− JetDriver.call(this, label, fn);
490− this.axis = axis;
491−}
492−AxisArm.prototype = Object.create(JetDriver.prototype);
493−AxisArm.prototype.constructor = AxisArm;
494−
495−function NamedArm(label, name, fn) {
496− JetDriver.call(this, label, fn);
497− this.name = name;
498−}
499−NamedArm.prototype = Object.create(JetDriver.prototype);
500−NamedArm.prototype.constructor = NamedArm;
501−
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)];
508− }
509− else {
510− var all = [];
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]));
516− }
517− }
518− out[labl] = all;
519− }
520− if ( children ) {
521− for ( var i = 0; i < children.length; ++i ) {
522− collectFromCore(labl, children[i], out);
523− }
524− }
525−}
526−
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;
532− this.drivers = {};
533− if ( drivers ) {
534− collectFromCore('', drivers, this.drivers);
535− }
536−}
537−
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);
542−};
543−
544−Context.prototype.trampoline = function(tgt, bus) {
545− return new Trampoline(tgt, bus);
546−};
547−
548−Context.prototype.isTrampoline = function(a) {
549− return (a instanceof Trampoline);
550−};
551−
552−Context.prototype.compile = function(cell) {
553− var i = 0;
554− var fresh = function() {
555− return "v" + ++i;
556− };
557− var body = new Block();
558− var constants = [];
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);
563−};
564−
565−Context.prototype.nock = function(subject, formula) {
566− var product, target;
567− if ( !formula.hasOwnProperty("target") ) {
568− this.compile(formula);
569− }
570− target = formula.target;
571− while ( true ) {
572− product = target(subject);
573− if ( product instanceof Trampoline ) {
574− subject = product.subject;
575− target = product.target;
576− }
577− else {
578− return product;
579− }
580− }
581−};
582−
583−Context.prototype.getMemo = function(key) {
584− return this.memo.get(key);
585−}
586−
587−Context.prototype.putMemo = function(key, val) {
588− this.memo.insert(key, val);
589−};
590−
591−Context.prototype.stackPush = function(item) {
592− this.tax = new Cell(item, this.tax);
593−};
594−
595−Context.prototype.stackPop = function() {
596− this.tax = this.tax.tail;
597−}
598−
599−Context.prototype.slog = function(item) {
600− // TODO: don't rewrite ++wash again, just call the kernel
601− console.log(item);
602−};
603−
604−function chum(n) {
605− if ( n.deep ) {
606− return Atom.cordToString(n.head) + n.tail.number.shortValue().toString(10);
607− }
608− else {
609− return Atom.cordToString(n);
610− }
611−}
612−
613−var ten = noun.dwim(10);
614−function skipHints(formula) {
615− while ( true ) {
616− if ( formula.deep ) {
617− if ( ten.equals(formula.head) ) {
618− formula = formula.tail.tail;
619− continue;
620− }
621− }
622− return formula;
623− }
624−}
625−
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) ) {
630− return zero;
631− }
632− else if ( !zero.equals(f.head) ) {
633− throw new Error("weird formula head");
634− }
635− else if ( 3 != f.tail.cap().valueOf() ) {
636− throw new Error("weird parent axis");
637− }
638− return f.tail;
639−}
640−
641−var nine = noun.dwim(9), constant_frag = noun.dwim(0,1);
642−function parseHookAxis(nock) {
643− var f = skipHints(nock),
644− op = f.head;
645− if ( !op.deep ) {
646− if ( zero.equals(op) ) {
647− if ( !f.tail.deep ) {
648− return f.tail;
649− }
650− }
651− else if ( nine.equals(op) ) {
652− var rest = f.tail;
653− if ( !rest.head.deep && constant_frag.equals(rest.tail) ) {
654− return rest.head;
655− }
656− }
657− }
658− return null;
659−}
660−
661−function parseHooks(noun) {
662− var o = {};
663− list.forEach(noun, function(c) {
664− var term = Atom.cordToString(c.head),
665− axis = parseHookAxis(c.tail);
666− if ( null != axis ) {
667− o[term] = axis;
668− }
669− });
670− return o;
671−}
672−
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);
681− }
682− return clue;
683−}
684−
685−Context.prototype.register = function(core, raw) {
686− var bat = core.head;
687− var loc = this.dash.get(bat);
688− if ( undefined === loc ) {
689− try {
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);
693− }
694− else {
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);
700− }
701− else {
702− var label = parentLoc.label + "/" + clue.name;
703− loc = new Location(this, clue.name, label, clue.parentAxis, clue.hooks, core, parentLoc);
704− }
705− }
706− bat.loc = loc;
707− this.dash.insert(bat, loc);
708− }
709− catch (e) {
710− console.log(e);
711− }
712− }
713−};
714−
715−export default {
716− Context: Context,
717−};