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 +4 -4
- data/lib/minjs/compressor.rb +237 -247
- data/lib/minjs/ecma262/base.rb +4 -1
- data/lib/minjs/ecma262/env.rb +25 -5
- data/lib/minjs/ecma262/exp.rb +5 -2
- data/lib/minjs/ecma262/lit.rb +41 -11
- data/lib/minjs/ecma262/st.rb +2 -4
- data/lib/minjs/expression.rb +12 -4
- data/lib/minjs/func.rb +6 -8
- data/lib/minjs/lex.rb +12 -9
- data/lib/minjs/minjs_compressor.rb +1 -1
- data/lib/minjs/statement.rb +28 -10
- data/lib/minjs/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c3d1d9049c22ff483762abe2eb89d9cbcfdde1bd
|
4
|
+
data.tar.gz: 9780d815f256edea332b814d84c7c299c870d8d2
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: dae0218ef56cdef8ca1fd8a602cedd6f36b23a328f1da3d9e17e19eab851b22bebe7b857ec72c223e04729a891eb2bb2b6ca4f1a24b099ccf5dd7bb166616594
|
7
|
+
data.tar.gz: 164cbde79345dcf7175af658571af6b5cef96b08ef4bc89d9600f21b6f91b310d369a53e0924355f0a16d94461899113a27b45f349a22bbbe721c011067bdab9
|
data/lib/minjs/compressor.rb
CHANGED
@@ -53,60 +53,44 @@ module Minjs
|
|
53
53
|
@logger.info '* parse'
|
54
54
|
parse(data)
|
55
55
|
|
56
|
-
|
57
|
-
|
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
|
-
|
98
|
-
|
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
|
-
|
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
|
-
|
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.
|
259
|
-
|
260
|
-
|
261
|
-
|
262
|
-
|
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
|
513
|
-
|
514
|
-
|
515
|
-
|
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::
|
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
|
-
|
540
|
-
scopes.
|
541
|
-
|
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
|
-
|
550
|
-
|
551
|
-
|
552
|
-
|
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
|
-
|
556
|
-
|
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
|
-
|
598
|
-
#p var_vars
|
574
|
+
var_vars_array = var_vars.sort {|(k1,v1), (k2,v2)| v2 <=> v1}
|
599
575
|
#
|
600
|
-
#
|
576
|
+
# create renaming table
|
601
577
|
#
|
602
|
-
|
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
|
583
|
+
while outer_vars[var_sym] or var_vars[var_sym]
|
607
584
|
var_sym = next_sym(var_sym)
|
608
585
|
end
|
609
|
-
|
610
|
-
|
611
|
-
|
612
|
-
|
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
|
-
|
619
|
-
|
620
|
-
|
621
|
-
|
622
|
-
|
623
|
-
|
624
|
-
|
625
|
-
|
626
|
-
|
627
|
-
|
628
|
-
|
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
|
-
|
644
|
-
|
645
|
-
|
646
|
-
|
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
|
-
|
669
|
-
|
670
|
-
|
671
|
-
|
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
|
-
|
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
|
-
|
771
|
-
|
772
|
-
|
773
|
-
|
774
|
-
|
775
|
-
|
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
|
-
|
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
|
-
|
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
|
data/lib/minjs/ecma262/base.rb
CHANGED
@@ -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}";
|
data/lib/minjs/ecma262/env.rb
CHANGED
@@ -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
|
-
|
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
|
data/lib/minjs/ecma262/exp.rb
CHANGED
@@ -427,7 +427,7 @@ module Minjs
|
|
427
427
|
end
|
428
428
|
|
429
429
|
def priority
|
430
|
-
PRIORITY_LEFT_HAND_SIDE + ((args
|
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
|
-
|
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
|
data/lib/minjs/ecma262/lit.rb
CHANGED
@@ -199,12 +199,21 @@ module Minjs
|
|
199
199
|
end
|
200
200
|
|
201
201
|
def to_js(options = {})
|
202
|
-
|
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
|
-
|
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
|
-
|
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)
|
data/lib/minjs/ecma262/st.rb
CHANGED
@@ -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,
|
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, @
|
1159
|
+
self.class.new(@context, @try, @catch, @finally)
|
1162
1160
|
end
|
1163
1161
|
|
1164
1162
|
def replace(from, to)
|
data/lib/minjs/expression.rb
CHANGED
@@ -31,7 +31,9 @@ module Minjs
|
|
31
31
|
} || lex.eval_lit {
|
32
32
|
object_literal(lex, context, options)
|
33
33
|
}
|
34
|
-
@logger.debug
|
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
|
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
|
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
|
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 =
|
12
|
-
new_context.var_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
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
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
|
-
|
625
|
-
oct =
|
626
|
-
|
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
|
732
|
-
pos0 = col -
|
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
|
-
|
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
|
data/lib/minjs/statement.rb
CHANGED
@@ -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
|
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
|
-
|
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,
|
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,
|
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
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.
|
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-
|
11
|
+
date: 2015-05-25 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|