ruby2js 1.0.0 → 1.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +8 -8
- data/lib/ruby2js.rb +2 -2
- data/lib/ruby2js/converter.rb +68 -474
- data/lib/ruby2js/converter/andasgn.rb +12 -0
- data/lib/ruby2js/converter/arg.rb +14 -0
- data/lib/ruby2js/converter/args.rb +13 -0
- data/lib/ruby2js/converter/array.rb +33 -0
- data/lib/ruby2js/converter/begin.rb +13 -0
- data/lib/ruby2js/converter/block.rb +16 -0
- data/lib/ruby2js/converter/blockpass.rb +11 -0
- data/lib/ruby2js/converter/boolean.rb +11 -0
- data/lib/ruby2js/converter/break.rb +12 -0
- data/lib/ruby2js/converter/case.rb +23 -0
- data/lib/ruby2js/converter/casgn.rb +16 -0
- data/lib/ruby2js/converter/class.rb +75 -0
- data/lib/ruby2js/converter/const.rb +10 -0
- data/lib/ruby2js/converter/def.rb +91 -0
- data/lib/ruby2js/converter/defined.rb +15 -0
- data/lib/ruby2js/converter/dstr.rb +16 -0
- data/lib/ruby2js/converter/for.rb +19 -0
- data/lib/ruby2js/converter/hash.rb +24 -0
- data/lib/ruby2js/converter/if.rb +34 -0
- data/lib/ruby2js/converter/ivar.rb +10 -0
- data/lib/ruby2js/converter/ivasgn.rb +11 -0
- data/lib/ruby2js/converter/kwbegin.rb +44 -0
- data/lib/ruby2js/converter/literal.rb +12 -0
- data/lib/ruby2js/converter/logical.rb +43 -0
- data/lib/ruby2js/converter/masgn.rb +20 -0
- data/lib/ruby2js/converter/next.rb +12 -0
- data/lib/ruby2js/converter/nil.rb +10 -0
- data/lib/ruby2js/converter/opasgn.rb +20 -0
- data/lib/ruby2js/converter/orasgn.rb +12 -0
- data/lib/ruby2js/converter/regexp.rb +21 -0
- data/lib/ruby2js/converter/return.rb +15 -0
- data/lib/ruby2js/converter/self.rb +10 -0
- data/lib/ruby2js/converter/send.rb +98 -0
- data/lib/ruby2js/converter/sym.rb +10 -0
- data/lib/ruby2js/converter/undef.rb +12 -0
- data/lib/ruby2js/converter/until.rb +12 -0
- data/lib/ruby2js/converter/untilpost.rb +13 -0
- data/lib/ruby2js/converter/var.rb +11 -0
- data/lib/ruby2js/converter/vasgn.rb +41 -0
- data/lib/ruby2js/converter/while.rb +12 -0
- data/lib/ruby2js/converter/whilepost.rb +14 -0
- data/lib/ruby2js/converter/xstr.rb +16 -0
- data/lib/ruby2js/filter/angularrb.rb +1 -1
- data/lib/ruby2js/filter/jquery.rb +95 -1
- data/lib/ruby2js/version.rb +1 -1
- data/ruby2js.gemspec +3 -3
- metadata +44 -2
@@ -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,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,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,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,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,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
|