Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Download
81146 views
1
// Generated by CoffeeScript 1.6.3
2
(function() {
3
var Access, Arr, Assign, Base, Block, Call, Class, Closure, Code, CodeFragment, Comment, Existence, Extends, For, IDENTIFIER, IDENTIFIER_STR, IS_STRING, If, In, Index, LEVEL_ACCESS, LEVEL_COND, LEVEL_LIST, LEVEL_OP, LEVEL_PAREN, LEVEL_TOP, Literal, METHOD_DEF, NEGATE, NO, Obj, Op, Param, Parens, RESERVED, Range, Return, SIMPLENUM, STRICT_PROSCRIBED, Scope, Slice, Splat, Switch, TAB, THIS, Throw, Try, UTILITIES, Value, While, YES, addLocationDataFn, compact, del, ends, extend, flatten, fragmentsToText, last, locationDataToString, merge, multident, some, starts, throwSyntaxError, unfoldSoak, utility, _ref, _ref1, _ref2, _ref3,
4
__hasProp = {}.hasOwnProperty,
5
__extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; },
6
__indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; },
7
__slice = [].slice;
8
9
Error.stackTraceLimit = Infinity;
10
11
Scope = require('./scope').Scope;
12
13
_ref = require('./lexer'), RESERVED = _ref.RESERVED, STRICT_PROSCRIBED = _ref.STRICT_PROSCRIBED;
14
15
_ref1 = require('./helpers'), compact = _ref1.compact, flatten = _ref1.flatten, extend = _ref1.extend, merge = _ref1.merge, del = _ref1.del, starts = _ref1.starts, ends = _ref1.ends, last = _ref1.last, some = _ref1.some, addLocationDataFn = _ref1.addLocationDataFn, locationDataToString = _ref1.locationDataToString, throwSyntaxError = _ref1.throwSyntaxError;
16
17
exports.extend = extend;
18
19
exports.addLocationDataFn = addLocationDataFn;
20
21
YES = function() {
22
return true;
23
};
24
25
NO = function() {
26
return false;
27
};
28
29
THIS = function() {
30
return this;
31
};
32
33
NEGATE = function() {
34
this.negated = !this.negated;
35
return this;
36
};
37
38
exports.CodeFragment = CodeFragment = (function() {
39
function CodeFragment(parent, code) {
40
var _ref2;
41
this.code = "" + code;
42
this.locationData = parent != null ? parent.locationData : void 0;
43
this.type = (parent != null ? (_ref2 = parent.constructor) != null ? _ref2.name : void 0 : void 0) || 'unknown';
44
}
45
46
CodeFragment.prototype.toString = function() {
47
return "" + this.code + (this.locationData ? ": " + locationDataToString(this.locationData) : '');
48
};
49
50
return CodeFragment;
51
52
})();
53
54
fragmentsToText = function(fragments) {
55
var fragment;
56
return ((function() {
57
var _i, _len, _results;
58
_results = [];
59
for (_i = 0, _len = fragments.length; _i < _len; _i++) {
60
fragment = fragments[_i];
61
_results.push(fragment.code);
62
}
63
return _results;
64
})()).join('');
65
};
66
67
exports.Base = Base = (function() {
68
function Base() {}
69
70
Base.prototype.compile = function(o, lvl) {
71
return fragmentsToText(this.compileToFragments(o, lvl));
72
};
73
74
Base.prototype.compileToFragments = function(o, lvl) {
75
var node;
76
o = extend({}, o);
77
if (lvl) {
78
o.level = lvl;
79
}
80
node = this.unfoldSoak(o) || this;
81
node.tab = o.indent;
82
if (o.level === LEVEL_TOP || !node.isStatement(o)) {
83
return node.compileNode(o);
84
} else {
85
return node.compileClosure(o);
86
}
87
};
88
89
Base.prototype.compileClosure = function(o) {
90
var jumpNode;
91
if (jumpNode = this.jumps()) {
92
jumpNode.error('cannot use a pure statement in an expression');
93
}
94
o.sharedScope = true;
95
return Closure.wrap(this).compileNode(o);
96
};
97
98
Base.prototype.cache = function(o, level, reused) {
99
var ref, sub;
100
if (!this.isComplex()) {
101
ref = level ? this.compileToFragments(o, level) : this;
102
return [ref, ref];
103
} else {
104
ref = new Literal(reused || o.scope.freeVariable('ref'));
105
sub = new Assign(ref, this);
106
if (level) {
107
return [sub.compileToFragments(o, level), [this.makeCode(ref.value)]];
108
} else {
109
return [sub, ref];
110
}
111
}
112
};
113
114
Base.prototype.cacheToCodeFragments = function(cacheValues) {
115
return [fragmentsToText(cacheValues[0]), fragmentsToText(cacheValues[1])];
116
};
117
118
Base.prototype.makeReturn = function(res) {
119
var me;
120
me = this.unwrapAll();
121
if (res) {
122
return new Call(new Literal("" + res + ".push"), [me]);
123
} else {
124
return new Return(me);
125
}
126
};
127
128
Base.prototype.contains = function(pred) {
129
var node;
130
node = void 0;
131
this.traverseChildren(false, function(n) {
132
if (pred(n)) {
133
node = n;
134
return false;
135
}
136
});
137
return node;
138
};
139
140
Base.prototype.lastNonComment = function(list) {
141
var i;
142
i = list.length;
143
while (i--) {
144
if (!(list[i] instanceof Comment)) {
145
return list[i];
146
}
147
}
148
return null;
149
};
150
151
Base.prototype.toString = function(idt, name) {
152
var tree;
153
if (idt == null) {
154
idt = '';
155
}
156
if (name == null) {
157
name = this.constructor.name;
158
}
159
tree = '\n' + idt + name;
160
if (this.soak) {
161
tree += '?';
162
}
163
this.eachChild(function(node) {
164
return tree += node.toString(idt + TAB);
165
});
166
return tree;
167
};
168
169
Base.prototype.eachChild = function(func) {
170
var attr, child, _i, _j, _len, _len1, _ref2, _ref3;
171
if (!this.children) {
172
return this;
173
}
174
_ref2 = this.children;
175
for (_i = 0, _len = _ref2.length; _i < _len; _i++) {
176
attr = _ref2[_i];
177
if (this[attr]) {
178
_ref3 = flatten([this[attr]]);
179
for (_j = 0, _len1 = _ref3.length; _j < _len1; _j++) {
180
child = _ref3[_j];
181
if (func(child) === false) {
182
return this;
183
}
184
}
185
}
186
}
187
return this;
188
};
189
190
Base.prototype.traverseChildren = function(crossScope, func) {
191
return this.eachChild(function(child) {
192
var recur;
193
recur = func(child);
194
if (recur !== false) {
195
return child.traverseChildren(crossScope, func);
196
}
197
});
198
};
199
200
Base.prototype.invert = function() {
201
return new Op('!', this);
202
};
203
204
Base.prototype.unwrapAll = function() {
205
var node;
206
node = this;
207
while (node !== (node = node.unwrap())) {
208
continue;
209
}
210
return node;
211
};
212
213
Base.prototype.children = [];
214
215
Base.prototype.isStatement = NO;
216
217
Base.prototype.jumps = NO;
218
219
Base.prototype.isComplex = YES;
220
221
Base.prototype.isChainable = NO;
222
223
Base.prototype.isAssignable = NO;
224
225
Base.prototype.unwrap = THIS;
226
227
Base.prototype.unfoldSoak = NO;
228
229
Base.prototype.assigns = NO;
230
231
Base.prototype.updateLocationDataIfMissing = function(locationData) {
232
this.locationData || (this.locationData = locationData);
233
return this.eachChild(function(child) {
234
return child.updateLocationDataIfMissing(locationData);
235
});
236
};
237
238
Base.prototype.error = function(message) {
239
return throwSyntaxError(message, this.locationData);
240
};
241
242
Base.prototype.makeCode = function(code) {
243
return new CodeFragment(this, code);
244
};
245
246
Base.prototype.wrapInBraces = function(fragments) {
247
return [].concat(this.makeCode('('), fragments, this.makeCode(')'));
248
};
249
250
Base.prototype.joinFragmentArrays = function(fragmentsList, joinStr) {
251
var answer, fragments, i, _i, _len;
252
answer = [];
253
for (i = _i = 0, _len = fragmentsList.length; _i < _len; i = ++_i) {
254
fragments = fragmentsList[i];
255
if (i) {
256
answer.push(this.makeCode(joinStr));
257
}
258
answer = answer.concat(fragments);
259
}
260
return answer;
261
};
262
263
return Base;
264
265
})();
266
267
exports.Block = Block = (function(_super) {
268
__extends(Block, _super);
269
270
function Block(nodes) {
271
this.expressions = compact(flatten(nodes || []));
272
}
273
274
Block.prototype.children = ['expressions'];
275
276
Block.prototype.push = function(node) {
277
this.expressions.push(node);
278
return this;
279
};
280
281
Block.prototype.pop = function() {
282
return this.expressions.pop();
283
};
284
285
Block.prototype.unshift = function(node) {
286
this.expressions.unshift(node);
287
return this;
288
};
289
290
Block.prototype.unwrap = function() {
291
if (this.expressions.length === 1) {
292
return this.expressions[0];
293
} else {
294
return this;
295
}
296
};
297
298
Block.prototype.isEmpty = function() {
299
return !this.expressions.length;
300
};
301
302
Block.prototype.isStatement = function(o) {
303
var exp, _i, _len, _ref2;
304
_ref2 = this.expressions;
305
for (_i = 0, _len = _ref2.length; _i < _len; _i++) {
306
exp = _ref2[_i];
307
if (exp.isStatement(o)) {
308
return true;
309
}
310
}
311
return false;
312
};
313
314
Block.prototype.jumps = function(o) {
315
var exp, _i, _len, _ref2;
316
_ref2 = this.expressions;
317
for (_i = 0, _len = _ref2.length; _i < _len; _i++) {
318
exp = _ref2[_i];
319
if (exp.jumps(o)) {
320
return exp;
321
}
322
}
323
};
324
325
Block.prototype.makeReturn = function(res) {
326
var expr, len;
327
len = this.expressions.length;
328
while (len--) {
329
expr = this.expressions[len];
330
if (!(expr instanceof Comment)) {
331
this.expressions[len] = expr.makeReturn(res);
332
if (expr instanceof Return && !expr.expression) {
333
this.expressions.splice(len, 1);
334
}
335
break;
336
}
337
}
338
return this;
339
};
340
341
Block.prototype.compileToFragments = function(o, level) {
342
if (o == null) {
343
o = {};
344
}
345
if (o.scope) {
346
return Block.__super__.compileToFragments.call(this, o, level);
347
} else {
348
return this.compileRoot(o);
349
}
350
};
351
352
Block.prototype.compileNode = function(o) {
353
var answer, compiledNodes, fragments, index, node, top, _i, _len, _ref2;
354
this.tab = o.indent;
355
top = o.level === LEVEL_TOP;
356
compiledNodes = [];
357
_ref2 = this.expressions;
358
for (index = _i = 0, _len = _ref2.length; _i < _len; index = ++_i) {
359
node = _ref2[index];
360
node = node.unwrapAll();
361
node = node.unfoldSoak(o) || node;
362
if (node instanceof Block) {
363
compiledNodes.push(node.compileNode(o));
364
} else if (top) {
365
node.front = true;
366
fragments = node.compileToFragments(o);
367
if (!node.isStatement(o)) {
368
fragments.unshift(this.makeCode("" + this.tab));
369
fragments.push(this.makeCode(";"));
370
}
371
compiledNodes.push(fragments);
372
} else {
373
compiledNodes.push(node.compileToFragments(o, LEVEL_LIST));
374
}
375
}
376
if (top) {
377
if (this.spaced) {
378
return [].concat(this.joinFragmentArrays(compiledNodes, '\n\n'), this.makeCode("\n"));
379
} else {
380
return this.joinFragmentArrays(compiledNodes, '\n');
381
}
382
}
383
if (compiledNodes.length) {
384
answer = this.joinFragmentArrays(compiledNodes, ', ');
385
} else {
386
answer = [this.makeCode("void 0")];
387
}
388
if (compiledNodes.length > 1 && o.level >= LEVEL_LIST) {
389
return this.wrapInBraces(answer);
390
} else {
391
return answer;
392
}
393
};
394
395
Block.prototype.compileRoot = function(o) {
396
var exp, fragments, i, name, prelude, preludeExps, rest, _i, _len, _ref2;
397
o.indent = o.bare ? '' : TAB;
398
o.level = LEVEL_TOP;
399
this.spaced = true;
400
o.scope = new Scope(null, this, null);
401
_ref2 = o.locals || [];
402
for (_i = 0, _len = _ref2.length; _i < _len; _i++) {
403
name = _ref2[_i];
404
o.scope.parameter(name);
405
}
406
prelude = [];
407
if (!o.bare) {
408
preludeExps = (function() {
409
var _j, _len1, _ref3, _results;
410
_ref3 = this.expressions;
411
_results = [];
412
for (i = _j = 0, _len1 = _ref3.length; _j < _len1; i = ++_j) {
413
exp = _ref3[i];
414
if (!(exp.unwrap() instanceof Comment)) {
415
break;
416
}
417
_results.push(exp);
418
}
419
return _results;
420
}).call(this);
421
rest = this.expressions.slice(preludeExps.length);
422
this.expressions = preludeExps;
423
if (preludeExps.length) {
424
prelude = this.compileNode(merge(o, {
425
indent: ''
426
}));
427
prelude.push(this.makeCode("\n"));
428
}
429
this.expressions = rest;
430
}
431
fragments = this.compileWithDeclarations(o);
432
if (o.bare) {
433
return fragments;
434
}
435
return [].concat(prelude, this.makeCode("(function() {\n"), fragments, this.makeCode("\n}).call(this);\n"));
436
};
437
438
Block.prototype.compileWithDeclarations = function(o) {
439
var assigns, declars, exp, fragments, i, post, rest, scope, spaced, _i, _len, _ref2, _ref3, _ref4;
440
fragments = [];
441
post = [];
442
_ref2 = this.expressions;
443
for (i = _i = 0, _len = _ref2.length; _i < _len; i = ++_i) {
444
exp = _ref2[i];
445
exp = exp.unwrap();
446
if (!(exp instanceof Comment || exp instanceof Literal)) {
447
break;
448
}
449
}
450
o = merge(o, {
451
level: LEVEL_TOP
452
});
453
if (i) {
454
rest = this.expressions.splice(i, 9e9);
455
_ref3 = [this.spaced, false], spaced = _ref3[0], this.spaced = _ref3[1];
456
_ref4 = [this.compileNode(o), spaced], fragments = _ref4[0], this.spaced = _ref4[1];
457
this.expressions = rest;
458
}
459
post = this.compileNode(o);
460
scope = o.scope;
461
if (scope.expressions === this) {
462
declars = o.scope.hasDeclarations();
463
assigns = scope.hasAssignments;
464
if (declars || assigns) {
465
if (i) {
466
fragments.push(this.makeCode('\n'));
467
}
468
fragments.push(this.makeCode("" + this.tab + "var "));
469
if (declars) {
470
fragments.push(this.makeCode(scope.declaredVariables().join(', ')));
471
}
472
if (assigns) {
473
if (declars) {
474
fragments.push(this.makeCode(",\n" + (this.tab + TAB)));
475
}
476
fragments.push(this.makeCode(scope.assignedVariables().join(",\n" + (this.tab + TAB))));
477
}
478
fragments.push(this.makeCode(";\n" + (this.spaced ? '\n' : '')));
479
} else if (fragments.length && post.length) {
480
fragments.push(this.makeCode("\n"));
481
}
482
}
483
return fragments.concat(post);
484
};
485
486
Block.wrap = function(nodes) {
487
if (nodes.length === 1 && nodes[0] instanceof Block) {
488
return nodes[0];
489
}
490
return new Block(nodes);
491
};
492
493
return Block;
494
495
})(Base);
496
497
exports.Literal = Literal = (function(_super) {
498
__extends(Literal, _super);
499
500
function Literal(value) {
501
this.value = value;
502
}
503
504
Literal.prototype.makeReturn = function() {
505
if (this.isStatement()) {
506
return this;
507
} else {
508
return Literal.__super__.makeReturn.apply(this, arguments);
509
}
510
};
511
512
Literal.prototype.isAssignable = function() {
513
return IDENTIFIER.test(this.value);
514
};
515
516
Literal.prototype.isStatement = function() {
517
var _ref2;
518
return (_ref2 = this.value) === 'break' || _ref2 === 'continue' || _ref2 === 'debugger';
519
};
520
521
Literal.prototype.isComplex = NO;
522
523
Literal.prototype.assigns = function(name) {
524
return name === this.value;
525
};
526
527
Literal.prototype.jumps = function(o) {
528
if (this.value === 'break' && !((o != null ? o.loop : void 0) || (o != null ? o.block : void 0))) {
529
return this;
530
}
531
if (this.value === 'continue' && !(o != null ? o.loop : void 0)) {
532
return this;
533
}
534
};
535
536
Literal.prototype.compileNode = function(o) {
537
var answer, code, _ref2;
538
code = this.value === 'this' ? ((_ref2 = o.scope.method) != null ? _ref2.bound : void 0) ? o.scope.method.context : this.value : this.value.reserved ? "\"" + this.value + "\"" : this.value;
539
answer = this.isStatement() ? "" + this.tab + code + ";" : code;
540
return [this.makeCode(answer)];
541
};
542
543
Literal.prototype.toString = function() {
544
return ' "' + this.value + '"';
545
};
546
547
return Literal;
548
549
})(Base);
550
551
exports.Undefined = (function(_super) {
552
__extends(Undefined, _super);
553
554
function Undefined() {
555
_ref2 = Undefined.__super__.constructor.apply(this, arguments);
556
return _ref2;
557
}
558
559
Undefined.prototype.isAssignable = NO;
560
561
Undefined.prototype.isComplex = NO;
562
563
Undefined.prototype.compileNode = function(o) {
564
return [this.makeCode(o.level >= LEVEL_ACCESS ? '(void 0)' : 'void 0')];
565
};
566
567
return Undefined;
568
569
})(Base);
570
571
exports.Null = (function(_super) {
572
__extends(Null, _super);
573
574
function Null() {
575
_ref3 = Null.__super__.constructor.apply(this, arguments);
576
return _ref3;
577
}
578
579
Null.prototype.isAssignable = NO;
580
581
Null.prototype.isComplex = NO;
582
583
Null.prototype.compileNode = function() {
584
return [this.makeCode("null")];
585
};
586
587
return Null;
588
589
})(Base);
590
591
exports.Bool = (function(_super) {
592
__extends(Bool, _super);
593
594
Bool.prototype.isAssignable = NO;
595
596
Bool.prototype.isComplex = NO;
597
598
Bool.prototype.compileNode = function() {
599
return [this.makeCode(this.val)];
600
};
601
602
function Bool(val) {
603
this.val = val;
604
}
605
606
return Bool;
607
608
})(Base);
609
610
exports.Return = Return = (function(_super) {
611
__extends(Return, _super);
612
613
function Return(expr) {
614
if (expr && !expr.unwrap().isUndefined) {
615
this.expression = expr;
616
}
617
}
618
619
Return.prototype.children = ['expression'];
620
621
Return.prototype.isStatement = YES;
622
623
Return.prototype.makeReturn = THIS;
624
625
Return.prototype.jumps = THIS;
626
627
Return.prototype.compileToFragments = function(o, level) {
628
var expr, _ref4;
629
expr = (_ref4 = this.expression) != null ? _ref4.makeReturn() : void 0;
630
if (expr && !(expr instanceof Return)) {
631
return expr.compileToFragments(o, level);
632
} else {
633
return Return.__super__.compileToFragments.call(this, o, level);
634
}
635
};
636
637
Return.prototype.compileNode = function(o) {
638
var answer;
639
answer = [];
640
answer.push(this.makeCode(this.tab + ("return" + (this.expression ? " " : ""))));
641
if (this.expression) {
642
answer = answer.concat(this.expression.compileToFragments(o, LEVEL_PAREN));
643
}
644
answer.push(this.makeCode(";"));
645
return answer;
646
};
647
648
return Return;
649
650
})(Base);
651
652
exports.Value = Value = (function(_super) {
653
__extends(Value, _super);
654
655
function Value(base, props, tag) {
656
if (!props && base instanceof Value) {
657
return base;
658
}
659
this.base = base;
660
this.properties = props || [];
661
if (tag) {
662
this[tag] = true;
663
}
664
return this;
665
}
666
667
Value.prototype.children = ['base', 'properties'];
668
669
Value.prototype.add = function(props) {
670
this.properties = this.properties.concat(props);
671
return this;
672
};
673
674
Value.prototype.hasProperties = function() {
675
return !!this.properties.length;
676
};
677
678
Value.prototype.isArray = function() {
679
return !this.properties.length && this.base instanceof Arr;
680
};
681
682
Value.prototype.isComplex = function() {
683
return this.hasProperties() || this.base.isComplex();
684
};
685
686
Value.prototype.isAssignable = function() {
687
return this.hasProperties() || this.base.isAssignable();
688
};
689
690
Value.prototype.isSimpleNumber = function() {
691
return this.base instanceof Literal && SIMPLENUM.test(this.base.value);
692
};
693
694
Value.prototype.isString = function() {
695
return this.base instanceof Literal && IS_STRING.test(this.base.value);
696
};
697
698
Value.prototype.isAtomic = function() {
699
var node, _i, _len, _ref4;
700
_ref4 = this.properties.concat(this.base);
701
for (_i = 0, _len = _ref4.length; _i < _len; _i++) {
702
node = _ref4[_i];
703
if (node.soak || node instanceof Call) {
704
return false;
705
}
706
}
707
return true;
708
};
709
710
Value.prototype.isStatement = function(o) {
711
return !this.properties.length && this.base.isStatement(o);
712
};
713
714
Value.prototype.assigns = function(name) {
715
return !this.properties.length && this.base.assigns(name);
716
};
717
718
Value.prototype.jumps = function(o) {
719
return !this.properties.length && this.base.jumps(o);
720
};
721
722
Value.prototype.isObject = function(onlyGenerated) {
723
if (this.properties.length) {
724
return false;
725
}
726
return (this.base instanceof Obj) && (!onlyGenerated || this.base.generated);
727
};
728
729
Value.prototype.isSplice = function() {
730
return last(this.properties) instanceof Slice;
731
};
732
733
Value.prototype.unwrap = function() {
734
if (this.properties.length) {
735
return this;
736
} else {
737
return this.base;
738
}
739
};
740
741
Value.prototype.cacheReference = function(o) {
742
var base, bref, name, nref;
743
name = last(this.properties);
744
if (this.properties.length < 2 && !this.base.isComplex() && !(name != null ? name.isComplex() : void 0)) {
745
return [this, this];
746
}
747
base = new Value(this.base, this.properties.slice(0, -1));
748
if (base.isComplex()) {
749
bref = new Literal(o.scope.freeVariable('base'));
750
base = new Value(new Parens(new Assign(bref, base)));
751
}
752
if (!name) {
753
return [base, bref];
754
}
755
if (name.isComplex()) {
756
nref = new Literal(o.scope.freeVariable('name'));
757
name = new Index(new Assign(nref, name.index));
758
nref = new Index(nref);
759
}
760
return [base.add(name), new Value(bref || base.base, [nref || name])];
761
};
762
763
Value.prototype.compileNode = function(o) {
764
var fragments, prop, props, _i, _len;
765
this.base.front = this.front;
766
props = this.properties;
767
fragments = this.base.compileToFragments(o, (props.length ? LEVEL_ACCESS : null));
768
if ((this.base instanceof Parens || props.length) && SIMPLENUM.test(fragmentsToText(fragments))) {
769
fragments.push(this.makeCode('.'));
770
}
771
for (_i = 0, _len = props.length; _i < _len; _i++) {
772
prop = props[_i];
773
fragments.push.apply(fragments, prop.compileToFragments(o));
774
}
775
return fragments;
776
};
777
778
Value.prototype.unfoldSoak = function(o) {
779
var _this = this;
780
return this.unfoldedSoak != null ? this.unfoldedSoak : this.unfoldedSoak = (function() {
781
var fst, i, ifn, prop, ref, snd, _i, _len, _ref4, _ref5;
782
if (ifn = _this.base.unfoldSoak(o)) {
783
(_ref4 = ifn.body.properties).push.apply(_ref4, _this.properties);
784
return ifn;
785
}
786
_ref5 = _this.properties;
787
for (i = _i = 0, _len = _ref5.length; _i < _len; i = ++_i) {
788
prop = _ref5[i];
789
if (!prop.soak) {
790
continue;
791
}
792
prop.soak = false;
793
fst = new Value(_this.base, _this.properties.slice(0, i));
794
snd = new Value(_this.base, _this.properties.slice(i));
795
if (fst.isComplex()) {
796
ref = new Literal(o.scope.freeVariable('ref'));
797
fst = new Parens(new Assign(ref, fst));
798
snd.base = ref;
799
}
800
return new If(new Existence(fst), snd, {
801
soak: true
802
});
803
}
804
return false;
805
})();
806
};
807
808
return Value;
809
810
})(Base);
811
812
exports.Comment = Comment = (function(_super) {
813
__extends(Comment, _super);
814
815
function Comment(comment) {
816
this.comment = comment;
817
}
818
819
Comment.prototype.isStatement = YES;
820
821
Comment.prototype.makeReturn = THIS;
822
823
Comment.prototype.compileNode = function(o, level) {
824
var code;
825
code = "/*" + (multident(this.comment, this.tab)) + (__indexOf.call(this.comment, '\n') >= 0 ? "\n" + this.tab : '') + "*/\n";
826
if ((level || o.level) === LEVEL_TOP) {
827
code = o.indent + code;
828
}
829
return [this.makeCode(code)];
830
};
831
832
return Comment;
833
834
})(Base);
835
836
exports.Call = Call = (function(_super) {
837
__extends(Call, _super);
838
839
function Call(variable, args, soak) {
840
this.args = args != null ? args : [];
841
this.soak = soak;
842
this.isNew = false;
843
this.isSuper = variable === 'super';
844
this.variable = this.isSuper ? null : variable;
845
}
846
847
Call.prototype.children = ['variable', 'args'];
848
849
Call.prototype.newInstance = function() {
850
var base, _ref4;
851
base = ((_ref4 = this.variable) != null ? _ref4.base : void 0) || this.variable;
852
if (base instanceof Call && !base.isNew) {
853
base.newInstance();
854
} else {
855
this.isNew = true;
856
}
857
return this;
858
};
859
860
Call.prototype.superReference = function(o) {
861
var accesses, method;
862
method = o.scope.namedMethod();
863
if (method != null ? method.klass : void 0) {
864
accesses = [new Access(new Literal('__super__'))];
865
if (method["static"]) {
866
accesses.push(new Access(new Literal('constructor')));
867
}
868
accesses.push(new Access(new Literal(method.name)));
869
return (new Value(new Literal(method.klass), accesses)).compile(o);
870
} else if (method != null ? method.ctor : void 0) {
871
return "" + method.name + ".__super__.constructor";
872
} else {
873
return this.error('cannot call super outside of an instance method.');
874
}
875
};
876
877
Call.prototype.superThis = function(o) {
878
var method;
879
method = o.scope.method;
880
return (method && !method.klass && method.context) || "this";
881
};
882
883
Call.prototype.unfoldSoak = function(o) {
884
var call, ifn, left, list, rite, _i, _len, _ref4, _ref5;
885
if (this.soak) {
886
if (this.variable) {
887
if (ifn = unfoldSoak(o, this, 'variable')) {
888
return ifn;
889
}
890
_ref4 = new Value(this.variable).cacheReference(o), left = _ref4[0], rite = _ref4[1];
891
} else {
892
left = new Literal(this.superReference(o));
893
rite = new Value(left);
894
}
895
rite = new Call(rite, this.args);
896
rite.isNew = this.isNew;
897
left = new Literal("typeof " + (left.compile(o)) + " === \"function\"");
898
return new If(left, new Value(rite), {
899
soak: true
900
});
901
}
902
call = this;
903
list = [];
904
while (true) {
905
if (call.variable instanceof Call) {
906
list.push(call);
907
call = call.variable;
908
continue;
909
}
910
if (!(call.variable instanceof Value)) {
911
break;
912
}
913
list.push(call);
914
if (!((call = call.variable.base) instanceof Call)) {
915
break;
916
}
917
}
918
_ref5 = list.reverse();
919
for (_i = 0, _len = _ref5.length; _i < _len; _i++) {
920
call = _ref5[_i];
921
if (ifn) {
922
if (call.variable instanceof Call) {
923
call.variable = ifn;
924
} else {
925
call.variable.base = ifn;
926
}
927
}
928
ifn = unfoldSoak(o, call, 'variable');
929
}
930
return ifn;
931
};
932
933
Call.prototype.compileNode = function(o) {
934
var arg, argIndex, compiledArgs, compiledArray, fragments, preface, _i, _len, _ref4, _ref5;
935
if ((_ref4 = this.variable) != null) {
936
_ref4.front = this.front;
937
}
938
compiledArray = Splat.compileSplattedArray(o, this.args, true);
939
if (compiledArray.length) {
940
return this.compileSplat(o, compiledArray);
941
}
942
compiledArgs = [];
943
_ref5 = this.args;
944
for (argIndex = _i = 0, _len = _ref5.length; _i < _len; argIndex = ++_i) {
945
arg = _ref5[argIndex];
946
if (argIndex) {
947
compiledArgs.push(this.makeCode(", "));
948
}
949
compiledArgs.push.apply(compiledArgs, arg.compileToFragments(o, LEVEL_LIST));
950
}
951
fragments = [];
952
if (this.isSuper) {
953
preface = this.superReference(o) + (".call(" + (this.superThis(o)));
954
if (compiledArgs.length) {
955
preface += ", ";
956
}
957
fragments.push(this.makeCode(preface));
958
} else {
959
if (this.isNew) {
960
fragments.push(this.makeCode('new '));
961
}
962
fragments.push.apply(fragments, this.variable.compileToFragments(o, LEVEL_ACCESS));
963
fragments.push(this.makeCode("("));
964
}
965
fragments.push.apply(fragments, compiledArgs);
966
fragments.push(this.makeCode(")"));
967
return fragments;
968
};
969
970
Call.prototype.compileSplat = function(o, splatArgs) {
971
var answer, base, fun, idt, name, ref;
972
if (this.isSuper) {
973
return [].concat(this.makeCode("" + (this.superReference(o)) + ".apply(" + (this.superThis(o)) + ", "), splatArgs, this.makeCode(")"));
974
}
975
if (this.isNew) {
976
idt = this.tab + TAB;
977
return [].concat(this.makeCode("(function(func, args, ctor) {\n" + idt + "ctor.prototype = func.prototype;\n" + idt + "var child = new ctor, result = func.apply(child, args);\n" + idt + "return Object(result) === result ? result : child;\n" + this.tab + "})("), this.variable.compileToFragments(o, LEVEL_LIST), this.makeCode(", "), splatArgs, this.makeCode(", function(){})"));
978
}
979
answer = [];
980
base = new Value(this.variable);
981
if ((name = base.properties.pop()) && base.isComplex()) {
982
ref = o.scope.freeVariable('ref');
983
answer = answer.concat(this.makeCode("(" + ref + " = "), base.compileToFragments(o, LEVEL_LIST), this.makeCode(")"), name.compileToFragments(o));
984
} else {
985
fun = base.compileToFragments(o, LEVEL_ACCESS);
986
if (SIMPLENUM.test(fragmentsToText(fun))) {
987
fun = this.wrapInBraces(fun);
988
}
989
if (name) {
990
ref = fragmentsToText(fun);
991
fun.push.apply(fun, name.compileToFragments(o));
992
} else {
993
ref = 'null';
994
}
995
answer = answer.concat(fun);
996
}
997
return answer = answer.concat(this.makeCode(".apply(" + ref + ", "), splatArgs, this.makeCode(")"));
998
};
999
1000
return Call;
1001
1002
})(Base);
1003
1004
exports.Extends = Extends = (function(_super) {
1005
__extends(Extends, _super);
1006
1007
function Extends(child, parent) {
1008
this.child = child;
1009
this.parent = parent;
1010
}
1011
1012
Extends.prototype.children = ['child', 'parent'];
1013
1014
Extends.prototype.compileToFragments = function(o) {
1015
return new Call(new Value(new Literal(utility('extends'))), [this.child, this.parent]).compileToFragments(o);
1016
};
1017
1018
return Extends;
1019
1020
})(Base);
1021
1022
exports.Access = Access = (function(_super) {
1023
__extends(Access, _super);
1024
1025
function Access(name, tag) {
1026
this.name = name;
1027
this.name.asKey = true;
1028
this.soak = tag === 'soak';
1029
}
1030
1031
Access.prototype.children = ['name'];
1032
1033
Access.prototype.compileToFragments = function(o) {
1034
var name;
1035
name = this.name.compileToFragments(o);
1036
if (IDENTIFIER.test(fragmentsToText(name))) {
1037
name.unshift(this.makeCode("."));
1038
} else {
1039
name.unshift(this.makeCode("["));
1040
name.push(this.makeCode("]"));
1041
}
1042
return name;
1043
};
1044
1045
Access.prototype.isComplex = NO;
1046
1047
return Access;
1048
1049
})(Base);
1050
1051
exports.Index = Index = (function(_super) {
1052
__extends(Index, _super);
1053
1054
function Index(index) {
1055
this.index = index;
1056
}
1057
1058
Index.prototype.children = ['index'];
1059
1060
Index.prototype.compileToFragments = function(o) {
1061
return [].concat(this.makeCode("["), this.index.compileToFragments(o, LEVEL_PAREN), this.makeCode("]"));
1062
};
1063
1064
Index.prototype.isComplex = function() {
1065
return this.index.isComplex();
1066
};
1067
1068
return Index;
1069
1070
})(Base);
1071
1072
exports.Range = Range = (function(_super) {
1073
__extends(Range, _super);
1074
1075
Range.prototype.children = ['from', 'to'];
1076
1077
function Range(from, to, tag) {
1078
this.from = from;
1079
this.to = to;
1080
this.exclusive = tag === 'exclusive';
1081
this.equals = this.exclusive ? '' : '=';
1082
}
1083
1084
Range.prototype.compileVariables = function(o) {
1085
var step, _ref4, _ref5, _ref6, _ref7;
1086
o = merge(o, {
1087
top: true
1088
});
1089
_ref4 = this.cacheToCodeFragments(this.from.cache(o, LEVEL_LIST)), this.fromC = _ref4[0], this.fromVar = _ref4[1];
1090
_ref5 = this.cacheToCodeFragments(this.to.cache(o, LEVEL_LIST)), this.toC = _ref5[0], this.toVar = _ref5[1];
1091
if (step = del(o, 'step')) {
1092
_ref6 = this.cacheToCodeFragments(step.cache(o, LEVEL_LIST)), this.step = _ref6[0], this.stepVar = _ref6[1];
1093
}
1094
_ref7 = [this.fromVar.match(SIMPLENUM), this.toVar.match(SIMPLENUM)], this.fromNum = _ref7[0], this.toNum = _ref7[1];
1095
if (this.stepVar) {
1096
return this.stepNum = this.stepVar.match(SIMPLENUM);
1097
}
1098
};
1099
1100
Range.prototype.compileNode = function(o) {
1101
var cond, condPart, from, gt, idx, idxName, known, lt, namedIndex, stepPart, to, varPart, _ref4, _ref5;
1102
if (!this.fromVar) {
1103
this.compileVariables(o);
1104
}
1105
if (!o.index) {
1106
return this.compileArray(o);
1107
}
1108
known = this.fromNum && this.toNum;
1109
idx = del(o, 'index');
1110
idxName = del(o, 'name');
1111
namedIndex = idxName && idxName !== idx;
1112
varPart = "" + idx + " = " + this.fromC;
1113
if (this.toC !== this.toVar) {
1114
varPart += ", " + this.toC;
1115
}
1116
if (this.step !== this.stepVar) {
1117
varPart += ", " + this.step;
1118
}
1119
_ref4 = ["" + idx + " <" + this.equals, "" + idx + " >" + this.equals], lt = _ref4[0], gt = _ref4[1];
1120
condPart = this.stepNum ? +this.stepNum > 0 ? "" + lt + " " + this.toVar : "" + gt + " " + this.toVar : known ? ((_ref5 = [+this.fromNum, +this.toNum], from = _ref5[0], to = _ref5[1], _ref5), from <= to ? "" + lt + " " + to : "" + gt + " " + to) : (cond = this.stepVar ? "" + this.stepVar + " > 0" : "" + this.fromVar + " <= " + this.toVar, "" + cond + " ? " + lt + " " + this.toVar + " : " + gt + " " + this.toVar);
1121
stepPart = this.stepVar ? "" + idx + " += " + this.stepVar : known ? namedIndex ? from <= to ? "++" + idx : "--" + idx : from <= to ? "" + idx + "++" : "" + idx + "--" : namedIndex ? "" + cond + " ? ++" + idx + " : --" + idx : "" + cond + " ? " + idx + "++ : " + idx + "--";
1122
if (namedIndex) {
1123
varPart = "" + idxName + " = " + varPart;
1124
}
1125
if (namedIndex) {
1126
stepPart = "" + idxName + " = " + stepPart;
1127
}
1128
return [this.makeCode("" + varPart + "; " + condPart + "; " + stepPart)];
1129
};
1130
1131
Range.prototype.compileArray = function(o) {
1132
var args, body, cond, hasArgs, i, idt, post, pre, range, result, vars, _i, _ref4, _ref5, _results;
1133
if (this.fromNum && this.toNum && Math.abs(this.fromNum - this.toNum) <= 20) {
1134
range = (function() {
1135
_results = [];
1136
for (var _i = _ref4 = +this.fromNum, _ref5 = +this.toNum; _ref4 <= _ref5 ? _i <= _ref5 : _i >= _ref5; _ref4 <= _ref5 ? _i++ : _i--){ _results.push(_i); }
1137
return _results;
1138
}).apply(this);
1139
if (this.exclusive) {
1140
range.pop();
1141
}
1142
return [this.makeCode("[" + (range.join(', ')) + "]")];
1143
}
1144
idt = this.tab + TAB;
1145
i = o.scope.freeVariable('i');
1146
result = o.scope.freeVariable('results');
1147
pre = "\n" + idt + result + " = [];";
1148
if (this.fromNum && this.toNum) {
1149
o.index = i;
1150
body = fragmentsToText(this.compileNode(o));
1151
} else {
1152
vars = ("" + i + " = " + this.fromC) + (this.toC !== this.toVar ? ", " + this.toC : '');
1153
cond = "" + this.fromVar + " <= " + this.toVar;
1154
body = "var " + vars + "; " + cond + " ? " + i + " <" + this.equals + " " + this.toVar + " : " + i + " >" + this.equals + " " + this.toVar + "; " + cond + " ? " + i + "++ : " + i + "--";
1155
}
1156
post = "{ " + result + ".push(" + i + "); }\n" + idt + "return " + result + ";\n" + o.indent;
1157
hasArgs = function(node) {
1158
return node != null ? node.contains(function(n) {
1159
return n instanceof Literal && n.value === 'arguments' && !n.asKey;
1160
}) : void 0;
1161
};
1162
if (hasArgs(this.from) || hasArgs(this.to)) {
1163
args = ', arguments';
1164
}
1165
return [this.makeCode("(function() {" + pre + "\n" + idt + "for (" + body + ")" + post + "}).apply(this" + (args != null ? args : '') + ")")];
1166
};
1167
1168
return Range;
1169
1170
})(Base);
1171
1172
exports.Slice = Slice = (function(_super) {
1173
__extends(Slice, _super);
1174
1175
Slice.prototype.children = ['range'];
1176
1177
function Slice(range) {
1178
this.range = range;
1179
Slice.__super__.constructor.call(this);
1180
}
1181
1182
Slice.prototype.compileNode = function(o) {
1183
var compiled, compiledText, from, fromCompiled, to, toStr, _ref4;
1184
_ref4 = this.range, to = _ref4.to, from = _ref4.from;
1185
fromCompiled = from && from.compileToFragments(o, LEVEL_PAREN) || [this.makeCode('0')];
1186
if (to) {
1187
compiled = to.compileToFragments(o, LEVEL_PAREN);
1188
compiledText = fragmentsToText(compiled);
1189
if (!(!this.range.exclusive && +compiledText === -1)) {
1190
toStr = ', ' + (this.range.exclusive ? compiledText : SIMPLENUM.test(compiledText) ? "" + (+compiledText + 1) : (compiled = to.compileToFragments(o, LEVEL_ACCESS), "+" + (fragmentsToText(compiled)) + " + 1 || 9e9"));
1191
}
1192
}
1193
return [this.makeCode(".slice(" + (fragmentsToText(fromCompiled)) + (toStr || '') + ")")];
1194
};
1195
1196
return Slice;
1197
1198
})(Base);
1199
1200
exports.Obj = Obj = (function(_super) {
1201
__extends(Obj, _super);
1202
1203
function Obj(props, generated) {
1204
this.generated = generated != null ? generated : false;
1205
this.objects = this.properties = props || [];
1206
}
1207
1208
Obj.prototype.children = ['properties'];
1209
1210
Obj.prototype.compileNode = function(o) {
1211
var answer, i, idt, indent, join, lastNoncom, node, prop, props, _i, _j, _len, _len1;
1212
props = this.properties;
1213
if (!props.length) {
1214
return [this.makeCode(this.front ? '({})' : '{}')];
1215
}
1216
if (this.generated) {
1217
for (_i = 0, _len = props.length; _i < _len; _i++) {
1218
node = props[_i];
1219
if (node instanceof Value) {
1220
node.error('cannot have an implicit value in an implicit object');
1221
}
1222
}
1223
}
1224
idt = o.indent += TAB;
1225
lastNoncom = this.lastNonComment(this.properties);
1226
answer = [];
1227
for (i = _j = 0, _len1 = props.length; _j < _len1; i = ++_j) {
1228
prop = props[i];
1229
join = i === props.length - 1 ? '' : prop === lastNoncom || prop instanceof Comment ? '\n' : ',\n';
1230
indent = prop instanceof Comment ? '' : idt;
1231
if (prop instanceof Assign && prop.variable instanceof Value && prop.variable.hasProperties()) {
1232
prop.variable.error('Invalid object key');
1233
}
1234
if (prop instanceof Value && prop["this"]) {
1235
prop = new Assign(prop.properties[0].name, prop, 'object');
1236
}
1237
if (!(prop instanceof Comment)) {
1238
if (!(prop instanceof Assign)) {
1239
prop = new Assign(prop, prop, 'object');
1240
}
1241
(prop.variable.base || prop.variable).asKey = true;
1242
}
1243
if (indent) {
1244
answer.push(this.makeCode(indent));
1245
}
1246
answer.push.apply(answer, prop.compileToFragments(o, LEVEL_TOP));
1247
if (join) {
1248
answer.push(this.makeCode(join));
1249
}
1250
}
1251
answer.unshift(this.makeCode("{" + (props.length && '\n')));
1252
answer.push(this.makeCode("" + (props.length && '\n' + this.tab) + "}"));
1253
if (this.front) {
1254
return this.wrapInBraces(answer);
1255
} else {
1256
return answer;
1257
}
1258
};
1259
1260
Obj.prototype.assigns = function(name) {
1261
var prop, _i, _len, _ref4;
1262
_ref4 = this.properties;
1263
for (_i = 0, _len = _ref4.length; _i < _len; _i++) {
1264
prop = _ref4[_i];
1265
if (prop.assigns(name)) {
1266
return true;
1267
}
1268
}
1269
return false;
1270
};
1271
1272
return Obj;
1273
1274
})(Base);
1275
1276
exports.Arr = Arr = (function(_super) {
1277
__extends(Arr, _super);
1278
1279
function Arr(objs) {
1280
this.objects = objs || [];
1281
}
1282
1283
Arr.prototype.children = ['objects'];
1284
1285
Arr.prototype.compileNode = function(o) {
1286
var answer, compiledObjs, fragments, index, obj, _i, _len;
1287
if (!this.objects.length) {
1288
return [this.makeCode('[]')];
1289
}
1290
o.indent += TAB;
1291
answer = Splat.compileSplattedArray(o, this.objects);
1292
if (answer.length) {
1293
return answer;
1294
}
1295
answer = [];
1296
compiledObjs = (function() {
1297
var _i, _len, _ref4, _results;
1298
_ref4 = this.objects;
1299
_results = [];
1300
for (_i = 0, _len = _ref4.length; _i < _len; _i++) {
1301
obj = _ref4[_i];
1302
_results.push(obj.compileToFragments(o, LEVEL_LIST));
1303
}
1304
return _results;
1305
}).call(this);
1306
for (index = _i = 0, _len = compiledObjs.length; _i < _len; index = ++_i) {
1307
fragments = compiledObjs[index];
1308
if (index) {
1309
answer.push(this.makeCode(", "));
1310
}
1311
answer.push.apply(answer, fragments);
1312
}
1313
if (fragmentsToText(answer).indexOf('\n') >= 0) {
1314
answer.unshift(this.makeCode("[\n" + o.indent));
1315
answer.push(this.makeCode("\n" + this.tab + "]"));
1316
} else {
1317
answer.unshift(this.makeCode("["));
1318
answer.push(this.makeCode("]"));
1319
}
1320
return answer;
1321
};
1322
1323
Arr.prototype.assigns = function(name) {
1324
var obj, _i, _len, _ref4;
1325
_ref4 = this.objects;
1326
for (_i = 0, _len = _ref4.length; _i < _len; _i++) {
1327
obj = _ref4[_i];
1328
if (obj.assigns(name)) {
1329
return true;
1330
}
1331
}
1332
return false;
1333
};
1334
1335
return Arr;
1336
1337
})(Base);
1338
1339
exports.Class = Class = (function(_super) {
1340
__extends(Class, _super);
1341
1342
function Class(variable, parent, body) {
1343
this.variable = variable;
1344
this.parent = parent;
1345
this.body = body != null ? body : new Block;
1346
this.boundFuncs = [];
1347
this.body.classBody = true;
1348
}
1349
1350
Class.prototype.children = ['variable', 'parent', 'body'];
1351
1352
Class.prototype.determineName = function() {
1353
var decl, tail;
1354
if (!this.variable) {
1355
return null;
1356
}
1357
decl = (tail = last(this.variable.properties)) ? tail instanceof Access && tail.name.value : this.variable.base.value;
1358
if (__indexOf.call(STRICT_PROSCRIBED, decl) >= 0) {
1359
this.variable.error("class variable name may not be " + decl);
1360
}
1361
return decl && (decl = IDENTIFIER.test(decl) && decl);
1362
};
1363
1364
Class.prototype.setContext = function(name) {
1365
return this.body.traverseChildren(false, function(node) {
1366
if (node.classBody) {
1367
return false;
1368
}
1369
if (node instanceof Literal && node.value === 'this') {
1370
return node.value = name;
1371
} else if (node instanceof Code) {
1372
node.klass = name;
1373
if (node.bound) {
1374
return node.context = name;
1375
}
1376
}
1377
});
1378
};
1379
1380
Class.prototype.addBoundFunctions = function(o) {
1381
var bvar, lhs, _i, _len, _ref4;
1382
_ref4 = this.boundFuncs;
1383
for (_i = 0, _len = _ref4.length; _i < _len; _i++) {
1384
bvar = _ref4[_i];
1385
lhs = (new Value(new Literal("this"), [new Access(bvar)])).compile(o);
1386
this.ctor.body.unshift(new Literal("" + lhs + " = " + (utility('bind')) + "(" + lhs + ", this)"));
1387
}
1388
};
1389
1390
Class.prototype.addProperties = function(node, name, o) {
1391
var assign, base, exprs, func, props;
1392
props = node.base.properties.slice(0);
1393
exprs = (function() {
1394
var _results;
1395
_results = [];
1396
while (assign = props.shift()) {
1397
if (assign instanceof Assign) {
1398
base = assign.variable.base;
1399
delete assign.context;
1400
func = assign.value;
1401
if (base.value === 'constructor') {
1402
if (this.ctor) {
1403
assign.error('cannot define more than one constructor in a class');
1404
}
1405
if (func.bound) {
1406
assign.error('cannot define a constructor as a bound function');
1407
}
1408
if (func instanceof Code) {
1409
assign = this.ctor = func;
1410
} else {
1411
this.externalCtor = o.scope.freeVariable('class');
1412
assign = new Assign(new Literal(this.externalCtor), func);
1413
}
1414
} else {
1415
if (assign.variable["this"]) {
1416
func["static"] = true;
1417
if (func.bound) {
1418
func.context = name;
1419
}
1420
} else {
1421
assign.variable = new Value(new Literal(name), [new Access(new Literal('prototype')), new Access(base)]);
1422
if (func instanceof Code && func.bound) {
1423
this.boundFuncs.push(base);
1424
func.bound = false;
1425
}
1426
}
1427
}
1428
}
1429
_results.push(assign);
1430
}
1431
return _results;
1432
}).call(this);
1433
return compact(exprs);
1434
};
1435
1436
Class.prototype.walkBody = function(name, o) {
1437
var _this = this;
1438
return this.traverseChildren(false, function(child) {
1439
var cont, exps, i, node, _i, _len, _ref4;
1440
cont = true;
1441
if (child instanceof Class) {
1442
return false;
1443
}
1444
if (child instanceof Block) {
1445
_ref4 = exps = child.expressions;
1446
for (i = _i = 0, _len = _ref4.length; _i < _len; i = ++_i) {
1447
node = _ref4[i];
1448
if (node instanceof Value && node.isObject(true)) {
1449
cont = false;
1450
exps[i] = _this.addProperties(node, name, o);
1451
}
1452
}
1453
child.expressions = exps = flatten(exps);
1454
}
1455
return cont && !(child instanceof Class);
1456
});
1457
};
1458
1459
Class.prototype.hoistDirectivePrologue = function() {
1460
var expressions, index, node;
1461
index = 0;
1462
expressions = this.body.expressions;
1463
while ((node = expressions[index]) && node instanceof Comment || node instanceof Value && node.isString()) {
1464
++index;
1465
}
1466
return this.directives = expressions.splice(0, index);
1467
};
1468
1469
Class.prototype.ensureConstructor = function(name, o) {
1470
var missing, ref, superCall;
1471
missing = !this.ctor;
1472
this.ctor || (this.ctor = new Code);
1473
this.ctor.ctor = this.ctor.name = name;
1474
this.ctor.klass = null;
1475
this.ctor.noReturn = true;
1476
if (missing) {
1477
if (this.parent) {
1478
superCall = new Literal("" + name + ".__super__.constructor.apply(this, arguments)");
1479
}
1480
if (this.externalCtor) {
1481
superCall = new Literal("" + this.externalCtor + ".apply(this, arguments)");
1482
}
1483
if (superCall) {
1484
ref = new Literal(o.scope.freeVariable('ref'));
1485
this.ctor.body.unshift(new Assign(ref, superCall));
1486
}
1487
this.addBoundFunctions(o);
1488
if (superCall) {
1489
this.ctor.body.push(ref);
1490
this.ctor.body.makeReturn();
1491
}
1492
return this.body.expressions.unshift(this.ctor);
1493
} else {
1494
return this.addBoundFunctions(o);
1495
}
1496
};
1497
1498
Class.prototype.compileNode = function(o) {
1499
var call, decl, klass, lname, name, params, _ref4;
1500
decl = this.determineName();
1501
name = decl || '_Class';
1502
if (name.reserved) {
1503
name = "_" + name;
1504
}
1505
lname = new Literal(name);
1506
this.hoistDirectivePrologue();
1507
this.setContext(name);
1508
this.walkBody(name, o);
1509
this.ensureConstructor(name, o);
1510
this.body.spaced = true;
1511
if (!(this.ctor instanceof Code)) {
1512
this.body.expressions.unshift(this.ctor);
1513
}
1514
this.body.expressions.push(lname);
1515
(_ref4 = this.body.expressions).unshift.apply(_ref4, this.directives);
1516
call = Closure.wrap(this.body);
1517
if (this.parent) {
1518
this.superClass = new Literal(o.scope.freeVariable('super', false));
1519
this.body.expressions.unshift(new Extends(lname, this.superClass));
1520
call.args.push(this.parent);
1521
params = call.variable.params || call.variable.base.params;
1522
params.push(new Param(this.superClass));
1523
}
1524
klass = new Parens(call, true);
1525
if (this.variable) {
1526
klass = new Assign(this.variable, klass);
1527
}
1528
return klass.compileToFragments(o);
1529
};
1530
1531
return Class;
1532
1533
})(Base);
1534
1535
exports.Assign = Assign = (function(_super) {
1536
__extends(Assign, _super);
1537
1538
function Assign(variable, value, context, options) {
1539
var forbidden, name, _ref4;
1540
this.variable = variable;
1541
this.value = value;
1542
this.context = context;
1543
this.param = options && options.param;
1544
this.subpattern = options && options.subpattern;
1545
forbidden = (_ref4 = (name = this.variable.unwrapAll().value), __indexOf.call(STRICT_PROSCRIBED, _ref4) >= 0);
1546
if (forbidden && this.context !== 'object') {
1547
this.variable.error("variable name may not be \"" + name + "\"");
1548
}
1549
}
1550
1551
Assign.prototype.children = ['variable', 'value'];
1552
1553
Assign.prototype.isStatement = function(o) {
1554
return (o != null ? o.level : void 0) === LEVEL_TOP && (this.context != null) && __indexOf.call(this.context, "?") >= 0;
1555
};
1556
1557
Assign.prototype.assigns = function(name) {
1558
return this[this.context === 'object' ? 'value' : 'variable'].assigns(name);
1559
};
1560
1561
Assign.prototype.unfoldSoak = function(o) {
1562
return unfoldSoak(o, this, 'variable');
1563
};
1564
1565
Assign.prototype.compileNode = function(o) {
1566
var answer, compiledName, isValue, match, name, val, varBase, _ref4, _ref5, _ref6, _ref7;
1567
if (isValue = this.variable instanceof Value) {
1568
if (this.variable.isArray() || this.variable.isObject()) {
1569
return this.compilePatternMatch(o);
1570
}
1571
if (this.variable.isSplice()) {
1572
return this.compileSplice(o);
1573
}
1574
if ((_ref4 = this.context) === '||=' || _ref4 === '&&=' || _ref4 === '?=') {
1575
return this.compileConditional(o);
1576
}
1577
}
1578
compiledName = this.variable.compileToFragments(o, LEVEL_LIST);
1579
name = fragmentsToText(compiledName);
1580
if (!this.context) {
1581
varBase = this.variable.unwrapAll();
1582
if (!varBase.isAssignable()) {
1583
this.variable.error("\"" + (this.variable.compile(o)) + "\" cannot be assigned");
1584
}
1585
if (!(typeof varBase.hasProperties === "function" ? varBase.hasProperties() : void 0)) {
1586
if (this.param) {
1587
o.scope.add(name, 'var');
1588
} else {
1589
o.scope.find(name);
1590
}
1591
}
1592
}
1593
if (this.value instanceof Code && (match = METHOD_DEF.exec(name))) {
1594
if (match[1]) {
1595
this.value.klass = match[1];
1596
}
1597
this.value.name = (_ref5 = (_ref6 = (_ref7 = match[2]) != null ? _ref7 : match[3]) != null ? _ref6 : match[4]) != null ? _ref5 : match[5];
1598
}
1599
val = this.value.compileToFragments(o, LEVEL_LIST);
1600
if (this.context === 'object') {
1601
return compiledName.concat(this.makeCode(": "), val);
1602
}
1603
answer = compiledName.concat(this.makeCode(" " + (this.context || '=') + " "), val);
1604
if (o.level <= LEVEL_LIST) {
1605
return answer;
1606
} else {
1607
return this.wrapInBraces(answer);
1608
}
1609
};
1610
1611
Assign.prototype.compilePatternMatch = function(o) {
1612
var acc, assigns, code, fragments, i, idx, isObject, ivar, name, obj, objects, olen, ref, rest, splat, top, val, value, vvar, vvarText, _i, _len, _ref4, _ref5, _ref6, _ref7, _ref8, _ref9;
1613
top = o.level === LEVEL_TOP;
1614
value = this.value;
1615
objects = this.variable.base.objects;
1616
if (!(olen = objects.length)) {
1617
code = value.compileToFragments(o);
1618
if (o.level >= LEVEL_OP) {
1619
return this.wrapInBraces(code);
1620
} else {
1621
return code;
1622
}
1623
}
1624
isObject = this.variable.isObject();
1625
if (top && olen === 1 && !((obj = objects[0]) instanceof Splat)) {
1626
if (obj instanceof Assign) {
1627
_ref4 = obj, (_ref5 = _ref4.variable, idx = _ref5.base), obj = _ref4.value;
1628
} else {
1629
idx = isObject ? obj["this"] ? obj.properties[0].name : obj : new Literal(0);
1630
}
1631
acc = IDENTIFIER.test(idx.unwrap().value || 0);
1632
value = new Value(value);
1633
value.properties.push(new (acc ? Access : Index)(idx));
1634
if (_ref6 = obj.unwrap().value, __indexOf.call(RESERVED, _ref6) >= 0) {
1635
obj.error("assignment to a reserved word: " + (obj.compile(o)));
1636
}
1637
return new Assign(obj, value, null, {
1638
param: this.param
1639
}).compileToFragments(o, LEVEL_TOP);
1640
}
1641
vvar = value.compileToFragments(o, LEVEL_LIST);
1642
vvarText = fragmentsToText(vvar);
1643
assigns = [];
1644
splat = false;
1645
if (!IDENTIFIER.test(vvarText) || this.variable.assigns(vvarText)) {
1646
assigns.push([this.makeCode("" + (ref = o.scope.freeVariable('ref')) + " = ")].concat(__slice.call(vvar)));
1647
vvar = [this.makeCode(ref)];
1648
vvarText = ref;
1649
}
1650
for (i = _i = 0, _len = objects.length; _i < _len; i = ++_i) {
1651
obj = objects[i];
1652
idx = i;
1653
if (isObject) {
1654
if (obj instanceof Assign) {
1655
_ref7 = obj, (_ref8 = _ref7.variable, idx = _ref8.base), obj = _ref7.value;
1656
} else {
1657
if (obj.base instanceof Parens) {
1658
_ref9 = new Value(obj.unwrapAll()).cacheReference(o), obj = _ref9[0], idx = _ref9[1];
1659
} else {
1660
idx = obj["this"] ? obj.properties[0].name : obj;
1661
}
1662
}
1663
}
1664
if (!splat && obj instanceof Splat) {
1665
name = obj.name.unwrap().value;
1666
obj = obj.unwrap();
1667
val = "" + olen + " <= " + vvarText + ".length ? " + (utility('slice')) + ".call(" + vvarText + ", " + i;
1668
if (rest = olen - i - 1) {
1669
ivar = o.scope.freeVariable('i');
1670
val += ", " + ivar + " = " + vvarText + ".length - " + rest + ") : (" + ivar + " = " + i + ", [])";
1671
} else {
1672
val += ") : []";
1673
}
1674
val = new Literal(val);
1675
splat = "" + ivar + "++";
1676
} else {
1677
name = obj.unwrap().value;
1678
if (obj instanceof Splat) {
1679
obj.error("multiple splats are disallowed in an assignment");
1680
}
1681
if (typeof idx === 'number') {
1682
idx = new Literal(splat || idx);
1683
acc = false;
1684
} else {
1685
acc = isObject && IDENTIFIER.test(idx.unwrap().value || 0);
1686
}
1687
val = new Value(new Literal(vvarText), [new (acc ? Access : Index)(idx)]);
1688
}
1689
if ((name != null) && __indexOf.call(RESERVED, name) >= 0) {
1690
obj.error("assignment to a reserved word: " + (obj.compile(o)));
1691
}
1692
assigns.push(new Assign(obj, val, null, {
1693
param: this.param,
1694
subpattern: true
1695
}).compileToFragments(o, LEVEL_LIST));
1696
}
1697
if (!(top || this.subpattern)) {
1698
assigns.push(vvar);
1699
}
1700
fragments = this.joinFragmentArrays(assigns, ', ');
1701
if (o.level < LEVEL_LIST) {
1702
return fragments;
1703
} else {
1704
return this.wrapInBraces(fragments);
1705
}
1706
};
1707
1708
Assign.prototype.compileConditional = function(o) {
1709
var left, right, _ref4;
1710
_ref4 = this.variable.cacheReference(o), left = _ref4[0], right = _ref4[1];
1711
if (!left.properties.length && left.base instanceof Literal && left.base.value !== "this" && !o.scope.check(left.base.value)) {
1712
this.variable.error("the variable \"" + left.base.value + "\" can't be assigned with " + this.context + " because it has not been declared before");
1713
}
1714
if (__indexOf.call(this.context, "?") >= 0) {
1715
o.isExistentialEquals = true;
1716
}
1717
return new Op(this.context.slice(0, -1), left, new Assign(right, this.value, '=')).compileToFragments(o);
1718
};
1719
1720
Assign.prototype.compileSplice = function(o) {
1721
var answer, exclusive, from, fromDecl, fromRef, name, to, valDef, valRef, _ref4, _ref5, _ref6;
1722
_ref4 = this.variable.properties.pop().range, from = _ref4.from, to = _ref4.to, exclusive = _ref4.exclusive;
1723
name = this.variable.compile(o);
1724
if (from) {
1725
_ref5 = this.cacheToCodeFragments(from.cache(o, LEVEL_OP)), fromDecl = _ref5[0], fromRef = _ref5[1];
1726
} else {
1727
fromDecl = fromRef = '0';
1728
}
1729
if (to) {
1730
if ((from != null ? from.isSimpleNumber() : void 0) && to.isSimpleNumber()) {
1731
to = +to.compile(o) - +fromRef;
1732
if (!exclusive) {
1733
to += 1;
1734
}
1735
} else {
1736
to = to.compile(o, LEVEL_ACCESS) + ' - ' + fromRef;
1737
if (!exclusive) {
1738
to += ' + 1';
1739
}
1740
}
1741
} else {
1742
to = "9e9";
1743
}
1744
_ref6 = this.value.cache(o, LEVEL_LIST), valDef = _ref6[0], valRef = _ref6[1];
1745
answer = [].concat(this.makeCode("[].splice.apply(" + name + ", [" + fromDecl + ", " + to + "].concat("), valDef, this.makeCode(")), "), valRef);
1746
if (o.level > LEVEL_TOP) {
1747
return this.wrapInBraces(answer);
1748
} else {
1749
return answer;
1750
}
1751
};
1752
1753
return Assign;
1754
1755
})(Base);
1756
1757
exports.Code = Code = (function(_super) {
1758
__extends(Code, _super);
1759
1760
function Code(params, body, tag) {
1761
this.params = params || [];
1762
this.body = body || new Block;
1763
this.bound = tag === 'boundfunc';
1764
if (this.bound) {
1765
this.context = '_this';
1766
}
1767
}
1768
1769
Code.prototype.children = ['params', 'body'];
1770
1771
Code.prototype.isStatement = function() {
1772
return !!this.ctor;
1773
};
1774
1775
Code.prototype.jumps = NO;
1776
1777
Code.prototype.compileNode = function(o) {
1778
var answer, code, exprs, i, idt, lit, p, param, params, ref, splats, uniqs, val, wasEmpty, _i, _j, _k, _l, _len, _len1, _len2, _len3, _len4, _m, _ref4, _ref5, _ref6, _ref7, _ref8;
1779
o.scope = new Scope(o.scope, this.body, this);
1780
o.scope.shared = del(o, 'sharedScope');
1781
o.indent += TAB;
1782
delete o.bare;
1783
delete o.isExistentialEquals;
1784
params = [];
1785
exprs = [];
1786
this.eachParamName(function(name) {
1787
if (!o.scope.check(name)) {
1788
return o.scope.parameter(name);
1789
}
1790
});
1791
_ref4 = this.params;
1792
for (_i = 0, _len = _ref4.length; _i < _len; _i++) {
1793
param = _ref4[_i];
1794
if (!param.splat) {
1795
continue;
1796
}
1797
_ref5 = this.params;
1798
for (_j = 0, _len1 = _ref5.length; _j < _len1; _j++) {
1799
p = _ref5[_j].name;
1800
if (p["this"]) {
1801
p = p.properties[0].name;
1802
}
1803
if (p.value) {
1804
o.scope.add(p.value, 'var', true);
1805
}
1806
}
1807
splats = new Assign(new Value(new Arr((function() {
1808
var _k, _len2, _ref6, _results;
1809
_ref6 = this.params;
1810
_results = [];
1811
for (_k = 0, _len2 = _ref6.length; _k < _len2; _k++) {
1812
p = _ref6[_k];
1813
_results.push(p.asReference(o));
1814
}
1815
return _results;
1816
}).call(this))), new Value(new Literal('arguments')));
1817
break;
1818
}
1819
_ref6 = this.params;
1820
for (_k = 0, _len2 = _ref6.length; _k < _len2; _k++) {
1821
param = _ref6[_k];
1822
if (param.isComplex()) {
1823
val = ref = param.asReference(o);
1824
if (param.value) {
1825
val = new Op('?', ref, param.value);
1826
}
1827
exprs.push(new Assign(new Value(param.name), val, '=', {
1828
param: true
1829
}));
1830
} else {
1831
ref = param;
1832
if (param.value) {
1833
lit = new Literal(ref.name.value + ' == null');
1834
val = new Assign(new Value(param.name), param.value, '=');
1835
exprs.push(new If(lit, val));
1836
}
1837
}
1838
if (!splats) {
1839
params.push(ref);
1840
}
1841
}
1842
wasEmpty = this.body.isEmpty();
1843
if (splats) {
1844
exprs.unshift(splats);
1845
}
1846
if (exprs.length) {
1847
(_ref7 = this.body.expressions).unshift.apply(_ref7, exprs);
1848
}
1849
for (i = _l = 0, _len3 = params.length; _l < _len3; i = ++_l) {
1850
p = params[i];
1851
params[i] = p.compileToFragments(o);
1852
o.scope.parameter(fragmentsToText(params[i]));
1853
}
1854
uniqs = [];
1855
this.eachParamName(function(name, node) {
1856
if (__indexOf.call(uniqs, name) >= 0) {
1857
node.error("multiple parameters named '" + name + "'");
1858
}
1859
return uniqs.push(name);
1860
});
1861
if (!(wasEmpty || this.noReturn)) {
1862
this.body.makeReturn();
1863
}
1864
if (this.bound) {
1865
if ((_ref8 = o.scope.parent.method) != null ? _ref8.bound : void 0) {
1866
this.bound = this.context = o.scope.parent.method.context;
1867
} else if (!this["static"]) {
1868
o.scope.parent.assign('_this', 'this');
1869
}
1870
}
1871
idt = o.indent;
1872
code = 'function';
1873
if (this.ctor) {
1874
code += ' ' + this.name;
1875
}
1876
code += '(';
1877
answer = [this.makeCode(code)];
1878
for (i = _m = 0, _len4 = params.length; _m < _len4; i = ++_m) {
1879
p = params[i];
1880
if (i) {
1881
answer.push(this.makeCode(", "));
1882
}
1883
answer.push.apply(answer, p);
1884
}
1885
answer.push(this.makeCode(') {'));
1886
if (!this.body.isEmpty()) {
1887
answer = answer.concat(this.makeCode("\n"), this.body.compileWithDeclarations(o), this.makeCode("\n" + this.tab));
1888
}
1889
answer.push(this.makeCode('}'));
1890
if (this.ctor) {
1891
return [this.makeCode(this.tab)].concat(__slice.call(answer));
1892
}
1893
if (this.front || (o.level >= LEVEL_ACCESS)) {
1894
return this.wrapInBraces(answer);
1895
} else {
1896
return answer;
1897
}
1898
};
1899
1900
Code.prototype.eachParamName = function(iterator) {
1901
var param, _i, _len, _ref4, _results;
1902
_ref4 = this.params;
1903
_results = [];
1904
for (_i = 0, _len = _ref4.length; _i < _len; _i++) {
1905
param = _ref4[_i];
1906
_results.push(param.eachName(iterator));
1907
}
1908
return _results;
1909
};
1910
1911
Code.prototype.traverseChildren = function(crossScope, func) {
1912
if (crossScope) {
1913
return Code.__super__.traverseChildren.call(this, crossScope, func);
1914
}
1915
};
1916
1917
return Code;
1918
1919
})(Base);
1920
1921
exports.Param = Param = (function(_super) {
1922
__extends(Param, _super);
1923
1924
function Param(name, value, splat) {
1925
var _ref4;
1926
this.name = name;
1927
this.value = value;
1928
this.splat = splat;
1929
if (_ref4 = (name = this.name.unwrapAll().value), __indexOf.call(STRICT_PROSCRIBED, _ref4) >= 0) {
1930
this.name.error("parameter name \"" + name + "\" is not allowed");
1931
}
1932
}
1933
1934
Param.prototype.children = ['name', 'value'];
1935
1936
Param.prototype.compileToFragments = function(o) {
1937
return this.name.compileToFragments(o, LEVEL_LIST);
1938
};
1939
1940
Param.prototype.asReference = function(o) {
1941
var node;
1942
if (this.reference) {
1943
return this.reference;
1944
}
1945
node = this.name;
1946
if (node["this"]) {
1947
node = node.properties[0].name;
1948
if (node.value.reserved) {
1949
node = new Literal(o.scope.freeVariable(node.value));
1950
}
1951
} else if (node.isComplex()) {
1952
node = new Literal(o.scope.freeVariable('arg'));
1953
}
1954
node = new Value(node);
1955
if (this.splat) {
1956
node = new Splat(node);
1957
}
1958
return this.reference = node;
1959
};
1960
1961
Param.prototype.isComplex = function() {
1962
return this.name.isComplex();
1963
};
1964
1965
Param.prototype.eachName = function(iterator, name) {
1966
var atParam, node, obj, _i, _len, _ref4;
1967
if (name == null) {
1968
name = this.name;
1969
}
1970
atParam = function(obj) {
1971
var node;
1972
node = obj.properties[0].name;
1973
if (!node.value.reserved) {
1974
return iterator(node.value, node);
1975
}
1976
};
1977
if (name instanceof Literal) {
1978
return iterator(name.value, name);
1979
}
1980
if (name instanceof Value) {
1981
return atParam(name);
1982
}
1983
_ref4 = name.objects;
1984
for (_i = 0, _len = _ref4.length; _i < _len; _i++) {
1985
obj = _ref4[_i];
1986
if (obj instanceof Assign) {
1987
this.eachName(iterator, obj.value.unwrap());
1988
} else if (obj instanceof Splat) {
1989
node = obj.name.unwrap();
1990
iterator(node.value, node);
1991
} else if (obj instanceof Value) {
1992
if (obj.isArray() || obj.isObject()) {
1993
this.eachName(iterator, obj.base);
1994
} else if (obj["this"]) {
1995
atParam(obj);
1996
} else {
1997
iterator(obj.base.value, obj.base);
1998
}
1999
} else {
2000
obj.error("illegal parameter " + (obj.compile()));
2001
}
2002
}
2003
};
2004
2005
return Param;
2006
2007
})(Base);
2008
2009
exports.Splat = Splat = (function(_super) {
2010
__extends(Splat, _super);
2011
2012
Splat.prototype.children = ['name'];
2013
2014
Splat.prototype.isAssignable = YES;
2015
2016
function Splat(name) {
2017
this.name = name.compile ? name : new Literal(name);
2018
}
2019
2020
Splat.prototype.assigns = function(name) {
2021
return this.name.assigns(name);
2022
};
2023
2024
Splat.prototype.compileToFragments = function(o) {
2025
return this.name.compileToFragments(o);
2026
};
2027
2028
Splat.prototype.unwrap = function() {
2029
return this.name;
2030
};
2031
2032
Splat.compileSplattedArray = function(o, list, apply) {
2033
var args, base, compiledNode, concatPart, fragments, i, index, node, _i, _len;
2034
index = -1;
2035
while ((node = list[++index]) && !(node instanceof Splat)) {
2036
continue;
2037
}
2038
if (index >= list.length) {
2039
return [];
2040
}
2041
if (list.length === 1) {
2042
node = list[0];
2043
fragments = node.compileToFragments(o, LEVEL_LIST);
2044
if (apply) {
2045
return fragments;
2046
}
2047
return [].concat(node.makeCode("" + (utility('slice')) + ".call("), fragments, node.makeCode(")"));
2048
}
2049
args = list.slice(index);
2050
for (i = _i = 0, _len = args.length; _i < _len; i = ++_i) {
2051
node = args[i];
2052
compiledNode = node.compileToFragments(o, LEVEL_LIST);
2053
args[i] = node instanceof Splat ? [].concat(node.makeCode("" + (utility('slice')) + ".call("), compiledNode, node.makeCode(")")) : [].concat(node.makeCode("["), compiledNode, node.makeCode("]"));
2054
}
2055
if (index === 0) {
2056
node = list[0];
2057
concatPart = node.joinFragmentArrays(args.slice(1), ', ');
2058
return args[0].concat(node.makeCode(".concat("), concatPart, node.makeCode(")"));
2059
}
2060
base = (function() {
2061
var _j, _len1, _ref4, _results;
2062
_ref4 = list.slice(0, index);
2063
_results = [];
2064
for (_j = 0, _len1 = _ref4.length; _j < _len1; _j++) {
2065
node = _ref4[_j];
2066
_results.push(node.compileToFragments(o, LEVEL_LIST));
2067
}
2068
return _results;
2069
})();
2070
base = list[0].joinFragmentArrays(base, ', ');
2071
concatPart = list[index].joinFragmentArrays(args, ', ');
2072
return [].concat(list[0].makeCode("["), base, list[index].makeCode("].concat("), concatPart, (last(list)).makeCode(")"));
2073
};
2074
2075
return Splat;
2076
2077
})(Base);
2078
2079
exports.While = While = (function(_super) {
2080
__extends(While, _super);
2081
2082
function While(condition, options) {
2083
this.condition = (options != null ? options.invert : void 0) ? condition.invert() : condition;
2084
this.guard = options != null ? options.guard : void 0;
2085
}
2086
2087
While.prototype.children = ['condition', 'guard', 'body'];
2088
2089
While.prototype.isStatement = YES;
2090
2091
While.prototype.makeReturn = function(res) {
2092
if (res) {
2093
return While.__super__.makeReturn.apply(this, arguments);
2094
} else {
2095
this.returns = !this.jumps({
2096
loop: true
2097
});
2098
return this;
2099
}
2100
};
2101
2102
While.prototype.addBody = function(body) {
2103
this.body = body;
2104
return this;
2105
};
2106
2107
While.prototype.jumps = function() {
2108
var expressions, node, _i, _len;
2109
expressions = this.body.expressions;
2110
if (!expressions.length) {
2111
return false;
2112
}
2113
for (_i = 0, _len = expressions.length; _i < _len; _i++) {
2114
node = expressions[_i];
2115
if (node.jumps({
2116
loop: true
2117
})) {
2118
return node;
2119
}
2120
}
2121
return false;
2122
};
2123
2124
While.prototype.compileNode = function(o) {
2125
var answer, body, rvar, set;
2126
o.indent += TAB;
2127
set = '';
2128
body = this.body;
2129
if (body.isEmpty()) {
2130
body = this.makeCode('');
2131
} else {
2132
if (this.returns) {
2133
body.makeReturn(rvar = o.scope.freeVariable('results'));
2134
set = "" + this.tab + rvar + " = [];\n";
2135
}
2136
if (this.guard) {
2137
if (body.expressions.length > 1) {
2138
body.expressions.unshift(new If((new Parens(this.guard)).invert(), new Literal("continue")));
2139
} else {
2140
if (this.guard) {
2141
body = Block.wrap([new If(this.guard, body)]);
2142
}
2143
}
2144
}
2145
body = [].concat(this.makeCode("\n"), body.compileToFragments(o, LEVEL_TOP), this.makeCode("\n" + this.tab));
2146
}
2147
answer = [].concat(this.makeCode(set + this.tab + "while ("), this.condition.compileToFragments(o, LEVEL_PAREN), this.makeCode(") {"), body, this.makeCode("}"));
2148
if (this.returns) {
2149
answer.push(this.makeCode("\n" + this.tab + "return " + rvar + ";"));
2150
}
2151
return answer;
2152
};
2153
2154
return While;
2155
2156
})(Base);
2157
2158
exports.Op = Op = (function(_super) {
2159
var CONVERSIONS, INVERSIONS;
2160
2161
__extends(Op, _super);
2162
2163
function Op(op, first, second, flip) {
2164
if (op === 'in') {
2165
return new In(first, second);
2166
}
2167
if (op === 'do') {
2168
return this.generateDo(first);
2169
}
2170
if (op === 'new') {
2171
if (first instanceof Call && !first["do"] && !first.isNew) {
2172
return first.newInstance();
2173
}
2174
if (first instanceof Code && first.bound || first["do"]) {
2175
first = new Parens(first);
2176
}
2177
}
2178
this.operator = CONVERSIONS[op] || op;
2179
this.first = first;
2180
this.second = second;
2181
this.flip = !!flip;
2182
return this;
2183
}
2184
2185
CONVERSIONS = {
2186
'==': '===',
2187
'!=': '!==',
2188
'of': 'in'
2189
};
2190
2191
INVERSIONS = {
2192
'!==': '===',
2193
'===': '!=='
2194
};
2195
2196
Op.prototype.children = ['first', 'second'];
2197
2198
Op.prototype.isSimpleNumber = NO;
2199
2200
Op.prototype.isUnary = function() {
2201
return !this.second;
2202
};
2203
2204
Op.prototype.isComplex = function() {
2205
var _ref4;
2206
return !(this.isUnary() && ((_ref4 = this.operator) === '+' || _ref4 === '-')) || this.first.isComplex();
2207
};
2208
2209
Op.prototype.isChainable = function() {
2210
var _ref4;
2211
return (_ref4 = this.operator) === '<' || _ref4 === '>' || _ref4 === '>=' || _ref4 === '<=' || _ref4 === '===' || _ref4 === '!==';
2212
};
2213
2214
Op.prototype.invert = function() {
2215
var allInvertable, curr, fst, op, _ref4;
2216
if (this.isChainable() && this.first.isChainable()) {
2217
allInvertable = true;
2218
curr = this;
2219
while (curr && curr.operator) {
2220
allInvertable && (allInvertable = curr.operator in INVERSIONS);
2221
curr = curr.first;
2222
}
2223
if (!allInvertable) {
2224
return new Parens(this).invert();
2225
}
2226
curr = this;
2227
while (curr && curr.operator) {
2228
curr.invert = !curr.invert;
2229
curr.operator = INVERSIONS[curr.operator];
2230
curr = curr.first;
2231
}
2232
return this;
2233
} else if (op = INVERSIONS[this.operator]) {
2234
this.operator = op;
2235
if (this.first.unwrap() instanceof Op) {
2236
this.first.invert();
2237
}
2238
return this;
2239
} else if (this.second) {
2240
return new Parens(this).invert();
2241
} else if (this.operator === '!' && (fst = this.first.unwrap()) instanceof Op && ((_ref4 = fst.operator) === '!' || _ref4 === 'in' || _ref4 === 'instanceof')) {
2242
return fst;
2243
} else {
2244
return new Op('!', this);
2245
}
2246
};
2247
2248
Op.prototype.unfoldSoak = function(o) {
2249
var _ref4;
2250
return ((_ref4 = this.operator) === '++' || _ref4 === '--' || _ref4 === 'delete') && unfoldSoak(o, this, 'first');
2251
};
2252
2253
Op.prototype.generateDo = function(exp) {
2254
var call, func, param, passedParams, ref, _i, _len, _ref4;
2255
passedParams = [];
2256
func = exp instanceof Assign && (ref = exp.value.unwrap()) instanceof Code ? ref : exp;
2257
_ref4 = func.params || [];
2258
for (_i = 0, _len = _ref4.length; _i < _len; _i++) {
2259
param = _ref4[_i];
2260
if (param.value) {
2261
passedParams.push(param.value);
2262
delete param.value;
2263
} else {
2264
passedParams.push(param);
2265
}
2266
}
2267
call = new Call(exp, passedParams);
2268
call["do"] = true;
2269
return call;
2270
};
2271
2272
Op.prototype.compileNode = function(o) {
2273
var answer, isChain, _ref4, _ref5;
2274
isChain = this.isChainable() && this.first.isChainable();
2275
if (!isChain) {
2276
this.first.front = this.front;
2277
}
2278
if (this.operator === 'delete' && o.scope.check(this.first.unwrapAll().value)) {
2279
this.error('delete operand may not be argument or var');
2280
}
2281
if (((_ref4 = this.operator) === '--' || _ref4 === '++') && (_ref5 = this.first.unwrapAll().value, __indexOf.call(STRICT_PROSCRIBED, _ref5) >= 0)) {
2282
this.error("cannot increment/decrement \"" + (this.first.unwrapAll().value) + "\"");
2283
}
2284
if (this.isUnary()) {
2285
return this.compileUnary(o);
2286
}
2287
if (isChain) {
2288
return this.compileChain(o);
2289
}
2290
if (this.operator === '?') {
2291
return this.compileExistence(o);
2292
}
2293
answer = [].concat(this.first.compileToFragments(o, LEVEL_OP), this.makeCode(' ' + this.operator + ' '), this.second.compileToFragments(o, LEVEL_OP));
2294
if (o.level <= LEVEL_OP) {
2295
return answer;
2296
} else {
2297
return this.wrapInBraces(answer);
2298
}
2299
};
2300
2301
Op.prototype.compileChain = function(o) {
2302
var fragments, fst, shared, _ref4;
2303
_ref4 = this.first.second.cache(o), this.first.second = _ref4[0], shared = _ref4[1];
2304
fst = this.first.compileToFragments(o, LEVEL_OP);
2305
fragments = fst.concat(this.makeCode(" " + (this.invert ? '&&' : '||') + " "), shared.compileToFragments(o), this.makeCode(" " + this.operator + " "), this.second.compileToFragments(o, LEVEL_OP));
2306
return this.wrapInBraces(fragments);
2307
};
2308
2309
Op.prototype.compileExistence = function(o) {
2310
var fst, ref;
2311
if (!o.isExistentialEquals && this.first.isComplex()) {
2312
ref = new Literal(o.scope.freeVariable('ref'));
2313
fst = new Parens(new Assign(ref, this.first));
2314
} else {
2315
fst = this.first;
2316
ref = fst;
2317
}
2318
return new If(new Existence(fst), ref, {
2319
type: 'if'
2320
}).addElse(this.second).compileToFragments(o);
2321
};
2322
2323
Op.prototype.compileUnary = function(o) {
2324
var op, parts, plusMinus;
2325
parts = [];
2326
op = this.operator;
2327
parts.push([this.makeCode(op)]);
2328
if (op === '!' && this.first instanceof Existence) {
2329
this.first.negated = !this.first.negated;
2330
return this.first.compileToFragments(o);
2331
}
2332
if (o.level >= LEVEL_ACCESS) {
2333
return (new Parens(this)).compileToFragments(o);
2334
}
2335
plusMinus = op === '+' || op === '-';
2336
if ((op === 'new' || op === 'typeof' || op === 'delete') || plusMinus && this.first instanceof Op && this.first.operator === op) {
2337
parts.push([this.makeCode(' ')]);
2338
}
2339
if ((plusMinus && this.first instanceof Op) || (op === 'new' && this.first.isStatement(o))) {
2340
this.first = new Parens(this.first);
2341
}
2342
parts.push(this.first.compileToFragments(o, LEVEL_OP));
2343
if (this.flip) {
2344
parts.reverse();
2345
}
2346
return this.joinFragmentArrays(parts, '');
2347
};
2348
2349
Op.prototype.toString = function(idt) {
2350
return Op.__super__.toString.call(this, idt, this.constructor.name + ' ' + this.operator);
2351
};
2352
2353
return Op;
2354
2355
})(Base);
2356
2357
exports.In = In = (function(_super) {
2358
__extends(In, _super);
2359
2360
function In(object, array) {
2361
this.object = object;
2362
this.array = array;
2363
}
2364
2365
In.prototype.children = ['object', 'array'];
2366
2367
In.prototype.invert = NEGATE;
2368
2369
In.prototype.compileNode = function(o) {
2370
var hasSplat, obj, _i, _len, _ref4;
2371
if (this.array instanceof Value && this.array.isArray()) {
2372
_ref4 = this.array.base.objects;
2373
for (_i = 0, _len = _ref4.length; _i < _len; _i++) {
2374
obj = _ref4[_i];
2375
if (!(obj instanceof Splat)) {
2376
continue;
2377
}
2378
hasSplat = true;
2379
break;
2380
}
2381
if (!hasSplat) {
2382
return this.compileOrTest(o);
2383
}
2384
}
2385
return this.compileLoopTest(o);
2386
};
2387
2388
In.prototype.compileOrTest = function(o) {
2389
var cmp, cnj, i, item, ref, sub, tests, _i, _len, _ref4, _ref5, _ref6;
2390
if (this.array.base.objects.length === 0) {
2391
return [this.makeCode("" + (!!this.negated))];
2392
}
2393
_ref4 = this.object.cache(o, LEVEL_OP), sub = _ref4[0], ref = _ref4[1];
2394
_ref5 = this.negated ? [' !== ', ' && '] : [' === ', ' || '], cmp = _ref5[0], cnj = _ref5[1];
2395
tests = [];
2396
_ref6 = this.array.base.objects;
2397
for (i = _i = 0, _len = _ref6.length; _i < _len; i = ++_i) {
2398
item = _ref6[i];
2399
if (i) {
2400
tests.push(this.makeCode(cnj));
2401
}
2402
tests = tests.concat((i ? ref : sub), this.makeCode(cmp), item.compileToFragments(o, LEVEL_ACCESS));
2403
}
2404
if (o.level < LEVEL_OP) {
2405
return tests;
2406
} else {
2407
return this.wrapInBraces(tests);
2408
}
2409
};
2410
2411
In.prototype.compileLoopTest = function(o) {
2412
var fragments, ref, sub, _ref4;
2413
_ref4 = this.object.cache(o, LEVEL_LIST), sub = _ref4[0], ref = _ref4[1];
2414
fragments = [].concat(this.makeCode(utility('indexOf') + ".call("), this.array.compileToFragments(o, LEVEL_LIST), this.makeCode(", "), ref, this.makeCode(") " + (this.negated ? '< 0' : '>= 0')));
2415
if (fragmentsToText(sub) === fragmentsToText(ref)) {
2416
return fragments;
2417
}
2418
fragments = sub.concat(this.makeCode(', '), fragments);
2419
if (o.level < LEVEL_LIST) {
2420
return fragments;
2421
} else {
2422
return this.wrapInBraces(fragments);
2423
}
2424
};
2425
2426
In.prototype.toString = function(idt) {
2427
return In.__super__.toString.call(this, idt, this.constructor.name + (this.negated ? '!' : ''));
2428
};
2429
2430
return In;
2431
2432
})(Base);
2433
2434
exports.Try = Try = (function(_super) {
2435
__extends(Try, _super);
2436
2437
function Try(attempt, errorVariable, recovery, ensure) {
2438
this.attempt = attempt;
2439
this.errorVariable = errorVariable;
2440
this.recovery = recovery;
2441
this.ensure = ensure;
2442
}
2443
2444
Try.prototype.children = ['attempt', 'recovery', 'ensure'];
2445
2446
Try.prototype.isStatement = YES;
2447
2448
Try.prototype.jumps = function(o) {
2449
var _ref4;
2450
return this.attempt.jumps(o) || ((_ref4 = this.recovery) != null ? _ref4.jumps(o) : void 0);
2451
};
2452
2453
Try.prototype.makeReturn = function(res) {
2454
if (this.attempt) {
2455
this.attempt = this.attempt.makeReturn(res);
2456
}
2457
if (this.recovery) {
2458
this.recovery = this.recovery.makeReturn(res);
2459
}
2460
return this;
2461
};
2462
2463
Try.prototype.compileNode = function(o) {
2464
var catchPart, ensurePart, placeholder, tryPart;
2465
o.indent += TAB;
2466
tryPart = this.attempt.compileToFragments(o, LEVEL_TOP);
2467
catchPart = this.recovery ? (placeholder = new Literal('_error'), this.errorVariable ? this.recovery.unshift(new Assign(this.errorVariable, placeholder)) : void 0, [].concat(this.makeCode(" catch ("), placeholder.compileToFragments(o), this.makeCode(") {\n"), this.recovery.compileToFragments(o, LEVEL_TOP), this.makeCode("\n" + this.tab + "}"))) : !(this.ensure || this.recovery) ? [this.makeCode(' catch (_error) {}')] : [];
2468
ensurePart = this.ensure ? [].concat(this.makeCode(" finally {\n"), this.ensure.compileToFragments(o, LEVEL_TOP), this.makeCode("\n" + this.tab + "}")) : [];
2469
return [].concat(this.makeCode("" + this.tab + "try {\n"), tryPart, this.makeCode("\n" + this.tab + "}"), catchPart, ensurePart);
2470
};
2471
2472
return Try;
2473
2474
})(Base);
2475
2476
exports.Throw = Throw = (function(_super) {
2477
__extends(Throw, _super);
2478
2479
function Throw(expression) {
2480
this.expression = expression;
2481
}
2482
2483
Throw.prototype.children = ['expression'];
2484
2485
Throw.prototype.isStatement = YES;
2486
2487
Throw.prototype.jumps = NO;
2488
2489
Throw.prototype.makeReturn = THIS;
2490
2491
Throw.prototype.compileNode = function(o) {
2492
return [].concat(this.makeCode(this.tab + "throw "), this.expression.compileToFragments(o), this.makeCode(";"));
2493
};
2494
2495
return Throw;
2496
2497
})(Base);
2498
2499
exports.Existence = Existence = (function(_super) {
2500
__extends(Existence, _super);
2501
2502
function Existence(expression) {
2503
this.expression = expression;
2504
}
2505
2506
Existence.prototype.children = ['expression'];
2507
2508
Existence.prototype.invert = NEGATE;
2509
2510
Existence.prototype.compileNode = function(o) {
2511
var cmp, cnj, code, _ref4;
2512
this.expression.front = this.front;
2513
code = this.expression.compile(o, LEVEL_OP);
2514
if (IDENTIFIER.test(code) && !o.scope.check(code)) {
2515
_ref4 = this.negated ? ['===', '||'] : ['!==', '&&'], cmp = _ref4[0], cnj = _ref4[1];
2516
code = "typeof " + code + " " + cmp + " \"undefined\" " + cnj + " " + code + " " + cmp + " null";
2517
} else {
2518
code = "" + code + " " + (this.negated ? '==' : '!=') + " null";
2519
}
2520
return [this.makeCode(o.level <= LEVEL_COND ? code : "(" + code + ")")];
2521
};
2522
2523
return Existence;
2524
2525
})(Base);
2526
2527
exports.Parens = Parens = (function(_super) {
2528
__extends(Parens, _super);
2529
2530
function Parens(body) {
2531
this.body = body;
2532
}
2533
2534
Parens.prototype.children = ['body'];
2535
2536
Parens.prototype.unwrap = function() {
2537
return this.body;
2538
};
2539
2540
Parens.prototype.isComplex = function() {
2541
return this.body.isComplex();
2542
};
2543
2544
Parens.prototype.compileNode = function(o) {
2545
var bare, expr, fragments;
2546
expr = this.body.unwrap();
2547
if (expr instanceof Value && expr.isAtomic()) {
2548
expr.front = this.front;
2549
return expr.compileToFragments(o);
2550
}
2551
fragments = expr.compileToFragments(o, LEVEL_PAREN);
2552
bare = o.level < LEVEL_OP && (expr instanceof Op || expr instanceof Call || (expr instanceof For && expr.returns));
2553
if (bare) {
2554
return fragments;
2555
} else {
2556
return this.wrapInBraces(fragments);
2557
}
2558
};
2559
2560
return Parens;
2561
2562
})(Base);
2563
2564
exports.For = For = (function(_super) {
2565
__extends(For, _super);
2566
2567
function For(body, source) {
2568
var _ref4;
2569
this.source = source.source, this.guard = source.guard, this.step = source.step, this.name = source.name, this.index = source.index;
2570
this.body = Block.wrap([body]);
2571
this.own = !!source.own;
2572
this.object = !!source.object;
2573
if (this.object) {
2574
_ref4 = [this.index, this.name], this.name = _ref4[0], this.index = _ref4[1];
2575
}
2576
if (this.index instanceof Value) {
2577
this.index.error('index cannot be a pattern matching expression');
2578
}
2579
this.range = this.source instanceof Value && this.source.base instanceof Range && !this.source.properties.length;
2580
this.pattern = this.name instanceof Value;
2581
if (this.range && this.index) {
2582
this.index.error('indexes do not apply to range loops');
2583
}
2584
if (this.range && this.pattern) {
2585
this.name.error('cannot pattern match over range loops');
2586
}
2587
if (this.own && !this.object) {
2588
this.index.error('cannot use own with for-in');
2589
}
2590
this.returns = false;
2591
}
2592
2593
For.prototype.children = ['body', 'source', 'guard', 'step'];
2594
2595
For.prototype.compileNode = function(o) {
2596
var body, bodyFragments, compare, compareDown, declare, declareDown, defPart, defPartFragments, down, forPartFragments, guardPart, idt1, increment, index, ivar, kvar, kvarAssign, lastJumps, lvar, name, namePart, ref, resultPart, returnResult, rvar, scope, source, step, stepNum, stepVar, svar, varPart, _ref4, _ref5;
2597
body = Block.wrap([this.body]);
2598
lastJumps = (_ref4 = last(body.expressions)) != null ? _ref4.jumps() : void 0;
2599
if (lastJumps && lastJumps instanceof Return) {
2600
this.returns = false;
2601
}
2602
source = this.range ? this.source.base : this.source;
2603
scope = o.scope;
2604
name = this.name && (this.name.compile(o, LEVEL_LIST));
2605
index = this.index && (this.index.compile(o, LEVEL_LIST));
2606
if (name && !this.pattern) {
2607
scope.find(name);
2608
}
2609
if (index) {
2610
scope.find(index);
2611
}
2612
if (this.returns) {
2613
rvar = scope.freeVariable('results');
2614
}
2615
ivar = (this.object && index) || scope.freeVariable('i');
2616
kvar = (this.range && name) || index || ivar;
2617
kvarAssign = kvar !== ivar ? "" + kvar + " = " : "";
2618
if (this.step && !this.range) {
2619
_ref5 = this.cacheToCodeFragments(this.step.cache(o, LEVEL_LIST)), step = _ref5[0], stepVar = _ref5[1];
2620
stepNum = stepVar.match(SIMPLENUM);
2621
}
2622
if (this.pattern) {
2623
name = ivar;
2624
}
2625
varPart = '';
2626
guardPart = '';
2627
defPart = '';
2628
idt1 = this.tab + TAB;
2629
if (this.range) {
2630
forPartFragments = source.compileToFragments(merge(o, {
2631
index: ivar,
2632
name: name,
2633
step: this.step
2634
}));
2635
} else {
2636
svar = this.source.compile(o, LEVEL_LIST);
2637
if ((name || this.own) && !IDENTIFIER.test(svar)) {
2638
defPart += "" + this.tab + (ref = scope.freeVariable('ref')) + " = " + svar + ";\n";
2639
svar = ref;
2640
}
2641
if (name && !this.pattern) {
2642
namePart = "" + name + " = " + svar + "[" + kvar + "]";
2643
}
2644
if (!this.object) {
2645
if (step !== stepVar) {
2646
defPart += "" + this.tab + step + ";\n";
2647
}
2648
if (!(this.step && stepNum && (down = +stepNum < 0))) {
2649
lvar = scope.freeVariable('len');
2650
}
2651
declare = "" + kvarAssign + ivar + " = 0, " + lvar + " = " + svar + ".length";
2652
declareDown = "" + kvarAssign + ivar + " = " + svar + ".length - 1";
2653
compare = "" + ivar + " < " + lvar;
2654
compareDown = "" + ivar + " >= 0";
2655
if (this.step) {
2656
if (stepNum) {
2657
if (down) {
2658
compare = compareDown;
2659
declare = declareDown;
2660
}
2661
} else {
2662
compare = "" + stepVar + " > 0 ? " + compare + " : " + compareDown;
2663
declare = "(" + stepVar + " > 0 ? (" + declare + ") : " + declareDown + ")";
2664
}
2665
increment = "" + ivar + " += " + stepVar;
2666
} else {
2667
increment = "" + (kvar !== ivar ? "++" + ivar : "" + ivar + "++");
2668
}
2669
forPartFragments = [this.makeCode("" + declare + "; " + compare + "; " + kvarAssign + increment)];
2670
}
2671
}
2672
if (this.returns) {
2673
resultPart = "" + this.tab + rvar + " = [];\n";
2674
returnResult = "\n" + this.tab + "return " + rvar + ";";
2675
body.makeReturn(rvar);
2676
}
2677
if (this.guard) {
2678
if (body.expressions.length > 1) {
2679
body.expressions.unshift(new If((new Parens(this.guard)).invert(), new Literal("continue")));
2680
} else {
2681
if (this.guard) {
2682
body = Block.wrap([new If(this.guard, body)]);
2683
}
2684
}
2685
}
2686
if (this.pattern) {
2687
body.expressions.unshift(new Assign(this.name, new Literal("" + svar + "[" + kvar + "]")));
2688
}
2689
defPartFragments = [].concat(this.makeCode(defPart), this.pluckDirectCall(o, body));
2690
if (namePart) {
2691
varPart = "\n" + idt1 + namePart + ";";
2692
}
2693
if (this.object) {
2694
forPartFragments = [this.makeCode("" + kvar + " in " + svar)];
2695
if (this.own) {
2696
guardPart = "\n" + idt1 + "if (!" + (utility('hasProp')) + ".call(" + svar + ", " + kvar + ")) continue;";
2697
}
2698
}
2699
bodyFragments = body.compileToFragments(merge(o, {
2700
indent: idt1
2701
}), LEVEL_TOP);
2702
if (bodyFragments && (bodyFragments.length > 0)) {
2703
bodyFragments = [].concat(this.makeCode("\n"), bodyFragments, this.makeCode("\n"));
2704
}
2705
return [].concat(defPartFragments, this.makeCode("" + (resultPart || '') + this.tab + "for ("), forPartFragments, this.makeCode(") {" + guardPart + varPart), bodyFragments, this.makeCode("" + this.tab + "}" + (returnResult || '')));
2706
};
2707
2708
For.prototype.pluckDirectCall = function(o, body) {
2709
var base, defs, expr, fn, idx, ref, val, _i, _len, _ref4, _ref5, _ref6, _ref7, _ref8, _ref9;
2710
defs = [];
2711
_ref4 = body.expressions;
2712
for (idx = _i = 0, _len = _ref4.length; _i < _len; idx = ++_i) {
2713
expr = _ref4[idx];
2714
expr = expr.unwrapAll();
2715
if (!(expr instanceof Call)) {
2716
continue;
2717
}
2718
val = expr.variable.unwrapAll();
2719
if (!((val instanceof Code) || (val instanceof Value && ((_ref5 = val.base) != null ? _ref5.unwrapAll() : void 0) instanceof Code && val.properties.length === 1 && ((_ref6 = (_ref7 = val.properties[0].name) != null ? _ref7.value : void 0) === 'call' || _ref6 === 'apply')))) {
2720
continue;
2721
}
2722
fn = ((_ref8 = val.base) != null ? _ref8.unwrapAll() : void 0) || val;
2723
ref = new Literal(o.scope.freeVariable('fn'));
2724
base = new Value(ref);
2725
if (val.base) {
2726
_ref9 = [base, val], val.base = _ref9[0], base = _ref9[1];
2727
}
2728
body.expressions[idx] = new Call(base, expr.args);
2729
defs = defs.concat(this.makeCode(this.tab), new Assign(ref, fn).compileToFragments(o, LEVEL_TOP), this.makeCode(';\n'));
2730
}
2731
return defs;
2732
};
2733
2734
return For;
2735
2736
})(While);
2737
2738
exports.Switch = Switch = (function(_super) {
2739
__extends(Switch, _super);
2740
2741
function Switch(subject, cases, otherwise) {
2742
this.subject = subject;
2743
this.cases = cases;
2744
this.otherwise = otherwise;
2745
}
2746
2747
Switch.prototype.children = ['subject', 'cases', 'otherwise'];
2748
2749
Switch.prototype.isStatement = YES;
2750
2751
Switch.prototype.jumps = function(o) {
2752
var block, conds, _i, _len, _ref4, _ref5, _ref6;
2753
if (o == null) {
2754
o = {
2755
block: true
2756
};
2757
}
2758
_ref4 = this.cases;
2759
for (_i = 0, _len = _ref4.length; _i < _len; _i++) {
2760
_ref5 = _ref4[_i], conds = _ref5[0], block = _ref5[1];
2761
if (block.jumps(o)) {
2762
return block;
2763
}
2764
}
2765
return (_ref6 = this.otherwise) != null ? _ref6.jumps(o) : void 0;
2766
};
2767
2768
Switch.prototype.makeReturn = function(res) {
2769
var pair, _i, _len, _ref4, _ref5;
2770
_ref4 = this.cases;
2771
for (_i = 0, _len = _ref4.length; _i < _len; _i++) {
2772
pair = _ref4[_i];
2773
pair[1].makeReturn(res);
2774
}
2775
if (res) {
2776
this.otherwise || (this.otherwise = new Block([new Literal('void 0')]));
2777
}
2778
if ((_ref5 = this.otherwise) != null) {
2779
_ref5.makeReturn(res);
2780
}
2781
return this;
2782
};
2783
2784
Switch.prototype.compileNode = function(o) {
2785
var block, body, cond, conditions, expr, fragments, i, idt1, idt2, _i, _j, _len, _len1, _ref4, _ref5, _ref6;
2786
idt1 = o.indent + TAB;
2787
idt2 = o.indent = idt1 + TAB;
2788
fragments = [].concat(this.makeCode(this.tab + "switch ("), (this.subject ? this.subject.compileToFragments(o, LEVEL_PAREN) : this.makeCode("false")), this.makeCode(") {\n"));
2789
_ref4 = this.cases;
2790
for (i = _i = 0, _len = _ref4.length; _i < _len; i = ++_i) {
2791
_ref5 = _ref4[i], conditions = _ref5[0], block = _ref5[1];
2792
_ref6 = flatten([conditions]);
2793
for (_j = 0, _len1 = _ref6.length; _j < _len1; _j++) {
2794
cond = _ref6[_j];
2795
if (!this.subject) {
2796
cond = cond.invert();
2797
}
2798
fragments = fragments.concat(this.makeCode(idt1 + "case "), cond.compileToFragments(o, LEVEL_PAREN), this.makeCode(":\n"));
2799
}
2800
if ((body = block.compileToFragments(o, LEVEL_TOP)).length > 0) {
2801
fragments = fragments.concat(body, this.makeCode('\n'));
2802
}
2803
if (i === this.cases.length - 1 && !this.otherwise) {
2804
break;
2805
}
2806
expr = this.lastNonComment(block.expressions);
2807
if (expr instanceof Return || (expr instanceof Literal && expr.jumps() && expr.value !== 'debugger')) {
2808
continue;
2809
}
2810
fragments.push(cond.makeCode(idt2 + 'break;\n'));
2811
}
2812
if (this.otherwise && this.otherwise.expressions.length) {
2813
fragments.push.apply(fragments, [this.makeCode(idt1 + "default:\n")].concat(__slice.call(this.otherwise.compileToFragments(o, LEVEL_TOP)), [this.makeCode("\n")]));
2814
}
2815
fragments.push(this.makeCode(this.tab + '}'));
2816
return fragments;
2817
};
2818
2819
return Switch;
2820
2821
})(Base);
2822
2823
exports.If = If = (function(_super) {
2824
__extends(If, _super);
2825
2826
function If(condition, body, options) {
2827
this.body = body;
2828
if (options == null) {
2829
options = {};
2830
}
2831
this.condition = options.type === 'unless' ? condition.invert() : condition;
2832
this.elseBody = null;
2833
this.isChain = false;
2834
this.soak = options.soak;
2835
}
2836
2837
If.prototype.children = ['condition', 'body', 'elseBody'];
2838
2839
If.prototype.bodyNode = function() {
2840
var _ref4;
2841
return (_ref4 = this.body) != null ? _ref4.unwrap() : void 0;
2842
};
2843
2844
If.prototype.elseBodyNode = function() {
2845
var _ref4;
2846
return (_ref4 = this.elseBody) != null ? _ref4.unwrap() : void 0;
2847
};
2848
2849
If.prototype.addElse = function(elseBody) {
2850
if (this.isChain) {
2851
this.elseBodyNode().addElse(elseBody);
2852
} else {
2853
this.isChain = elseBody instanceof If;
2854
this.elseBody = this.ensureBlock(elseBody);
2855
}
2856
return this;
2857
};
2858
2859
If.prototype.isStatement = function(o) {
2860
var _ref4;
2861
return (o != null ? o.level : void 0) === LEVEL_TOP || this.bodyNode().isStatement(o) || ((_ref4 = this.elseBodyNode()) != null ? _ref4.isStatement(o) : void 0);
2862
};
2863
2864
If.prototype.jumps = function(o) {
2865
var _ref4;
2866
return this.body.jumps(o) || ((_ref4 = this.elseBody) != null ? _ref4.jumps(o) : void 0);
2867
};
2868
2869
If.prototype.compileNode = function(o) {
2870
if (this.isStatement(o)) {
2871
return this.compileStatement(o);
2872
} else {
2873
return this.compileExpression(o);
2874
}
2875
};
2876
2877
If.prototype.makeReturn = function(res) {
2878
if (res) {
2879
this.elseBody || (this.elseBody = new Block([new Literal('void 0')]));
2880
}
2881
this.body && (this.body = new Block([this.body.makeReturn(res)]));
2882
this.elseBody && (this.elseBody = new Block([this.elseBody.makeReturn(res)]));
2883
return this;
2884
};
2885
2886
If.prototype.ensureBlock = function(node) {
2887
if (node instanceof Block) {
2888
return node;
2889
} else {
2890
return new Block([node]);
2891
}
2892
};
2893
2894
If.prototype.compileStatement = function(o) {
2895
var answer, body, child, cond, exeq, ifPart, indent;
2896
child = del(o, 'chainChild');
2897
exeq = del(o, 'isExistentialEquals');
2898
if (exeq) {
2899
return new If(this.condition.invert(), this.elseBodyNode(), {
2900
type: 'if'
2901
}).compileToFragments(o);
2902
}
2903
indent = o.indent + TAB;
2904
cond = this.condition.compileToFragments(o, LEVEL_PAREN);
2905
body = this.ensureBlock(this.body).compileToFragments(merge(o, {
2906
indent: indent
2907
}));
2908
ifPart = [].concat(this.makeCode("if ("), cond, this.makeCode(") {\n"), body, this.makeCode("\n" + this.tab + "}"));
2909
if (!child) {
2910
ifPart.unshift(this.makeCode(this.tab));
2911
}
2912
if (!this.elseBody) {
2913
return ifPart;
2914
}
2915
answer = ifPart.concat(this.makeCode(' else '));
2916
if (this.isChain) {
2917
o.chainChild = true;
2918
answer = answer.concat(this.elseBody.unwrap().compileToFragments(o, LEVEL_TOP));
2919
} else {
2920
answer = answer.concat(this.makeCode("{\n"), this.elseBody.compileToFragments(merge(o, {
2921
indent: indent
2922
}), LEVEL_TOP), this.makeCode("\n" + this.tab + "}"));
2923
}
2924
return answer;
2925
};
2926
2927
If.prototype.compileExpression = function(o) {
2928
var alt, body, cond, fragments;
2929
cond = this.condition.compileToFragments(o, LEVEL_COND);
2930
body = this.bodyNode().compileToFragments(o, LEVEL_LIST);
2931
alt = this.elseBodyNode() ? this.elseBodyNode().compileToFragments(o, LEVEL_LIST) : [this.makeCode('void 0')];
2932
fragments = cond.concat(this.makeCode(" ? "), body, this.makeCode(" : "), alt);
2933
if (o.level >= LEVEL_COND) {
2934
return this.wrapInBraces(fragments);
2935
} else {
2936
return fragments;
2937
}
2938
};
2939
2940
If.prototype.unfoldSoak = function() {
2941
return this.soak && this;
2942
};
2943
2944
return If;
2945
2946
})(Base);
2947
2948
Closure = {
2949
wrap: function(expressions, statement, noReturn) {
2950
var args, argumentsNode, call, func, meth;
2951
if (expressions.jumps()) {
2952
return expressions;
2953
}
2954
func = new Code([], Block.wrap([expressions]));
2955
args = [];
2956
argumentsNode = expressions.contains(this.isLiteralArguments);
2957
if (argumentsNode && expressions.classBody) {
2958
argumentsNode.error("Class bodies shouldn't reference arguments");
2959
}
2960
if (argumentsNode || expressions.contains(this.isLiteralThis)) {
2961
meth = new Literal(argumentsNode ? 'apply' : 'call');
2962
args = [new Literal('this')];
2963
if (argumentsNode) {
2964
args.push(new Literal('arguments'));
2965
}
2966
func = new Value(func, [new Access(meth)]);
2967
}
2968
func.noReturn = noReturn;
2969
call = new Call(func, args);
2970
if (statement) {
2971
return Block.wrap([call]);
2972
} else {
2973
return call;
2974
}
2975
},
2976
isLiteralArguments: function(node) {
2977
return node instanceof Literal && node.value === 'arguments' && !node.asKey;
2978
},
2979
isLiteralThis: function(node) {
2980
return (node instanceof Literal && node.value === 'this' && !node.asKey) || (node instanceof Code && node.bound) || (node instanceof Call && node.isSuper);
2981
}
2982
};
2983
2984
unfoldSoak = function(o, parent, name) {
2985
var ifn;
2986
if (!(ifn = parent[name].unfoldSoak(o))) {
2987
return;
2988
}
2989
parent[name] = ifn.body;
2990
ifn.body = new Value(parent);
2991
return ifn;
2992
};
2993
2994
UTILITIES = {
2995
"extends": function() {
2996
return "function(child, parent) { for (var key in parent) { if (" + (utility('hasProp')) + ".call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; }";
2997
},
2998
bind: function() {
2999
return 'function(fn, me){ return function(){ return fn.apply(me, arguments); }; }';
3000
},
3001
indexOf: function() {
3002
return "[].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; }";
3003
},
3004
hasProp: function() {
3005
return '{}.hasOwnProperty';
3006
},
3007
slice: function() {
3008
return '[].slice';
3009
}
3010
};
3011
3012
LEVEL_TOP = 1;
3013
3014
LEVEL_PAREN = 2;
3015
3016
LEVEL_LIST = 3;
3017
3018
LEVEL_COND = 4;
3019
3020
LEVEL_OP = 5;
3021
3022
LEVEL_ACCESS = 6;
3023
3024
TAB = ' ';
3025
3026
IDENTIFIER_STR = "[$A-Za-z_\\x7f-\\uffff][$\\w\\x7f-\\uffff]*";
3027
3028
IDENTIFIER = RegExp("^" + IDENTIFIER_STR + "$");
3029
3030
SIMPLENUM = /^[+-]?\d+$/;
3031
3032
METHOD_DEF = RegExp("^(?:(" + IDENTIFIER_STR + ")\\.prototype(?:\\.(" + IDENTIFIER_STR + ")|\\[(\"(?:[^\\\\\"\\r\\n]|\\\\.)*\"|'(?:[^\\\\'\\r\\n]|\\\\.)*')\\]|\\[(0x[\\da-fA-F]+|\\d*\\.?\\d+(?:[eE][+-]?\\d+)?)\\]))|(" + IDENTIFIER_STR + ")$");
3033
3034
IS_STRING = /^['"]/;
3035
3036
utility = function(name) {
3037
var ref;
3038
ref = "__" + name;
3039
Scope.root.assign(ref, UTILITIES[name]());
3040
return ref;
3041
};
3042
3043
multident = function(code, tab) {
3044
code = code.replace(/\n/g, '$&' + tab);
3045
return code.replace(/\s+$/, '');
3046
};
3047
3048
}).call(this);
3049
3050