minjs 0.1.5 → 0.1.7

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: 82f88a2a64ab93ccafd2abd3e699e8d5fa7682d0
4
- data.tar.gz: 3e9aec62b059e22695c0111169b75c5bd3fc1141
3
+ metadata.gz: 6a8187931f76664dfc06d3ff52d9c41f984d0faa
4
+ data.tar.gz: 6f03506bef8148d713bff2ef74c377d6305876fd
5
5
  SHA512:
6
- metadata.gz: b58b34b47810cec665a86a8d831f7a222a558eb0ed21996de5332caddd13a3e15000544bc9a7867ed0a3341535eb55bebe8af4092e73dc9d0b8f34e143cf2b88
7
- data.tar.gz: 93c25a509a9bf2c6864433f4ef955b64887bb35471be4d4fe1b68fdcaf736341e9c04634150adf8136097a2ada5d2f6815298ac1257b62a8192512d716f0754b
6
+ metadata.gz: 33a3e964e04dca6ade14ee7ec3b10cc07c3b0fb73c0a99176dd240914987a3f2d786a93e69ef42a0843ac2b4a4f7edf89d796ad5c1f46dd3ac6ecefef3038119
7
+ data.tar.gz: 17cd44a4d705ac698f535b2ec2cf909f77da132ce33ac995933a7956af264b5dc9eb5d2434c2363d0043e301c681bc4d0670bad871059b24a445ae4dd4a86005
@@ -61,6 +61,9 @@ module Minjs
61
61
  @logger.info '* block_to_statement'
62
62
  block_to_statement
63
63
 
64
+ @logger.info '* reduce_if'
65
+ reduce_if
66
+
64
67
  @logger.info '* if_to_cond'
65
68
  if_to_cond
66
69
 
@@ -196,7 +199,7 @@ module Minjs
196
199
  ]
197
200
  }
198
201
  st.traverse(parent) {|st2, parent2|
199
- if st2.kind_of? ECMA262::StVar and st2.context == @context
202
+ if st2.kind_of? ECMA262::StVar and st2.context.var_env == @context.var_env
200
203
  st2.instance_eval{
201
204
  blk = []
202
205
  @vars.each do |vl|
@@ -207,9 +210,9 @@ module Minjs
207
210
  end
208
211
  parent2.replace(st2, ECMA262::StBlock.new(ECMA262::StatementList.new(blk)))
209
212
  }
210
- elsif st2.kind_of? ECMA262::StForVar and st2.context == @context
213
+ elsif st2.kind_of? ECMA262::StForVar and st2.context.var_env == @context.var_env
211
214
  parent2.replace(st2, st2.to_st_for)
212
- elsif st2.kind_of? ECMA262::StForInVar and st2.context == @context
215
+ elsif st2.kind_of? ECMA262::StForInVar and st2.context.var_env == @context.var_env
213
216
  parent2.replace(st2, st2.to_st_for_in)
214
217
  end
215
218
  }
@@ -220,12 +223,14 @@ module Minjs
220
223
  end
221
224
  }
222
225
  remove_block_in_block
226
+ self
223
227
  end
224
228
 
225
229
  def remove_paren(node = @prog)
226
230
  node.traverse(nil) {|st, parent|
227
231
  if st.respond_to? :remove_paren
228
232
  st.remove_paren
233
+ st.add_paren
229
234
  end
230
235
  }
231
236
  self
@@ -246,19 +251,68 @@ module Minjs
246
251
  }
247
252
  break if !_retry
248
253
  end
254
+ self
249
255
  end
250
256
 
251
257
  def block_to_statement(node = @prog)
252
258
  node.traverse(nil) {|st, parent|
253
- if st.kind_of? ECMA262::StBlock and !parent.kind_of?(ECMA262::StTry)
254
- if st.to_statement?
255
- parent.replace(st, st.to_statement)
259
+ if st.kind_of? ECMA262::StIf
260
+ #
261
+ # To determine removing "if block" is available or not is difficult.
262
+ # For example, next codes block must not be removed, because
263
+ # "else" cluase combined to second "if" statement.
264
+ #
265
+ #
266
+ # if(a){ //<= this block must not be removed
267
+ # while(true)
268
+ # if(b){
269
+ # ;
270
+ # }
271
+ # }
272
+ # else{
273
+ # ;
274
+ # }
275
+
276
+ # The "else" cluase's block can be removed without condition.
277
+ if st.else_st and st.else_st.kind_of? ECMA262::StBlock and st.else_st.to_statement?
278
+ st.replace(st.else_st, st.else_st.to_statement)
279
+ end
280
+ #
281
+ # if "if" statement has no "else" clause, its block can be removed.
282
+ #
283
+ if st.else_st.nil? and st.then_st.kind_of? ECMA262::StBlock and st.then_st.to_statement?
284
+ st.replace(st.then_st, st.then_st.to_statement)
285
+ #
286
+ # if "if" statement has "else" clause, check "then" branch.
287
+ # If branch has no "if" statement or
288
+ # has "if-else" statement, its block can be removed.
289
+ #
290
+ elsif st.else_st and st.then_st.kind_of? ECMA262::StBlock and st.then_st.to_statement?
291
+ deblock = true
292
+ last_st = st.then_st.last_statement.map{|x|
293
+ if x.kind_of? ECMA262::StIf and x.else_st.nil?
294
+ deblock = false
295
+ end
296
+ }
297
+ if deblock
298
+ st.replace(st.then_st, st.then_st.to_statement)
299
+ end
256
300
  end
257
301
  end
258
302
  }
303
+ node.traverse(nil) {|st, parent|
304
+ if st.kind_of? ECMA262::StBlock and !parent.kind_of?(ECMA262::StTry) and !parent.kind_of?(ECMA262::StIf)
305
+ if st.to_statement?
306
+ parent.replace(st, st.to_statement)
307
+ end
308
+ end
309
+ }
259
310
  self
260
311
  end
261
312
 
313
+ def if_block_to_statemet(node = @prog)
314
+ end
315
+
262
316
  def if_to_cond(node = nil)
263
317
  node = @prog if node.nil?
264
318
  node.traverse(nil) {|st, parent|
@@ -304,6 +358,7 @@ module Minjs
304
358
  end
305
359
  }
306
360
  remove_paren
361
+ self
307
362
  end
308
363
 
309
364
  def compress_var(node = @prog)
@@ -311,13 +366,29 @@ module Minjs
311
366
  #traverse all statemtns and expression
312
367
  #
313
368
  node.traverse(nil) {|st, parent|
314
- if st.kind_of? ECMA262::StFunc and st.context.var_env.outer
315
- var_sym = :a
369
+ var_sym = :a
370
+ if st.kind_of? ECMA262::StTry and st.catch
371
+ _context = st.catch_context
372
+ _parent = st
373
+ _st = st.catch[1]
374
+ elsif st.kind_of? ECMA262::StFunc #and st.context.var_env.outer
375
+ _context = st.context
376
+ _parent = parent
377
+ _st = st
378
+ else
379
+ _parent = nil
380
+ _context = nil
381
+ _st = nil
382
+ end
383
+ if _parent and _context and _st
316
384
  #
317
- # collect all variables under this function
385
+ # collect all variables under this function/catch
318
386
  #
319
387
  vars = {}
320
- st.traverse(parent) {|st2|
388
+ if st.kind_of? ECMA262::StTry
389
+ vars[st.catch[0].val.to_sym] = 1
390
+ end
391
+ _st.traverse(_parent) {|st2|
321
392
  if st2.kind_of? ECMA262::IdentifierName
322
393
  vars[st2.val.to_sym] ||= 0
323
394
  vars[st2.val.to_sym] += 1
@@ -327,22 +398,35 @@ module Minjs
327
398
  # collect all var variables under this function
328
399
  #
329
400
  var_vars = {}
330
- st.context.var_env.record.binding.each do|k, v|
331
- var_vars[k] = vars[k]
332
- end
333
- st.traverse(parent) {|st2|
334
- if st2.kind_of? ECMA262::StFunc
335
- st2.context.var_env.record.binding.each do|k, v|
336
- var_vars[k] = vars[k]
401
+ if st.kind_of? ECMA262::StFunc
402
+ _context.var_env.record.binding.each do|k, v|
403
+ var_vars[k] = (vars[k] || 1)
404
+ end
405
+ _st.traverse(parent) {|st2|
406
+ if st2.kind_of? ECMA262::StFunc
407
+ st2.context.var_env.record.binding.each do|k, v|
408
+ var_vars[k] = (vars[k] || 1)
409
+ end
337
410
  end
411
+ }
412
+ end
413
+ #
414
+ # collect all lexical variables under this catch clause
415
+ #
416
+ # currently, only catch's args is lex_var
417
+ #
418
+ lex_vars = {}
419
+ if st.kind_of? ECMA262::StTry
420
+ _context.lex_env.record.binding.each do|k, v|
421
+ lex_vars[k] = (vars[k] || 1)
338
422
  end
339
- }
423
+ end
340
424
  #
341
- # check `eval' function is exist under this function
425
+ # check `eval' function is exist under this function/catch
342
426
  #
343
427
  unless var_vars[:eval]
344
428
  eval_flag = false
345
- st.traverse(parent) {|st2|
429
+ _st.traverse(_parent) {|st2|
346
430
  if st2.kind_of? ECMA262::ExpCall and st2.name.to_js({}) == "eval"
347
431
  eval_flag = true
348
432
  break
@@ -370,8 +454,10 @@ module Minjs
370
454
  #
371
455
  # rename `name' to `var_sym'
372
456
  #
373
- st.traverse(parent){|st2|
374
- if st2.kind_of? ECMA262::IdentifierName and st2.context and st2.context.var_env == st.context.var_env.outer
457
+ _st.traverse(_parent){|st2|
458
+ if st2.kind_of? ECMA262::IdentifierName and st2.context.nil?
459
+ ;# TODO, currently special identifier such as 'this' has no context
460
+ elsif st2.kind_of? ECMA262::IdentifierName and st2.context.var_env.outer == nil # global scope
375
461
  ;
376
462
  elsif st2.kind_of? ECMA262::IdentifierName and st2.val == name
377
463
  st2.instance_eval{
@@ -385,6 +471,38 @@ module Minjs
385
471
  end
386
472
  var_sym = next_sym(var_sym)
387
473
  }
474
+ lex_vars.each {|name, count|
475
+ if name.nil?
476
+ next
477
+ end
478
+ while(vars[var_sym])
479
+ var_sym = next_sym(var_sym)
480
+ end
481
+ if name.to_s.bytesize > var_sym.to_s.bytesize
482
+ #
483
+ # rename `name' to `var_sym'
484
+ #
485
+ _st.traverse(_parent){|st2|
486
+ if st2.kind_of? ECMA262::IdentifierName and st2.context.nil?
487
+ ;# TODO, currently special identifier such as 'this' has no context
488
+ elsif st2.kind_of? ECMA262::IdentifierName and st2.context.lex_env.outer == nil # global scope
489
+ ;
490
+ elsif st2.kind_of? ECMA262::IdentifierName and st2.val == name
491
+ st2.instance_eval{
492
+ @val = var_sym
493
+ }
494
+ end
495
+ }
496
+ if st.kind_of? ECMA262::StTry
497
+ if st.catch[0].kind_of? ECMA262::IdentifierName
498
+ st.catch[0].instance_eval{
499
+ @val = var_sym
500
+ }
501
+ end
502
+ end
503
+ end
504
+ var_sym = next_sym(var_sym)
505
+ }
388
506
  end
389
507
  }
390
508
  self
@@ -396,22 +514,27 @@ module Minjs
396
514
  st.reduce(parent)
397
515
  end
398
516
  }
517
+ self
399
518
  end
400
519
 
401
520
  def simple_replacement(node = @prog)
402
521
  node.traverse(nil) {|st, parent|
522
+ #
403
523
  #true => !0
404
524
  #false => !1
525
+ #
405
526
  if st.kind_of? ECMA262::Boolean
406
527
  if st.true?
407
528
  parent.replace(st, ECMA262::ExpParen.new(ECMA262::ExpLogicalNot.new(ECMA262::ECMA262Numeric.new(0))))
408
529
  else
409
530
  parent.replace(st, ECMA262::ExpParen.new(ECMA262::ExpLogicalNot.new(ECMA262::ECMA262Numeric.new(1))))
410
531
  end
532
+ #
411
533
  #if(true){<then>}else{<else>} => then
534
+ #
412
535
  elsif st.kind_of? ECMA262::StIf
413
- if st.cond.kind_of? ECMA262::Boolean
414
- if st.cond.true?
536
+ if st.cond.respond_to? :to_ecma262_boolean
537
+ if st.cond.to_ecma262_boolean
415
538
  parent.replace(st, st.then_st)
416
539
  elsif st.else_st
417
540
  parent.replace(st, st.else_st)
@@ -419,8 +542,19 @@ module Minjs
419
542
  parent.replace(st, ECMA262::StEmpty.new())
420
543
  end
421
544
  end
545
+ #
546
+ # while(true) => for(;;)
547
+ # while(false) => remove
548
+ #
549
+ elsif st.kind_of? ECMA262::StWhile and st.exp.respond_to? :to_ecma262_boolean
550
+ if st.exp.to_ecma262_boolean
551
+ parent.replace(st, ECMA262::StFor.new(nil,nil,nil, st.statement))
552
+ else
553
+ parent.replace(st, ECMA262::StEmpty.new)
554
+ end
422
555
  end
423
556
  }
557
+ self
424
558
  end
425
559
 
426
560
  def return_to_exp(node = @prog)
@@ -446,7 +580,7 @@ module Minjs
446
580
  # var a; a=1
447
581
  # => var a=1
448
582
  #
449
- def assignment_after_var(node = @prog)
583
+ def assignment_after_var_old(node = @prog)
450
584
  node.traverse(nil) {|st, parent|
451
585
  if st.kind_of? ECMA262::StExp and parent.kind_of? ECMA262::SourceElements
452
586
  if st.exp.kind_of? ECMA262::ExpAssign
@@ -476,6 +610,102 @@ module Minjs
476
610
  end
477
611
  end
478
612
  }
613
+ self
614
+ end
615
+ #
616
+ # reduce_if
617
+ #
618
+ # 1) rewrite nested "if" statemet such as:
619
+ # if(a)
620
+ # if(b) ...;
621
+ #
622
+ # to:
623
+ #
624
+ # if(a && b) ...;
625
+ #
626
+ # NOTE:
627
+ # both if must not have "else" clause
628
+ #
629
+ def reduce_if(node = @prog)
630
+ node.traverse(nil) {|st, parent|
631
+ if st.kind_of? ECMA262::StIf
632
+ if st.else_st.nil? and
633
+ st.then_st.kind_of? ECMA262::StIf and st.then_st.else_st.nil?
634
+ st.replace(st.cond, ECMA262::ExpLogicalAnd.new(st.cond, st.then_st.cond))
635
+ st.replace(st.then_st, st.then_st.then_st)
636
+ end
637
+ end
638
+ }
639
+ self
640
+ end
641
+
642
+ def assignment_after_var(node = @prog)
643
+ def rewrite_var(var_st, name, initializer)
644
+ var_st.normalization
645
+ i = 0
646
+ var_st.vars.each do |_name, _initializer|
647
+ if _name == name and _initializer.nil?
648
+ var_st.vars[i] = [name, initializer]
649
+ var_st.normalization
650
+ return true
651
+ end
652
+ i += 1
653
+ end
654
+ false
655
+ end
656
+ node.traverse(nil) {|st, parent|
657
+ if st.kind_of? ECMA262::StVar and parent.kind_of? ECMA262::SourceElements
658
+ #
659
+ # index of 'var statement' is 0, after calling reorder_var
660
+ #
661
+ catch(:break){
662
+ idx = 1
663
+ while true
664
+ st2 = parent[idx]
665
+ if st2.kind_of? ECMA262::StEmpty
666
+ idx +=1
667
+ next
668
+ elsif st2.kind_of? ECMA262::StExp and st2.exp.kind_of? ECMA262::ExpAssign
669
+ if rewrite_var(st, st2.exp.val, st2.exp.val2)
670
+ parent.replace(st2, ECMA262::StEmpty.new())
671
+ else
672
+ throw :break
673
+ end
674
+ idx += 1
675
+ next
676
+ elsif st2.kind_of? ECMA262::StFor and st2.exp1.kind_of? ECMA262::ExpAssign
677
+ if rewrite_var(st, st2.exp1.val, st2.exp1.val2)
678
+ st2.replace(st2.exp1, nil)
679
+ else
680
+ throw :break
681
+ end
682
+ throw :break
683
+ elsif st2.kind_of? ECMA262::StExp and st2.exp.kind_of? ECMA262::ExpComma
684
+ exp_parent = st2
685
+ exp = st2.exp
686
+
687
+ while exp.val.kind_of? ECMA262::ExpComma
688
+ exp_parent = exp
689
+ exp = exp.val
690
+ end
691
+
692
+ if exp.val.kind_of? ECMA262::ExpAssign
693
+ if rewrite_var(st, exp.val.val, exp.val.val2)
694
+ exp_parent.replace(exp, exp.val2)
695
+ else
696
+ throw :break
697
+ end
698
+ else
699
+ throw :break
700
+ end
701
+ else
702
+ throw :break
703
+ end
704
+ end
705
+ }
706
+ end
707
+ }
708
+ self
479
709
  end
480
710
  end
481
711
  end
@@ -203,73 +203,6 @@ module Minjs
203
203
  def to_js(options = {})
204
204
  concat options, @source_elements
205
205
  end
206
- =begin
207
- def grouping
208
- remove_empty_statement
209
- nsl = []
210
- sl = []
211
- g = []
212
- @source_elements.each do |st|
213
- if st.to_exp?
214
- g.push(st)
215
- else
216
- if g.length > 0
217
- sl.push(g)
218
- end
219
- sl.push([st])
220
- g = []
221
- end
222
- end
223
- if g.length > 0
224
- sl.push(g)
225
- end
226
-
227
- sl.each do |g|
228
- if g.length == 1
229
- nsl.push(g[0])
230
- else
231
- i = 1
232
- t = g[0].to_exp
233
- while i < g.length
234
- t = ExpComma.new(t, g[i].to_exp)
235
- i += 1
236
- end
237
- nsl.push(StExp.new(t))
238
- end
239
- end
240
-
241
- @source_elements = nsl
242
- end
243
-
244
- def replace(from, to)
245
- idx = @source_elements.index(from)
246
- if idx
247
- @source_elements[idx] = to
248
- end
249
- end
250
-
251
- def remove(st)
252
- @source_elements.delete(st)
253
- end
254
-
255
- def remove_empty_statement
256
- @source_elements.reject!{|x|
257
- x.class == StEmpty
258
- }
259
- end
260
-
261
- def each(&block)
262
- @source_elements.each(&block)
263
- end
264
-
265
- def [](i)
266
- @source_elements[i]
267
- end
268
-
269
- def index(st)
270
- @source_elements.index(st)
271
- end
272
- =end
273
206
  end
274
207
  end
275
208
  end
@@ -8,12 +8,14 @@ module Minjs
8
8
  @binding = {}
9
9
  @options = {}
10
10
  end
11
+
11
12
  def create_mutable_binding(n, d, options = {})
12
13
  if n.kind_of? IdentifierName
13
14
  n = n.val
14
15
  end
15
16
  @binding[n] = {:value => nil}
16
17
  end
18
+
17
19
  def set_mutable_binding(n, v, s, options = {})
18
20
  if n.kind_of? IdentifierName
19
21
  n = n.val
@@ -54,7 +56,8 @@ module Minjs
54
56
  attr_accessor :this_binding
55
57
 
56
58
  def initialize(options = {})
57
- @var_env = @lex_env = LexEnv.new(options)
59
+ @var_env = LexEnv.new(options)
60
+ @lex_env = LexEnv.new(options)
58
61
  @this_binding = ExObject.new(
59
62
  {
60
63
  attr: {