minjs 0.1.2
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.
- checksums.yaml +7 -0
- data/.gitignore +9 -0
- data/.rspec +2 -0
- data/.travis.yml +3 -0
- data/CODE_OF_CONDUCT.md +13 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +21 -0
- data/README.md +43 -0
- data/Rakefile +7 -0
- data/bin/console +14 -0
- data/bin/setup +7 -0
- data/exe/minjs +12 -0
- data/lib/minjs/compressor.rb +418 -0
- data/lib/minjs/ctype.rb +846 -0
- data/lib/minjs/ecma262/base.rb +128 -0
- data/lib/minjs/ecma262/env.rb +78 -0
- data/lib/minjs/ecma262/exp.rb +630 -0
- data/lib/minjs/ecma262/lit.rb +552 -0
- data/lib/minjs/ecma262/punc.rb +84 -0
- data/lib/minjs/ecma262/st.rb +808 -0
- data/lib/minjs/ecma262.rb +6 -0
- data/lib/minjs/exceptions.rb +15 -0
- data/lib/minjs/expression.rb +714 -0
- data/lib/minjs/func.rb +86 -0
- data/lib/minjs/lex.rb +745 -0
- data/lib/minjs/literal.rb +45 -0
- data/lib/minjs/minjs_compressor.rb +47 -0
- data/lib/minjs/program.rb +32 -0
- data/lib/minjs/statement.rb +438 -0
- data/lib/minjs/version.rb +3 -0
- data/lib/minjs.rb +16 -0
- data/minjs.gemspec +31 -0
- metadata +132 -0
@@ -0,0 +1,808 @@
|
|
1
|
+
module Minjs
|
2
|
+
module ECMA262
|
3
|
+
class St < Base
|
4
|
+
def to_exp?
|
5
|
+
false
|
6
|
+
end
|
7
|
+
|
8
|
+
def replace(from, to)
|
9
|
+
puts "warning: not implement"
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
#statement_list
|
14
|
+
class StList < St
|
15
|
+
attr_reader :statement_list
|
16
|
+
#
|
17
|
+
# statement_list: [statement, statement, ...]
|
18
|
+
#
|
19
|
+
def initialize(statement_list)
|
20
|
+
@statement_list = statement_list
|
21
|
+
end
|
22
|
+
|
23
|
+
def grouping
|
24
|
+
sl = @statement_list
|
25
|
+
i = 0
|
26
|
+
while i < sl.length
|
27
|
+
st = sl[i]
|
28
|
+
i0 = i
|
29
|
+
prev = nil
|
30
|
+
t = nil
|
31
|
+
while st and st.to_exp?
|
32
|
+
if prev and prev.to_exp?
|
33
|
+
t = ECMA262::ExpComma.new(t, st.to_exp({}))
|
34
|
+
elsif prev.nil?
|
35
|
+
t = st.to_exp({})
|
36
|
+
else
|
37
|
+
break
|
38
|
+
end
|
39
|
+
prev = st
|
40
|
+
i += 1
|
41
|
+
st = sl[i]
|
42
|
+
end
|
43
|
+
if i0 != i and i - i0 >= 2
|
44
|
+
sl[i0...i] = StExp.new(t)
|
45
|
+
i = (i - i0 + 1)
|
46
|
+
else
|
47
|
+
i += 1
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
def replace(from, to)
|
53
|
+
idx = @statement_list.index(from)
|
54
|
+
if idx
|
55
|
+
@statement_list[idx] = to
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
def remove(st)
|
60
|
+
@statement_list.delete(st)
|
61
|
+
end
|
62
|
+
|
63
|
+
def traverse(parent, &block)
|
64
|
+
@statement_list.each do|st|
|
65
|
+
st.traverse(self, &block)
|
66
|
+
end
|
67
|
+
yield self, parent
|
68
|
+
end
|
69
|
+
|
70
|
+
def to_js(options = {})
|
71
|
+
concat options, @statement_list
|
72
|
+
end
|
73
|
+
|
74
|
+
def length
|
75
|
+
@statement_list.length
|
76
|
+
end
|
77
|
+
|
78
|
+
def to_exp?
|
79
|
+
@statement_list.each do |s|
|
80
|
+
return false if s.to_exp? == false
|
81
|
+
end
|
82
|
+
return true
|
83
|
+
end
|
84
|
+
|
85
|
+
def to_exp(options)
|
86
|
+
return nil if to_exp? == false
|
87
|
+
t = @statement_list[0].to_exp(options)
|
88
|
+
return t.to_exp(options) if @statement_list.length <= 1
|
89
|
+
i = 1
|
90
|
+
while(i < @statement_list.length)
|
91
|
+
t = ExpComma.new(t, @statement_list[i])
|
92
|
+
i += 1
|
93
|
+
end
|
94
|
+
t
|
95
|
+
end
|
96
|
+
|
97
|
+
def each(&block)
|
98
|
+
@statement_list.each(&block)
|
99
|
+
end
|
100
|
+
|
101
|
+
def [](i)
|
102
|
+
@statement_list[i]
|
103
|
+
end
|
104
|
+
|
105
|
+
def index(st)
|
106
|
+
@statement_list.index(st)
|
107
|
+
end
|
108
|
+
end
|
109
|
+
#
|
110
|
+
# 12.1
|
111
|
+
#
|
112
|
+
class StBlock < St
|
113
|
+
attr_reader :statement_list
|
114
|
+
|
115
|
+
#statement_list:StList
|
116
|
+
def initialize(statement_list)
|
117
|
+
if statement_list.class == Array
|
118
|
+
raise 'bad class'
|
119
|
+
end
|
120
|
+
@statement_list = statement_list
|
121
|
+
end
|
122
|
+
|
123
|
+
def traverse(parent, &block)
|
124
|
+
@statement_list.traverse(self, &block)
|
125
|
+
yield self, parent
|
126
|
+
end
|
127
|
+
|
128
|
+
def to_js(options = {})
|
129
|
+
concat(options, "{", @statement_list, "}")
|
130
|
+
end
|
131
|
+
|
132
|
+
def to_exp?
|
133
|
+
@statement_list.length == 1 and @statement_list[0].to_exp?
|
134
|
+
end
|
135
|
+
|
136
|
+
def to_exp(options)
|
137
|
+
@statement_list[0].to_exp({})
|
138
|
+
end
|
139
|
+
end
|
140
|
+
#
|
141
|
+
# 12.2
|
142
|
+
#
|
143
|
+
class StVar < St
|
144
|
+
attr_reader :vars
|
145
|
+
attr_reader :context
|
146
|
+
#
|
147
|
+
# vars:
|
148
|
+
# [[name0,init0],[name1,init1],...]
|
149
|
+
#
|
150
|
+
def initialize(context, vars)
|
151
|
+
@vars = vars
|
152
|
+
@context = context
|
153
|
+
end
|
154
|
+
|
155
|
+
def replace(from, to)
|
156
|
+
@vars.each do |x|
|
157
|
+
if x[0] == from
|
158
|
+
x[0] = to
|
159
|
+
break
|
160
|
+
elsif x[1] and x[1] == from
|
161
|
+
x[1] = to
|
162
|
+
break
|
163
|
+
end
|
164
|
+
end
|
165
|
+
end
|
166
|
+
|
167
|
+
def traverse(parent, &block)
|
168
|
+
@vars.each do |x|
|
169
|
+
x[0].traverse(self, &block)
|
170
|
+
if x[1]
|
171
|
+
x[1].traverse(self, &block)
|
172
|
+
end
|
173
|
+
end
|
174
|
+
yield self, parent
|
175
|
+
end
|
176
|
+
|
177
|
+
def to_js(options = {})
|
178
|
+
t = concat(options, :var, @vars.collect{|x|
|
179
|
+
if x[1]
|
180
|
+
concat options, x[0], '=', x[1]
|
181
|
+
else
|
182
|
+
concat options, x[0]
|
183
|
+
end
|
184
|
+
}.join(","))
|
185
|
+
if t.length > 0
|
186
|
+
concat(options, t, ";")
|
187
|
+
else
|
188
|
+
""
|
189
|
+
end
|
190
|
+
end
|
191
|
+
|
192
|
+
def normalization
|
193
|
+
# if var has no initializer, move it to latter
|
194
|
+
v1 = []
|
195
|
+
v2 = []
|
196
|
+
@vars.each do |x|
|
197
|
+
if x[1].nil?
|
198
|
+
v2.push(x)
|
199
|
+
else
|
200
|
+
v1.push(x)
|
201
|
+
end
|
202
|
+
end
|
203
|
+
@vars = v1.concat(v2)
|
204
|
+
end
|
205
|
+
end
|
206
|
+
|
207
|
+
#12.3 empty
|
208
|
+
class StEmpty < St
|
209
|
+
def initialize()
|
210
|
+
end
|
211
|
+
def traverse(parent, &block)
|
212
|
+
yield self, parent
|
213
|
+
end
|
214
|
+
def to_js(options = {})
|
215
|
+
";"
|
216
|
+
end
|
217
|
+
end
|
218
|
+
|
219
|
+
#12.4
|
220
|
+
class StExp < St
|
221
|
+
attr_reader :exp
|
222
|
+
|
223
|
+
def initialize(exp)
|
224
|
+
@exp = exp
|
225
|
+
end
|
226
|
+
def traverse(parent, &block)
|
227
|
+
@exp.traverse(self, &block)
|
228
|
+
yield self, parent
|
229
|
+
end
|
230
|
+
def to_js(options = {})
|
231
|
+
concat(options, @exp, ";")
|
232
|
+
end
|
233
|
+
|
234
|
+
def to_exp(options)
|
235
|
+
@exp
|
236
|
+
end
|
237
|
+
|
238
|
+
def to_exp?
|
239
|
+
true
|
240
|
+
end
|
241
|
+
end
|
242
|
+
|
243
|
+
#12.5
|
244
|
+
class StIf < St
|
245
|
+
attr_reader :then_st, :else_st, :cond
|
246
|
+
|
247
|
+
def initialize(cond, then_st, else_st)
|
248
|
+
@cond = cond
|
249
|
+
@then_st = then_st
|
250
|
+
@else_st = else_st
|
251
|
+
end
|
252
|
+
|
253
|
+
def replace(from, to)
|
254
|
+
if from == @then_st
|
255
|
+
@then_st = to
|
256
|
+
elsif from == @else_st
|
257
|
+
@else_st = to
|
258
|
+
end
|
259
|
+
end
|
260
|
+
|
261
|
+
def traverse(parent, &block)
|
262
|
+
@cond.traverse(self, &block)
|
263
|
+
@then_st.traverse(self, &block)
|
264
|
+
if @else_st
|
265
|
+
@else_st.traverse(self, &block)
|
266
|
+
end
|
267
|
+
yield self, parent
|
268
|
+
end
|
269
|
+
|
270
|
+
def to_js(options = {})
|
271
|
+
if @else_st
|
272
|
+
concat options, :if, "(", @cond, ")", @then_st, :else, @else_st
|
273
|
+
else
|
274
|
+
concat options, :if, "(", @cond, ")", @then_st
|
275
|
+
end
|
276
|
+
end
|
277
|
+
|
278
|
+
def to_exp?
|
279
|
+
return false if @then_st.to_exp? == false
|
280
|
+
return false if @else_st and @else_st.to_exp? == false
|
281
|
+
return true
|
282
|
+
end
|
283
|
+
|
284
|
+
def to_exp(options)
|
285
|
+
return nil if to_exp? == false
|
286
|
+
if @else_st
|
287
|
+
then_exp = @then_st.to_exp(options)
|
288
|
+
else_exp = @else_st.to_exp(options)
|
289
|
+
else
|
290
|
+
then_exp = @then_st.to_exp(options)
|
291
|
+
#else_exp = ECMA262Numeric.new(0)
|
292
|
+
return ExpLogicalAnd.new(ExpParen.new(@cond), ExpParen.new(then_exp))
|
293
|
+
end
|
294
|
+
if then_exp.kind_of? ExpComma
|
295
|
+
then_exp = ExpParen.new(then_exp)
|
296
|
+
end
|
297
|
+
if else_exp.kind_of? ExpComma
|
298
|
+
else_exp = ExpParen.new(else_exp)
|
299
|
+
end
|
300
|
+
|
301
|
+
if @cond.kind_of? ExpComma
|
302
|
+
ExpCond.new(ExpParen.new(@cond), then_exp, else_exp)
|
303
|
+
elsif @cond.kind_of? ExpAssign
|
304
|
+
ExpCond.new(ExpParen.new(@cond), then_exp, else_exp)
|
305
|
+
else
|
306
|
+
ExpCond.new(@cond, then_exp, else_exp)
|
307
|
+
end
|
308
|
+
end
|
309
|
+
end
|
310
|
+
|
311
|
+
#12.6
|
312
|
+
class StWhile < St
|
313
|
+
def initialize(exp, statement)
|
314
|
+
@exp, @statement = exp, statement
|
315
|
+
end
|
316
|
+
|
317
|
+
def replace(from, to)
|
318
|
+
if from == @statement
|
319
|
+
@statement = to
|
320
|
+
end
|
321
|
+
end
|
322
|
+
|
323
|
+
def traverse(parent, &block)
|
324
|
+
@exp.traverse(self, &block)
|
325
|
+
@statement.traverse(self, &block)
|
326
|
+
yield self, parent
|
327
|
+
end
|
328
|
+
|
329
|
+
def to_js(options = {})
|
330
|
+
if @statement.kind_of? StBlock and @statement.statement_list.length == 1
|
331
|
+
statement = @statement.statement_list.statement_list[0]
|
332
|
+
else
|
333
|
+
statement = @statement
|
334
|
+
end
|
335
|
+
|
336
|
+
concat(options, :while, "(", @exp, ")", statement)
|
337
|
+
end
|
338
|
+
end
|
339
|
+
|
340
|
+
class StDoWhile < St
|
341
|
+
def initialize(exp, statement)
|
342
|
+
@exp, @statement = exp, statement
|
343
|
+
end
|
344
|
+
|
345
|
+
def replace(from, to)
|
346
|
+
if from == @statement
|
347
|
+
@statement = to
|
348
|
+
end
|
349
|
+
end
|
350
|
+
|
351
|
+
def traverse(parent, &block)
|
352
|
+
@exp.traverse(self, &block)
|
353
|
+
@statement.traverse(self, &block)
|
354
|
+
yield self, parent
|
355
|
+
end
|
356
|
+
|
357
|
+
def to_js(options = {})
|
358
|
+
if @statement.kind_of? StBlock and @statement.statement_list.length == 1
|
359
|
+
statement = @statement.statement_list.statement_list[0]
|
360
|
+
else
|
361
|
+
statement = @statement
|
362
|
+
end
|
363
|
+
|
364
|
+
concat options, :do, statement, :while, "(", @exp, ")", ";"
|
365
|
+
end
|
366
|
+
end
|
367
|
+
|
368
|
+
class StForVar < St
|
369
|
+
attr_reader :context
|
370
|
+
|
371
|
+
#
|
372
|
+
# var_decl_list
|
373
|
+
# [[name0, init0],[name1, init1], ...]
|
374
|
+
#
|
375
|
+
def initialize(context, var_decl_list, exp2, exp3, statement)
|
376
|
+
@context = context
|
377
|
+
@var_decl_list = var_decl_list
|
378
|
+
@exp2 = exp2
|
379
|
+
@exp3 = exp3
|
380
|
+
@statement = statement
|
381
|
+
end
|
382
|
+
|
383
|
+
def replace(from, to)
|
384
|
+
if from == @statement
|
385
|
+
@statement = to
|
386
|
+
end
|
387
|
+
end
|
388
|
+
|
389
|
+
def traverse(parent, &block)
|
390
|
+
@var_decl_list.each do |x|
|
391
|
+
x[0].traverse(self, &block)
|
392
|
+
if x[1]
|
393
|
+
x[1].traverse(self, &block)
|
394
|
+
end
|
395
|
+
end
|
396
|
+
@exp2.traverse(self, &block)
|
397
|
+
@exp3.traverse(self, &block)
|
398
|
+
@statement.traverse(self, &block)
|
399
|
+
yield self, parent
|
400
|
+
end
|
401
|
+
|
402
|
+
#
|
403
|
+
# for(var ...; ; ) => for(...; ; )
|
404
|
+
#
|
405
|
+
def to_st_for
|
406
|
+
tt = nil
|
407
|
+
@var_decl_list.each{|x|
|
408
|
+
if x[1]
|
409
|
+
t = ExpAssign.new(x[0], x[1])
|
410
|
+
else
|
411
|
+
t = x[0]
|
412
|
+
end
|
413
|
+
if tt.nil?
|
414
|
+
tt = t
|
415
|
+
else
|
416
|
+
tt = ExpComma.new(tt, t)
|
417
|
+
end
|
418
|
+
}
|
419
|
+
StFor.new(tt, @exp2, @exp3, @statement)
|
420
|
+
end
|
421
|
+
|
422
|
+
def to_js(options = {})
|
423
|
+
if @statement.kind_of? StBlock and @statement.statement_list.length == 1
|
424
|
+
statement = @statement.statement_list.statement_list[0]
|
425
|
+
else
|
426
|
+
statement = @statement
|
427
|
+
end
|
428
|
+
|
429
|
+
_var_decl_list = @var_decl_list.collect{|x|
|
430
|
+
if x[1] #with initialiser
|
431
|
+
concat options, x[0], '=', x[1]
|
432
|
+
else
|
433
|
+
concat options, x[0]
|
434
|
+
end
|
435
|
+
}.join(",")
|
436
|
+
# if options[:compress_var]
|
437
|
+
# t = concat({:for_args => true}.merge(options), :for, "(", _var_decl_list, ";", @exp2, ";", @exp3, ")")
|
438
|
+
# else
|
439
|
+
t = concat({:for_args => true}.merge(options), :for, "(", _var_decl_list, ";", @exp2, ";", @exp3, ")")
|
440
|
+
# end
|
441
|
+
concat options, t, statement
|
442
|
+
end
|
443
|
+
end
|
444
|
+
|
445
|
+
class StFor < St
|
446
|
+
def initialize(exp1, exp2, exp3, statement)
|
447
|
+
@exp1 = exp1
|
448
|
+
@exp2 = exp2
|
449
|
+
@exp3 = exp3
|
450
|
+
@statement = statement
|
451
|
+
end
|
452
|
+
|
453
|
+
def replace(from, to)
|
454
|
+
if from == @statement
|
455
|
+
@statement = to
|
456
|
+
end
|
457
|
+
end
|
458
|
+
|
459
|
+
def traverse(parent, &block)
|
460
|
+
@exp1.traverse(self, &block)
|
461
|
+
@exp2.traverse(self, &block)
|
462
|
+
@exp3.traverse(self, &block)
|
463
|
+
@statement.traverse(self, &block)
|
464
|
+
yield self, parent
|
465
|
+
end
|
466
|
+
|
467
|
+
def to_js(options = {})
|
468
|
+
if @statement.kind_of? StBlock and @statement.statement_list.length == 1
|
469
|
+
statement = @statement.statement_list.statement_list[0]
|
470
|
+
else
|
471
|
+
statement = @statement
|
472
|
+
end
|
473
|
+
|
474
|
+
concat options, :for, "(", @exp1, ";", @exp2, ";", @exp3, ")", statement
|
475
|
+
end
|
476
|
+
end
|
477
|
+
|
478
|
+
class StForInVar < St
|
479
|
+
attr_reader :context
|
480
|
+
|
481
|
+
def initialize(context, var_decl, exp2, statement)
|
482
|
+
@context = context
|
483
|
+
@var_decl = var_decl
|
484
|
+
@exp2 = exp2
|
485
|
+
@statement = statement
|
486
|
+
end
|
487
|
+
|
488
|
+
def traverse(parent, &block)
|
489
|
+
@var_decl[0].traverse(self, &block)
|
490
|
+
@var_decl[1].traverse(self, &block) if @var_decl[1]
|
491
|
+
@exp2.traverse(self, &block)
|
492
|
+
@statement.traverse(self, &block)
|
493
|
+
yield self, parent
|
494
|
+
end
|
495
|
+
|
496
|
+
def replace(from, to)
|
497
|
+
if from == @statement
|
498
|
+
@statement = to
|
499
|
+
end
|
500
|
+
end
|
501
|
+
|
502
|
+
def to_st_for_in
|
503
|
+
if @var_decl[1]
|
504
|
+
t = ExpAssign.new(@var_decl[0], @var_decl[1])
|
505
|
+
else
|
506
|
+
t = @var_decl[0]
|
507
|
+
end
|
508
|
+
StForIn.new(t, @exp2, @statement)
|
509
|
+
end
|
510
|
+
def to_js(options = {})
|
511
|
+
if @statement.kind_of? StBlock and @statement.statement_list.length == 1
|
512
|
+
statement = @statement.statement_list.statement_list[0]
|
513
|
+
else
|
514
|
+
statement = @statement
|
515
|
+
end
|
516
|
+
|
517
|
+
if @var_decl[1] #with initialiser
|
518
|
+
_var_decl = concat(options, @var_decl[0], '=', @var_decl[1])
|
519
|
+
else
|
520
|
+
_var_decl = concat(options, @var_decl[0])
|
521
|
+
end
|
522
|
+
|
523
|
+
# if options[:compress_var]
|
524
|
+
# concat options, :for, "(", _var_decl, :in, @exp2, ")", statement
|
525
|
+
# else
|
526
|
+
concat options, :for, "(", :var, _var_decl, :in, @exp2, ")", statement
|
527
|
+
# end
|
528
|
+
end
|
529
|
+
end
|
530
|
+
|
531
|
+
class StForIn < St
|
532
|
+
def initialize(exp1, exp2, statement)
|
533
|
+
@exp1 = exp1
|
534
|
+
@exp2 = exp2
|
535
|
+
@statement = statement
|
536
|
+
end
|
537
|
+
|
538
|
+
def replace(from, to)
|
539
|
+
if from == @statement
|
540
|
+
@statement = to
|
541
|
+
end
|
542
|
+
end
|
543
|
+
|
544
|
+
def traverse(parent, &block)
|
545
|
+
@exp1.traverse(self, &block)
|
546
|
+
@exp2.traverse(self, &block)
|
547
|
+
@statement.traverse(self, &block)
|
548
|
+
yield self, parent
|
549
|
+
end
|
550
|
+
|
551
|
+
def to_js(options = {})
|
552
|
+
if @statement.kind_of? StBlock and @statement.statement_list.length == 1
|
553
|
+
statement = @statement.statement_list.statement_list[0]
|
554
|
+
else
|
555
|
+
statement = @statement
|
556
|
+
end
|
557
|
+
|
558
|
+
concat options, :for, '(', @exp1, :in, @exp2, ')', statement
|
559
|
+
end
|
560
|
+
end
|
561
|
+
|
562
|
+
#12.7
|
563
|
+
class StContinue < St
|
564
|
+
def initialize(exp = nil)
|
565
|
+
@exp = exp
|
566
|
+
end
|
567
|
+
def traverse(parent, &block)
|
568
|
+
@exp.traverse(self, &block) if @exp
|
569
|
+
yield self, parent
|
570
|
+
end
|
571
|
+
def to_js(options = {})
|
572
|
+
if @exp
|
573
|
+
concat options, :continue, @exp, ";"
|
574
|
+
else
|
575
|
+
concat options, :continue, ";"
|
576
|
+
end
|
577
|
+
end
|
578
|
+
end
|
579
|
+
|
580
|
+
#12.8
|
581
|
+
class StBreak < St
|
582
|
+
def initialize(exp = nil)
|
583
|
+
@exp = exp
|
584
|
+
end
|
585
|
+
|
586
|
+
def traverse(parent, &block)
|
587
|
+
@exp.traverse(self, &block) if @exp
|
588
|
+
yield self, parent
|
589
|
+
end
|
590
|
+
|
591
|
+
def to_js(options = {})
|
592
|
+
if @exp
|
593
|
+
concat options, :break, @exp, ";"
|
594
|
+
else
|
595
|
+
concat options, :break, ";"
|
596
|
+
end
|
597
|
+
end
|
598
|
+
end
|
599
|
+
|
600
|
+
#12.9
|
601
|
+
class StReturn < St
|
602
|
+
attr_reader :exp
|
603
|
+
|
604
|
+
def initialize(exp = nil)
|
605
|
+
@exp = exp
|
606
|
+
end
|
607
|
+
|
608
|
+
def replace(from, to)
|
609
|
+
if from == @exp
|
610
|
+
@exp = to
|
611
|
+
end
|
612
|
+
end
|
613
|
+
def traverse(parent, &block)
|
614
|
+
@exp.traverse(self, &block) if @exp
|
615
|
+
yield self, parent
|
616
|
+
end
|
617
|
+
|
618
|
+
def to_js(options = {})
|
619
|
+
if @exp
|
620
|
+
concat options, :return, @exp, ";"
|
621
|
+
else
|
622
|
+
concat options, :return, ";"
|
623
|
+
end
|
624
|
+
end
|
625
|
+
end
|
626
|
+
#12.10
|
627
|
+
class StWith < St
|
628
|
+
def initialize(exp, statement)
|
629
|
+
@exp = exp
|
630
|
+
@statement = statement
|
631
|
+
end
|
632
|
+
|
633
|
+
def traverse(parent, &block)
|
634
|
+
@exp.traverse(self, &block)
|
635
|
+
@statement.traverse(self, &block)
|
636
|
+
yield self, parent
|
637
|
+
end
|
638
|
+
|
639
|
+
def to_js(options = {})
|
640
|
+
concat options, :with, "(", @exp, ")","{", @statement, "}"
|
641
|
+
end
|
642
|
+
end
|
643
|
+
#12.11
|
644
|
+
class StSwitch < St
|
645
|
+
#
|
646
|
+
# block: [condition, blocks]
|
647
|
+
#
|
648
|
+
def initialize(exp, blocks)
|
649
|
+
@exp = exp
|
650
|
+
@blocks = blocks
|
651
|
+
end
|
652
|
+
|
653
|
+
def replace(from, to)
|
654
|
+
if @exp == from
|
655
|
+
@exp = to
|
656
|
+
elsif @blocks == from
|
657
|
+
@blocks = to
|
658
|
+
end
|
659
|
+
end
|
660
|
+
|
661
|
+
def traverse(parent, &blocks)
|
662
|
+
@exp.traverse(self, &blocks)
|
663
|
+
@blocks.each do |b|
|
664
|
+
if b[0]
|
665
|
+
b[0].traverse(self, &blocks)
|
666
|
+
end
|
667
|
+
b[1].traverse(self, &blocks)
|
668
|
+
end
|
669
|
+
yield self, parent
|
670
|
+
end
|
671
|
+
|
672
|
+
def to_js(options = {})
|
673
|
+
t = concat(options, :switch, "(", @exp, ")", "{")
|
674
|
+
@blocks.each do |b|
|
675
|
+
if b[0]
|
676
|
+
t = concat(options, t, :case, b[0], ":", b[1])
|
677
|
+
else
|
678
|
+
t = concat(options, t, :default, ":", b[1])
|
679
|
+
end
|
680
|
+
end
|
681
|
+
t = concat(options, t, "}")
|
682
|
+
end
|
683
|
+
end
|
684
|
+
#12.12
|
685
|
+
class StLabelled < St
|
686
|
+
def initialize(id, statement)
|
687
|
+
@id = id
|
688
|
+
@statement = statement
|
689
|
+
end
|
690
|
+
|
691
|
+
def replace(from, to)
|
692
|
+
if from == @id
|
693
|
+
@id = to
|
694
|
+
elsif from == @statement
|
695
|
+
@statement = to
|
696
|
+
end
|
697
|
+
end
|
698
|
+
|
699
|
+
def traverse(parent, &block)
|
700
|
+
@id.traverse(self, &block)
|
701
|
+
@statement.traverse(self, &block)
|
702
|
+
yield self, parent
|
703
|
+
end
|
704
|
+
|
705
|
+
def to_js(options = {})
|
706
|
+
concat options, @id, ":", @statement
|
707
|
+
end
|
708
|
+
end
|
709
|
+
|
710
|
+
#12.13
|
711
|
+
class StThrow < St
|
712
|
+
def initialize(exp)
|
713
|
+
@exp = exp
|
714
|
+
end
|
715
|
+
|
716
|
+
def traverse(parent, &block)
|
717
|
+
@exp.traverse(self, &block)
|
718
|
+
yield self, parent
|
719
|
+
end
|
720
|
+
|
721
|
+
def to_js(options = {})
|
722
|
+
concat options, :throw, @exp, ";"
|
723
|
+
end
|
724
|
+
end
|
725
|
+
|
726
|
+
#12.14
|
727
|
+
class StTry < St
|
728
|
+
def initialize(try, catch, finally)
|
729
|
+
@try = try
|
730
|
+
@catch = catch
|
731
|
+
@finally = finally
|
732
|
+
end
|
733
|
+
|
734
|
+
def replace(from, to)
|
735
|
+
if from == @try
|
736
|
+
@try = to
|
737
|
+
elsif from == @catch[0]
|
738
|
+
@catch[0] = to
|
739
|
+
elsif from == @catch[1]
|
740
|
+
@catch[1] = to
|
741
|
+
elsif from == @finally
|
742
|
+
@finally = to
|
743
|
+
else
|
744
|
+
raise 'unknown'
|
745
|
+
end
|
746
|
+
end
|
747
|
+
|
748
|
+
def traverse(parent, &block)
|
749
|
+
@try.traverse(self, &block)
|
750
|
+
if @catch
|
751
|
+
@catch[0].traverse(self, &block)
|
752
|
+
@catch[1].traverse(self, &block)
|
753
|
+
end
|
754
|
+
@finally.traverse(self, &block) if @finally
|
755
|
+
yield self, parent
|
756
|
+
end
|
757
|
+
|
758
|
+
def to_js(options = {})
|
759
|
+
if @catch and @finally
|
760
|
+
concat(options, :try, @try, :catch, "(", @catch[0], ")", @catch[1], :finally, @finally)
|
761
|
+
elsif @catch
|
762
|
+
concat(options, :try, @try, :catch, "(", @catch[0], ")", @catch[1])
|
763
|
+
else
|
764
|
+
concat(options, :try, @try, :finally, @finally)
|
765
|
+
end
|
766
|
+
end
|
767
|
+
end
|
768
|
+
#12.15
|
769
|
+
class StDebugger < St
|
770
|
+
def traverse
|
771
|
+
yield self, parent
|
772
|
+
end
|
773
|
+
def to_js(options = {})
|
774
|
+
concat options, :debugger, ";"
|
775
|
+
end
|
776
|
+
end
|
777
|
+
#13 function
|
778
|
+
class StFunc < St
|
779
|
+
attr_reader :name
|
780
|
+
attr_reader :args
|
781
|
+
attr_reader :statement
|
782
|
+
attr_reader :context
|
783
|
+
attr_reader :decl
|
784
|
+
|
785
|
+
def initialize(context, name, args, statements, decl = false)
|
786
|
+
@name = name
|
787
|
+
@args = args
|
788
|
+
@statements = statements #=> Prog
|
789
|
+
@context = context
|
790
|
+
@decl = decl
|
791
|
+
end
|
792
|
+
|
793
|
+
def traverse(parent, &block)
|
794
|
+
@name.traverse(self, &block) if @name
|
795
|
+
@args.each do |arg|
|
796
|
+
arg.traverse(self, &block)
|
797
|
+
end
|
798
|
+
@statements.traverse(self, &block)
|
799
|
+
yield self, parent
|
800
|
+
end
|
801
|
+
|
802
|
+
def to_js(options = {})
|
803
|
+
_args = @args.collect{|x|x.to_js(options)}.join(",")
|
804
|
+
concat options, :function, @name, '(', _args, ")", "{", @statements, "}"
|
805
|
+
end
|
806
|
+
end
|
807
|
+
end
|
808
|
+
end
|