style-script 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/LICENSE +22 -0
- data/bin/style +5 -0
- data/examples/blocks.style +57 -0
- data/examples/code.style +173 -0
- data/examples/hello.style +1 -0
- data/examples/poignant.style +186 -0
- data/examples/potion.style +205 -0
- data/examples/underscore.style +603 -0
- data/lib/style-script.rb +21 -0
- data/lib/style_script/command_line.rb +235 -0
- data/lib/style_script/grammar.y +491 -0
- data/lib/style_script/lexer.js +363 -0
- data/lib/style_script/lexer.rb +272 -0
- data/lib/style_script/nodes.js +756 -0
- data/lib/style_script/nodes.rb +1079 -0
- data/lib/style_script/parse_error.rb +29 -0
- data/lib/style_script/parser.js +544 -0
- data/lib/style_script/parser.rb +2716 -0
- data/lib/style_script/repl.js +33 -0
- data/lib/style_script/rewriter.js +377 -0
- data/lib/style_script/rewriter.rb +289 -0
- data/lib/style_script/runner.js +11 -0
- data/lib/style_script/scope.js +129 -0
- data/lib/style_script/scope.rb +95 -0
- data/lib/style_script/std/style-script.js +96 -0
- data/lib/style_script/style-script.js +50 -0
- data/lib/style_script/value.rb +64 -0
- data/package.json +8 -0
- data/style-script.gemspec +21 -0
- metadata +93 -0
@@ -0,0 +1,756 @@
|
|
1
|
+
(function(){
|
2
|
+
var AccessorNode, CallNode, CommentNode, Expressions, ExtendsNode, IndexNode, LiteralNode, Node, ReturnNode, TAB, TRAILING_WHITESPACE, ThisNode, ValueNode, any, compact, del, dup, flatten, inherit, merge, statement;
|
3
|
+
var __hasProp = Object.prototype.hasOwnProperty;
|
4
|
+
process.mixin(require('./scope'));
|
5
|
+
// The abstract base class for all StyleScript nodes.
|
6
|
+
// All nodes are implement a "compile_node" method, which performs the
|
7
|
+
// code generation for that node. To compile a node, call the "compile"
|
8
|
+
// method, which wraps "compile_node" in some extra smarts, to know when the
|
9
|
+
// generated code should be wrapped up in a closure. An options hash is passed
|
10
|
+
// and cloned throughout, containing messages from higher in the AST,
|
11
|
+
// information about the current scope, and indentation level.
|
12
|
+
exports.Expressions = function Expressions() {
|
13
|
+
var __a;
|
14
|
+
var arguments = Array.prototype.slice.call(arguments, 0);
|
15
|
+
this.name = this.constructor.name;
|
16
|
+
__a = this.values = arguments;
|
17
|
+
return Expressions === this.constructor ? this : __a;
|
18
|
+
};
|
19
|
+
exports.LiteralNode = function LiteralNode() {
|
20
|
+
var __a;
|
21
|
+
var arguments = Array.prototype.slice.call(arguments, 0);
|
22
|
+
this.name = this.constructor.name;
|
23
|
+
__a = this.values = arguments;
|
24
|
+
return LiteralNode === this.constructor ? this : __a;
|
25
|
+
};
|
26
|
+
exports.ReturnNode = function ReturnNode() {
|
27
|
+
var __a;
|
28
|
+
var arguments = Array.prototype.slice.call(arguments, 0);
|
29
|
+
this.name = this.constructor.name;
|
30
|
+
__a = this.values = arguments;
|
31
|
+
return ReturnNode === this.constructor ? this : __a;
|
32
|
+
};
|
33
|
+
exports.CommentNode = function CommentNode() {
|
34
|
+
var __a;
|
35
|
+
var arguments = Array.prototype.slice.call(arguments, 0);
|
36
|
+
this.name = this.constructor.name;
|
37
|
+
__a = this.values = arguments;
|
38
|
+
return CommentNode === this.constructor ? this : __a;
|
39
|
+
};
|
40
|
+
exports.CallNode = function CallNode() {
|
41
|
+
var __a;
|
42
|
+
var arguments = Array.prototype.slice.call(arguments, 0);
|
43
|
+
this.name = this.constructor.name;
|
44
|
+
__a = this.values = arguments;
|
45
|
+
return CallNode === this.constructor ? this : __a;
|
46
|
+
};
|
47
|
+
exports.ExtendsNode = function ExtendsNode() {
|
48
|
+
var __a;
|
49
|
+
var arguments = Array.prototype.slice.call(arguments, 0);
|
50
|
+
this.name = this.constructor.name;
|
51
|
+
__a = this.values = arguments;
|
52
|
+
return ExtendsNode === this.constructor ? this : __a;
|
53
|
+
};
|
54
|
+
exports.ValueNode = function ValueNode() {
|
55
|
+
var __a;
|
56
|
+
var arguments = Array.prototype.slice.call(arguments, 0);
|
57
|
+
this.name = this.constructor.name;
|
58
|
+
__a = this.values = arguments;
|
59
|
+
return ValueNode === this.constructor ? this : __a;
|
60
|
+
};
|
61
|
+
exports.AccessorNode = function AccessorNode() {
|
62
|
+
var __a;
|
63
|
+
var arguments = Array.prototype.slice.call(arguments, 0);
|
64
|
+
this.name = this.constructor.name;
|
65
|
+
__a = this.values = arguments;
|
66
|
+
return AccessorNode === this.constructor ? this : __a;
|
67
|
+
};
|
68
|
+
exports.IndexNode = function IndexNode() {
|
69
|
+
var __a;
|
70
|
+
var arguments = Array.prototype.slice.call(arguments, 0);
|
71
|
+
this.name = this.constructor.name;
|
72
|
+
__a = this.values = arguments;
|
73
|
+
return IndexNode === this.constructor ? this : __a;
|
74
|
+
};
|
75
|
+
exports.RangeNode = function RangeNode() {
|
76
|
+
var __a;
|
77
|
+
var arguments = Array.prototype.slice.call(arguments, 0);
|
78
|
+
this.name = this.constructor.name;
|
79
|
+
__a = this.values = arguments;
|
80
|
+
return RangeNode === this.constructor ? this : __a;
|
81
|
+
};
|
82
|
+
exports.SliceNode = function SliceNode() {
|
83
|
+
var __a;
|
84
|
+
var arguments = Array.prototype.slice.call(arguments, 0);
|
85
|
+
this.name = this.constructor.name;
|
86
|
+
__a = this.values = arguments;
|
87
|
+
return SliceNode === this.constructor ? this : __a;
|
88
|
+
};
|
89
|
+
exports.ThisNode = function ThisNode() {
|
90
|
+
var __a;
|
91
|
+
var arguments = Array.prototype.slice.call(arguments, 0);
|
92
|
+
this.name = this.constructor.name;
|
93
|
+
__a = this.values = arguments;
|
94
|
+
return ThisNode === this.constructor ? this : __a;
|
95
|
+
};
|
96
|
+
exports.AssignNode = function AssignNode() {
|
97
|
+
var __a;
|
98
|
+
var arguments = Array.prototype.slice.call(arguments, 0);
|
99
|
+
this.name = this.constructor.name;
|
100
|
+
__a = this.values = arguments;
|
101
|
+
return AssignNode === this.constructor ? this : __a;
|
102
|
+
};
|
103
|
+
exports.OpNode = function OpNode() {
|
104
|
+
var __a;
|
105
|
+
var arguments = Array.prototype.slice.call(arguments, 0);
|
106
|
+
this.name = this.constructor.name;
|
107
|
+
__a = this.values = arguments;
|
108
|
+
return OpNode === this.constructor ? this : __a;
|
109
|
+
};
|
110
|
+
exports.CodeNode = function CodeNode() {
|
111
|
+
var __a;
|
112
|
+
var arguments = Array.prototype.slice.call(arguments, 0);
|
113
|
+
this.name = this.constructor.name;
|
114
|
+
__a = this.values = arguments;
|
115
|
+
return CodeNode === this.constructor ? this : __a;
|
116
|
+
};
|
117
|
+
exports.SplatNode = function SplatNode() {
|
118
|
+
var __a;
|
119
|
+
var arguments = Array.prototype.slice.call(arguments, 0);
|
120
|
+
this.name = this.constructor.name;
|
121
|
+
__a = this.values = arguments;
|
122
|
+
return SplatNode === this.constructor ? this : __a;
|
123
|
+
};
|
124
|
+
exports.ObjectNode = function ObjectNode() {
|
125
|
+
var __a;
|
126
|
+
var arguments = Array.prototype.slice.call(arguments, 0);
|
127
|
+
this.name = this.constructor.name;
|
128
|
+
__a = this.values = arguments;
|
129
|
+
return ObjectNode === this.constructor ? this : __a;
|
130
|
+
};
|
131
|
+
exports.ArrayNode = function ArrayNode() {
|
132
|
+
var __a;
|
133
|
+
var arguments = Array.prototype.slice.call(arguments, 0);
|
134
|
+
this.name = this.constructor.name;
|
135
|
+
__a = this.values = arguments;
|
136
|
+
return ArrayNode === this.constructor ? this : __a;
|
137
|
+
};
|
138
|
+
exports.PushNode = function PushNode() {
|
139
|
+
var __a;
|
140
|
+
var arguments = Array.prototype.slice.call(arguments, 0);
|
141
|
+
this.name = this.constructor.name;
|
142
|
+
__a = this.values = arguments;
|
143
|
+
return PushNode === this.constructor ? this : __a;
|
144
|
+
};
|
145
|
+
exports.ClosureNode = function ClosureNode() {
|
146
|
+
var __a;
|
147
|
+
var arguments = Array.prototype.slice.call(arguments, 0);
|
148
|
+
this.name = this.constructor.name;
|
149
|
+
__a = this.values = arguments;
|
150
|
+
return ClosureNode === this.constructor ? this : __a;
|
151
|
+
};
|
152
|
+
exports.WhileNode = function WhileNode() {
|
153
|
+
var __a;
|
154
|
+
var arguments = Array.prototype.slice.call(arguments, 0);
|
155
|
+
this.name = this.constructor.name;
|
156
|
+
__a = this.values = arguments;
|
157
|
+
return WhileNode === this.constructor ? this : __a;
|
158
|
+
};
|
159
|
+
exports.ForNode = function ForNode() {
|
160
|
+
var __a;
|
161
|
+
var arguments = Array.prototype.slice.call(arguments, 0);
|
162
|
+
this.name = this.constructor.name;
|
163
|
+
__a = this.values = arguments;
|
164
|
+
return ForNode === this.constructor ? this : __a;
|
165
|
+
};
|
166
|
+
exports.TryNode = function TryNode() {
|
167
|
+
var __a;
|
168
|
+
var arguments = Array.prototype.slice.call(arguments, 0);
|
169
|
+
this.name = this.constructor.name;
|
170
|
+
__a = this.values = arguments;
|
171
|
+
return TryNode === this.constructor ? this : __a;
|
172
|
+
};
|
173
|
+
exports.ThrowNode = function ThrowNode() {
|
174
|
+
var __a;
|
175
|
+
var arguments = Array.prototype.slice.call(arguments, 0);
|
176
|
+
this.name = this.constructor.name;
|
177
|
+
__a = this.values = arguments;
|
178
|
+
return ThrowNode === this.constructor ? this : __a;
|
179
|
+
};
|
180
|
+
exports.ExistenceNode = function ExistenceNode() {
|
181
|
+
var __a;
|
182
|
+
var arguments = Array.prototype.slice.call(arguments, 0);
|
183
|
+
this.name = this.constructor.name;
|
184
|
+
__a = this.values = arguments;
|
185
|
+
return ExistenceNode === this.constructor ? this : __a;
|
186
|
+
};
|
187
|
+
exports.ParentheticalNode = function ParentheticalNode() {
|
188
|
+
var __a;
|
189
|
+
var arguments = Array.prototype.slice.call(arguments, 0);
|
190
|
+
this.name = this.constructor.name;
|
191
|
+
__a = this.values = arguments;
|
192
|
+
return ParentheticalNode === this.constructor ? this : __a;
|
193
|
+
};
|
194
|
+
exports.IfNode = function IfNode() {
|
195
|
+
var __a;
|
196
|
+
var arguments = Array.prototype.slice.call(arguments, 0);
|
197
|
+
this.name = this.constructor.name;
|
198
|
+
__a = this.values = arguments;
|
199
|
+
return IfNode === this.constructor ? this : __a;
|
200
|
+
};
|
201
|
+
exports.Expressions.wrap = function wrap(values) {
|
202
|
+
return this.values = values;
|
203
|
+
};
|
204
|
+
// Some helper functions
|
205
|
+
// Tabs are two spaces for pretty printing.
|
206
|
+
TAB = ' ';
|
207
|
+
TRAILING_WHITESPACE = /\s+$/g;
|
208
|
+
// Flatten nested arrays recursively.
|
209
|
+
flatten = function flatten(list) {
|
210
|
+
var __a, __b, item, memo;
|
211
|
+
memo = [];
|
212
|
+
__a = list;
|
213
|
+
for (__b = 0; __b < __a.length; __b++) {
|
214
|
+
item = __a[__b];
|
215
|
+
if (item instanceof Array) {
|
216
|
+
return memo.concat(flatten(item));
|
217
|
+
}
|
218
|
+
memo.push(item);
|
219
|
+
memo;
|
220
|
+
}
|
221
|
+
return memo;
|
222
|
+
};
|
223
|
+
// Remove all null values from an array.
|
224
|
+
compact = function compact(input) {
|
225
|
+
var __a, __b, __c, item;
|
226
|
+
__a = []; __b = input;
|
227
|
+
for (__c = 0; __c < __b.length; __c++) {
|
228
|
+
item = __b[__c];
|
229
|
+
if ((typeof item !== "undefined" && item !== null)) {
|
230
|
+
__a.push(item);
|
231
|
+
}
|
232
|
+
}
|
233
|
+
return __a;
|
234
|
+
};
|
235
|
+
// Dup an array or object.
|
236
|
+
dup = function dup(input) {
|
237
|
+
var __a, __b, __c, __d, key, output, val;
|
238
|
+
if (input instanceof Array) {
|
239
|
+
__a = []; __b = input;
|
240
|
+
for (__c = 0; __c < __b.length; __c++) {
|
241
|
+
val = __b[__c];
|
242
|
+
__a.push(val);
|
243
|
+
}
|
244
|
+
return __a;
|
245
|
+
} else {
|
246
|
+
output = {
|
247
|
+
};
|
248
|
+
__d = input;
|
249
|
+
for (key in __d) {
|
250
|
+
val = __d[key];
|
251
|
+
if (__hasProp.call(__d, key)) {
|
252
|
+
((output[key] = val));
|
253
|
+
}
|
254
|
+
}
|
255
|
+
return output;
|
256
|
+
}
|
257
|
+
};
|
258
|
+
// Merge objects.
|
259
|
+
merge = function merge(src, dest) {
|
260
|
+
var __a, key, val;
|
261
|
+
__a = src;
|
262
|
+
for (key in __a) {
|
263
|
+
val = __a[key];
|
264
|
+
if (__hasProp.call(__a, key)) {
|
265
|
+
((dest[key] = val));
|
266
|
+
}
|
267
|
+
}
|
268
|
+
return dest;
|
269
|
+
};
|
270
|
+
// Do any of the elements in the list pass a truth test?
|
271
|
+
any = function any(list, test) {
|
272
|
+
var __a, __b, __c, item, result;
|
273
|
+
result = (function() {
|
274
|
+
__a = []; __b = list;
|
275
|
+
for (__c = 0; __c < __b.length; __c++) {
|
276
|
+
item = __b[__c];
|
277
|
+
if (test(item)) {
|
278
|
+
__a.push(true);
|
279
|
+
}
|
280
|
+
}
|
281
|
+
return __a;
|
282
|
+
}).call(this);
|
283
|
+
return !!result.length;
|
284
|
+
};
|
285
|
+
// Delete a key from an object, returning the value.
|
286
|
+
del = function del(obj, key) {
|
287
|
+
var val;
|
288
|
+
val = obj[key];
|
289
|
+
delete obj[key];
|
290
|
+
return val;
|
291
|
+
};
|
292
|
+
// Quickie inheritance convenience wrapper to reduce typing.
|
293
|
+
inherit = function inherit(parent, props) {
|
294
|
+
var __a, __b, klass, name, prop;
|
295
|
+
klass = del(props, 'constructor');
|
296
|
+
__a = function(){};
|
297
|
+
__a.prototype = parent.prototype;
|
298
|
+
klass.__superClass__ = parent.prototype;
|
299
|
+
klass.prototype = new __a();
|
300
|
+
klass.prototype.constructor = klass;
|
301
|
+
__b = props;
|
302
|
+
for (name in __b) {
|
303
|
+
prop = __b[name];
|
304
|
+
if (__hasProp.call(__b, name)) {
|
305
|
+
((klass.prototype[name] = prop));
|
306
|
+
}
|
307
|
+
}
|
308
|
+
return klass;
|
309
|
+
};
|
310
|
+
// # Provide a quick implementation of a children method.
|
311
|
+
// children: (klass, attrs...) ->
|
312
|
+
// klass::children: ->
|
313
|
+
// nodes: this[attr] for attr in attrs
|
314
|
+
// compact flatten nodes
|
315
|
+
// Mark a node as a statement, or a statement only.
|
316
|
+
statement = function statement(klass, only) {
|
317
|
+
klass.prototype.is_statement = function is_statement() {
|
318
|
+
return true;
|
319
|
+
};
|
320
|
+
if (only) {
|
321
|
+
return ((klass.prototype.is_statement_only = function is_statement_only() {
|
322
|
+
return true;
|
323
|
+
}));
|
324
|
+
}
|
325
|
+
};
|
326
|
+
// The abstract base class for all StyleScript nodes.
|
327
|
+
// All nodes are implement a "compile_node" method, which performs the
|
328
|
+
// code generation for that node. To compile a node, call the "compile"
|
329
|
+
// method, which wraps "compile_node" in some extra smarts, to know when the
|
330
|
+
// generated code should be wrapped up in a closure. An options hash is passed
|
331
|
+
// and cloned throughout, containing messages from higher in the AST,
|
332
|
+
// information about the current scope, and indentation level.
|
333
|
+
Node = (exports.Node = function Node() { });
|
334
|
+
// This is extremely important -- we convert JS statements into expressions
|
335
|
+
// by wrapping them in a closure, only if it's possible, and we're not at
|
336
|
+
// the top level of a block (which would be unnecessary), and we haven't
|
337
|
+
// already been asked to return the result.
|
338
|
+
Node.prototype.compile = function compile(o) {
|
339
|
+
var closure, top;
|
340
|
+
this.options = dup(o || {
|
341
|
+
});
|
342
|
+
this.indent = o.indent;
|
343
|
+
top = this.top_sensitive() ? o.top : del(o, 'top');
|
344
|
+
closure = this.is_statement() && !this.is_statement_only() && !top && !o.returns && !this instanceof CommentNode && !this.contains(function(node) {
|
345
|
+
return node.is_statement_only();
|
346
|
+
});
|
347
|
+
return closure ? this.compile_closure(this.options) : this.compile_node(this.options);
|
348
|
+
};
|
349
|
+
// Statements converted into expressions share scope with their parent
|
350
|
+
// closure, to preserve JavaScript-style lexical scope.
|
351
|
+
Node.prototype.compile_closure = function compile_closure(o) {
|
352
|
+
this.indent = o.indent;
|
353
|
+
o.shared_scope = o.scope;
|
354
|
+
return ClosureNode.wrap(this).compile(o);
|
355
|
+
};
|
356
|
+
// Quick short method for the current indentation level, plus tabbing in.
|
357
|
+
Node.prototype.idt = function idt(tabs) {
|
358
|
+
var __a, __b, __c, __d, i, idt;
|
359
|
+
idt = (this.indent || '');
|
360
|
+
__c = 0; __d = (tabs || 0);
|
361
|
+
for (__b=0, i=__c; (__c <= __d ? i < __d : i > __d); (__c <= __d ? i += 1 : i -= 1), __b++) {
|
362
|
+
idt += TAB;
|
363
|
+
}
|
364
|
+
return idt;
|
365
|
+
};
|
366
|
+
// Does this node, or any of its children, contain a node of a certain kind?
|
367
|
+
Node.prototype.contains = function contains(block) {
|
368
|
+
var __a, __b, node;
|
369
|
+
__a = this.children;
|
370
|
+
for (__b = 0; __b < __a.length; __b++) {
|
371
|
+
node = __a[__b];
|
372
|
+
if (block(node)) {
|
373
|
+
return true;
|
374
|
+
}
|
375
|
+
if (node instanceof Node && node.contains(block)) {
|
376
|
+
return true;
|
377
|
+
}
|
378
|
+
}
|
379
|
+
return false;
|
380
|
+
};
|
381
|
+
// Default implementations of the common node methods.
|
382
|
+
Node.prototype.unwrap = function unwrap() {
|
383
|
+
return this;
|
384
|
+
};
|
385
|
+
Node.prototype.children = [];
|
386
|
+
Node.prototype.is_statement = function is_statement() {
|
387
|
+
return false;
|
388
|
+
};
|
389
|
+
Node.prototype.is_statement_only = function is_statement_only() {
|
390
|
+
return false;
|
391
|
+
};
|
392
|
+
Node.prototype.top_sensitive = function top_sensitive() {
|
393
|
+
return false;
|
394
|
+
};
|
395
|
+
// A collection of nodes, each one representing an expression.
|
396
|
+
Expressions = (exports.Expressions = inherit(Node, {
|
397
|
+
constructor: function constructor(nodes) {
|
398
|
+
this.expressions = flatten(nodes);
|
399
|
+
this.children = this.expressions;
|
400
|
+
return this;
|
401
|
+
},
|
402
|
+
// Tack an expression on to the end of this expression list.
|
403
|
+
push: function push(node) {
|
404
|
+
this.expressions.push(node);
|
405
|
+
return this;
|
406
|
+
},
|
407
|
+
// Tack an expression on to the beginning of this expression list.
|
408
|
+
unshift: function unshift(node) {
|
409
|
+
this.expressions.unshift(node);
|
410
|
+
return this;
|
411
|
+
},
|
412
|
+
// If this Expressions consists of a single node, pull it back out.
|
413
|
+
unwrap: function unwrap() {
|
414
|
+
return this.expressions.length === 1 ? this.expressions[0] : this;
|
415
|
+
},
|
416
|
+
// Is this an empty block of code?
|
417
|
+
empty: function empty() {
|
418
|
+
return this.expressions.length === 0;
|
419
|
+
},
|
420
|
+
// Is the node last in this block of expressions?
|
421
|
+
is_last: function is_last(node) {
|
422
|
+
var l;
|
423
|
+
l = this.expressions.length;
|
424
|
+
this.last_index = this.last_index || this.expressions[l - 1] instanceof CommentNode ? -2 : -1;
|
425
|
+
return node === this.expressions[l - this.last_index];
|
426
|
+
},
|
427
|
+
compile: function compile(o) {
|
428
|
+
return o.scope ? compile.__superClass__.constructor.call(this, o) : this.compile_root(o);
|
429
|
+
},
|
430
|
+
// Compile each expression in the Expressions body.
|
431
|
+
compile_node: function compile_node(o) {
|
432
|
+
var __a, __b, __c, node;
|
433
|
+
return ((function() {
|
434
|
+
__a = []; __b = this.expressions;
|
435
|
+
for (__c = 0; __c < __b.length; __c++) {
|
436
|
+
node = __b[__c];
|
437
|
+
__a.push(this.compile_expression(node, dup(o)));
|
438
|
+
}
|
439
|
+
return __a;
|
440
|
+
}).call(this)).join("\n");
|
441
|
+
},
|
442
|
+
// If this is the top-level Expressions, wrap everything in a safety closure.
|
443
|
+
compile_root: function compile_root(o) {
|
444
|
+
var code, indent;
|
445
|
+
o.indent = (this.indent = (indent = o.no_wrap ? '' : TAB));
|
446
|
+
o.scope = new Scope(null, this, null);
|
447
|
+
code = o.globals ? this.compile_node(o) : this.compile_with_declarations(o);
|
448
|
+
code = code.replace(TRAILING_WHITESPACE, '');
|
449
|
+
return o.no_wrap ? code : "(function(){\n" + code + "\n})();";
|
450
|
+
},
|
451
|
+
// Compile the expressions body, with declarations of all inner variables
|
452
|
+
// pushed up to the top.
|
453
|
+
compile_with_declarations: function compile_with_declarations(o) {
|
454
|
+
var args, argv, code;
|
455
|
+
code = this.compile_node(o);
|
456
|
+
args = this.contains(function(node) {
|
457
|
+
return node instanceof ValueNode && node.is_arguments();
|
458
|
+
});
|
459
|
+
argv = args && o.scope.check('arguments') ? '' : 'var ';
|
460
|
+
if (args) {
|
461
|
+
code = this.idt() + argv + "arguments = Array.prototype.slice.call(arguments, 0);\n" + code;
|
462
|
+
}
|
463
|
+
if (o.scope.has_assignments(this)) {
|
464
|
+
code = this.idt() + 'var ' + o.scope.compiled_assignments() + ";\n" + code;
|
465
|
+
}
|
466
|
+
if (o.scope.has_declarations(this)) {
|
467
|
+
code = this.idt() + 'var ' + o.scope.compiled_declarations() + ";\n" + code;
|
468
|
+
}
|
469
|
+
return code;
|
470
|
+
},
|
471
|
+
// Compiles a single expression within the expressions body.
|
472
|
+
compile_expression: function compile_expression(node, o) {
|
473
|
+
var returns, stmt, temp;
|
474
|
+
this.indent = o.indent;
|
475
|
+
stmt = node.is_statement();
|
476
|
+
// We need to return the result if this is the last node in the expressions body.
|
477
|
+
returns = del(o, 'returns') && this.is_last(node) && !node.is_statement_only();
|
478
|
+
// Return the regular compile of the node, unless we need to return the result.
|
479
|
+
if (!(returns)) {
|
480
|
+
return (stmt ? '' : this.idt()) + node.compile(merge(o, {
|
481
|
+
top: true
|
482
|
+
})) + (stmt ? '' : ';');
|
483
|
+
}
|
484
|
+
// If it's a statement, the node knows how to return itself.
|
485
|
+
if (node.is_statement()) {
|
486
|
+
return node.compile(merge(o, {
|
487
|
+
returns: true
|
488
|
+
}));
|
489
|
+
}
|
490
|
+
// If it's not part of a constructor, we can just return the value of the expression.
|
491
|
+
if (!((o.scope.method == undefined ? undefined : o.scope.method.is_constructor()))) {
|
492
|
+
return this.idt() + 'return ' + node.compile(o);
|
493
|
+
}
|
494
|
+
// It's the last line of a constructor, add a safety check.
|
495
|
+
temp = o.scope.free_variable();
|
496
|
+
return this.idt() + temp + ' = ' + node.compile(o) + ";\n" + this.idt() + "return " + o.scope.method.name + ' === this.constructor ? this : ' + temp + ';';
|
497
|
+
}
|
498
|
+
}));
|
499
|
+
// Wrap up a node as an Expressions, unless it already is one.
|
500
|
+
Expressions.wrap = function wrap(nodes) {
|
501
|
+
if (nodes.length === 1 && nodes[0] instanceof Expressions) {
|
502
|
+
return nodes[0];
|
503
|
+
}
|
504
|
+
return new Expressions(nodes);
|
505
|
+
};
|
506
|
+
statement(Expressions);
|
507
|
+
// Literals are static values that can be passed through directly into
|
508
|
+
// JavaScript without translation, eg.: strings, numbers, true, false, null...
|
509
|
+
LiteralNode = (exports.LiteralNode = inherit(Node, {
|
510
|
+
constructor: function constructor(value) {
|
511
|
+
this.value = value;
|
512
|
+
this.children = [value];
|
513
|
+
return this;
|
514
|
+
},
|
515
|
+
// Break and continue must be treated as statements -- they lose their meaning
|
516
|
+
// when wrapped in a closure.
|
517
|
+
is_statement: function is_statement() {
|
518
|
+
return this.value === 'break' || this.value === 'continue';
|
519
|
+
},
|
520
|
+
compile_node: function compile_node(o) {
|
521
|
+
var end, idt;
|
522
|
+
idt = this.is_statement() ? this.idt() : '';
|
523
|
+
end = this.is_statement() ? ';' : '';
|
524
|
+
return idt + this.value + end;
|
525
|
+
}
|
526
|
+
}));
|
527
|
+
LiteralNode.prototype.is_statement_only = LiteralNode.prototype.is_statement;
|
528
|
+
// Return an expression, or wrap it in a closure and return it.
|
529
|
+
ReturnNode = (exports.ReturnNode = inherit(Node, {
|
530
|
+
constructor: function constructor(expression) {
|
531
|
+
this.expression = expression;
|
532
|
+
this.children = [expression];
|
533
|
+
return this;
|
534
|
+
},
|
535
|
+
compile_node: function compile_node(o) {
|
536
|
+
if (this.expression.is_statement()) {
|
537
|
+
return this.expression.compile(merge(o, {
|
538
|
+
returns: true
|
539
|
+
}));
|
540
|
+
}
|
541
|
+
return this.idt() + 'return ' + this.expression.compile(o) + ';';
|
542
|
+
}
|
543
|
+
}));
|
544
|
+
statement(ReturnNode, true);
|
545
|
+
// A value, indexed or dotted into, or vanilla.
|
546
|
+
ValueNode = (exports.ValueNode = inherit(Node, {
|
547
|
+
SOAK: " == undefined ? undefined : ",
|
548
|
+
constructor: function constructor(base, properties) {
|
549
|
+
this.base = base;
|
550
|
+
this.properties = flatten(properties || []);
|
551
|
+
this.children = flatten(this.base, this.properties);
|
552
|
+
return this;
|
553
|
+
},
|
554
|
+
push: function push(prop) {
|
555
|
+
this.properties.push(prop);
|
556
|
+
this.children.push(prop);
|
557
|
+
return this;
|
558
|
+
},
|
559
|
+
has_properties: function has_properties() {
|
560
|
+
return this.properties.length || this.base instanceof ThisNode;
|
561
|
+
},
|
562
|
+
is_array: function is_array() {
|
563
|
+
return this.base instanceof ArrayNode && !this.has_properties();
|
564
|
+
},
|
565
|
+
is_object: function is_object() {
|
566
|
+
return this.base instanceof ObjectNode && !this.has_properties();
|
567
|
+
},
|
568
|
+
is_splice: function is_splice() {
|
569
|
+
return this.has_properties() && this.properties[this.properties.length - 1] instanceof SliceNode;
|
570
|
+
},
|
571
|
+
is_arguments: function is_arguments() {
|
572
|
+
return this.base === 'arguments';
|
573
|
+
},
|
574
|
+
unwrap: function unwrap() {
|
575
|
+
return this.properties.length ? this : this.base;
|
576
|
+
},
|
577
|
+
// Values are statements if their base is a statement.
|
578
|
+
is_statement: function is_statement() {
|
579
|
+
return this.base.is_statement && this.base.is_statement() && !this.has_properties();
|
580
|
+
},
|
581
|
+
compile_node: function compile_node(o) {
|
582
|
+
var __a, __b, baseline, code, only, part, parts, prop, props, soaked, temp;
|
583
|
+
soaked = false;
|
584
|
+
only = del(o, 'only_first');
|
585
|
+
props = only ? this.properties.slice(0, this.properties.length) : this.properties;
|
586
|
+
baseline = this.base.compile(o);
|
587
|
+
parts = [baseline];
|
588
|
+
__a = props;
|
589
|
+
for (__b = 0; __b < __a.length; __b++) {
|
590
|
+
prop = __a[__b];
|
591
|
+
if (prop instanceof AccessorNode && prop.soak) {
|
592
|
+
soaked = true;
|
593
|
+
if (this.base instanceof CallNode && prop === props[0]) {
|
594
|
+
temp = o.scope.free_variable();
|
595
|
+
parts[parts.length - 1] = '(' + temp + ' = ' + baseline + ')' + this.SOAK + ((baseline = temp + prop.compile(o)));
|
596
|
+
} else {
|
597
|
+
parts[parts.length - 1] = this.SOAK + (baseline += prop.compile(o));
|
598
|
+
}
|
599
|
+
} else {
|
600
|
+
part = prop.compile(o);
|
601
|
+
baseline += part;
|
602
|
+
parts.push(part);
|
603
|
+
}
|
604
|
+
}
|
605
|
+
this.last = parts[parts.length - 1];
|
606
|
+
this.source = parts.length > 1 ? parts.slice(0, parts.length).join('') : null;
|
607
|
+
code = parts.join('').replace(/\)\(\)\)/, '()))');
|
608
|
+
if (!(soaked)) {
|
609
|
+
return code;
|
610
|
+
}
|
611
|
+
return '(' + code + ')';
|
612
|
+
}
|
613
|
+
}));
|
614
|
+
// Pass through StyleScript comments into JavaScript comments at the
|
615
|
+
// same position.
|
616
|
+
CommentNode = (exports.CommentNode = inherit(Node, {
|
617
|
+
constructor: function constructor(lines) {
|
618
|
+
this.lines = lines;
|
619
|
+
return this;
|
620
|
+
},
|
621
|
+
compile_node: function compile_node(o) {
|
622
|
+
var delimiter;
|
623
|
+
delimiter = "\n" + this.idt() + '//';
|
624
|
+
return delimiter + this.lines.join(delimiter);
|
625
|
+
}
|
626
|
+
}));
|
627
|
+
statement(CommentNode);
|
628
|
+
// Node for a function invocation. Takes care of converting super() calls into
|
629
|
+
// calls against the prototype's function of the same name.
|
630
|
+
CallNode = (exports.CallNode = inherit(Node, {
|
631
|
+
constructor: function constructor(variable, args) {
|
632
|
+
this.variable = variable;
|
633
|
+
this.args = args || [];
|
634
|
+
this.children = flatten([this.variable, this.args]);
|
635
|
+
this.prefix = '';
|
636
|
+
return this;
|
637
|
+
},
|
638
|
+
new_instance: function new_instance() {
|
639
|
+
this.prefix = 'new ';
|
640
|
+
return this;
|
641
|
+
},
|
642
|
+
push: function push(arg) {
|
643
|
+
this.args.push(arg);
|
644
|
+
this.children.push(arg);
|
645
|
+
return this;
|
646
|
+
},
|
647
|
+
// Compile a vanilla function call.
|
648
|
+
compile_node: function compile_node(o) {
|
649
|
+
var __a, __b, __c, arg, args;
|
650
|
+
if (any(this.args, function(a) {
|
651
|
+
return a instanceof SplatNode;
|
652
|
+
})) {
|
653
|
+
return this.compile_splat(o);
|
654
|
+
}
|
655
|
+
args = ((function() {
|
656
|
+
__a = []; __b = this.args;
|
657
|
+
for (__c = 0; __c < __b.length; __c++) {
|
658
|
+
arg = __b[__c];
|
659
|
+
__a.push(arg.compile(o));
|
660
|
+
}
|
661
|
+
return __a;
|
662
|
+
}).call(this)).join(', ');
|
663
|
+
if (this.variable === 'super') {
|
664
|
+
return this.compile_super(args, o);
|
665
|
+
}
|
666
|
+
return this.prefix + this.variable.compile(o) + '(' + args + ')';
|
667
|
+
},
|
668
|
+
// Compile a call against the superclass's implementation of the current function.
|
669
|
+
compile_super: function compile_super(args, o) {
|
670
|
+
var arg_part, meth, methname;
|
671
|
+
methname = o.scope.method.name;
|
672
|
+
arg_part = args.length ? ', ' + args : '';
|
673
|
+
meth = o.scope.method.proto ? o.scope.method.proto + '.__superClass__.' + methname : methname + '.__superClass__.constructor';
|
674
|
+
return meth + '.call(this' + arg_part + ')';
|
675
|
+
},
|
676
|
+
// Compile a function call being passed variable arguments.
|
677
|
+
compile_splat: function compile_splat(o) {
|
678
|
+
var __a, __b, arg, args, code, i, meth, obj;
|
679
|
+
meth = this.variable.compile(o);
|
680
|
+
obj = this.variable.source || 'this';
|
681
|
+
args = (function() {
|
682
|
+
__a = []; __b = this.args;
|
683
|
+
for (i = 0; i < __b.length; i++) {
|
684
|
+
arg = __b[i];
|
685
|
+
__a.push((function() {
|
686
|
+
code = arg.compile(o);
|
687
|
+
code = arg instanceof SplatNode ? code : '[' + code + ']';
|
688
|
+
return i === 0 ? code : '.concat(' + code + ')';
|
689
|
+
}).call(this));
|
690
|
+
}
|
691
|
+
return __a;
|
692
|
+
}).call(this);
|
693
|
+
return this.prefix + meth + '.apply(' + obj + ', ' + args.join('') + ')';
|
694
|
+
},
|
695
|
+
// If the code generation wished to use the result of a function call
|
696
|
+
// in multiple places, ensure that the function is only ever called once.
|
697
|
+
compile_reference: function compile_reference(o) {
|
698
|
+
var call, reference;
|
699
|
+
reference = o.scope.free_variable();
|
700
|
+
call = new ParentheticalNode(new AssignNode(reference, this));
|
701
|
+
return [call, reference];
|
702
|
+
}
|
703
|
+
}));
|
704
|
+
// Node to extend an object's prototype with an ancestor object.
|
705
|
+
// After goog.inherits from the Closure Library.
|
706
|
+
ExtendsNode = (exports.ExtendsNode = inherit(Node, {
|
707
|
+
constructor: function constructor(child, parent) {
|
708
|
+
this.child = child;
|
709
|
+
this.parent = parent;
|
710
|
+
this.children = [child, parent];
|
711
|
+
return this;
|
712
|
+
},
|
713
|
+
// Hooking one constructor into another's prototype chain.
|
714
|
+
compile_node: function compile_node(o) {
|
715
|
+
var child, constructor, parent;
|
716
|
+
constructor = o.scope.free_variable();
|
717
|
+
child = this.child.compile(o);
|
718
|
+
parent = this.parent.compile(o);
|
719
|
+
return this.idt() + constructor + ' = function(){};\n' + this.idt() + constructor + '.prototype = ' + parent + ".prototype;\n" + this.idt() + child + '.__superClass__ = ' + parent + ".prototype;\n" + this.idt() + child + '.prototype = new ' + constructor + "();\n" + this.idt() + child + '.prototype.constructor = ' + child + ';';
|
720
|
+
}
|
721
|
+
}));
|
722
|
+
statement(ExtendsNode);
|
723
|
+
// A dotted accessor into a part of a value, or the :: shorthand for
|
724
|
+
// an accessor into the object's prototype.
|
725
|
+
AccessorNode = (exports.AccessorNode = inherit(Node, {
|
726
|
+
constructor: function constructor(name, tag) {
|
727
|
+
this.name = name;
|
728
|
+
this.children = [this.name];
|
729
|
+
this.prototype = tag === 'prototype';
|
730
|
+
this.soak = tag === 'soak';
|
731
|
+
return this;
|
732
|
+
},
|
733
|
+
compile_node: function compile_node(o) {
|
734
|
+
return '.' + (this.prototype ? 'prototype.' : '') + this.name.compile(o);
|
735
|
+
}
|
736
|
+
}));
|
737
|
+
// An indexed accessor into a part of an array or object.
|
738
|
+
IndexNode = (exports.IndexNode = inherit(Node, {
|
739
|
+
constructor: function constructor(index) {
|
740
|
+
this.children = [(this.index = index)];
|
741
|
+
return this;
|
742
|
+
},
|
743
|
+
compile_node: function compile_node(o) {
|
744
|
+
return '[' + this.index.compile(o) + ']';
|
745
|
+
}
|
746
|
+
}));
|
747
|
+
// A this-reference, using '@'.
|
748
|
+
ThisNode = (exports.ThisNode = inherit(Node, {
|
749
|
+
constructor: function constructor(property) {
|
750
|
+
return this.property = property || null;
|
751
|
+
},
|
752
|
+
compile_node: function compile_node(o) {
|
753
|
+
return 'this' + (this.property ? '.' + this.property : '');
|
754
|
+
}
|
755
|
+
}));
|
756
|
+
})();
|