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