ruby2js 1.0.0 → 1.1.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.
Files changed (50) hide show
  1. checksums.yaml +8 -8
  2. data/lib/ruby2js.rb +2 -2
  3. data/lib/ruby2js/converter.rb +68 -474
  4. data/lib/ruby2js/converter/andasgn.rb +12 -0
  5. data/lib/ruby2js/converter/arg.rb +14 -0
  6. data/lib/ruby2js/converter/args.rb +13 -0
  7. data/lib/ruby2js/converter/array.rb +33 -0
  8. data/lib/ruby2js/converter/begin.rb +13 -0
  9. data/lib/ruby2js/converter/block.rb +16 -0
  10. data/lib/ruby2js/converter/blockpass.rb +11 -0
  11. data/lib/ruby2js/converter/boolean.rb +11 -0
  12. data/lib/ruby2js/converter/break.rb +12 -0
  13. data/lib/ruby2js/converter/case.rb +23 -0
  14. data/lib/ruby2js/converter/casgn.rb +16 -0
  15. data/lib/ruby2js/converter/class.rb +75 -0
  16. data/lib/ruby2js/converter/const.rb +10 -0
  17. data/lib/ruby2js/converter/def.rb +91 -0
  18. data/lib/ruby2js/converter/defined.rb +15 -0
  19. data/lib/ruby2js/converter/dstr.rb +16 -0
  20. data/lib/ruby2js/converter/for.rb +19 -0
  21. data/lib/ruby2js/converter/hash.rb +24 -0
  22. data/lib/ruby2js/converter/if.rb +34 -0
  23. data/lib/ruby2js/converter/ivar.rb +10 -0
  24. data/lib/ruby2js/converter/ivasgn.rb +11 -0
  25. data/lib/ruby2js/converter/kwbegin.rb +44 -0
  26. data/lib/ruby2js/converter/literal.rb +12 -0
  27. data/lib/ruby2js/converter/logical.rb +43 -0
  28. data/lib/ruby2js/converter/masgn.rb +20 -0
  29. data/lib/ruby2js/converter/next.rb +12 -0
  30. data/lib/ruby2js/converter/nil.rb +10 -0
  31. data/lib/ruby2js/converter/opasgn.rb +20 -0
  32. data/lib/ruby2js/converter/orasgn.rb +12 -0
  33. data/lib/ruby2js/converter/regexp.rb +21 -0
  34. data/lib/ruby2js/converter/return.rb +15 -0
  35. data/lib/ruby2js/converter/self.rb +10 -0
  36. data/lib/ruby2js/converter/send.rb +98 -0
  37. data/lib/ruby2js/converter/sym.rb +10 -0
  38. data/lib/ruby2js/converter/undef.rb +12 -0
  39. data/lib/ruby2js/converter/until.rb +12 -0
  40. data/lib/ruby2js/converter/untilpost.rb +13 -0
  41. data/lib/ruby2js/converter/var.rb +11 -0
  42. data/lib/ruby2js/converter/vasgn.rb +41 -0
  43. data/lib/ruby2js/converter/while.rb +12 -0
  44. data/lib/ruby2js/converter/whilepost.rb +14 -0
  45. data/lib/ruby2js/converter/xstr.rb +16 -0
  46. data/lib/ruby2js/filter/angularrb.rb +1 -1
  47. data/lib/ruby2js/filter/jquery.rb +95 -1
  48. data/lib/ruby2js/version.rb +1 -1
  49. data/ruby2js.gemspec +3 -3
  50. metadata +44 -2
@@ -0,0 +1,12 @@
1
+ module Ruby2JS
2
+ class Converter
3
+
4
+ # (and-asgn
5
+ # (lvasgn :a
6
+ # (int 1))
7
+
8
+ handle :and_asgn do |var, value|
9
+ "#{ parse var } = #{parse var} && #{ parse value }"
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,14 @@
1
+ module Ruby2JS
2
+ class Converter
3
+
4
+ # (arg :a)
5
+ # (blockarg :b)
6
+
7
+ # NOTE: process_all appends a nil child for unknown reasons
8
+
9
+ handle :arg, :blockarg do |arg, unknown=nil|
10
+ raise NotImplementedError, "argument #{ unknown.inspect }" if unknown
11
+ arg
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,13 @@
1
+ module Ruby2JS
2
+ class Converter
3
+
4
+ # (args
5
+ # (arg :a)
6
+ # (restarg :b)
7
+ # (blockarg :c))
8
+
9
+ handle :args do |*args|
10
+ args.map { |arg| parse arg }.join(', ')
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,33 @@
1
+ module Ruby2JS
2
+ class Converter
3
+
4
+ # (array
5
+ # (int 1)
6
+ # (int 2))
7
+
8
+ handle :array do |*items|
9
+ splat = items.rindex { |a| a.type == :splat }
10
+ if splat
11
+ item = items[splat].children.first
12
+ if items.length == 1
13
+ parse item
14
+ elsif splat == items.length - 1
15
+ parse s(:send, s(:array, *items[0..-2]), :concat, item)
16
+ elsif splat == 0
17
+ parse s(:send, item, :concat, s(:array, *items[1..-1]))
18
+ else
19
+ parse s(:send,
20
+ s(:send, s(:array, *items[0..splat-1]), :concat, item),
21
+ :concat, s(:array, *items[splat+1..-1]))
22
+ end
23
+ else
24
+ items.map! { |item| parse item }
25
+ if items.map {|item| item.length+2}.reduce(&:+).to_i < 72
26
+ "[#{ items.join(', ') }]"
27
+ else
28
+ "[#@nl#{ items.join(",#@ws") }#@nl]"
29
+ end
30
+ end
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,13 @@
1
+ module Ruby2JS
2
+ class Converter
3
+
4
+ # (begin
5
+ # (...)
6
+ # (...))
7
+
8
+ handle :begin do |*statements|
9
+ state = @state
10
+ statements.map{ |statement| parse statement, state }.join(@sep)
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,16 @@
1
+ module Ruby2JS
2
+ class Converter
3
+
4
+ # (block
5
+ # (send nil :x)
6
+ # (args
7
+ # (arg :a))
8
+ # (lvar :a))
9
+
10
+ handle :block do |call, args, block|
11
+ block ||= s(:begin)
12
+ function = s(:def, nil, args, block)
13
+ parse s(:send, *call.children, function)
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,11 @@
1
+ module Ruby2JS
2
+ class Converter
3
+
4
+ # (block-pass
5
+ # (lvar :a))
6
+
7
+ handle :block_pass do |arg|
8
+ parse arg
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,11 @@
1
+ module Ruby2JS
2
+ class Converter
3
+
4
+ # (true)
5
+ # (false)
6
+
7
+ handle :true, :false do
8
+ @ast.type.to_s
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,12 @@
1
+ module Ruby2JS
2
+ class Converter
3
+
4
+ # (break
5
+ # (int 1))
6
+
7
+ handle :break do |n=nil|
8
+ raise NotImplementedError, "break argument #{ n.inspect }" if n
9
+ 'break'
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,23 @@
1
+ module Ruby2JS
2
+ class Converter
3
+
4
+ # (case
5
+ # (send nil :a)
6
+ # (when
7
+ # (int 1)
8
+ # (...))
9
+ # (...))
10
+
11
+ handle :case do |expr, *whens, other|
12
+ whens.map! do |node|
13
+ *values, code = node.children
14
+ cases = values.map {|value| "case #{ parse value }:#@ws"}.join
15
+ "#{ cases }#{ parse code }#{@sep}break#@sep"
16
+ end
17
+
18
+ other = "#{@nl}default:#@ws#{ parse other }#@nl" if other
19
+
20
+ "switch (#{ parse expr }) {#@nl#{whens.join(@nl)}#{other}}"
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,16 @@
1
+ module Ruby2JS
2
+ class Converter
3
+
4
+ # (casgn nil :a
5
+ # (int 1))
6
+
7
+ handle :casgn do |cbase, var, value|
8
+ begin
9
+ var = "#{ parse cbase }.var" if cbase
10
+ "const #{ var } = #{ parse value }"
11
+ ensure
12
+ @vars[var] = true
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,75 @@
1
+ module Ruby2JS
2
+ class Converter
3
+
4
+ # (class
5
+ # (const nil :A)
6
+ # (const nil :B)
7
+ # (...)
8
+
9
+ handle :class do |name, inheritance, *body|
10
+ init = s(:def, :initialize, s(:args))
11
+ body.compact!
12
+
13
+ if body.length == 1 and body.first.type == :begin
14
+ body = body.first.children.dup
15
+ end
16
+
17
+ body.map! do |m|
18
+ if m.type == :def
19
+ if m.children.first == :initialize
20
+ # constructor: remove from body and overwrite init function
21
+ init = m
22
+ nil
23
+ else
24
+ # method: add to prototype
25
+ s(:send, s(:attr, name, :prototype), "#{m.children[0]}=",
26
+ s(:block, s(:send, nil, :proc), *m.children[1..-1]))
27
+ end
28
+ elsif m.type == :defs and m.children.first == s(:self)
29
+ # class method definition: add to prototype
30
+ s(:send, name, "#{m.children[1]}=",
31
+ s(:block, s(:send, nil, :proc), *m.children[2..-1]))
32
+ elsif m.type == :send and m.children.first == nil
33
+ # class method call
34
+ s(:send, name, *m.children[1..-1])
35
+ elsif m.type == :lvasgn
36
+ # class variable
37
+ s(:send, name, "#{m.children[0]}=", *m.children[1..-1])
38
+ elsif m.type == :casgn and m.children[0] == nil
39
+ # class constant
40
+ s(:send, name, "#{m.children[1]}=", *m.children[2..-1])
41
+ else
42
+ raise NotImplementedError, "class #{ m.type }"
43
+ end
44
+ end
45
+
46
+ if inheritance
47
+ body.unshift s(:send, name, :prototype=, s(:send, inheritance, :new))
48
+ else
49
+ # look for a sequence of methods
50
+ methods = 0
51
+ body.compact.each do |node|
52
+ break unless node and node.type == :send and node.children[0]
53
+ break unless node.children[0].type == :attr
54
+ break unless node.children[0].children[0..1] == [name, :prototype]
55
+ break unless node.children[1] =~ /=$/
56
+ methods += 1
57
+ end
58
+
59
+ # collapse sequence of methods to a single assignment
60
+ if methods > 1
61
+ pairs = body[0...methods].map do |node|
62
+ s(:pair, s(:str, node.children[1].chomp('=')), node.children[2])
63
+ end
64
+ body.shift(methods)
65
+ body.unshift s(:send, name, :prototype=, s(:hash, *pairs))
66
+ end
67
+ end
68
+
69
+ # prepend constructor
70
+ body.unshift s(:def, parse(name), *init.children[1..-1])
71
+
72
+ parse s(:begin, *body.compact)
73
+ end
74
+ end
75
+ end
@@ -0,0 +1,10 @@
1
+ module Ruby2JS
2
+ class Converter
3
+
4
+ # (const nil :C)
5
+
6
+ handle :const do |receiver, name|
7
+ "#{ parse receiver }#{ '.' if receiver }#{ name }"
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,91 @@
1
+ module Ruby2JS
2
+ class Converter
3
+
4
+ # (def :f
5
+ # (args
6
+ # (arg :x)
7
+ # (...)
8
+
9
+ handle :def do |name, args, body=nil|
10
+ body ||= s(:begin)
11
+ if name =~ /[!?]$/
12
+ raise NotImplementedError, "invalid method name #{ name }"
13
+ end
14
+
15
+ vars = {}
16
+ vars.merge! @vars unless name
17
+ if args and !args.children.empty?
18
+ # splats
19
+ if args.children.last.type == :restarg
20
+ if args.children[-1].children.first
21
+ body = s(:begin, body) unless body.type == :begin
22
+ assign = s(:lvasgn, args.children[-1].children.first,
23
+ s(:send, s(:attr,
24
+ s(:attr, s(:const, nil, :Array), :prototype), :slice),
25
+ :call, s(:lvar, :arguments),
26
+ s(:int, args.children.length-1)))
27
+ body = s(:begin, assign, *body.children)
28
+ end
29
+
30
+ args = s(:args, *args.children[0..-2])
31
+
32
+ elsif args.children.last.type == :blockarg and
33
+ args.children.length > 1 and args.children[-2].type == :restarg
34
+ body = s(:begin, body) unless body.type == :begin
35
+ blk = args.children[-1].children.first
36
+ vararg = args.children[-2].children.first
37
+ last = s(:send, s(:attr, s(:lvar, :arguments), :length), :-,
38
+ s(:int, 1))
39
+
40
+ # set block argument to the last argument passed
41
+ assign2 = s(:lvasgn, blk, s(:send, s(:lvar, :arguments), :[], last))
42
+
43
+ if vararg
44
+ # extract arguments between those defined and the last
45
+ assign1 = s(:lvasgn, vararg, s(:send, s(:attr, s(:attr, s(:const,
46
+ nil, :Array), :prototype), :slice), :call, s(:lvar, :arguments),
47
+ s(:int, args.children.length-1), last))
48
+ # push block argument back onto args if not a function
49
+ pushback = s(:if, s(:send, s(:send, nil, :typeof, s(:lvar, blk)),
50
+ :"!==", s(:str, "function")), s(:begin, s(:send, s(:lvar,
51
+ vararg), :push, s(:lvar, blk)), s(:lvasgn, blk, s(:nil))), nil)
52
+ # set block argument to null if all arguments were defined
53
+ pushback = s(:if, s(:send, s(:attr, s(:lvar, :arguments),
54
+ :length), :<=, s(:int, args.children.length-2)), s(:lvasgn,
55
+ blk, s(:nil)), pushback)
56
+ # combine statements
57
+ body = s(:begin, assign1, assign2, pushback, *body.children)
58
+ else
59
+ # set block argument to null if all arguments were defined
60
+ ignore = s(:if, s(:send, s(:attr, s(:lvar, :arguments),
61
+ :length), :<=, s(:int, args.children.length-2)), s(:lvasgn,
62
+ blk, s(:nil)), nil)
63
+ body = s(:begin, assign2, ignore, *body.children)
64
+ end
65
+
66
+ args = s(:args, *args.children[0..-3])
67
+ end
68
+
69
+ # optional arguments
70
+ args.children.each_with_index do |arg, i|
71
+ if arg.type == :optarg
72
+ body = s(:begin, body) unless body.type == :begin
73
+ argname, value = arg.children
74
+ children = args.children.dup
75
+ children[i] = s(:arg, argname)
76
+ args = s(:args, *children)
77
+ body = s(:begin, body) unless body.type == :begin
78
+ default = s(:if, s(:send, s(:defined?, s(:lvar, argname)), :!),
79
+ s(:lvasgn, argname, value), nil)
80
+ body = s(:begin, default, *body.children)
81
+ end
82
+ vars[arg.children.first] = true
83
+ end
84
+ end
85
+
86
+ nl = @nl unless body == s(:begin)
87
+ "function#{ " #{name}" if name }(#{ parse args }) " +
88
+ "{#{nl}#{ scope body, vars}#{nl}}"
89
+ end
90
+ end
91
+ end
@@ -0,0 +1,15 @@
1
+ module Ruby2JS
2
+ class Converter
3
+
4
+ # (defined? :@a)
5
+
6
+ # (undefined? :@a)
7
+
8
+ # NOTE: undefined is not produced directly by Parser
9
+
10
+ handle :defined?, :undefined? do |var|
11
+ op = (@ast.type == :defined? ? "!==" : "===")
12
+ "typeof #{ parse var } #{ op } 'undefined'"
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,16 @@
1
+ module Ruby2JS
2
+ class Converter
3
+
4
+ # (dstr
5
+ # (str 'a')
6
+ # (...))
7
+
8
+ # (dsym
9
+ # (str 'a')
10
+ # (...))
11
+
12
+ handle :dstr, :dsym do |*children|
13
+ children.map{ |child| parse child }.join(' + ')
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,19 @@
1
+ module Ruby2JS
2
+ class Converter
3
+
4
+ # (xstr
5
+ # (str 'a'))
6
+ # (for
7
+ # (lvasgn :i)
8
+ # (array
9
+ # (int 1))
10
+ # (...)
11
+
12
+ handle :for do |var, expression, block|
13
+ parse s(:block,
14
+ s(:send, expression, :forEach),
15
+ s(:args, s(:arg, var.children.last)),
16
+ block);
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,24 @@
1
+ module Ruby2JS
2
+ class Converter
3
+
4
+ # (hash
5
+ # (pair
6
+ # (sym :name)
7
+ # (str "value")))
8
+
9
+ handle :hash do |*pairs|
10
+ pairs.map! do |node|
11
+ left, right = node.children
12
+ key = parse left
13
+ key = $1 if key =~ /\A"([a-zA-Z_$][a-zA-Z_$0-9]*)"\Z/
14
+ "#{key}: #{parse right}"
15
+ end
16
+
17
+ if pairs.map {|item| item.length+2}.reduce(&:+).to_i < 72
18
+ "{#{ pairs.join(', ') }}"
19
+ else
20
+ "{#@nl#{ pairs.join(",#@ws") }#@nl}"
21
+ end
22
+ end
23
+ end
24
+ end