minjs 0.1.10 → 0.2.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: fc081d9afd40b166f51a4c5644c9de92885717c8
4
- data.tar.gz: 36f9da0d2cc3b20cfc15665f78e9a7cfe9021d7b
3
+ metadata.gz: c3d1d9049c22ff483762abe2eb89d9cbcfdde1bd
4
+ data.tar.gz: 9780d815f256edea332b814d84c7c299c870d8d2
5
5
  SHA512:
6
- metadata.gz: 56bdd17c30497dfe92cc8d2e53e5e8685814032acf69f2d0b31dae8f59e49739769297e4efe175f75f615f97f1ed662031d713b54330d7f2806107fe5d41e826
7
- data.tar.gz: 40424bea0a9de0995419e53bf100d9ce7f8d42f08f32782e118c72023508897129c4aa338e671d44edde40c459aa1b772ca3aed35dd0dd45bfcffedb925a11cf
6
+ metadata.gz: dae0218ef56cdef8ca1fd8a602cedd6f36b23a328f1da3d9e17e19eab851b22bebe7b857ec72c223e04729a891eb2bb2b6ca4f1a24b099ccf5dd7bb166616594
7
+ data.tar.gz: 164cbde79345dcf7175af658571af6b5cef96b08ef4bc89d9600f21b6f91b310d369a53e0924355f0a16d94461899113a27b45f349a22bbbe721c011067bdab9
@@ -53,60 +53,44 @@ module Minjs
53
53
  @logger.info '* parse'
54
54
  parse(data)
55
55
 
56
- @logger.info '* reorder_function_decl'
57
- reorder_function_decl
58
-
59
- @logger.info '* simple_replacement'
60
- simple_replacement
61
-
62
- @logger.info '* reorder_var'
63
- reorder_var
64
-
65
- @logger.info '* assignment_after_var'
66
- assignment_after_var
67
-
68
- @logger.info '* grouping_statement'
69
- grouping_statement
70
-
71
- @logger.info '* reduce_if'
72
- reduce_if
73
-
74
- @logger.info '* block_to_statement'
75
- block_to_statement
76
-
77
- @logger.info '* if_to_cond'
78
- if_to_cond
79
-
80
- @logger.info '* optimize_if_return'
81
- optimize_if_return
82
-
83
- @logger.info '* compress_var'
84
- compress_var(@prog, :longer => true)
85
- compress_var
86
-
87
- @logger.info '* reduce_exp'
88
- reduce_exp
89
-
90
- grouping_statement
91
- block_to_statement
92
- if_to_cond
93
-
94
- #feature
95
- optimize_if_return2
56
+ if options[:only_parse]
57
+ return
58
+ end
96
59
 
97
- @logger.info '* remove_paren'
98
- remove_paren
60
+ algo = [
61
+ :reorder_function_decl,
62
+ :simple_replacement,
63
+ :reorder_var,
64
+ :assignment_after_var,
65
+ :grouping_statement,
66
+ :reduce_if,
67
+ :block_to_statement,
68
+ :if_to_cond,
69
+ :optimize_if_return,
70
+ :compress_var,
71
+ :reduce_exp,
72
+ :grouping_statement,
73
+ :block_to_statement,
74
+ :if_to_cond,
75
+ :optimize_if_return2,
76
+ :remove_paren,
77
+ ]
78
+ algo.each do |a|
79
+ if (options.empty? || options[:all] || options[a]) && !options[("no_" + a.to_s).to_sym]
80
+ @logger.info "* #{a}"
81
+ __send__(a, @prog)
82
+ end
83
+ end
99
84
 
100
85
  @heading_comments.reverse.each do |c|
101
86
  @prog.source_elements.source_elements.unshift(c)
102
87
  end
103
- to_js(options)
88
+ self
104
89
  end
105
90
 
106
91
  def parse(data)
107
92
  @lex = Minjs::Lex.new(data, :logger => @logger)
108
93
  @global_context = ECMA262::Context.new
109
-
110
94
  @heading_comments = []
111
95
  @lex.eval_lit{
112
96
  while a = @lex.ws_lit
@@ -116,11 +100,7 @@ module Minjs
116
100
  }
117
101
  @prog = source_elements(@lex, @global_context)
118
102
 
119
- #a = @prog.deep_dup
120
- #a == @prog
121
-
122
103
  remove_empty_statement
123
- #@prog
124
104
  self
125
105
  end
126
106
 
@@ -191,14 +171,18 @@ module Minjs
191
171
  end
192
172
 
193
173
  def reorder_function_decl(node = @prog)
174
+ flist = []
194
175
  node.traverse(nil) {|st, parent|
195
176
  if st.kind_of? ECMA262::StFunc and parent.kind_of? ECMA262::StatementList and st.decl?
196
177
  if parent.index(st)
197
- parent.remove(st)
198
- parent.source_elements.unshift(st)
178
+ flist.push([st, parent])
199
179
  end
200
180
  end
201
181
  }
182
+ flist.reverse.each do |st, parent|
183
+ parent.remove(st)
184
+ parent.statement_list.unshift(st)
185
+ end
202
186
  self
203
187
  end
204
188
 
@@ -254,13 +238,18 @@ module Minjs
254
238
 
255
239
  idx = 0
256
240
  elems.each do |e|
241
+ next if e.kind_of? ECMA262::StFunc and e.decl?
257
242
  found = false
258
- e.traverse(nil){|ee, pp|
259
- if ee.kind_of? ECMA262::IdentifierName and var_vars[ee.val.to_sym]
260
- found = true
261
- break
262
- end
263
- }
243
+ if e.kind_of? ECMA262::StFunc and e.decl?
244
+ ;
245
+ else
246
+ e.traverse(nil){|ee, pp|
247
+ if ee.kind_of? ECMA262::IdentifierName and var_vars[ee.val.to_sym]
248
+ found = true
249
+ break
250
+ end
251
+ }
252
+ end
264
253
  break if found
265
254
  idx += 1
266
255
  end
@@ -275,35 +264,6 @@ module Minjs
275
264
  end
276
265
  self
277
266
  }
278
- =begin
279
- st.traverse(parent) {|st2, parent2|
280
- #
281
- #if var statment has initializer,
282
- #
283
- #
284
- if st2.kind_of? ECMA262::StVar and st2.context.var_env == @context.var_env
285
- st2.instance_eval{
286
- blk = []
287
- @vars.each do |vl|
288
- if vl[1]
289
- blk.push(ECMA262::StExp.new(ECMA262::ExpAssign.new(vl[0], vl[1])))
290
- else
291
- end
292
- end
293
- parent2.replace(st2, ECMA262::StBlock.new(ECMA262::StatementList.new(blk)))
294
- }
295
- elsif st2.kind_of? ECMA262::StForVar and st2.context.var_env == @context.var_env
296
- parent2.replace(st2, st2.to_st_for)
297
- elsif st2.kind_of? ECMA262::StForInVar and st2.context.var_env == @context.var_env
298
- parent2.replace(st2, st2.to_st_for_in)
299
- end
300
- }
301
-
302
- }
303
- end
304
- }
305
- remove_block_in_block
306
- =end
307
267
  self
308
268
  end
309
269
 
@@ -509,76 +469,93 @@ module Minjs
509
469
  self
510
470
  end
511
471
 
512
- def compress_var(node = @prog, options = {})
513
- if options[:longer]
514
- var_sym = :aaaaaaaaaa
515
- end
472
+ def compress_var(node = @prog)
473
+ #compress_var_sub(@prog, :longer => true)
474
+ compress_var_sub
475
+ end
516
476
 
477
+ def compress_var_sub(node = @prog, options = {})
517
478
  #
518
479
  #traverse all statemtns and expression
519
480
  #
520
481
  scopes = []
521
482
  node.traverse(nil) {|st, parent|
522
- if st.kind_of? ECMA262::StTry and st.catch
523
- _context = st.catch_context
524
- _parent = st
525
- _st = st.catch[1]
526
- elsif st.kind_of? ECMA262::StFunc
483
+ if st.kind_of? ECMA262::StFunc
527
484
  _context = st.context
528
485
  _parent = parent
529
486
  _st = st
530
- else
531
- _parent = nil
532
- _context = nil
533
- _st = nil
534
- end
535
- if _parent and _context and _st
536
487
  scopes.push([st, parent, _parent, _context, _st])
537
488
  end
538
489
  }
539
- #node.traverse(nil) {|st, parent|
540
- scopes.reverse.each {|st, parent, _parent, _context, _st|
541
- #p "*#{st.name.to_js}"
542
- if !options[:longer]
543
- var_sym = :a
544
- end
490
+ scopes.reverse!
491
+ scopes.each {|st, parent, _parent, _context, _st|
492
+ var_sym = :a
545
493
  if _parent and _context and _st
546
494
  #
547
495
  # collect and counting all variables under this function/catch
496
+ # collect and counting all var-variables under this function/catch
548
497
  #
549
- vars = {}
550
- if st.kind_of? ECMA262::StTry
551
- vars[st.catch[0].val.to_sym] = 1
552
- end
498
+ all_vars = {}
499
+ var_vars = {}
500
+ var_vars_list = []
501
+ outer_vars = {}
502
+ nesting_vars = {}
503
+ nesting_vars_list = []
504
+
553
505
  _st.traverse(_parent) {|st2|
506
+ #
507
+ # In this function,
508
+ #
509
+ # 1. outer_vars:
510
+ # Variables which locate out of this function(or global variable)
511
+ # Them name cannot be renamed
512
+ # 2. nesting_vars:
513
+ # Variables which locate in the function of this function.
514
+ # Them name cannot be renamed
515
+ # 3. var_vars:
516
+ # Variables which have same scope in this function.
517
+ # Them name can be renamed under the following conditions
518
+ #
519
+ # a. If the new name is not used, the name can be renamed to it.
520
+ # b. If the new name belongs to var_vars, the name cannot be renamed.
521
+ # c. If the new name belongs to outer_vars the name cannot be renamed.
522
+ # d. If the new name belongs to nesting_vars, the name can be rename
523
+ # to it after rename nesting_vars's name to another name.
524
+ #
554
525
  if st2.kind_of? ECMA262::IdentifierName
555
- vars[st2.val.to_sym] ||= 0
556
- vars[st2.val.to_sym] += 1
526
+ var_name = st2.val.to_sym
527
+ st2_env = st2.binding_env
528
+ all_vars[var_name] ||= 0
529
+ all_vars[var_name] += 1
530
+ if st2_env == nil #global
531
+ outer_vars[var_name] ||= 0
532
+ outer_vars[var_name] += 1
533
+ elsif st2_env == @global_context.var_env #global
534
+ outer_vars[var_name] ||= 0
535
+ outer_vars[var_name] += 1
536
+ elsif st2_env == st.context.var_env
537
+ var_vars[var_name] ||= 0
538
+ var_vars[var_name] += 1
539
+ var_vars_list.push(st2)
540
+ else
541
+ e = st2.binding_env
542
+ while e
543
+ e = e.outer
544
+ if e == st.context.var_env
545
+ nesting_vars[var_name] ||= 0
546
+ nesting_vars[var_name] += 1
547
+ nesting_vars_list.push(st2)
548
+ break
549
+ end
550
+ if e.nil?
551
+ outer_vars[var_name] ||= 0
552
+ outer_vars[var_name] += 1
553
+ break
554
+ end
555
+ end
556
+ end
557
557
  end
558
558
  }
559
- #
560
- # collect all var variables under this function
561
- #
562
- var_vars = {}
563
- if st.kind_of? ECMA262::StFunc
564
- _context.var_env.record.binding.each do|k, v|
565
- var_vars[k] = (vars[k] || 1)
566
- end
567
- end
568
- #
569
- # collect all lexical variables under this catch clause
570
- #
571
- # currently, only catch's args is lex_var
572
- #
573
- lex_vars = {}
574
- if st.kind_of? ECMA262::StTry
575
- _context.lex_env.record.binding.each do|k, v|
576
- lex_vars[k] = (vars[k] || 1)
577
- end
578
- end
579
- #
580
- # check `eval' function is exist under this function/catch
581
- #
582
559
  unless var_vars[:eval]
583
560
  eval_flag = false
584
561
  _st.traverse(_parent) {|st2|
@@ -594,97 +571,83 @@ module Minjs
594
571
  #
595
572
  # sort var_vars
596
573
  #
597
- var_vars = var_vars.sort {|(k1,v1), (k2,v2)| v2 <=> v1}
598
- #p var_vars
574
+ var_vars_array = var_vars.sort {|(k1,v1), (k2,v2)| v2 <=> v1}
599
575
  #
600
- # check var_vars
576
+ # create renaming table
601
577
  #
602
- var_vars.each {|name, count|
578
+ rename_table = {}
579
+ var_vars_array.each {|name, count|
603
580
  if name.nil?
604
- next
581
+ next #bug?
605
582
  end
606
- while(vars[var_sym])
583
+ while outer_vars[var_sym] or var_vars[var_sym]
607
584
  var_sym = next_sym(var_sym)
608
585
  end
609
- if (!options[:longer] && name.to_s.bytesize >= var_sym.to_s.bytesize) or
610
- (options[:longer] && name.to_s.bytesize <= var_sym.to_s.bytesize)
611
- #
612
- # rename `name' to `var_sym'
613
- #
614
- func_name = nil
615
- if _st.kind_of? ECMA262::StFunc and _st.decl?
616
- func_name = _st.name
586
+ #rename nesting_vars
587
+ if nesting_vars[var_sym]
588
+ nesting_vars_list.each do |x|
589
+ raise 'error' if x.binding_env(:var).nil?
590
+ raise 'error' if x.binding_env(:lex).nil?
617
591
  end
618
- _st.traverse(_parent){|st2|
619
- if st2.kind_of? ECMA262::IdentifierName and st2.context.nil?
620
- ;# this
621
- elsif st2.kind_of? ECMA262::IdentifierName and st2.context.var_env.outer == nil # global scope
622
- ;
623
- elsif st2.kind_of? ECMA262::IdentifierName and st2.val == name
624
- # scope of function's name is outer
625
- if st2.eql?(func_name)
626
- else
627
- st2.instance_eval{
628
- @val = var_sym
629
- }
630
- end
631
- elsif st2.kind_of? ECMA262::StFunc
632
- if st2.context.var_env.record.binding[name]
633
- st2.context.var_env.record.binding[var_sym] = st2.context.var_env.record.binding[name]
634
- st2.context.var_env.record.binding.delete(name)
635
- end
636
- elsif st2.kind_of? ECMA262::StTry
637
- if st2.catch_context.lex_env.record.binding[name]
638
- st2.catch_context.lex_env.record.binding[var_sym] = st2.catch_context.lex_env.record.binding[name]
639
- st2.catch_context.lex_env.record.binding.delete(name)
640
- end
592
+
593
+ var_sym2 = "abc#{var_sym.to_s}".to_sym
594
+ while all_vars[var_sym2]
595
+ var_sym2 = next_sym(var_sym2)
596
+ end
597
+ rl = {}
598
+ nesting_vars_list.each do |x|
599
+ if x.val.to_sym == var_sym
600
+ _var_env = x.binding_env(:var)
601
+ _lex_env = x.binding_env(:lex)
602
+ rl[_var_env] = true
603
+ rl[_lex_env] = true
641
604
  end
642
- }
643
- end
644
- var_sym = next_sym(var_sym)
645
- }
646
- lex_vars.each {|name, count|
647
- if name.nil?
648
- next
649
- end
650
- while(vars[var_sym])
651
- var_sym = next_sym(var_sym)
652
- end
653
- if name.to_s.bytesize > var_sym.to_s.bytesize
654
- #
655
- # rename `name' to `var_sym'
656
- #
657
- _st.traverse(_parent){|st2|
658
- if st2.kind_of? ECMA262::IdentifierName and st2.context.nil?
659
- ;# TODO, currently special identifier such as 'this' has no context
660
- elsif st2.kind_of? ECMA262::IdentifierName and st2.context.lex_env.outer == nil # global scope
661
- ;
662
- elsif st2.kind_of? ECMA262::IdentifierName and st2.val == name
663
- st2.instance_eval{
664
- @val = var_sym
665
- }
605
+ end
606
+ rl.keys.each do |_env|
607
+ if _env && _env.record.binding[var_sym]
608
+ _env.record.binding[var_sym2] = _env.record.binding[var_sym]
609
+ _env.record.binding.delete var_sym
666
610
  end
667
- }
668
- if st.kind_of? ECMA262::StTry
669
- if st.catch[0].kind_of? ECMA262::IdentifierName
670
- st.catch[0].instance_eval{
671
- @val = var_sym
611
+ end
612
+
613
+ nesting_vars_list.each do |x|
614
+ if x.val.to_sym == var_sym
615
+ x.instance_eval{
616
+ @val = var_sym2
672
617
  }
673
- elsif st2.kind_of? ECMA262::StFunc
674
- if st2.context.var_env.record.binding[name]
675
- st2.context.var_env.record.binding[var_sym] = st2.context.var_env.record.binding[name]
676
- st2.context.var_env.record.binding.delete(name)
677
- end
678
- elsif st2.kind_of? ECMA262::StTry
679
- if st2.catch_context.lex_env.record.binding[name]
680
- st2.catch_context.lex_env.record.binding[var_sym] = st2.catch_context.lex_env.record.binding[name]
681
- st2.catch_context.lex_env.record.binding.delete(name)
682
- end
683
618
  end
619
+ raise 'error' if x.binding_env(:var).nil?
620
+ raise 'error' if x.binding_env(:lex).nil?
684
621
  end
685
622
  end
623
+ rename_table[name] = var_sym
686
624
  var_sym = next_sym(var_sym)
687
625
  }
626
+ var_vars_list.each {|st2|
627
+ raise 'error' if st2.binding_env(:var).nil?
628
+ raise 'error' if st2.binding_env(:lex).nil?
629
+ }
630
+
631
+ rename_table.each do |name, new_name|
632
+ if name != new_name
633
+ if st.context.var_env.record.binding[name]
634
+ st.context.var_env.record.binding[new_name] = st.context.var_env.record.binding[name]
635
+ st.context.var_env.record.binding.delete(name)
636
+ end
637
+ if st.context.lex_env.record.binding[name]
638
+ st.context.lex_env.record.binding[new_name] = st.context.lex_env.record.binding[name]
639
+ st.context.lex_env.record.binding.delete(name)
640
+ end
641
+ end
642
+ end
643
+
644
+ var_vars_list.each {|st2|
645
+ st2.instance_eval{
646
+ @val = rename_table[@val]
647
+ }
648
+ raise 'error' if st2.binding_env(:var).nil?
649
+ raise 'error' if st2.binding_env(:lex).nil?
650
+ }
688
651
  end
689
652
  }
690
653
  self
@@ -700,6 +663,7 @@ module Minjs
700
663
  end
701
664
 
702
665
  def simple_replacement(node = @prog)
666
+ retry_flag = false
703
667
  node.traverse(nil) {|st, parent|
704
668
  #
705
669
  #true => !0
@@ -715,20 +679,7 @@ module Minjs
715
679
  #if(true){<then>}else{<else>} => then
716
680
  #
717
681
  elsif st.kind_of? ECMA262::StIf
718
- #if(a)z;else;
719
- #if(a)z;else{}
720
- # => {if(a)z;}
721
- if st.else_st and st.else_st.empty?
722
- st.replace(st.else_st, nil)
723
- parent.replace(st, ECMA262::StBlock.new([st]))
724
- end
725
- #if(a);
726
- # => a
727
- #if(a){}
728
- # => a
729
- if st.then_st.empty? and st.else_st.nil?
730
- parent.replace(st, ECMA262::StExp.new(st.cond))
731
- elsif st.cond.respond_to? :to_ecma262_boolean
682
+ if st.cond.respond_to? :to_ecma262_boolean
732
683
  if st.cond.to_ecma262_boolean
733
684
  parent.replace(st, st.then_st)
734
685
  elsif st.else_st
@@ -747,6 +698,12 @@ module Minjs
747
698
  else
748
699
  parent.replace(st, ECMA262::StEmpty.new)
749
700
  end
701
+ #
702
+ # new A() => (new A)
703
+ #
704
+ elsif st.kind_of? ECMA262::ExpNew and st.args and st.args.length == 0
705
+ st.replace(st.args, nil)
706
+ parent.add_paren.remove_paren
750
707
  end
751
708
  }
752
709
  self
@@ -755,27 +712,54 @@ module Minjs
755
712
  #
756
713
  # reduce_if
757
714
  #
758
- # 1) rewrite nested "if" statemet such as:
759
- # if(a)
760
- # if(b) ...;
761
- #
762
- # to:
763
- #
764
- # if(a && b) ...;
765
- #
766
- # NOTE:
767
- # both if must not have "else" clause
768
- #
769
715
  def reduce_if(node = @prog)
770
- node.traverse(nil) {|st, parent|
771
- if st.kind_of? ECMA262::StIf
772
- if st.else_st.nil? and
773
- st.then_st.kind_of? ECMA262::StIf and st.then_st.else_st.nil?
774
- st.replace(st.cond, ECMA262::ExpLogicalAnd.new(st.cond, st.then_st.cond))
775
- st.replace(st.then_st, st.then_st.then_st)
716
+ retry_flag = true
717
+ while(retry_flag)
718
+ retry_flag = false
719
+ node.traverse(nil) {|st, parent|
720
+ if st.kind_of? ECMA262::StIf
721
+ # if(a)
722
+ # if(b) ...;
723
+ # if(a && b) ...;
724
+ #
725
+ if st.else_st.nil? and
726
+ st.then_st.kind_of? ECMA262::StIf and st.then_st.else_st.nil?
727
+ st.replace(st.cond, ECMA262::ExpLogicalAnd.new(st.cond, st.then_st.cond))
728
+ st.replace(st.then_st, st.then_st.then_st)
729
+ end
730
+ #if(a);
731
+ # => a
732
+ #if(a){}
733
+ # => a
734
+ if st.then_st.empty? and st.else_st.nil?
735
+ parent.replace(st, ECMA262::StExp.new(st.cond))
736
+ retry_flag = true
737
+ end
738
+ #if(a)z;else;
739
+ #if(a)z;else{}
740
+ # => {if(a)z;}
741
+ if st.else_st and st.else_st.empty?
742
+ st.replace(st.else_st, nil)
743
+ parent.replace(st, ECMA262::StBlock.new([st]))
744
+ retry_flag = true
745
+ end
746
+
747
+ #if(a);else z;
748
+ #=>if(!a)z;
749
+ #if(a){}else z;
750
+ #=>if(!a)z;
751
+ if st.then_st.empty? and st.else_st
752
+ st.replace(st.cond, ECMA262::ExpLogicalNot.new(st.cond));
753
+ else_st = st.else_st
754
+ st.replace(st.else_st, nil)
755
+ st.replace(st.then_st, else_st)
756
+ parent.replace(st, ECMA262::StBlock.new([st]))
757
+ retry_flag = true
758
+ end
776
759
  end
777
- end
778
- }
760
+ }
761
+ block_to_statement if retry_flag
762
+ end
779
763
  self
780
764
  end
781
765
 
@@ -858,10 +842,16 @@ end
858
842
  if $0 == __FILE__
859
843
  argv = ARGV.dup
860
844
  f = []
845
+ options = {}
861
846
  argv.each do |x|
862
- f.push(open(x.to_s).read())
847
+ if x.match(/^--?/)
848
+ opt = $'.gsub(/-/, '_').to_sym
849
+ options[opt] = true
850
+ else
851
+ f.push(open(x.to_s).read())
852
+ end
863
853
  end
864
854
  comp = Minjs::Compressor.new(:debug => false)
865
- comp.compress(f.join("\n"))
866
- puts comp.to_js({})
855
+ comp.compress(f.join("\n"), options)
856
+ puts comp.to_js(options)
867
857
  end
@@ -39,10 +39,13 @@ module Minjs
39
39
  end
40
40
  #for debug
41
41
  unless options[:no_debug]
42
- if @logger and @logger.debug?
42
+ if (@logger and @logger.debug?) || options[:debug]
43
43
  if js.match(/;\z/) and !options[:for_args]
44
44
  nl = "\n"
45
45
  end
46
+ if js.match(/}\z/) and !options[:for_args]
47
+ nl = "\n"
48
+ end
46
49
  end
47
50
  end
48
51
  js = "#{sep}#{js}#{nl}";
@@ -25,6 +25,12 @@ module Minjs
25
25
  end
26
26
  end
27
27
 
28
+ class DeclarativeEnvRecord < EnvRecord
29
+ end
30
+
31
+ class ObjectEnvRecord < EnvRecord
32
+ end
33
+
28
34
  class ExObject
29
35
  def initialize(options = {})
30
36
  @attr = options[:attr] || {}
@@ -35,14 +41,30 @@ module Minjs
35
41
  class LexEnv
36
42
  attr_reader :record
37
43
  attr_reader :outer
44
+ attr_reader :type
38
45
 
39
46
  def initialize(options = {})
40
47
  @outer = options[:outer]
41
- @record = EnvRecord.new
48
+ if options[:type] == :object
49
+ @record = ObjectEnvRecord.new
50
+ else #if options[:type] == :declarative
51
+ @record = DeclarativeEnvRecord.new
52
+ end
42
53
  end
43
54
 
44
55
  def new_declarative_env(outer = nil)
45
- LexEnv.new(outer: (outer || self))
56
+ e = LexEnv.new(outer: (outer || self), type: :declarative)
57
+ end
58
+
59
+ def new_object_env(object, outer = nil)#TODO
60
+ raise 'TODO'
61
+ e = LexEnv.new(outer: (outer || self), type: :object)
62
+ object.val.each do |k, v|
63
+ if k.id_name?
64
+ e.create_mutable_binding(k)
65
+ e.set_mutable_binding(k, v)
66
+ end
67
+ end
46
68
  end
47
69
 
48
70
  def debug
@@ -58,6 +80,7 @@ module Minjs
58
80
  def initialize(options = {})
59
81
  @var_env = LexEnv.new(options)
60
82
  @lex_env = LexEnv.new(options)
83
+ #TODO
61
84
  @this_binding = ExObject.new(
62
85
  {
63
86
  attr: {
@@ -73,9 +96,6 @@ module Minjs
73
96
  @var_env.debug
74
97
  end
75
98
 
76
- def inspect
77
- @var_env.record.binding.to_s
78
- end
79
99
  end
80
100
  end
81
101
  end
@@ -427,7 +427,7 @@ module Minjs
427
427
  end
428
428
 
429
429
  def priority
430
- PRIORITY_LEFT_HAND_SIDE + ((args && args.length == 0) ? 1 : 0)
430
+ PRIORITY_LEFT_HAND_SIDE + ((args == nil) ? 1 : 0)
431
431
  end
432
432
 
433
433
  def deep_dup
@@ -438,6 +438,8 @@ module Minjs
438
438
  def replace(from, to)
439
439
  if @name .eql? from
440
440
  @name = from
441
+ elsif @args .eql? from
442
+ @args = to
441
443
  elsif @args and (idx = @args.index(from))
442
444
  @args[idx] = to
443
445
  end
@@ -458,7 +460,8 @@ module Minjs
458
460
  end
459
461
 
460
462
  def to_js(options = {})
461
- if @args and @args.length > 0
463
+ #TODO => simple_replacement
464
+ if @args# and @args.length > 0
462
465
  args = @args.collect{|x| x.to_js(options)}.join(",")
463
466
  concat options, :new, @name, '(', args, ')'
464
467
  else
@@ -199,12 +199,21 @@ module Minjs
199
199
  end
200
200
 
201
201
  def to_js(options = {})
202
- t = "\""
202
+ dq = @val.to_s.each_codepoint.select{|x| x == 0x22}.length
203
+ sq = @val.to_s.each_codepoint.select{|x| x == 0x27}.length
204
+ if dq <= sq
205
+ t = "\""
206
+ else
207
+ t = "\'"
208
+ end
209
+
203
210
  @val.to_s.each_codepoint do |c|
204
211
  if c == 0x5c
205
212
  t << ('\\\\')
206
- elsif c == 0x22
213
+ elsif c == 0x22 and dq <= sq
207
214
  t << ('\"')
215
+ elsif c == 0x27 and dq > sq
216
+ t << ('\\\'')
208
217
  elsif c >= 0x20 and c <= 0x7f
209
218
  t << ("%c" % c)
210
219
  elsif c == 8
@@ -227,7 +236,11 @@ module Minjs
227
236
  t << [c].pack("U*")
228
237
  end
229
238
  end
230
- t << "\""
239
+ if dq <= sq
240
+ t << "\""
241
+ else
242
+ t << "\'"
243
+ end
231
244
  end
232
245
 
233
246
  def to_ecma262_boolean
@@ -454,7 +467,13 @@ module Minjs
454
467
 
455
468
  class ECMA262Object < Literal
456
469
  include Ctype
457
- private
470
+ attr_reader :val
471
+
472
+ #val is tupple [[k,v],[k,v],...]
473
+ def initialize(val)
474
+ @val = val
475
+ end
476
+
458
477
  def idname?(name)
459
478
  return false if name.length == 0
460
479
  s = name.codepoints
@@ -466,13 +485,6 @@ module Minjs
466
485
  return true
467
486
  end
468
487
 
469
- public
470
- attr_reader :val
471
-
472
- def initialize(val)
473
- @val = val
474
- end
475
-
476
488
  def deep_dup
477
489
  self.class.new(@val.collect{|x, y| [x.deep_dup, y ? y.deep_dup : y]})
478
490
  end
@@ -633,6 +645,24 @@ module Minjs
633
645
  def to_js(options = {})
634
646
  val.to_s
635
647
  end
648
+
649
+ def binding_env(type = :var)
650
+ return nil if context.nil?
651
+ if type == :var
652
+ v = context.var_env
653
+ else
654
+ v = context.lex_env
655
+ end
656
+
657
+ while v
658
+ if v.record.binding[val]
659
+ return v
660
+ else
661
+ v = v.outer
662
+ end
663
+ end
664
+ nil
665
+ end
636
666
  end
637
667
 
638
668
  ID_THIS = IdentifierName.get(nil, :this)
@@ -1146,19 +1146,17 @@ module Minjs
1146
1146
  #12.14
1147
1147
  class StTry < St
1148
1148
  attr_reader :context
1149
- attr_reader :catch_context
1150
1149
  attr_reader :try, :catch, :finally
1151
1150
 
1152
- def initialize(context, catch_context, try, catch, finally)
1151
+ def initialize(context, try, catch, finally)
1153
1152
  @context = context
1154
- @catch_context = catch_context
1155
1153
  @try = try
1156
1154
  @catch = catch
1157
1155
  @finally = finally
1158
1156
  end
1159
1157
 
1160
1158
  def deep_dup
1161
- self.class.new(@context, @catch_context, @try, @catch, @finally)
1159
+ self.class.new(@context, @try, @catch, @finally)
1162
1160
  end
1163
1161
 
1164
1162
  def replace(from, to)
@@ -31,7 +31,9 @@ module Minjs
31
31
  } || lex.eval_lit {
32
32
  object_literal(lex, context, options)
33
33
  }
34
- @logger.debug "*** primary_exp => #{t ? t.to_js : t}"
34
+ @logger.debug {
35
+ "*** primary_exp => #{t ? t.to_js : t}"
36
+ }
35
37
  t
36
38
  end
37
39
 
@@ -162,7 +164,9 @@ module Minjs
162
164
  } || lex.eval_lit{
163
165
  new_exp(lex, context, options)
164
166
  }
165
- @logger.debug "*** left_hand_side_exp => #{t ? t.to_js: t}"
167
+ @logger.debug{
168
+ "*** left_hand_side_exp => #{t ? t.to_js: t}"
169
+ }
166
170
  t
167
171
  end
168
172
 
@@ -696,7 +700,9 @@ module Minjs
696
700
  raise ParseError.new("unexpceted token", lex)
697
701
  end
698
702
  else
699
- @logger.debug "*** assignment_exp => #{t ? t.to_js : t}"
703
+ @logger.debug {
704
+ "*** assignment_exp => #{t ? t.to_js : t}"
705
+ }
700
706
  t
701
707
  end
702
708
  }
@@ -716,7 +722,9 @@ module Minjs
716
722
  raise ParseError.new("unexpceted token", lex)
717
723
  end
718
724
  end
719
- @logger.debug "*** expression => #{t ? t.to_js : t}"
725
+ @logger.debug{
726
+ "*** expression => #{t ? t.to_js : t}"
727
+ }
720
728
  t
721
729
  }
722
730
  end
data/lib/minjs/func.rb CHANGED
@@ -6,10 +6,9 @@ module Minjs
6
6
  def func_declaration(lex, context)
7
7
  return nil if lex.match_lit(ECMA262::ID_FUNCTION).nil?
8
8
  lex.eval_lit {
9
- new_env = context.lex_env.new_declarative_env()
10
9
  new_context = ECMA262::Context.new
11
- new_context.lex_env = new_env
12
- new_context.var_env = new_env
10
+ new_context.lex_env = context.lex_env.new_declarative_env()
11
+ new_context.var_env = context.var_env.new_declarative_env()
13
12
 
14
13
  if id=identifier(lex, context) and
15
14
  lex.match_lit(ECMA262::PUNC_LPARENTHESIS) and
@@ -39,11 +38,10 @@ module Minjs
39
38
  @logger.debug "*** func_exp"
40
39
 
41
40
  lex.eval_lit {
42
- id_opt = identifier(lex, context)
43
- new_env = context.lex_env.new_declarative_env()
44
- new_context = ECMA262::Context.new
45
- new_context.lex_env = new_env
46
- new_context.var_env = new_env
41
+ id_opt = identifier(lex, context)
42
+ new_context = ECMA262::Context.new
43
+ new_context.lex_env = context.lex_env.new_declarative_env()
44
+ new_context.var_env = context.var_env.new_declarative_env()
47
45
 
48
46
  if lex.match_lit(ECMA262::PUNC_LPARENTHESIS) and
49
47
  args = formal_parameter_list(lex, new_context) and
data/lib/minjs/lex.rb CHANGED
@@ -618,15 +618,18 @@ module Minjs
618
618
  @pos += 4
619
619
  t
620
620
  else
621
- #
621
+ # line continuation
622
+ if line_terminator?(@codes[@pos])
623
+ ""
622
624
  # octal
623
625
  # Annex B
624
- if octal?(@codes[@pos])
625
- oct = 0
626
- while octal?(@codes[@pos])
626
+ elsif octal?(@codes[@pos])
627
+ oct = (@codes[@pos] - 0x30)
628
+ 2.times do
629
+ break unless octal?(@codes[@pos+1])
630
+ @pos += 1
627
631
  oct *= 8
628
632
  oct += (@codes[@pos] - 0x30)
629
- @pos += 1
630
633
  end
631
634
  [oct].pack("U*")
632
635
  else
@@ -728,8 +731,8 @@ module Minjs
728
731
  pos0 = pos
729
732
  pos = 0
730
733
  end
731
- if col and col > 2
732
- pos0 = col - 2;
734
+ if col and col >= 1
735
+ pos0 = col - 1;
733
736
  end
734
737
  t = ''
735
738
  t << @codes[pos..(pos+80)].pack("U*")
@@ -782,13 +785,13 @@ module Minjs
782
785
  break if _pos >= pos
783
786
  if line_terminator?(code)
784
787
  row += 1
785
- row = 0
788
+ col = 0
786
789
  else
787
790
  col += 1
788
791
  end
789
792
  _pos += 1
790
793
  end
791
- return [row+1, col]
794
+ return [row+1, col+1]
792
795
  end
793
796
  end
794
797
  end
@@ -33,7 +33,7 @@ module Minjs
33
33
  tmp.close
34
34
  end
35
35
  #TODO
36
- t = Minjs::Compressor.new(:logger => logger).compress(data)
36
+ t = Minjs::Compressor.new(:logger => logger).compress(data).to_js
37
37
  if logger.info?
38
38
  tmp = open(output, "w")
39
39
  tmp.write(t)
@@ -101,6 +101,8 @@ module Minjs
101
101
  dn = v[0]
102
102
  context.var_env.record.create_mutable_binding(dn, nil)
103
103
  context.var_env.record.set_mutable_binding(dn, :undefined, nil)
104
+ context.lex_env.record.create_mutable_binding(dn, nil)
105
+ context.lex_env.record.set_mutable_binding(dn, :undefined, nil)
104
106
  end
105
107
  ECMA262::StVar.new(context, vl)
106
108
  else
@@ -146,17 +148,22 @@ module Minjs
146
148
  #
147
149
  def empty_statement(lex, context)
148
150
  lex.eval_lit{
149
- a = lex.fwd_lit(:nolt => true)
151
+ a = lex.fwd_lit
150
152
  if a == ECMA262::PUNC_SEMICOLON
151
153
  ECMA262::StEmpty.new
152
- elsif a == ECMA262::LIT_LINE_FEED
153
- ECMA262::StEmpty.new
154
- elsif a.lt?
155
- ECMA262::StEmpty.new
156
154
  else
157
155
  nil
158
156
  end
159
- }
157
+ }# || lex.eval_lit {
158
+ # a = lex.fwd_lit(:nolt => true)
159
+ # if a == ECMA262::LIT_LINE_FEED
160
+ # ECMA262::StEmpty.new
161
+ # elsif a.lt?
162
+ # ECMA262::StEmpty.new
163
+ # else
164
+ # nil
165
+ # end
166
+ # }
160
167
  end
161
168
  #
162
169
  #12.4
@@ -226,6 +233,8 @@ module Minjs
226
233
  #10.5
227
234
  context.var_env.record.create_mutable_binding(v[0], nil)
228
235
  context.var_env.record.set_mutable_binding(v[0], :undefined, nil)
236
+ context.lex_env.record.create_mutable_binding(v[0], nil)
237
+ context.lex_env.record.set_mutable_binding(v[0], :undefined, nil)
229
238
  ECMA262::StForInVar.new(context, v, e, s)
230
239
  else
231
240
  nil
@@ -241,6 +250,8 @@ module Minjs
241
250
  dn = v[0]
242
251
  context.var_env.record.create_mutable_binding(dn, nil)
243
252
  context.var_env.record.set_mutable_binding(dn, :undefined, nil)
253
+ context.lex_env.record.create_mutable_binding(dn, nil)
254
+ context.lex_env.record.set_mutable_binding(dn, :undefined, nil)
244
255
  end
245
256
  ECMA262::StForVar.new(context, vl, e, e2, s)
246
257
  else
@@ -404,7 +415,10 @@ module Minjs
404
415
  return nil unless lex.match_lit(ECMA262::ID_TRY)
405
416
  lex.eval_lit {
406
417
  catch_context = ECMA262::Context.new
407
- catch_env = context.lex_env.new_declarative_env()
418
+ #
419
+ # catch context must be executable lexical environment
420
+ #
421
+ catch_env = context.var_env.new_declarative_env()
408
422
  catch_context.lex_env = catch_env
409
423
  catch_context.var_env = context.var_env
410
424
 
@@ -416,11 +430,11 @@ module Minjs
416
430
  break nil unless c
417
431
 
418
432
  f = try_finally(lex, context)
419
- ECMA262::StTry.new(context, catch_context, t, c, f)
433
+ ECMA262::StTry.new(context, t, c, f)
420
434
  } || lex.eval_lit{
421
435
  f = try_finally(lex, context)
422
436
  break nil unless f
423
- ECMA262::StTry.new(context, catch_context, t, nil, f)
437
+ ECMA262::StTry.new(context, t, nil, f)
424
438
  }
425
439
  }
426
440
  end
@@ -429,7 +443,11 @@ module Minjs
429
443
 
430
444
  if lex.match_lit(ECMA262::PUNC_LPARENTHESIS) and i=identifier(lex, catch_context) and lex.match_lit(ECMA262::PUNC_RPARENTHESIS) and b=block(lex, catch_context)
431
445
  catch_context.lex_env.record.create_mutable_binding(i, nil)
432
- catch_context.lex_env.record.set_mutable_binding(i, :undefined, nil)
446
+ catch_context.lex_env.record.set_mutable_binding(i, :undefined, nil, {:_parameter_list => true})
447
+ catch_context.var_env.record.create_mutable_binding(i, nil)
448
+ catch_context.var_env.record.set_mutable_binding(i, :undefined, nil, {:_parameter_list => true})
449
+ catch_context.var_env.record.binding.each do|k, v|
450
+ end
433
451
  [i, b]
434
452
  else
435
453
  nil
data/lib/minjs/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Minjs
2
- VERSION = "0.1.10"
2
+ VERSION = "0.2.0"
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.1.10
4
+ version: 0.2.0
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-21 00:00:00.000000000 Z
11
+ date: 2015-05-25 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler