sexp2ruby 0.0.1 → 0.0.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.rspec +3 -0
- data/.travis.yml +1 -2
- data/README.md +9 -0
- data/lib/{sexp2ruby/core_extensions → core_extensions}/regexp.rb +0 -0
- data/lib/sexp2ruby/node/alias.rb +9 -0
- data/lib/sexp2ruby/node/and.rb +9 -0
- data/lib/sexp2ruby/node/arglist.rb +16 -0
- data/lib/sexp2ruby/node/args.rb +33 -0
- data/lib/sexp2ruby/node/array.rb +9 -0
- data/lib/sexp2ruby/node/attrasgn.rb +27 -0
- data/lib/sexp2ruby/node/back_ref.rb +9 -0
- data/lib/sexp2ruby/node/base.rb +36 -0
- data/lib/sexp2ruby/node/begin.rb +19 -0
- data/lib/sexp2ruby/node/block.rb +24 -0
- data/lib/sexp2ruby/node/block_pass.rb +10 -0
- data/lib/sexp2ruby/node/break.rb +14 -0
- data/lib/sexp2ruby/node/call.rb +70 -0
- data/lib/sexp2ruby/node/case.rb +27 -0
- data/lib/sexp2ruby/node/cdecl.rb +17 -0
- data/lib/sexp2ruby/node/class.rb +9 -0
- data/lib/sexp2ruby/node/colon2.rb +9 -0
- data/lib/sexp2ruby/node/colon3.rb +9 -0
- data/lib/sexp2ruby/node/const.rb +9 -0
- data/lib/sexp2ruby/node/cvar.rb +9 -0
- data/lib/sexp2ruby/node/cvasgn.rb +9 -0
- data/lib/sexp2ruby/node/cvdecl.rb +9 -0
- data/lib/sexp2ruby/node/defined.rb +9 -0
- data/lib/sexp2ruby/node/defn.rb +66 -0
- data/lib/sexp2ruby/node/defs.rb +17 -0
- data/lib/sexp2ruby/node/dot2.rb +9 -0
- data/lib/sexp2ruby/node/dot3.rb +9 -0
- data/lib/sexp2ruby/node/dregx.rb +19 -0
- data/lib/sexp2ruby/node/dregx_once.rb +9 -0
- data/lib/sexp2ruby/node/dstr.rb +9 -0
- data/lib/sexp2ruby/node/dsym.rb +9 -0
- data/lib/sexp2ruby/node/dxstr.rb +9 -0
- data/lib/sexp2ruby/node/ensure.rb +18 -0
- data/lib/sexp2ruby/node/evstr.rb +9 -0
- data/lib/sexp2ruby/node/false.rb +9 -0
- data/lib/sexp2ruby/node/flip2.rb +9 -0
- data/lib/sexp2ruby/node/flip3.rb +9 -0
- data/lib/sexp2ruby/node/for.rb +17 -0
- data/lib/sexp2ruby/node/gasgn.rb +9 -0
- data/lib/sexp2ruby/node/gvar.rb +9 -0
- data/lib/sexp2ruby/node/hash.rb +53 -0
- data/lib/sexp2ruby/node/iasgn.rb +14 -0
- data/lib/sexp2ruby/node/if.rb +41 -0
- data/lib/sexp2ruby/node/iter.rb +50 -0
- data/lib/sexp2ruby/node/ivar.rb +9 -0
- data/lib/sexp2ruby/node/kwsplat.rb +9 -0
- data/lib/sexp2ruby/node/lasgn.rb +11 -0
- data/lib/sexp2ruby/node/lit.rb +15 -0
- data/lib/sexp2ruby/node/lvar.rb +9 -0
- data/lib/sexp2ruby/node/masgn.rb +46 -0
- data/lib/sexp2ruby/node/match.rb +9 -0
- data/lib/sexp2ruby/node/match2.rb +11 -0
- data/lib/sexp2ruby/node/match3.rb +17 -0
- data/lib/sexp2ruby/node/module.rb +9 -0
- data/lib/sexp2ruby/node/next.rb +14 -0
- data/lib/sexp2ruby/node/nil.rb +9 -0
- data/lib/sexp2ruby/node/not.rb +9 -0
- data/lib/sexp2ruby/node/nth_ref.rb +9 -0
- data/lib/sexp2ruby/node/op_asgn1.rb +16 -0
- data/lib/sexp2ruby/node/op_asgn2.rb +17 -0
- data/lib/sexp2ruby/node/op_asgn_and.rb +13 -0
- data/lib/sexp2ruby/node/op_asgn_or.rb +13 -0
- data/lib/sexp2ruby/node/or.rb +9 -0
- data/lib/sexp2ruby/node/postexe.rb +9 -0
- data/lib/sexp2ruby/node/redo.rb +9 -0
- data/lib/sexp2ruby/node/resbody.rb +19 -0
- data/lib/sexp2ruby/node/rescue.rb +32 -0
- data/lib/sexp2ruby/node/retry.rb +9 -0
- data/lib/sexp2ruby/node/return.rb +13 -0
- data/lib/sexp2ruby/node/sclass.rb +9 -0
- data/lib/sexp2ruby/node/self.rb +9 -0
- data/lib/sexp2ruby/node/splat.rb +13 -0
- data/lib/sexp2ruby/node/str.rb +9 -0
- data/lib/sexp2ruby/node/super.rb +10 -0
- data/lib/sexp2ruby/node/svalue.rb +13 -0
- data/lib/sexp2ruby/node/to_ary.rb +9 -0
- data/lib/sexp2ruby/node/true.rb +9 -0
- data/lib/sexp2ruby/node/undef.rb +9 -0
- data/lib/sexp2ruby/node/until.rb +9 -0
- data/lib/sexp2ruby/node/valias.rb +9 -0
- data/lib/sexp2ruby/node/when.rb +24 -0
- data/lib/sexp2ruby/node/while.rb +9 -0
- data/lib/sexp2ruby/node/xstr.rb +9 -0
- data/lib/sexp2ruby/node/yield.rb +18 -0
- data/lib/sexp2ruby/node/zsuper.rb +9 -0
- data/lib/sexp2ruby/processor.rb +121 -912
- data/lib/sexp2ruby/version.rb +1 -1
- data/lib/sexp2ruby.rb +88 -1
- data/sexp2ruby.gemspec +1 -0
- data/spec/lib/processor_spec.rb +478 -1
- metadata +104 -8
- data/Rakefile +0 -92
- data/test/test_ruby2ruby.rb +0 -496
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e6521d5161ee2027c4a9fcfbfa58a6f8800a1032
|
4
|
+
data.tar.gz: dd984a8d70a35a285dae0b591e4cc523424c1417
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f87f34c8f9ca2006e15738e8329289ae087bc928b2d0c0eb06e9d813f20f7346796c0935347f0913841ff466cbe5b0f486856264944ee9e87dca4af76f2e77b2
|
7
|
+
data.tar.gz: 43e0e32832b2a01b3966770a812c917bc130f3489bb29d4900c5d554d110ee80badd8b50967a245c170aec0e15c510772277b00feb2dc12a2e6b7a6f3c9d2fd0
|
data/.rspec
ADDED
data/.travis.yml
CHANGED
data/README.md
CHANGED
@@ -1,11 +1,15 @@
|
|
1
1
|
sexp2ruby
|
2
2
|
=========
|
3
3
|
|
4
|
+
[![Build Status][5]][6] [![Code Climate][7]][8]
|
5
|
+
|
4
6
|
`sexp2ruby` generates ruby from RubyParser S-expressions.
|
5
7
|
It is a fork of [ruby2ruby][1] with slightly different goals.
|
6
8
|
|
7
9
|
- Generates ruby that follows [ruby-style-guide][3] where possible
|
8
10
|
- Prefers OO design over performance
|
11
|
+
- Drops support for ruby 1.8.7
|
12
|
+
- Depends on [activesupport][4]
|
9
13
|
- Uses bundler instead of hoe
|
10
14
|
- Uses rspec instead of minitest
|
11
15
|
|
@@ -30,3 +34,8 @@ so `deep_clone` if you need to preserve it.
|
|
30
34
|
[1]: https://github.com/seattlerb/ruby2ruby
|
31
35
|
[2]: http://docs.seattlerb.org/ruby2ruby
|
32
36
|
[3]: https://github.com/bbatsov/ruby-style-guide
|
37
|
+
[4]: https://rubygems.org/gems/activesupport
|
38
|
+
[5]: https://travis-ci.org/jaredbeck/sexp2ruby.svg
|
39
|
+
[6]: https://travis-ci.org/jaredbeck/sexp2ruby
|
40
|
+
[7]: https://codeclimate.com/github/jaredbeck/sexp2ruby/badges/gpa.svg
|
41
|
+
[8]: https://codeclimate.com/github/jaredbeck/sexp2ruby
|
File without changes
|
@@ -0,0 +1,16 @@
|
|
1
|
+
module Sexp2Ruby
|
2
|
+
module Node
|
3
|
+
class Arglist < Base
|
4
|
+
def to_s(exp)
|
5
|
+
code = []
|
6
|
+
until exp.empty? do
|
7
|
+
arg = exp.shift
|
8
|
+
to_wrap = arg.first == :rescue
|
9
|
+
arg_code = process arg
|
10
|
+
code << (to_wrap ? "(#{arg_code})" : arg_code)
|
11
|
+
end
|
12
|
+
code.join ', '
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
module Sexp2Ruby
|
2
|
+
module Node
|
3
|
+
class Args < Base
|
4
|
+
def to_s(exp)
|
5
|
+
args = []
|
6
|
+
|
7
|
+
until exp.empty? do
|
8
|
+
arg = exp.shift
|
9
|
+
case arg
|
10
|
+
when Symbol then
|
11
|
+
args << arg
|
12
|
+
when Sexp then
|
13
|
+
case arg.first
|
14
|
+
when :lasgn then
|
15
|
+
args << process(arg)
|
16
|
+
when :masgn then
|
17
|
+
args << process(arg)
|
18
|
+
when :kwarg then
|
19
|
+
_, k, v = arg
|
20
|
+
args << "#{k}: #{process v}"
|
21
|
+
else
|
22
|
+
raise "unknown arg type #{arg.first.inspect}"
|
23
|
+
end
|
24
|
+
else
|
25
|
+
raise "unknown arg type #{arg.inspect}"
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
"(#{args.join ', '})"
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
module Sexp2Ruby
|
2
|
+
module Node
|
3
|
+
class Attrasgn < Base
|
4
|
+
def to_s(exp)
|
5
|
+
receiver = process exp.shift
|
6
|
+
name = exp.shift
|
7
|
+
rhs = exp.pop
|
8
|
+
args = s(:array, *exp)
|
9
|
+
exp.clear
|
10
|
+
|
11
|
+
case name
|
12
|
+
when :[]= then
|
13
|
+
args = process args
|
14
|
+
"#{receiver}#{args} = #{process rhs}"
|
15
|
+
else
|
16
|
+
raise "dunno what to do: #{args.inspect}" unless args.size == 1 # s(:array)
|
17
|
+
name = name.to_s.sub(/=$/, '')
|
18
|
+
if rhs && rhs != s(:arglist)
|
19
|
+
"#{receiver}.#{name} = #{process(rhs)}"
|
20
|
+
else
|
21
|
+
raise "dunno what to do: #{rhs.inspect}"
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
module Sexp2Ruby
|
2
|
+
module Node
|
3
|
+
|
4
|
+
# A node in the AST.
|
5
|
+
class Base
|
6
|
+
ASSIGN_NODES = Processor::ASSIGN_NODES
|
7
|
+
LF = Processor::LF
|
8
|
+
LINE_LENGTH = 78 # cutoff for one-liners
|
9
|
+
|
10
|
+
attr_reader :processor
|
11
|
+
delegate(
|
12
|
+
:call_push,
|
13
|
+
:call_pop,
|
14
|
+
:cond_loop,
|
15
|
+
:hash_syntax,
|
16
|
+
:in_context,
|
17
|
+
:indent,
|
18
|
+
:indent_lvl,
|
19
|
+
:finish,
|
20
|
+
:parenthesize,
|
21
|
+
:process,
|
22
|
+
:process_arglist,
|
23
|
+
:process_dregx,
|
24
|
+
:process_iasgn,
|
25
|
+
:ruby19_hash_key?,
|
26
|
+
:util_dthing,
|
27
|
+
:util_module_or_class,
|
28
|
+
to: :processor
|
29
|
+
)
|
30
|
+
|
31
|
+
def initialize(processor)
|
32
|
+
@processor = processor
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module Sexp2Ruby
|
2
|
+
module Node
|
3
|
+
|
4
|
+
# TODO: figure out how to do rescue and ensure ENTIRELY w/o begin
|
5
|
+
class Begin < Base
|
6
|
+
def to_s(exp)
|
7
|
+
code = []
|
8
|
+
code << "begin"
|
9
|
+
until exp.empty?
|
10
|
+
src = process(exp.shift)
|
11
|
+
src = indent(src) unless src =~ /(^|\n)(rescue|ensure)/ # ensure no level 0 rescues
|
12
|
+
code << src
|
13
|
+
end
|
14
|
+
code << "end"
|
15
|
+
code.join(LF)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module Sexp2Ruby
|
2
|
+
module Node
|
3
|
+
class Block < Base
|
4
|
+
def to_s(exp)
|
5
|
+
result = []
|
6
|
+
|
7
|
+
exp << nil if exp.empty?
|
8
|
+
until exp.empty? do
|
9
|
+
code = exp.shift
|
10
|
+
if code.nil? or code.first == :nil
|
11
|
+
result << "# do nothing\n"
|
12
|
+
else
|
13
|
+
result << process(code)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
result = parenthesize result.join LF
|
18
|
+
result += LF unless result.start_with? "("
|
19
|
+
|
20
|
+
result
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,70 @@
|
|
1
|
+
module Sexp2Ruby
|
2
|
+
module Node
|
3
|
+
class Call < Base
|
4
|
+
|
5
|
+
# binary operation messages
|
6
|
+
BINARY = [:<=>, :==, :<, :>, :<=, :>=, :-, :+, :*, :/, :%, :<<, :>>, :**, :'!=']
|
7
|
+
|
8
|
+
def to_s(exp)
|
9
|
+
receiver_node_type = exp.first.nil? ? nil : exp.first.first
|
10
|
+
receiver = process exp.shift
|
11
|
+
receiver = "(#{receiver})" if ASSIGN_NODES.include? receiver_node_type
|
12
|
+
|
13
|
+
name = exp.shift
|
14
|
+
args = []
|
15
|
+
|
16
|
+
# this allows us to do both old and new sexp forms:
|
17
|
+
exp.push(*exp.pop[1..-1]) if exp.size == 1 && exp.first.first == :arglist
|
18
|
+
|
19
|
+
call_push(name)
|
20
|
+
|
21
|
+
in_context :arglist do
|
22
|
+
until exp.empty? do
|
23
|
+
arg_type = exp.first.sexp_type
|
24
|
+
is_empty_hash = (exp.first == s(:hash))
|
25
|
+
arg = process exp.shift
|
26
|
+
|
27
|
+
next if arg.empty?
|
28
|
+
|
29
|
+
strip_hash = (arg_type == :hash and
|
30
|
+
not BINARY.include? name and
|
31
|
+
not is_empty_hash and
|
32
|
+
(exp.empty? or exp.first.sexp_type == :splat))
|
33
|
+
wrap_arg = ASSIGN_NODES.include? arg_type
|
34
|
+
|
35
|
+
arg = arg[2..-3] if strip_hash
|
36
|
+
arg = "(#{arg})" if wrap_arg
|
37
|
+
|
38
|
+
args << arg
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
case name
|
43
|
+
when *BINARY then
|
44
|
+
"(#{receiver} #{name} #{args.join(', ')})"
|
45
|
+
when :[] then
|
46
|
+
receiver ||= "self"
|
47
|
+
"#{receiver}[#{args.join(', ')}]"
|
48
|
+
when :[]= then
|
49
|
+
receiver ||= "self"
|
50
|
+
rhs = args.pop
|
51
|
+
"#{receiver}[#{args.join(', ')}] = #{rhs}"
|
52
|
+
when :"!" then
|
53
|
+
"(not #{receiver})"
|
54
|
+
when :"-@" then
|
55
|
+
"-#{receiver}"
|
56
|
+
when :"+@" then
|
57
|
+
"+#{receiver}"
|
58
|
+
else
|
59
|
+
args = nil if args.empty?
|
60
|
+
args = "(#{args.join(', ')})" if args
|
61
|
+
receiver = "#{receiver}." if receiver
|
62
|
+
|
63
|
+
"#{receiver}#{name}#{args}"
|
64
|
+
end
|
65
|
+
ensure
|
66
|
+
call_pop
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
module Sexp2Ruby
|
2
|
+
module Node
|
3
|
+
class Case < Base
|
4
|
+
def to_s(exp)
|
5
|
+
result = []
|
6
|
+
expr = process exp.shift
|
7
|
+
if expr
|
8
|
+
result << "case #{expr}"
|
9
|
+
else
|
10
|
+
result << "case"
|
11
|
+
end
|
12
|
+
until exp.empty?
|
13
|
+
pt = exp.shift
|
14
|
+
if pt and pt.first == :when
|
15
|
+
result << "#{process(pt)}"
|
16
|
+
else
|
17
|
+
code = indent(process(pt))
|
18
|
+
code = indent("# do nothing") if code =~ /^\s*$/
|
19
|
+
result << "else\n#{code}"
|
20
|
+
end
|
21
|
+
end
|
22
|
+
result << "end"
|
23
|
+
result.join(LF)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,66 @@
|
|
1
|
+
module Sexp2Ruby
|
2
|
+
module Node
|
3
|
+
class Defn < Base
|
4
|
+
def to_s(exp)
|
5
|
+
type1 = exp[1].first
|
6
|
+
type2 = exp[2].first rescue nil
|
7
|
+
expect = [:ivar, :iasgn, :attrset]
|
8
|
+
|
9
|
+
# s(name, args, ivar|iasgn|attrset)
|
10
|
+
if exp.size == 3 and type1 == :args and expect.include? type2
|
11
|
+
name = exp.first # don't shift in case we pass through
|
12
|
+
case type2
|
13
|
+
when :ivar then
|
14
|
+
ivar_name = exp.ivar.last
|
15
|
+
|
16
|
+
meth_name = ivar_name.to_s[1..-1].to_sym
|
17
|
+
expected = s(meth_name, s(:args), s(:ivar, ivar_name))
|
18
|
+
|
19
|
+
if exp == expected
|
20
|
+
exp.clear
|
21
|
+
return "attr_reader #{name.inspect}"
|
22
|
+
end
|
23
|
+
when :attrset then
|
24
|
+
# TODO: deprecate? this is a PT relic
|
25
|
+
exp.clear
|
26
|
+
return "attr_writer :#{name.to_s[0..-2]}"
|
27
|
+
when :iasgn then
|
28
|
+
ivar_name = exp.iasgn[1]
|
29
|
+
meth_name = "#{ivar_name.to_s[1..-1]}=".to_sym
|
30
|
+
arg_name = exp.args.last
|
31
|
+
expected = s(meth_name, s(:args, arg_name),
|
32
|
+
s(:iasgn, ivar_name, s(:lvar, arg_name)))
|
33
|
+
|
34
|
+
if exp == expected
|
35
|
+
exp.clear
|
36
|
+
return "attr_writer :#{name.to_s[0..-2]}"
|
37
|
+
end
|
38
|
+
else
|
39
|
+
raise "Unknown defn type: #{exp.inspect}"
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
comm = exp.comments
|
44
|
+
name = exp.shift
|
45
|
+
args = process exp.shift
|
46
|
+
args = "" if args == "()"
|
47
|
+
|
48
|
+
exp.shift if exp == s(s(:nil)) # empty it out of a default nil expression
|
49
|
+
|
50
|
+
# REFACTOR: use process_block but get it happier wrt parenthesize
|
51
|
+
body = []
|
52
|
+
until exp.empty? do
|
53
|
+
body << process(exp.shift)
|
54
|
+
end
|
55
|
+
|
56
|
+
body << "# do nothing" if body.empty?
|
57
|
+
body = body.join(LF)
|
58
|
+
body = body.lines.to_a[1..-2].join(LF) if
|
59
|
+
body =~ /^\Abegin/ && body =~ /^end\z/
|
60
|
+
body = indent(body) unless body =~ /(^|\n)rescue/
|
61
|
+
|
62
|
+
"#{comm}def #{name}#{args}\n#{body}\nend".gsub(/\n\s*\n+/, LF)
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module Sexp2Ruby
|
2
|
+
module Node
|
3
|
+
class Defs < Base
|
4
|
+
def to_s(exp)
|
5
|
+
lhs = exp.shift
|
6
|
+
var = [:self, :cvar, :dvar, :ivar, :gvar, :lvar].include? lhs.first
|
7
|
+
name = exp.shift
|
8
|
+
|
9
|
+
lhs = process(lhs)
|
10
|
+
lhs = "(#{lhs})" unless var
|
11
|
+
|
12
|
+
exp.unshift "#{lhs}.#{name}"
|
13
|
+
process_defn(exp)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module Sexp2Ruby
|
2
|
+
module Node
|
3
|
+
class Dregx < Base
|
4
|
+
def to_s(exp)
|
5
|
+
options = re_opt exp.pop if Fixnum === exp.last
|
6
|
+
"/" << util_dthing(:dregx, exp) << "/#{options}"
|
7
|
+
end
|
8
|
+
|
9
|
+
private
|
10
|
+
|
11
|
+
# Return the appropriate regexp flags for a given numeric code.
|
12
|
+
def re_opt options
|
13
|
+
bits = (0..8).map { |n| options[n] * 2**n }
|
14
|
+
bits.delete 0
|
15
|
+
bits.map { |n| Regexp::CODES[n] }.join
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|