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.
@@ -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