minjs 0.2.0 → 0.2.1

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.
@@ -68,7 +68,7 @@ module Minjs
68
68
  end
69
69
 
70
70
  def debug
71
- STDERR.puts @record.binding
71
+ STDERR.puts @record.binding.keys.join(", ")
72
72
  end
73
73
  end
74
74
 
@@ -232,6 +232,12 @@ module Minjs
232
232
  self
233
233
  end
234
234
 
235
+ def to_ecma262_boolean
236
+ return nil unless @val.respond_to? :to_ecma262_boolean
237
+ return nil if @val.to_ecma262_boolean.nil?
238
+ @val.to_ecma262_boolean
239
+ end
240
+
235
241
  def ecma262_typeof
236
242
  if @val.respond_to? :ecma262_typeof
237
243
  @val.ecma262_typeof
@@ -676,7 +682,6 @@ module Minjs
676
682
  PRIORITY_UNARY
677
683
  end
678
684
 
679
- #feature
680
685
  def reduce(parent)
681
686
  if @val.kind_of? ECMA262Numeric and (@val.to_js == "0" || @val.to_js == "1")
682
687
  return
@@ -695,6 +700,20 @@ module Minjs
695
700
  end
696
701
  end
697
702
 
703
+ def to_ecma262_boolean
704
+ return nil unless @val.respond_to? :to_ecma262_boolean
705
+ return nil if @val.to_ecma262_boolean.nil?
706
+ !@val.to_ecma262_boolean
707
+ end
708
+
709
+ def to_ecma262_number
710
+ if @val.respond_to? :to_ecma262_number
711
+ v = @val.to_ecma262_number
712
+ return nil if v.nil?
713
+ v == 0 ? 1 : 0
714
+ end
715
+ end
716
+
698
717
  def ecma262_eval(type)
699
718
  if @val.respond_to? :ecma262_eval
700
719
  e = @val.ecma262_eval(type)
@@ -733,30 +752,14 @@ module Minjs
733
752
  end
734
753
 
735
754
  def reduce(parent)
736
- # a * 1 => a
737
- if @val.kind_of? ECMA262Numeric and @val2.kind_of? ECMA262Numeric and @val.to_num == 1
738
- parent.replace(self, @val2)
739
- end
740
- # 1 * b => b
741
- if @val.kind_of? ECMA262Numeric and @val2.kind_of? ECMA262Numeric and @val2.to_num == 1
742
- parent.replace(self, @val)
743
- end
744
- # N * M => (N * M)
745
- if @val.kind_of? ECMA262Numeric and @val2.kind_of? ECMA262Numeric and @val.integer? and @val2.integer?
746
- parent.replace(self, ECMA262Numeric.new(@val.to_num * @val2.to_num))
747
- end
748
- =begin
749
- # ((a * N) * M) or ((N * a) * M)
750
- if @val2.kind_of? ECMA262Numeric and @val2.integer? and @val.kind_of? ExpMul
751
- if @val.val2.kind_of? ECMA262Numeric and @val.val2.integer?
752
- @val2 = ECMA262Numeric.new(@val.val2.to_num * @val2.to_num)
753
- @val = @val.val
754
- elsif @val.val.kind_of? ECMA262Numeric and @val.val.integer?
755
- @val2 = ECMA262Numeric.new(@val.val.to_num * @val2.to_num)
756
- @val = @val.val2
755
+ # A * B
756
+ if @val.respond_to? :to_ecma262_number and @val2.respond_to? :to_ecma262_number
757
+ v = @val.to_ecma262_number
758
+ v2 = @val2.to_ecma262_number
759
+ if !v.nil? and !v2.nil?
760
+ parent.replace(self, ECMA262Numeric.new(v * v2))
757
761
  end
758
762
  end
759
- =end
760
763
  end
761
764
 
762
765
  def ecma262_typeof
@@ -815,17 +818,31 @@ module Minjs
815
818
  end
816
819
 
817
820
  def reduce(parent)
818
- # a + 0 => a
819
- if @val.kind_of? ECMA262Numeric and @val2.kind_of? ECMA262Numeric and @val.to_num == 0
820
- parent.replace(self, @val2)
821
- end
822
- # 0 + b => b
823
- if @val.kind_of? ECMA262Numeric and @val2.kind_of? ECMA262Numeric and @val2.to_num == 0
824
- parent.replace(self, @val)
825
- end
826
- # N + M => (N + M)
827
- if @val.kind_of? ECMA262Numeric and @val2.kind_of? ECMA262Numeric and @val.integer? and @val2.integer?
828
- parent.replace(self, ECMA262Numeric.new(@val.to_num + @val2.to_num))
821
+ #
822
+ # String + String/
823
+ # a + b = a.concat(b)
824
+ if @val.kind_of? ECMA262String or @val2.kind_of? ECMA262String
825
+ if @val.respond_to? :to_ecma262_string and @val2.respond_to? :to_ecma262_string
826
+ v = @val.to_ecma262_string
827
+ v2 = @val2.to_ecma262_string
828
+ if !v.nil? and !v2.nil?
829
+ new_str = ECMA262String.new(v + v2)
830
+ parent.replace(self, new_str)
831
+ end
832
+ end
833
+ #
834
+ # Numeric + Numeric
835
+ #
836
+ elsif @val.respond_to? :to_ecma262_number and @val2.respond_to? :to_ecma262_number
837
+ #
838
+ #11.6.3 Applying the Additive Operators to Numbers(TODO)
839
+ #
840
+ # N + M => (N + M)
841
+ v = @val.to_ecma262_number
842
+ v2 = @val2.to_ecma262_number
843
+ if !v.nil? and !v2.nil?
844
+ parent.replace(self, ECMA262Numeric.new(v + v2))
845
+ end
829
846
  end
830
847
  end
831
848
  end
@@ -844,17 +861,13 @@ module Minjs
844
861
  end
845
862
 
846
863
  def reduce(parent)
847
- # a - 0 => a
848
- if @val.kind_of? ECMA262Numeric and @val2.kind_of? ECMA262Numeric and @val.to_num == 0
849
- parent.replace(self, @val2)
850
- end
851
- # 0 - b => b
852
- if @val2.kind_of? ECMA262Numeric and @val.kind_of? ECMA262Numeric and @val2.to_num == 0
853
- parent.replace(self, @val)
854
- end
855
- # N - M => (N - M)
856
- if @val.kind_of? ECMA262Numeric and @val2.kind_of? ECMA262Numeric and @val.integer? and @val2.integer?
857
- parent.replace(self, ECMA262Numeric.new(@val.to_num - @val2.to_num))
864
+ # A - B
865
+ if @val.respond_to? :to_ecma262_number and @val2.respond_to? :to_ecma262_number
866
+ v = @val.to_ecma262_number
867
+ v2 = @val2.to_ecma262_number
868
+ if !v.nil? and !v2.nil?
869
+ parent.replace(self, ECMA262Numeric.new(v - v2))
870
+ end
858
871
  end
859
872
  end
860
873
 
@@ -1180,6 +1193,19 @@ module Minjs
1180
1193
  PRIORITY_LOGICAL_AND
1181
1194
  end
1182
1195
 
1196
+ 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
1207
+ end
1208
+
1183
1209
  def ecma262_typeof
1184
1210
  if @val.respond_to? :ecma262_typeof and @val2.respond_to? :ecma262_typeof
1185
1211
  if @val.ecma262_typeof == @val2.ecma262_typeof
@@ -1200,6 +1226,19 @@ module Minjs
1200
1226
  PRIORITY_LOGICAL_OR
1201
1227
  end
1202
1228
 
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
1240
+ end
1241
+
1203
1242
  def ecma262_typeof
1204
1243
  if @val.respond_to? :ecma262_typeof and @val2.respond_to? :ecma262_typeof
1205
1244
  if @val.ecma262_typeof == @val2.ecma262_typeof
@@ -1,4 +1,5 @@
1
1
  # coding: utf-8
2
+ require 'set'
2
3
  module Minjs
3
4
  module ECMA262
4
5
  class Literal < Base
@@ -119,6 +120,14 @@ module Minjs
119
120
  false
120
121
  end
121
122
 
123
+ def to_ecma262_string
124
+ "null"
125
+ end
126
+
127
+ def to_ecma262_number
128
+ 0
129
+ end
130
+
122
131
  def ecma262_typeof
123
132
  :boolean
124
133
  end
@@ -156,6 +165,14 @@ module Minjs
156
165
  @val == :true
157
166
  end
158
167
 
168
+ def to_ecma262_string
169
+ if @val == :false
170
+ "false"
171
+ else
172
+ "true"
173
+ end
174
+ end
175
+
159
176
  def to_ecma262_boolean
160
177
  if @val == :false
161
178
  false
@@ -164,6 +181,14 @@ module Minjs
164
181
  end
165
182
  end
166
183
 
184
+ def to_ecma262_number
185
+ if @val == :false
186
+ 0
187
+ else
188
+ 1
189
+ end
190
+ end
191
+
167
192
  def ecma262_typeof
168
193
  :boolean
169
194
  end
@@ -180,6 +205,7 @@ module Minjs
180
205
  end
181
206
 
182
207
  class ECMA262String < Literal
208
+ include Ctype
183
209
  attr_reader :val
184
210
 
185
211
  def initialize(val)
@@ -251,38 +277,209 @@ module Minjs
251
277
  end
252
278
  end
253
279
 
280
+ def to_ecma262_string
281
+ @val.dup
282
+ end
283
+ # 9.3.1 ToNumber Applied to the String Type
284
+ def to_ecma262_number
285
+ begin
286
+ pos1 = pos0 = pos = 0
287
+ v = @val.codepoints
288
+ while true
289
+ return 0 if v[pos].nil? # ToInteger(empty string) => 0
290
+ if white_space?(v[pos]) or line_terminator?(v[pos])
291
+ pos += 1
292
+ else
293
+ break
294
+ end
295
+ end
296
+ #hex
297
+ if v[pos] == 0x30 and (v[pos+1] == 0x78 || v[pos+1] == 0x58) and hex_number?(v[pos+2])
298
+ base = 16
299
+ pos += 2
300
+ pos0 = pos
301
+ while true
302
+ break if v[pos].nil?
303
+ if hex_number?(v[pos])
304
+ pos += 1
305
+ else
306
+ break
307
+ end
308
+ end
309
+ #decimal
310
+ else
311
+ base = 10
312
+ sign = 1
313
+ pos0 = pos
314
+ if v[pos].nil?
315
+ raise :error
316
+ elsif v[pos] == 0x2b #+
317
+ pos += 1
318
+ elsif v[pos] == 0x2d #-
319
+ sign = -1
320
+ pos += 1
321
+ end
322
+ has_decimal = false
323
+ has_exp = false
324
+
325
+ while true
326
+ break if v[pos].nil?
327
+ if v[pos] >= 0x30 and v[pos] <= 0x39
328
+ pos += 1
329
+ elsif v[pos] == 0x2e #.
330
+ pos += 1
331
+ has_decimal = true
332
+ break;
333
+ else
334
+ break
335
+ end
336
+ end
337
+ if has_decimal
338
+ while true
339
+ break if v[pos].nil?
340
+ if v[pos] >= 0x30 and v[pos] <= 0x39
341
+ pos += 1
342
+ elsif v[pos] == 0x45 or v[pos] == 0x65 #E/e
343
+ pos += 1
344
+ has_exp = true
345
+ break;
346
+ else
347
+ break
348
+ end
349
+ end
350
+ end
351
+ if has_exp
352
+ if v[pos] == 0x2b #+
353
+ pos += 1
354
+ else v[pos] == 0x2d #-
355
+ pos += 1
356
+ end
357
+ while true
358
+ break if v[pos].nil?
359
+ if v[pos] >= 0x30 and v[pos] <= 0x39
360
+ pos += 1
361
+ else
362
+ break
363
+ end
364
+ end
365
+ end
366
+ end
367
+ pos1 = pos
368
+ while white_space?(v[pos]) or line_terminator?(v[pos])
369
+ raise :error if v[pos].nil?
370
+ pos += 1
371
+ end
372
+ raise :error unless v[pos].nil?
373
+ if base == 16
374
+ ret = v[pos0...pos1].pack("U*").to_i(base)
375
+ else
376
+ ret = v[pos0...pos1].pack("U*").to_f
377
+ end
378
+ rescue => e
379
+ ret = nil #Float::NAN
380
+ end
381
+ ret
382
+ end
383
+
254
384
  def ecma262_typeof
255
385
  :string
256
386
  end
257
387
  end
258
388
 
389
+ #
390
+ # 8.5 The Number Type
391
+ #
392
+ # ECMA262 say:
393
+ #
394
+ # The Number type has exactly 18437736874454810627
395
+ # (that is, 264−253+3) values, representing the
396
+ # double-precision 64-bit format IEEE 754 values
397
+ # as specified in the IEEE Standard for Binary
398
+ # Floating-Point Arithmetic
399
+ #
400
+ # To simplify the implementation,
401
+ # Minjs assumes that ruby has IEEE754 dobule precision.
402
+ #
259
403
  class ECMA262Numeric < Literal
260
- attr_reader :integer, :decimal, :exp
404
+ attr_reader :integer, :decimal, :exp, :number
405
+
406
+ if Float::DIG != 15
407
+ if defined?(@logger)
408
+ @logger.warn{
409
+ "minjs assumes that ruby has IEEE754 dobule precision."
410
+ }
411
+ end
412
+ end
261
413
 
262
414
  def initialize(integer, decimal = nil, exp = nil)
263
- if integer == :nan
264
- integer = nil
265
- @nan = true
266
- elsif integer == :infinity
267
- integer = nil
268
- @infinity = true
269
- elsif integer.kind_of? Float
270
- @integer, @decimal = integer.to_i.to_s
271
- @decimal = (integer - @integer).to_s.sub(/^.*0\./, '')
272
- else
273
- @integer = integer.to_s
274
- if decimal
275
- @decimal = decimal.to_s
415
+ if integer == :nan or integer == "NaN"
416
+ @number = Float::NAN
417
+ @integer = "NaN"
418
+ @decimal = nil
419
+ @exp = nil
420
+ elsif integer == :infinity or integer == Float::INFINITY or integer == "Infinity"
421
+ @number = Float::INFINITY
422
+ @integer = "Infinity"
423
+ @decimal = nil
424
+ @exp = nil
425
+ elsif integer == -Float::INFINITY or integer == "-Infinity"
426
+ @number = -Float::INFINITY
427
+ @integer = "-Infinity"
428
+ @decimal = nil
429
+ @exp = nil
430
+ elsif integer.kind_of? String
431
+ @integer = integer.to_s #String
432
+ @decimal = decimal.to_s #String
433
+ @exp = exp ? exp.to_i : nil
434
+ if @decimal == ""
435
+ d = ""
436
+ else
437
+ d = ".#{@decimal}"
438
+ end
439
+ if @exp
440
+ @number = "#{integer}#{d}e#{exp}".to_f
441
+ else
442
+ @number = "#{integer}#{d}".to_f
276
443
  end
277
- if exp
278
- @exp = exp.to_i
444
+ if @number.kind_of? Float and @number.nan?
445
+ @integer = "NaN"
446
+ @decimal = nil
447
+ @exp = nil
448
+ elsif @number == Float::INFINITY
449
+ @integer = "Infinity"
450
+ @decimal = nil
451
+ @exp = nil
452
+ elsif @number == -Float::INFINITY
453
+ @integer = "-Infinity"
454
+ @decimal = nil
455
+ @exp = nil
456
+ end
457
+ elsif integer.kind_of? Numeric
458
+ if integer.kind_of? Float and integer.nan?
459
+ @number = Float::NAN
460
+ @decimal = nil
461
+ @exp = nil
462
+ elsif integer == Float::INFINITY
463
+ @number = Float::INFINITY
464
+ @decimal = nil
465
+ @exp = nil
466
+ elsif integer == -Float::INFINITY
467
+ @number = -Float::INFINITY
468
+ @decimal = nil
469
+ @exp = nil
470
+ else
471
+ @number = integer
472
+ @integer = @number.to_i.to_s
473
+ @decimal = (@number - @integer.to_i).to_s.sub(/0\.?/, '')
474
+ @exp = nil
279
475
  end
476
+ else
477
+ raise 'internal error'
280
478
  end
281
- @decimal = nil if @decimal == 0
282
479
  end
283
480
 
284
481
  def deep_dup
285
- self.class.new(@integer, @decimal, @exp)
482
+ self.class.new(@number)
286
483
  end
287
484
 
288
485
  def traverse(parent, &block)
@@ -294,69 +491,75 @@ module Minjs
294
491
  end
295
492
 
296
493
  def to_js(options = {})
297
- if @nan
494
+ if nan?
298
495
  return "NaN"
496
+ elsif @number == Float::INFINITY
497
+ return "Infinity"
498
+ elsif @number == -Float::INFINITY
499
+ return "-Infinity"
299
500
  end
300
- t = @integer.dup.to_s
501
+ t0 = to_ecma262_string
502
+ t = @integer.nil? ? "" : @integer.dup.to_s
301
503
 
302
- if @decimal
504
+ d = @decimal.to_s
505
+ if d == '0'
506
+ d = ''
507
+ end
508
+ if d.length > 0
303
509
  if @integer == '0'
304
- t = ".#{@decimal}"
510
+ t = ".#{d}"
305
511
  else
306
- t << ".#{@decimal}"
512
+ t << ".#{d}"
307
513
  end
308
514
  end
309
515
  if @exp
310
516
  t << "e#{@exp}"
311
517
  end
312
518
 
313
- if @decimal.nil? and @exp.nil? and t.match(/0{3,}$/)
519
+ if !t.match(/e/) and !t.match(/\./) and t.match(/0{3,}$/)
314
520
  len = $&.length
315
521
  t.sub!(/0+$/, "e#{len}")
316
522
  end
317
- t
523
+ t.sub!(/e\+/, 'e')
524
+ t0.sub!(/e\+/, 'e')
525
+
526
+ t.length <= t0.length ? t : t0
318
527
  end
319
528
 
320
- def integer?
321
- @decimal.nil?
529
+ def to_i
530
+ to_ecma262_string.to_i
322
531
  end
323
532
 
324
- def to_num
325
- if @decimal
326
- to_f
327
- else
328
- to_i
329
- end
533
+ def to_f
534
+ to_ecma262_string.to_f
330
535
  end
331
536
 
332
- def to_i
333
- if @exp
334
- @integer.to_i * (10 ** @exp.to_i)
335
- else
336
- @integer.to_i
337
- end
537
+ def nan?
538
+ @number.kind_of? Float and @number.nan?
338
539
  end
339
540
 
340
- def to_f
341
- d = @decimal
342
- if d.to_s == ''
343
- d = '0'
344
- end
345
- "#{@integer}.#{d}e#{@exp}".to_f
541
+ def infinity?
542
+ @number == Float::INFINITY || @number == -Float::INFINITY
543
+ end
544
+
545
+ def number?
546
+ !nan? and !infinity?
346
547
  end
347
548
 
348
549
  #
349
550
  # 9.8.1
350
551
  #
351
552
  def to_ecma262_string
352
- if @nan
553
+ if nan?
353
554
  "NaN"
555
+ elsif @number == Float::INFINITY
556
+ "Infinity"
557
+ elsif @number == -Float::INFINITY
558
+ "-Infinity"
354
559
  elsif @integer == '0' and @decimal.nil? and @exp.nil?
355
560
  "0"
356
- elsif @intinify
357
- "Infinity"
358
561
  else
359
- f = to_f.to_s
562
+ f = @number.to_f.to_s
360
563
  _n, _e = f.split('e')
361
564
  _i, _d = _n.split('.')
362
565
 
@@ -392,6 +595,18 @@ module Minjs
392
595
  end
393
596
  end
394
597
 
598
+ def to_ecma262_number
599
+ if nan?
600
+ nil
601
+ elsif @number == Float::INFINITY
602
+ nil
603
+ elsif @number == -Float::INFINITY
604
+ nil
605
+ else
606
+ @number
607
+ end
608
+ end
609
+
395
610
  def ecma262_typeof
396
611
  :number
397
612
  end
@@ -423,6 +638,10 @@ module Minjs
423
638
  yield self, parent
424
639
  end
425
640
 
641
+ def to_ecma262_boolean
642
+ true
643
+ end
644
+
426
645
  def ==(obj)
427
646
  self.class == obj.class and @body == obj.body and @flags == obj.flags
428
647
  end
@@ -512,12 +731,7 @@ module Minjs
512
731
  else
513
732
  if x.kind_of? ECMA262Numeric
514
733
  a = "#{x.to_ecma262_string}"
515
- b = "#{x.to_js}"
516
- if a.length <= b.length || a == "Infinity"
517
- t = a
518
- else
519
- t = b
520
- end
734
+ t = a
521
735
  elsif idname?(x.val.to_s)
522
736
  t = "#{x.val.to_s}"
523
737
  else
@@ -612,7 +826,7 @@ module Minjs
612
826
  @@sym[val] ||= self.new(context, val)
613
827
  end
614
828
 
615
- RESERVED_WORD = [
829
+ RESERVED_WORD = Set.new [
616
830
  :break, :do, :instanceof, :typeof, :case, :else,
617
831
  :new, :var, :catch, :finally, :return, :void, :continue,
618
832
  :for, :switch, :while,:debugger, :function, :this, :with,
@@ -623,11 +837,11 @@ module Minjs
623
837
  :null, :false, :true
624
838
  ]
625
839
  def reserved?
626
- RESERVED_WORD.index(val)
840
+ RESERVED_WORD.include?(val)
627
841
  end
628
842
 
629
843
  def self.reserved?(val)
630
- RESERVED_WORD.index(val)
844
+ RESERVED_WORD.include?(val)
631
845
  end
632
846
 
633
847
  def traverse(parent)
@@ -279,10 +279,6 @@ module Minjs
279
279
  @else_st = else_st
280
280
  end
281
281
 
282
- def deep_dup
283
- self.class.new(@cond.deep_dup, @then_st.deep_dup, @else_st.deep_dup)
284
- end
285
-
286
282
  def replace(from, to)
287
283
  if from .eql? @cond
288
284
  @cond = to
data/lib/minjs/lex.rb CHANGED
@@ -59,14 +59,6 @@ module Minjs
59
59
  @error_pos = @pos
60
60
  return ret
61
61
  else
62
- # p pos0
63
- # p @pos
64
- #@error_pos = @pos
65
- #debug_lit
66
- #raise 'no hint'
67
- #regexp_literal
68
- #div_punctuator
69
- #nil #unknown
70
62
  ECMA262::LIT_DIV_OR_REGEXP_LITERAL
71
63
  end
72
64
  end
@@ -194,7 +186,8 @@ module Minjs
194
186
  chars.push(@codes[@pos])
195
187
  @pos += 1
196
188
  else
197
- return ECMA262::IdentifierName.new(nil, chars.pack("U*").to_sym)
189
+ name = chars.pack("U*").to_sym
190
+ return ECMA262::IdentifierName.new(nil, name)
198
191
  end
199
192
  end
200
193
  end
@@ -488,7 +481,7 @@ module Minjs
488
481
  raise ParseError.new("The source character immediately following a NumericLiteral must not be an IdentifierStart or DecimalDigit", self)
489
482
  end
490
483
 
491
- return ECMA262::ECMA262Numeric.new(0, f, e)
484
+ return ECMA262::ECMA262Numeric.new('0', f, e)
492
485
  end
493
486
 
494
487
  if code >= 0x30 and code <= 0x39