minjs 0.2.1 → 0.2.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 8a1f04643d50c1beca0d24712ec63604fd2f0cd8
4
- data.tar.gz: 95e7f5fe15dcf50dbc08e2428ef4d9b1d7735a06
3
+ metadata.gz: dd046433e1cdd1a40960158f44872ced89f083f2
4
+ data.tar.gz: 1482ef6536af057e27c05a4c448e4c74f953b9f7
5
5
  SHA512:
6
- metadata.gz: 86c244ba18493772c481a2242758a589634e7799c7da5e545c22b3c2366908c2281dadf16a0f074bcb8c60ecccb2bac5137e379d2f245cf4c8694abb3a23f2c9
7
- data.tar.gz: 0e84e49b46819f3991fde8a2821121eead7a29373e4e1dc23c7a41e6a35fb72eaf6a108bf9881256ba36bcb722b58ee91d8feedc25cd833794f89e807f6d9cea
6
+ metadata.gz: 37778bbbc0b9dc971d5b9c82b0136dc13ab2266408653bbf59d57eecf22367645bff60acad24ac95814a046308c668b6cc5debe7d46eafc60abbfae4486c98b1
7
+ data.tar.gz: 4435d429c220f49996ebf69d2bef7406102fa1c78099b9328c342f30e2a70dee4ffda51a801f17442e78165f1300e122f09318f4b3b807207becb95f26bff145
@@ -8,6 +8,7 @@ require 'minjs/expression'
8
8
  require 'minjs/func'
9
9
  require 'minjs/program'
10
10
  require 'minjs/exceptions'
11
+ require 'minjs/version'
11
12
  require 'logger'
12
13
 
13
14
  module Minjs
@@ -17,6 +18,7 @@ module Minjs
17
18
  include Exp
18
19
  include Func
19
20
  include Program
21
+ include Ctype
20
22
 
21
23
  attr_reader :prog
22
24
 
@@ -63,8 +65,8 @@ module Minjs
63
65
  :reorder_var,
64
66
  :assignment_after_var,
65
67
  :grouping_statement,
66
- :reduce_if,
67
68
  :block_to_statement,
69
+ :reduce_if,
68
70
  :if_to_cond,
69
71
  :optimize_if_return,
70
72
  :compress_var,
@@ -73,8 +75,8 @@ module Minjs
73
75
  :block_to_statement,
74
76
  :if_to_cond,
75
77
  :optimize_if_return2,
76
- :optimize_if_return3,
77
- :remove_paren,
78
+ :block_to_statement,
79
+ :add_remove_paren,
78
80
  ]
79
81
  algo.each do |a|
80
82
  if (options.empty? || options[:all] || options[a]) && !options[("no_" + a.to_s).to_sym]
@@ -167,7 +169,7 @@ module Minjs
167
169
  st.grouping
168
170
  end
169
171
  }
170
- remove_paren
172
+ add_remove_paren
171
173
  self
172
174
  end
173
175
 
@@ -274,7 +276,7 @@ module Minjs
274
276
  self
275
277
  end
276
278
 
277
- def remove_paren(node = @prog)
279
+ def add_remove_paren(node = @prog)
278
280
  node.traverse(nil) {|st, parent|
279
281
  if st.respond_to? :remove_paren
280
282
  st.remove_paren
@@ -284,41 +286,15 @@ module Minjs
284
286
  self
285
287
  end
286
288
 
287
- def remove_block_in_block(node = @prog)
288
- while true
289
- _retry = false
290
- node.traverse(nil) {|st, parent|
291
- if parent.kind_of? ECMA262::StatementList and st.kind_of? ECMA262::StBlock
292
- idx = parent.index(st)
293
- parent.statement_list[idx..idx] = st.statement_list.statement_list
294
- _retry = true
295
- break
296
- elsif st.kind_of? ECMA262::StBlock
297
- ;
298
- end
299
- }
300
- break if !_retry
301
- end
302
- self
303
- end
304
-
305
- def block_to_statement(node = @prog)
306
- node.traverse(nil) {|st, parent|
307
- if st.kind_of? ECMA262::StBlock and !parent.kind_of?(ECMA262::StTry) and !parent.kind_of?(ECMA262::StIf)
308
- if st.to_statement?
309
- parent.replace(st, st.to_statement)
310
- end
311
- end
312
- }
313
- if_block_to_statement
289
+ def remove_paren(node = @prog)
290
+ add_remove_paren(node)
314
291
  end
315
292
 
316
293
  #
317
- # To determine removing "if block" is available or not is difficult.
318
- # For example, next codes block must not be removed, because
294
+ # To determine removing "block" is available or not is difficult.
295
+ # For example, next code's if-block must not be removed, because
319
296
  # "else" cluase combined to second "if" statement.
320
297
  #
321
- #
322
298
  # if(a){ //<= this block must not be removed
323
299
  # while(true)
324
300
  # if(b){
@@ -328,7 +304,49 @@ module Minjs
328
304
  # else{
329
305
  # ;
330
306
  # }
307
+ #
308
+ # The next code's while-block must not be removed, because
309
+ # "else" cluase combined to second "if" statement.
310
+ #
311
+ # if(a)
312
+ # while(true){ //<= this block must not be removed
313
+ # if(b){
314
+ # ;
315
+ # }
316
+ # }
317
+ # else{
318
+ # ;
319
+ # }
320
+ #
321
+ # To solve this problem, first, every then-clause without block
322
+ # converts to block statement. After converted, all blocks
323
+ # except then-clause can be removed safety.
324
+ #
325
+ def then_to_block(node = @prog)
326
+ node.traverse(nil) {|st, parent|
327
+ if st.kind_of? ECMA262::StIf
328
+ if !st.then_st.kind_of?(ECMA262::StBlock)
329
+ st.replace(st.then_st, ECMA262::StBlock.new([st.then_st]))
330
+ end
331
+ end
332
+ }
333
+ end
334
+
335
+ def block_to_statement(node = @prog)
336
+ remove_empty_statement
337
+ then_to_block
338
+ node.traverse(nil) {|st, parent|
339
+ if st.kind_of? ECMA262::StBlock and !parent.kind_of?(ECMA262::StTry) and !parent.kind_of?(ECMA262::StIf)
340
+ if st.to_statement?
341
+ parent.replace(st, st.to_statement)
342
+ end
343
+ end
344
+ }
345
+ if_block_to_statement
346
+ end
347
+
331
348
  def if_block_to_statement(node = @prog)
349
+ remove_empty_statement
332
350
  # The "else" cluase's block can be removed always
333
351
  node.traverse(nil) {|st, parent|
334
352
  if st.kind_of? ECMA262::StIf
@@ -341,6 +359,47 @@ module Minjs
341
359
  end
342
360
  end
343
361
  }
362
+ node.traverse(nil) {|st, parent|
363
+ if st.kind_of? ECMA262::StIf
364
+ if st.then_st and st.then_st.kind_of? ECMA262::StBlock
365
+ st.then_st.remove_empty_statement
366
+ end
367
+ if !st.else_st and st.then_st.kind_of? ECMA262::StBlock and st.then_st.to_statement?
368
+ st.replace(st.then_st, st.then_st.to_statement)
369
+ elsif st.then_st.kind_of? ECMA262::StBlock and st.then_st.to_statement?
370
+ _st = st.then_st
371
+ st2 = st.then_st.to_statement
372
+ while true
373
+ if st2.kind_of? ECMA262::StVar or st2.kind_of? ECMA262::StEmpty or
374
+ st2.kind_of? ECMA262::StExp or st2.kind_of? ECMA262::StBlock or
375
+ st2.kind_of? ECMA262::StDoWhile or st2.kind_of? ECMA262::StSwitch or
376
+ st2.kind_of? ECMA262::StContinue or st2.kind_of? ECMA262::StBreak or
377
+ st2.kind_of? ECMA262::StReturn or st2.kind_of? ECMA262::StThrow or
378
+ st2.kind_of? ECMA262::StTry or st2.kind_of? ECMA262::StDebugger
379
+ st.replace(st.then_st, st.then_st.to_statement)
380
+ break;
381
+ elsif st2.kind_of? ECMA262::StWhile or
382
+ st2.kind_of? ECMA262::StFor or
383
+ st2.kind_of? ECMA262::StForIn or
384
+ st2.kind_of? ECMA262::StForVar or
385
+ st2.kind_of? ECMA262::StForInVar or
386
+ st2.kind_of? ECMA262::StWith or
387
+ st2.kind_of? ECMA262::StLabelled
388
+ st2 = st2.statement
389
+ elsif st2.kind_of? ECMA262::StIf
390
+ if st2.else_st
391
+ st2 = st2.else_st
392
+ else
393
+ break
394
+ end
395
+ else #?
396
+ break
397
+ end
398
+ end
399
+ end
400
+ end
401
+ }
402
+ =begin
344
403
  node.traverse(nil) {|st0, parent|
345
404
  st = st0.deep_dup
346
405
  if st.kind_of? ECMA262::StIf
@@ -355,11 +414,22 @@ module Minjs
355
414
  _lex = Minjs::Lex.new(st.to_js)
356
415
  _context = ECMA262::Context.new
357
416
  _if = if_statement(_lex, _context)
417
+ reduce_exp(_if)
358
418
  if _if == st #
359
- parent.replace(st0, st)
419
+ if st0.then_st and st0.then_st.kind_of? ECMA262::StBlock
420
+ st0.then_st.remove_empty_statement
421
+ end
422
+ if st0.then_st and st0.then_st.kind_of? ECMA262::StBlock and st0.then_st.to_statement?
423
+ st0.replace(st0.then_st, st0.then_st.to_statement)
424
+ end
425
+ else
426
+ p '!='
427
+ puts st.to_js
428
+ puts _if.to_js
360
429
  end
361
430
  end
362
431
  }
432
+ =end
363
433
  self
364
434
  end
365
435
 
@@ -370,14 +440,25 @@ module Minjs
370
440
  #
371
441
  # if(a)b
372
442
  # =>
373
- # a&&b;
443
+ # a&&b; or a?b:0;
444
+ #
445
+ # NOTE:
446
+ # Sometimes, "conditional operator" will be shorter than
447
+ # "logical and operator", because "conditional operator"'s
448
+ # priority is lower than almost all other expressions.
374
449
  #
375
450
  def if_to_cond(node = @prog)
376
451
  node.traverse(nil) {|st, parent|
377
452
  if st.kind_of? ECMA262::StIf
378
453
  if st.to_exp?
379
454
  t = ECMA262::StExp.new(st.to_exp({}))
380
- remove_paren(t)
455
+ t2 = ECMA262::StExp.new(st.to_exp({cond: true}))
456
+ if t2.to_js.length < t.to_js.length
457
+ t = t2
458
+ end
459
+ add_remove_paren(t)
460
+ simple_replacement(t)
461
+
381
462
  if t.to_js.length <= st.to_js.length
382
463
  parent.replace(st, t)
383
464
  end
@@ -396,7 +477,8 @@ module Minjs
396
477
  if st.kind_of? ECMA262::StIf
397
478
  if st.to_return?
398
479
  t = st.to_return
399
- remove_paren(t)
480
+ add_remove_paren(t)
481
+ simple_replacement(t)
400
482
  if t.to_js.length <= st.to_js.length
401
483
  parent.replace(st, t)
402
484
  end
@@ -410,49 +492,55 @@ module Minjs
410
492
  # if(a)return b;
411
493
  # return c;
412
494
  #
413
- # => if(a)return b;else return c;
414
495
  # => return a?b:c;
415
496
  #
416
497
  def optimize_if_return(node = @prog)
417
- retry_flag = true
418
- while retry_flag
419
- retry_flag = false
420
- node.traverse(nil) {|st0, parent0|
421
- if st0.kind_of? ECMA262::StIf and parent0.kind_of? ECMA262::StatementList
422
- i = parent0.index(st0)
423
- break if i.nil?
424
- parent = parent0.deep_dup
425
- st = parent[i]
426
- #
427
- if parent[i+1].nil? and !parent.kind_of?(ECMA262::SourceElements)
428
- next
498
+ node.traverse(nil) {|st0, parent0|
499
+ if st0.kind_of? ECMA262::StatementList
500
+ st0.remove_empty_statement
501
+ st = st0.deep_dup
502
+ while true
503
+ #check last statement
504
+ ls = st.statement_list[-1]
505
+ ls2 = st.statement_list[-2]
506
+ if st.kind_of? ECMA262::SourceElements and !(ls.kind_of? ECMA262::StReturn)
507
+ ls2 = ls
508
+ ls = ECMA262::StReturn.new(ECMA262::ExpVoid.new(ECMA262::ECMA262Numeric.new(0)))
429
509
  end
430
- if parent[i+1].nil? or parent[i+1].to_return?
431
- s = st
432
- while s.kind_of? ECMA262::StIf and s.else_st and s.then_st.to_return?
433
- s = s.else_st
434
- end
435
- if s and s.kind_of? ECMA262::StIf and s.then_st.to_return?
436
- if parent[i+1]
437
- s.replace(s.else_st, parent[i+1])
438
- parent.replace(parent[i+1], ECMA262::StEmpty.new)
439
- else
440
- s.replace(s.else_st, ECMA262::StReturn.new(ECMA262::ExpVoid.new(ECMA262::ECMA262Numeric.new(0))))
441
- end
442
- if_to_cond(parent)
443
- if parent.to_js(:no_debug => true).length <= parent0.to_js(:no_debug => true).length
444
- parent0.replace(st0, st)
445
- if parent[i+1]
446
- parent0.replace(parent0[i+1], ECMA262::StEmpty.new)
447
- end
448
- retry_flag = true
449
- node = parent0
450
- end
451
- end
510
+ break if ls.nil?
511
+ break if ls2.nil?
512
+ break if !ls.to_return?
513
+ break if !ls2.kind_of?(ECMA262::StIf)
514
+ break if ls2.else_st
515
+ break if !ls2.then_st.to_return?
516
+
517
+ # if !ls2.then_st.kind_of? ECMA262::StIf and !ls2.then_st.to_return?
518
+ # break
519
+ # end
520
+ # if ls2.then_st.kind_of? ECMA262::StIf and !ls2.then_to_return?
521
+ # break
522
+ # end
523
+
524
+ then_exp = ls2.then_st.to_return.exp
525
+ else_exp = ls.to_return.exp
526
+ then_exp = ECMA262::ExpVoid.new(ECMA262::ECMA262Numeric.new(0)) if then_exp.nil?
527
+ else_exp = ECMA262::ExpVoid.new(ECMA262::ECMA262Numeric.new(0)) if else_exp.nil?
528
+ if ls2.cond.kind_of? ECMA262::ExpLogicalNot
529
+ cond = ECMA262::ExpCond.new(ls2.cond.val, else_exp, then_exp)
530
+ else
531
+ cond = ECMA262::ExpCond.new(ls2.cond, then_exp, else_exp)
452
532
  end
533
+ ret = ECMA262::StReturn.new(cond)
534
+ #puts ret.to_js
535
+ #puts ls2.to_js
536
+ st.replace(ls2, ret)
537
+ st.remove(ls)
453
538
  end
454
- }
455
- end
539
+ if st0.to_js.length > st.to_js.length
540
+ parent0.replace(st0, st)
541
+ end
542
+ end
543
+ }
456
544
  self
457
545
  end
458
546
 
@@ -470,23 +558,7 @@ module Minjs
470
558
  idx = parent.index(st)
471
559
  parent[idx+1..0] = st.else_st
472
560
  st.replace(st.else_st, nil)
473
- end
474
- end
475
- }
476
- self
477
- end
478
- #
479
- # feature
480
- #
481
- # if(a)b;else return c;
482
- # =>
483
- # if(!a)return c;b;
484
- #
485
- def optimize_if_return3(node = @prog)
486
- node.traverse(nil) {|st, parent|
487
- if st.kind_of? ECMA262::StIf and st.else_st and parent.kind_of? ECMA262::StatementList
488
- st.remove_empty_statement
489
- if (st.else_st.kind_of? ECMA262::StBlock and st.else_st[-1].kind_of? ECMA262::StReturn) or
561
+ elsif (st.else_st.kind_of? ECMA262::StBlock and st.else_st[-1].kind_of? ECMA262::StReturn) or
490
562
  st.else_st.kind_of? ECMA262::StReturn
491
563
  idx = parent.index(st)
492
564
  parent[idx+1..0] = st.then_st
@@ -504,19 +576,64 @@ module Minjs
504
576
  def compress_var(node = @prog, options = {})
505
577
  func_scopes = []
506
578
  catch_scopes = []
579
+ with_scopes = []
580
+ #
581
+ # ECMA262 10.2:
582
+ #
583
+ # Usually a Lexical Environment is associated with some
584
+ # specific syntactic structure of ECMAScript code such as a
585
+ # FunctionDeclaration, a WithStatement, or a Catch clause of a
586
+ # TryStatement and a new Lexical Environment is created each
587
+ # time such code is evaluated.
588
+ #
507
589
  node.traverse(nil) {|st, parent|
508
590
  if st.kind_of? ECMA262::StFunc
509
591
  func_scopes.push([st, parent])
510
592
  elsif st.kind_of? ECMA262::StTry
511
593
  catch_scopes.push([st, parent])
512
594
  elsif st.kind_of? ECMA262::StWith
513
- #TODO
595
+ with_scopes.push([st, parent])
514
596
  end
515
597
  }
516
- #10.2
517
598
  #
518
- # Catch clause of a TryStatement and a new Lexical Environment is
519
- # created each time such code is evaluated.
599
+ # 10.2, 12.14
600
+ #
601
+ #eee = 'global';
602
+ #function test()
603
+ #{
604
+ # /*
605
+ # "eee" is local variable(belongs to this function)
606
+ # because var declaration is exist in this function.
607
+ # (see also catch's scope comment)
608
+ # So, global variable 'eee' is not changed.
609
+ # */
610
+ # eee = 'function';
611
+ # try{
612
+ # console.log(eee); //=>function
613
+ # throw "exception";
614
+ # }
615
+ # catch(eee){
616
+ # /*
617
+ # The catch's variable scope will be created at execution time.
618
+ # so next var declaration should belong to "test" function.
619
+ # */
620
+ # var eee;
621
+ # /*
622
+ # In execution time, "eee" belongs to this
623
+ # catch-clause's scope.
624
+ # */
625
+ # console.log(eee); //=>exception
626
+ # /*
627
+ # Next function has its own scope and 'eee' belongs to its.
628
+ # */
629
+ # (function(){
630
+ # var eee;
631
+ # console.log(eee); //=>undefined
632
+ # })();
633
+ # }
634
+ #}
635
+ #console.log(eee); //=>global
636
+ #test();
520
637
  #
521
638
  catch_scopes.each{|st, parent|
522
639
  catch_context = ECMA262::Context.new
@@ -527,13 +644,24 @@ module Minjs
527
644
  st.catch[0].context = catch_context
528
645
 
529
646
  st.catch[1].traverse(parent){|st2|
530
- if st2.kind_of? ECMA262::IdentifierName and st2 == st.catch[0] and
531
- st2.binding_env == st.catch[0].binding_env
647
+ if st2.kind_of? ECMA262::IdentifierName and st2 == st.catch[0] and st2.binding_env == st.catch[0].binding_env
532
648
  st2.context = catch_context
533
649
  end
534
650
  }
535
651
  func_scopes.unshift([st, parent])
536
652
  }
653
+ # with_scopes.each{|st, parent|
654
+ # with_context = ECMA262::Context.new
655
+ # with_context.lex_env = st.context.lex_env.new_declarative_env()
656
+ # with_context.var_env = st.context.var_env
657
+ # st.statement.traverse(st) {|st2|
658
+ # if st2.kind_of? ECMA262::IdentifierName and st2.binding_env == st.context.var_env
659
+ # st2.context = with_context
660
+ # with_context.lex_env.record.create_mutable_binding(st2, nil)
661
+ # with_context.lex_env.record.set_mutable_binding(st2, :undefined, nil)
662
+ # end
663
+ # }
664
+ # }
537
665
  func_scopes.reverse!
538
666
  func_scopes.each {|st, parent|
539
667
  if st.kind_of? ECMA262::StFunc
@@ -586,10 +714,6 @@ module Minjs
586
714
  elsif st2_lex_env == @global_context.lex_env #global
587
715
  outer_vars[var_name] ||= 0
588
716
  outer_vars[var_name] += 1
589
- # elsif st2_lex_env == context.lex_env and st2_lex_env != context.lex_env
590
- # nesting_vars[var_name] ||= 0
591
- # nesting_vars[var_name] += 1
592
- # nesting_vars_list.push(st2)
593
717
  elsif st2_lex_env == context.lex_env
594
718
  var_vars[var_name] ||= 0
595
719
  var_vars[var_name] += 1
@@ -620,6 +744,10 @@ module Minjs
620
744
  eval_flag = true
621
745
  break
622
746
  end
747
+ if st2.kind_of? ECMA262::StWith
748
+ eval_flag = true
749
+ break
750
+ end
623
751
  }
624
752
  if eval_flag
625
753
  next
@@ -637,14 +765,18 @@ module Minjs
637
765
  if name.nil?
638
766
  next #bug?
639
767
  end
640
- #STDERR.puts "trying to rename #{name}"
768
+ if name.length == 1
769
+ #STDERR.puts "#{name}=>#{count}"
770
+ next
771
+ end
772
+ #STDERR.puts "trying to rename #{name}(#{count})"
641
773
  while true
642
774
  #condition b
643
- if var_vars[var_sym]
644
- #STDERR.puts "var_vars has #{var_sym}"
645
- #condigion c
646
- elsif outer_vars[var_sym]
775
+ if outer_vars[var_sym]
647
776
  #STDERR.puts "outer_vars has #{var_sym}"
777
+ elsif var_vars[var_sym]
778
+ #STDERR.puts "var_vars has #{var_sym}(#{var_vars[var_sym]})"
779
+ #condigion c
648
780
  else #condition a&d
649
781
  #STDERR.puts "->#{var_sym}"
650
782
  break
@@ -687,7 +819,7 @@ module Minjs
687
819
  }
688
820
  end
689
821
  #raise 'error' if x.binding_env(:var).nil?
690
- raise 'error' if x.binding_env(:lex).nil?
822
+ raise x.to_js if x.binding_env(:lex).nil?
691
823
  end
692
824
  end
693
825
  rename_table[name] = var_sym
@@ -711,11 +843,13 @@ module Minjs
711
843
  end
712
844
 
713
845
  var_vars_list.each {|st2|
714
- st2.instance_eval{
715
- @val = rename_table[@val]
716
- }
717
- #raise 'error' if st2.binding_env(:var).nil?
718
- raise 'error' if st2.binding_env(:lex).nil?
846
+ st2.instance_eval{
847
+ if rename_table[@val]
848
+ @val = rename_table[@val]
849
+ #raise 'error' if st2.binding_env(:var).nil?
850
+ raise st2.to_js if st2.binding_env(:lex).nil?
851
+ end
852
+ }
719
853
  }
720
854
  }
721
855
  self
@@ -731,7 +865,6 @@ module Minjs
731
865
  end
732
866
 
733
867
  def simple_replacement(node = @prog)
734
- retry_flag = false
735
868
  node.traverse(nil) {|st, parent|
736
869
  #
737
870
  #true => !0
@@ -777,6 +910,40 @@ module Minjs
777
910
  elsif st.kind_of? ECMA262::ExpNew and st.args and st.args.length == 0
778
911
  st.replace(st.args, nil)
779
912
  parent.add_paren.remove_paren
913
+ #
914
+ # !c?a:b => c?b:a
915
+ # true?a:b => a
916
+ # false?a:b => b
917
+ #
918
+ elsif st.kind_of? ECMA262::ExpCond
919
+ if st.val.kind_of? ECMA262::ExpLogicalNot
920
+ st.instance_eval{
921
+ @val = @val.val
922
+ t = @val2
923
+ @val2 = @val3
924
+ @val3 = t
925
+ }
926
+ simple_replacement(st)
927
+ end
928
+
929
+ if st.val.respond_to? :to_ecma262_boolean
930
+ if st.val.to_ecma262_boolean.nil?
931
+ ;
932
+ elsif st.val.to_ecma262_boolean
933
+ parent.replace(st, st.val2)
934
+ else
935
+ parent.replace(st, st.val3)
936
+ end
937
+ end
938
+ #
939
+ # A["B"] => A.N
940
+ #
941
+ elsif st.kind_of? ECMA262::ExpPropBrac and st.val2.kind_of? ECMA262::ECMA262String
942
+ if idname?(st.val2.val)
943
+ parent.replace(st, ECMA262::ExpProp.new(st.val, st.val2))
944
+ elsif !st.val2.to_ecma262_number.nil? and (v=ECMA262::ECMA262Numeric.new(st.val2.to_ecma262_number)).to_ecma262_string == st.val2.to_ecma262_string
945
+ st.replace(st.val2, v)
946
+ end
780
947
  end
781
948
  }
782
949
  self
@@ -787,7 +954,7 @@ module Minjs
787
954
  #
788
955
  def reduce_if(node = @prog)
789
956
  retry_flag = true
790
- while(retry_flag)
957
+ while retry_flag
791
958
  retry_flag = false
792
959
  node.traverse(nil) {|st, parent|
793
960
  if st.kind_of? ECMA262::StIf
@@ -800,14 +967,6 @@ module Minjs
800
967
  st.replace(st.cond, ECMA262::ExpLogicalAnd.new(st.cond, st.then_st.cond))
801
968
  st.replace(st.then_st, st.then_st.then_st)
802
969
  end
803
- #if(a);
804
- # => a
805
- #if(a){}
806
- # => a
807
- if st.then_st.empty? and st.else_st.nil?
808
- parent.replace(st, ECMA262::StExp.new(st.cond))
809
- retry_flag = true
810
- end
811
970
  #if(a)z;else;
812
971
  #if(a)z;else{}
813
972
  # => {if(a)z;}
@@ -815,12 +974,12 @@ module Minjs
815
974
  st.replace(st.else_st, nil)
816
975
  parent.replace(st, ECMA262::StBlock.new([st]))
817
976
  retry_flag = true
977
+ break
818
978
  end
819
-
820
979
  #if(a);else z;
821
- #=>if(!a)z;
980
+ #=>{if(!a)z};
822
981
  #if(a){}else z;
823
- #=>if(!a)z;
982
+ #=>{if(!a)z};
824
983
  if st.then_st.empty? and st.else_st
825
984
  st.replace(st.cond, ECMA262::ExpLogicalNot.new(st.cond));
826
985
  else_st = st.else_st
@@ -828,40 +987,53 @@ module Minjs
828
987
  st.replace(st.then_st, else_st)
829
988
  parent.replace(st, ECMA262::StBlock.new([st]))
830
989
  retry_flag = true
990
+ break
991
+ end
992
+ #if(a);
993
+ # => a
994
+ #if(a){}
995
+ # => a
996
+ if st.then_st.empty? and st.else_st.nil?
997
+ parent.replace(st, ECMA262::StExp.new(st.cond))
831
998
  end
832
999
  =begin
833
- #feature
834
- #
835
1000
  #if(!(a&&b))
836
1001
  #=>
837
1002
  #if(!a||!b)
838
- #
839
- #if(!(a||b))
840
- #=>
841
- #if(!a&&!b)
842
- #
843
1003
  if st.cond.kind_of? ECMA262::ExpLogicalNot and st.cond.val.kind_of? ECMA262::ExpParen and
844
1004
  st.cond.val.val.kind_of? ECMA262::ExpLogicalAnd
845
1005
  a = ECMA262::ExpLogicalNot.new(st.cond.val.val.val)
846
1006
  b = ECMA262::ExpLogicalNot.new(st.cond.val.val.val2)
847
- r = ECMA262::ExpLogicalOr.new(a,b).add_paren.remove_paren
848
- if r.to_js.length < st.cond.to_js.length
1007
+ r = ECMA262::ExpLogicalOr.new(a,b).add_remove_paren
1008
+ if r.to_js.length <= st.cond.to_js.length
849
1009
  st.replace(st.cond, r)
850
1010
  end
851
- elsif st.cond.kind_of? ECMA262::ExpLogicalNot and st.cond.val.kind_of? ECMA262::ExpParen and
1011
+ end
1012
+ #if(!(a||b))
1013
+ #=>
1014
+ #if(!a&&!b)
1015
+ if st.cond.kind_of? ECMA262::ExpLogicalNot and st.cond.val.kind_of? ECMA262::ExpParen and
852
1016
  st.cond.val.val.kind_of? ECMA262::ExpLogicalOr
853
1017
  a = ECMA262::ExpLogicalNot.new(st.cond.val.val.val)
854
1018
  b = ECMA262::ExpLogicalNot.new(st.cond.val.val.val2)
855
- r = ECMA262::ExpLogicalAnd.new(a,b).add_paren.remove_paren
856
- if r.to_js.length < st.cond.to_js.length
1019
+ r = ECMA262::ExpLogicalAnd.new(a,b).add_remove_paren
1020
+ if r.to_js.length <= st.cond.to_js.length
857
1021
  st.replace(st.cond, r)
858
1022
  end
859
1023
  end
860
1024
  =end
1025
+ #if((a))
1026
+ if st.cond.kind_of? ECMA262::ExpParen
1027
+ st.replace(st.cond, st.cond.val)
1028
+ end
1029
+ #if(!!a)
1030
+ if st.cond.kind_of? ECMA262::ExpLogicalNot and st.cond.val.kind_of? ECMA262::ExpLogicalNot
1031
+ st.replace(st.cond, st.cond.val.val)
1032
+ end
861
1033
  end
862
1034
  }
863
- block_to_statement if retry_flag
864
1035
  end
1036
+ block_to_statement
865
1037
  self
866
1038
  end
867
1039
 
@@ -946,14 +1118,24 @@ if $0 == __FILE__
946
1118
  f = []
947
1119
  options = {}
948
1120
  argv.each do |x|
949
- if x.match(/^--?/)
1121
+ if x.match(/^--?version/)
1122
+ puts Minjs::VERSION
1123
+ exit(0)
1124
+ elsif x.match(/^--?/)
950
1125
  opt = $'.gsub(/-/, '_').to_sym
951
1126
  options[opt] = true
952
1127
  else
953
1128
  f.push(open(x.to_s).read())
954
1129
  end
955
1130
  end
1131
+
1132
+ js = f.join("\n")
1133
+
956
1134
  comp = Minjs::Compressor.new(:debug => false)
957
- comp.compress(f.join("\n"), options)
958
- puts comp.to_js(options)
1135
+ comp.compress(js, options)
1136
+ comp_js = comp.to_js(options)
1137
+ #p comp_js.length
1138
+ js = comp_js
1139
+ puts js
1140
+
959
1141
  end
@@ -863,5 +863,16 @@ module Minjs
863
863
  return true
864
864
  end
865
865
  end
866
+
867
+ def idname?(name)
868
+ return false if name.length == 0
869
+ s = name.codepoints
870
+ return false unless identifier_start?(s[0])
871
+ s.unshift
872
+ s.each do |code|
873
+ return false unless identifier_part?(code)
874
+ end
875
+ return true
876
+ end
866
877
  end
867
878
  end
@@ -67,6 +67,16 @@ module Minjs
67
67
  puts "warning: #{self.class}: == not implement"
68
68
  raise "warning: #{self.class}: == not implement"
69
69
  end
70
+
71
+ def add_remove_paren(node = self)
72
+ node.traverse(nil) {|st, parent|
73
+ if st.respond_to? :remove_paren
74
+ st.add_paren
75
+ st.remove_paren
76
+ end
77
+ }
78
+ node
79
+ end
70
80
  end
71
81
 
72
82
  class StatementList < Base
@@ -111,8 +121,16 @@ module Minjs
111
121
  end
112
122
 
113
123
  if idx = new_sl.index{|x| x.class == StReturn}
114
- while idx < new_sl.length - 1
115
- new_sl.pop
124
+ idx += 1
125
+ while idx < new_sl.length
126
+ if new_sl[idx].kind_of? StVar
127
+ ;
128
+ elsif new_sl[idx].kind_of? StFunc
129
+ ;
130
+ else
131
+ new_sl[idx] = StEmpty.new
132
+ end
133
+ idx += 1
116
134
  end
117
135
  end
118
136
 
@@ -153,6 +171,7 @@ module Minjs
153
171
  end
154
172
 
155
173
  def traverse(parent, &block)
174
+ _self = self
156
175
  @statement_list.each do|st|
157
176
  st.traverse(self, &block)
158
177
  end
@@ -240,6 +259,13 @@ module Minjs
240
259
  def deep_dup
241
260
  self.class.new(context, source_elements.deep_dup)
242
261
  end
262
+
263
+ def replace(from, to)
264
+ if from == @source_elements
265
+ @source_elements = to
266
+ end
267
+ end
268
+
243
269
  def traverse(parent, &block)
244
270
  @source_elements.traverse(self, &block)
245
271
  yield self, parent
@@ -360,11 +360,15 @@ module Minjs
360
360
  end
361
361
 
362
362
  def replace(from, to)
363
- @args.each_index do |i|
364
- arg = @args[i]
365
- if arg .eql? from
366
- @args[i] = to
367
- break
363
+ if @name .eql? from
364
+ @name = to
365
+ else
366
+ @args.each_index do |i|
367
+ arg = @args[i]
368
+ if arg .eql? from
369
+ @args[i] = to
370
+ break
371
+ end
368
372
  end
369
373
  end
370
374
  end
@@ -466,8 +470,7 @@ module Minjs
466
470
  end
467
471
 
468
472
  def to_js(options = {})
469
- #TODO => simple_replacement
470
- if @args# and @args.length > 0
473
+ if @args
471
474
  args = @args.collect{|x| x.to_js(options)}.join(",")
472
475
  concat options, :new, @name, '(', args, ')'
473
476
  else
@@ -1194,16 +1197,13 @@ module Minjs
1194
1197
  end
1195
1198
 
1196
1199
  def to_ecma262_boolean
1197
- if @val.respond_to? :to_ecma262_boolean and @val2.respond_to? :to_ecma262_boolean
1198
- return nil if @val.to_ecma262_boolean == nil or @val2.to_ecma262_boolean == nil
1199
- if @val.to_ecma262_boolean and @val2.to_ecma262_boolean
1200
- true
1201
- else
1202
- false
1203
- end
1204
- else
1205
- nil
1206
- end
1200
+ return nil if !(@val.respond_to? :to_ecma262_boolean)
1201
+ return nil if @val.to_ecma262_boolean == nil
1202
+ return false if @val.to_ecma262_boolean == false
1203
+ return nil if !(@val2.respond_to? :to_ecma262_boolean)
1204
+ return nil if @val2.to_ecma262_boolean == nil
1205
+ return false if @val2.to_ecma262_boolean == false
1206
+ true
1207
1207
  end
1208
1208
 
1209
1209
  def ecma262_typeof
@@ -1227,16 +1227,13 @@ module Minjs
1227
1227
  end
1228
1228
 
1229
1229
  def to_ecma262_boolean
1230
- if @val.respond_to? :to_ecma262_boolean and @val2.respond_to? :to_ecma262_boolean
1231
- return nil if @val.to_ecma262_boolean == nil or @val2.to_ecma262_boolean == nil
1232
- if @val.to_ecma262_boolean or @val2.to_ecma262_boolean
1233
- true
1234
- else
1235
- false
1236
- end
1237
- else
1238
- nil
1239
- end
1230
+ return nil if !(@val.respond_to? :to_ecma262_boolean)
1231
+ return nil if @val.to_ecma262_boolean == nil
1232
+ return true if @val.to_ecma262_boolean == true
1233
+ return nil if !(@val2.respond_to? :to_ecma262_boolean)
1234
+ return nil if @val2.to_ecma262_boolean == nil
1235
+ return true if @val2.to_ecma262_boolean == true
1236
+ false
1240
1237
  end
1241
1238
 
1242
1239
  def ecma262_typeof
@@ -1255,6 +1252,7 @@ module Minjs
1255
1252
  #
1256
1253
  class ExpCond < Exp
1257
1254
  attr_reader :val, :val2, :val3
1255
+ alias :cond :val
1258
1256
 
1259
1257
  def initialize(val, val2, val3)
1260
1258
  @val = val
@@ -693,16 +693,17 @@ module Minjs
693
693
  @val = val
694
694
  end
695
695
 
696
- def idname?(name)
697
- return false if name.length == 0
698
- s = name.codepoints
699
- return false unless identifier_start?(s[0])
700
- s.unshift
701
- s.each do |code|
702
- return false unless identifier_part?(code)
703
- end
704
- return true
705
- end
696
+ #=>Ctype
697
+ # def idname?(name)
698
+ # return false if name.length == 0
699
+ # s = name.codepoints
700
+ # return false unless identifier_start?(s[0])
701
+ # s.unshift
702
+ # s.each do |code|
703
+ # return false unless identifier_part?(code)
704
+ # end
705
+ # return true
706
+ # end
706
707
 
707
708
  def deep_dup
708
709
  self.class.new(@val.collect{|x, y| [x.deep_dup, y ? y.deep_dup : y]})
@@ -37,6 +37,12 @@ module Minjs
37
37
  self.class.new(@statement_list.deep_dup)
38
38
  end
39
39
 
40
+ def replace(from, to)
41
+ if from == @statement_list
42
+ @statement_list = to
43
+ end
44
+ end
45
+
40
46
  def traverse(parent, &block)
41
47
  @statement_list.traverse(self, &block)
42
48
  yield self, parent
@@ -84,6 +90,14 @@ module Minjs
84
90
  end
85
91
  end
86
92
 
93
+ def to_return?
94
+ to_statement? and to_statement.to_return?
95
+ end
96
+
97
+ def to_return
98
+ to_statement.to_return
99
+ end
100
+
87
101
  def empty?
88
102
  @statement_list.statement_list.select{|s|
89
103
  s.class != StEmpty
@@ -181,6 +195,7 @@ module Minjs
181
195
  x[1] = x[1].val
182
196
  end
183
197
  end
198
+ self
184
199
  end
185
200
 
186
201
  def add_paren
@@ -262,6 +277,7 @@ module Minjs
262
277
  if @exp.kind_of? ExpParen
263
278
  @exp = @exp.val if @exp.remove_paren?
264
279
  end
280
+ self
265
281
  end
266
282
 
267
283
  def add_paren
@@ -327,24 +343,22 @@ module Minjs
327
343
 
328
344
  def to_return
329
345
  then_exp = then_st.exp;
330
- else_exp = else_st.exp;
346
+ if @else_st
347
+ else_exp = else_st.exp;
348
+ end
331
349
 
332
350
  if then_exp.nil?
333
351
  then_exp = ExpVoid.new(ECMA262Numeric.new(0))
334
352
  end
335
- if else_exp.nil?
353
+ if @else_st and else_exp.nil?
336
354
  else_exp = ExpVoid.new(ECMA262Numeric.new(0))
337
355
  end
338
356
  if @else_st
339
- ret = StReturn.new(ExpCond.new(@cond, then_exp, else_exp).add_paren)
340
- else
341
- ret = StReturn.new(ExpLogicalAnd.new(@cond, then_exp).add_paren)
342
- end
343
- if ret.to_js.length <= to_js.length
344
- ret
357
+ ret = add_remove_paren StReturn.new(ExpCond.new(@cond, then_exp, else_exp))
345
358
  else
346
- self
359
+ ret = add_remove_paren StReturn.new(ExpLogicalAnd.new(@cond, then_exp))
347
360
  end
361
+ ret
348
362
  end
349
363
 
350
364
  def to_exp?
@@ -361,20 +375,28 @@ module Minjs
361
375
  cond = @cond.deep_dup
362
376
  if !@else_st
363
377
  then_exp = @then_st.to_exp(options)
364
- if cond.kind_of? ExpLogicalNot
365
- return ExpParen.new(ExpLogicalOr.new(ExpParen.new(cond.val), ExpParen.new(then_exp)))
378
+ if(options[:cond])
379
+ if cond.kind_of? ExpLogicalNot
380
+ add_remove_paren ExpCond.new(cond.val, ECMA262Numeric.new(0), then_exp)
381
+ else
382
+ add_remove_paren ExpCond.new(cond, then_exp, ECMA262Numeric.new(0))
383
+ end
366
384
  else
367
- return ExpParen.new(ExpLogicalAnd.new(ExpParen.new(cond), ExpParen.new(then_exp)))
385
+ if cond.kind_of? ExpLogicalNot
386
+ add_remove_paren ExpLogicalOr.new(cond.val, then_exp)
387
+ else
388
+ add_remove_paren ExpLogicalAnd.new(cond, then_exp)
389
+ end
368
390
  end
369
391
  else
370
- then_exp = ExpParen.new(@then_st.to_exp(options))
371
- else_exp = ExpParen.new(@else_st.to_exp(options))
372
- end
392
+ then_exp = @then_st.to_exp(options)
393
+ else_exp = @else_st.to_exp(options)
373
394
 
374
- if cond.kind_of? ExpLogicalNot
375
- ExpCond.new(ExpParen.new(cond.val), else_exp, then_exp)
376
- else
377
- ExpCond.new(ExpParen.new(cond), then_exp, else_exp)
395
+ if cond.kind_of? ExpLogicalNot
396
+ add_remove_paren ExpCond.new(cond.val, else_exp, then_exp)
397
+ else
398
+ add_remove_paren ExpCond.new(cond, then_exp, else_exp)
399
+ end
378
400
  end
379
401
  end
380
402
 
@@ -842,7 +864,7 @@ module Minjs
842
864
  end
843
865
 
844
866
  def deep_dup
845
- self.class.new(@exp)
867
+ self.class.new(@exp ? @exp.deep_dup : nil)
846
868
  end
847
869
 
848
870
  def traverse(parent, &block)
@@ -873,7 +895,7 @@ module Minjs
873
895
  end
874
896
 
875
897
  def deep_dup
876
- self.class.new(@exp)
898
+ self.class.new(@exp ? @exp.deep_dup : nil)
877
899
  end
878
900
 
879
901
  def traverse(parent, &block)
@@ -903,10 +925,6 @@ module Minjs
903
925
  @exp = exp
904
926
  end
905
927
 
906
- def deep_dup
907
- self.class.new(@exp)
908
- end
909
-
910
928
  def deep_dup
911
929
  self.class.new(exp ? exp.deep_dup : nil)
912
930
  end
@@ -955,15 +973,16 @@ module Minjs
955
973
  end
956
974
  #12.10
957
975
  class StWith < St
958
- attr_reader :exp, :statement
976
+ attr_reader :exp, :statement, :context
959
977
 
960
- def initialize(exp, statement)
978
+ def initialize(context, exp, statement)
979
+ @context = context
961
980
  @exp = exp
962
981
  @statement = statement
963
982
  end
964
983
 
965
984
  def deep_dup
966
- self.class.new(@exp, @statement)
985
+ self.class.new(@context, @exp.deep_dup, @statement.deep_dup)
967
986
  end
968
987
 
969
988
  def replace(from, to)
@@ -1014,7 +1033,7 @@ module Minjs
1014
1033
  end
1015
1034
 
1016
1035
  def deep_dup
1017
- self.class.new(@exp,
1036
+ self.class.new(@exp.deep_dup,
1018
1037
  @blocks.collect{|x, y|
1019
1038
  [
1020
1039
  x ? x.deep_dup : nil,
@@ -1085,7 +1104,7 @@ module Minjs
1085
1104
  end
1086
1105
 
1087
1106
  def deep_dup
1088
- self.class.new(@label, @statement)
1107
+ self.class.new(@label.deep_dup, @statement.deep_dup)
1089
1108
  end
1090
1109
 
1091
1110
  def replace(from, to)
@@ -1121,7 +1140,7 @@ module Minjs
1121
1140
  end
1122
1141
 
1123
1142
  def deep_dup
1124
- self.class.new(@exp)
1143
+ self.class.new(@exp.deep_dup)
1125
1144
  end
1126
1145
 
1127
1146
  def traverse(parent, &block)
@@ -1152,7 +1171,10 @@ module Minjs
1152
1171
  end
1153
1172
 
1154
1173
  def deep_dup
1155
- self.class.new(@context, @try, @catch, @finally)
1174
+ self.class.new(@context,
1175
+ @try.deep_dup,
1176
+ @catch ? [@catch[0].deep_dup, @catch[1].deep_dup] : nil,
1177
+ @finally ? @finally.deep_dup : nil)
1156
1178
  end
1157
1179
 
1158
1180
  def replace(from, to)
@@ -338,7 +338,7 @@ module Minjs
338
338
  return nil unless lex.match_lit(ECMA262::ID_WITH)
339
339
  lex.eval_lit {
340
340
  if lex.match_lit(ECMA262::PUNC_LPARENTHESIS) and e=exp(lex, context, {}) and lex.match_lit(ECMA262::PUNC_RPARENTHESIS) and s=statement(lex, context)
341
- ECMA262::StWith.new(e, s)
341
+ ECMA262::StWith.new(context, e, s)
342
342
  else
343
343
  raise ParseError.new("switch_statement", lex)
344
344
  end
@@ -1,3 +1,3 @@
1
1
  module Minjs
2
- VERSION = "0.2.1"
2
+ VERSION = "0.2.2"
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: minjs
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.1
4
+ version: 0.2.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Issei Numata
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2015-05-26 00:00:00.000000000 Z
11
+ date: 2015-05-29 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler