rephrase 0.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.
- checksums.yaml +7 -0
- data/CHANGELOG.md +3 -0
- data/README.md +5 -0
- data/lib/rephrase/version.rb +5 -0
- data/lib/rephrase.rb +276 -0
- metadata +80 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 35b9da1b746b755618ad23cc57fa70559f35064277b61965278544333d678f1d
|
4
|
+
data.tar.gz: 0467c2c8bc54226c445ed39cedb4a16ca85a945c326bd3bae26abf049f5622b2
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: '0912d93aac2a5fdbdf6c69490947530b6147f2fb55eff205c3839fdc1ad48dd6adddf35d2db868cef4da109b82fdae5b74a489f93d73d6dfed3a65ee8cd8d381'
|
7
|
+
data.tar.gz: aa45eefab2311a46c513af8f161345065cb08e2efdd56f7cbfc20e75c56bccf9b1907a90ba4a97e43976fc00efac096387b272895e68a49d212694e1ed7b9f92
|
data/CHANGELOG.md
ADDED
data/README.md
ADDED
@@ -0,0 +1,5 @@
|
|
1
|
+
# Rephrase - a gem for manipulating Ruby code
|
2
|
+
|
3
|
+
[](http://rubygems.org/gems/rephrase)
|
4
|
+
[](https://github.com/digital-fabric/rephrase/actions?query=workflow%3ATests)
|
5
|
+
[](https://github.com/digital-fabric/rephrase/blob/master/LICENSE)
|
data/lib/rephrase.rb
ADDED
@@ -0,0 +1,276 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# for use with IRB, see https://dev.to/okinawarb/how-can-i-use-rubyvm-abstractsyntaxtree-in-irb-m2k
|
4
|
+
# for use in Pry, see https://dev.to/okinawarb/using-rubyvm-abstractsyntaxtree-of-in-pry-4cm3
|
5
|
+
|
6
|
+
class Rephrase
|
7
|
+
class FakeNode
|
8
|
+
def self.list(children)
|
9
|
+
new(:LIST_EMBEDDED, children)
|
10
|
+
end
|
11
|
+
|
12
|
+
def self.iter_scope(children)
|
13
|
+
new(:ITER_SCOPE, children)
|
14
|
+
end
|
15
|
+
|
16
|
+
attr_reader :type, :children
|
17
|
+
|
18
|
+
def initialize(type, children)
|
19
|
+
@type = type
|
20
|
+
@children = children
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def convert(ctx, node)
|
25
|
+
ctx[:buffer] ||= +''
|
26
|
+
ctx[:indent] ||= 0
|
27
|
+
method_name = :"on_#{node.type.downcase}"
|
28
|
+
if respond_to?(method_name)
|
29
|
+
send(method_name, ctx, node)
|
30
|
+
ctx[:buffer]
|
31
|
+
else
|
32
|
+
raise "Could not convert #{node.type} node to ruby"
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def on_scope(ctx, node)
|
37
|
+
body = node.children.last
|
38
|
+
# if body.type != :BLOCK
|
39
|
+
# body = FakeNode.new(:BLOCK, [body])
|
40
|
+
# end
|
41
|
+
emit(ctx, "proc do", [body], "end")
|
42
|
+
end
|
43
|
+
|
44
|
+
def on_block(ctx, node)
|
45
|
+
last_idx = node.children.size - 1
|
46
|
+
node.children.each_with_index do |c, idx|
|
47
|
+
emit(ctx, c)
|
48
|
+
emit(ctx, "\n") if idx < last_idx
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
def on_iter(ctx, node)
|
53
|
+
call, scope = node.children
|
54
|
+
emit(ctx, call)
|
55
|
+
emit(ctx, FakeNode.iter_scope(scope.children))
|
56
|
+
end
|
57
|
+
|
58
|
+
def on_iter_scope(ctx, node)
|
59
|
+
args, arg_spec, body = node.children
|
60
|
+
emit(ctx, " do")
|
61
|
+
emit(ctx, " |", args.map(&:to_s).join(", "), "|") unless args.empty?
|
62
|
+
emit(ctx, "\n")
|
63
|
+
emit(ctx, body)
|
64
|
+
emit(ctx, "\nend")
|
65
|
+
end
|
66
|
+
|
67
|
+
def on_const(ctx, node)
|
68
|
+
emit(ctx, node.children.first.to_s)
|
69
|
+
end
|
70
|
+
|
71
|
+
def on_colon2(ctx, node)
|
72
|
+
left, right = node.children
|
73
|
+
emit(ctx, left, "::", right.to_s)
|
74
|
+
end
|
75
|
+
|
76
|
+
def on_call(ctx, node)
|
77
|
+
receiver, method, args = node.children
|
78
|
+
args = args && FakeNode.list(args.children)
|
79
|
+
case method
|
80
|
+
when :[]
|
81
|
+
emit(ctx, receiver, "[", args, "]")
|
82
|
+
else
|
83
|
+
if args
|
84
|
+
emit(ctx, receiver, ".", "#{method}(", args, ")")
|
85
|
+
else
|
86
|
+
emit(ctx, receiver, ".", "#{method}()")
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
def on_fcall(ctx, node)
|
92
|
+
method, args = node.children
|
93
|
+
args = args && FakeNode.list(args.children)
|
94
|
+
emit(ctx, "#{method}(", args, ")")
|
95
|
+
end
|
96
|
+
|
97
|
+
def on_vcall(ctx, node)
|
98
|
+
emit(ctx, node.children.first.to_s, "()")
|
99
|
+
end
|
100
|
+
|
101
|
+
def on_opcall(ctx, node)
|
102
|
+
left, op, right = node.children
|
103
|
+
if op == :!
|
104
|
+
emit(ctx, "!(", left, ")")
|
105
|
+
else
|
106
|
+
emit(ctx, left, " #{op} ", right.children.first)
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
def on_dasgn_curr(ctx, node)
|
111
|
+
left, right = node.children
|
112
|
+
emit(ctx, left.to_s, " = ", right)
|
113
|
+
end
|
114
|
+
|
115
|
+
def on_iasgn(ctx, node)
|
116
|
+
left, right = node.children
|
117
|
+
emit(ctx, left.to_s, " = ", right)
|
118
|
+
end
|
119
|
+
|
120
|
+
def on_if(ctx, node)
|
121
|
+
cond, branch1, branch2 = node.children
|
122
|
+
if branch2
|
123
|
+
emit(ctx, "if ", cond, "\n", branch1, "\nelse\n", branch2, "\nend")
|
124
|
+
else
|
125
|
+
emit(ctx, "if ", cond, "\n", branch1, "\nend")
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
129
|
+
def on_unless(ctx, node)
|
130
|
+
cond, branch1, branch2 = node.children
|
131
|
+
if branch2
|
132
|
+
emit(ctx, "unless ", cond, "\n", branch1, "\nelse\n", branch2, "\nend")
|
133
|
+
else
|
134
|
+
emit(ctx, "unless ", cond, "\n", branch1, "\nend")
|
135
|
+
end
|
136
|
+
end
|
137
|
+
|
138
|
+
def on_while(ctx, node)
|
139
|
+
cond, body = node.children
|
140
|
+
emit(ctx, "while ", cond, "\n", body, "\nend")
|
141
|
+
end
|
142
|
+
|
143
|
+
def on_lit(ctx, node)
|
144
|
+
emit(ctx, node.children.first.inspect)
|
145
|
+
end
|
146
|
+
|
147
|
+
def on_nil(ctx, node)
|
148
|
+
emit(ctx, "nil")
|
149
|
+
end
|
150
|
+
|
151
|
+
def on_true(ctx, node)
|
152
|
+
emit(ctx, "true")
|
153
|
+
end
|
154
|
+
|
155
|
+
def on_false(ctx, node)
|
156
|
+
emit(ctx, "false")
|
157
|
+
end
|
158
|
+
|
159
|
+
def on_dvar(ctx, node)
|
160
|
+
emit(ctx, node.children.first.to_s)
|
161
|
+
end
|
162
|
+
|
163
|
+
def on_ivar(ctx, node)
|
164
|
+
emit(ctx, node.children.first.to_s)
|
165
|
+
end
|
166
|
+
|
167
|
+
def on_str(ctx, node)
|
168
|
+
emit(ctx, node.children.first.inspect)
|
169
|
+
end
|
170
|
+
|
171
|
+
def on_dstr(ctx, node)
|
172
|
+
prefix, evstr1, rest = node.children
|
173
|
+
emit(ctx, "\"", prefix.inspect[1..-2], evstr1)
|
174
|
+
if rest
|
175
|
+
rest.children.compact.each do |n|
|
176
|
+
case n.type
|
177
|
+
when :STR
|
178
|
+
emit(ctx, n.children.first.inspect[1..-2])
|
179
|
+
when :EVSTR
|
180
|
+
emit(ctx, n)
|
181
|
+
else
|
182
|
+
raise "Unexpected node #{n.type.inspect} encountered in DSTR"
|
183
|
+
end
|
184
|
+
end
|
185
|
+
end
|
186
|
+
emit(ctx, "\"")
|
187
|
+
end
|
188
|
+
|
189
|
+
def on_evstr(ctx, node)
|
190
|
+
emit(ctx, "\#{", node.children.first, "}")
|
191
|
+
end
|
192
|
+
|
193
|
+
def on_and(ctx, node)
|
194
|
+
left, right = node.children
|
195
|
+
emit(ctx, left, " && ", right)
|
196
|
+
end
|
197
|
+
|
198
|
+
def on_or(ctx, node)
|
199
|
+
left, right = node.children
|
200
|
+
emit(ctx, left, " || ", right)
|
201
|
+
end
|
202
|
+
|
203
|
+
def on_list(ctx, node)
|
204
|
+
items = node.children[0..-2]
|
205
|
+
last_idx = items.size - 1
|
206
|
+
emit(ctx, "[")
|
207
|
+
items.each_with_index do |c, idx|
|
208
|
+
emit(ctx, c)
|
209
|
+
emit(ctx, ", ") if idx < last_idx
|
210
|
+
end
|
211
|
+
emit(ctx, "]")
|
212
|
+
end
|
213
|
+
|
214
|
+
def on_list_embedded(ctx, node)
|
215
|
+
items = node.children.compact
|
216
|
+
last_idx = items.size - 1
|
217
|
+
items.each_with_index do |c, idx|
|
218
|
+
emit(ctx, c)
|
219
|
+
emit(ctx, ", ") if idx < last_idx
|
220
|
+
end
|
221
|
+
end
|
222
|
+
|
223
|
+
def on_hash(ctx, node)
|
224
|
+
list = node.children.first
|
225
|
+
idx = 0
|
226
|
+
emit(ctx, "{")
|
227
|
+
while true
|
228
|
+
k, v = list.children[idx, 2]
|
229
|
+
break unless k
|
230
|
+
|
231
|
+
emit(ctx, ", ") if idx > 0
|
232
|
+
idx += 2
|
233
|
+
emit(ctx, k, " => ", v)
|
234
|
+
end
|
235
|
+
emit(ctx, "}")
|
236
|
+
end
|
237
|
+
|
238
|
+
def on_attrasgn(ctx, node)
|
239
|
+
left, op, args = node.children
|
240
|
+
emit(ctx, left)
|
241
|
+
case op
|
242
|
+
when :[]=
|
243
|
+
args_list = args.children[0..-2]
|
244
|
+
subscript = FakeNode.list(args_list[0..-2])
|
245
|
+
right = args_list.last
|
246
|
+
emit(ctx, "[", subscript, "] = ", right)
|
247
|
+
else
|
248
|
+
raise "Unsupported ATTRASGN op #{op.inspect}"
|
249
|
+
end
|
250
|
+
end
|
251
|
+
|
252
|
+
def on_rescue(ctx, node)
|
253
|
+
code, rescue_body = node.children
|
254
|
+
emit(ctx, code)
|
255
|
+
emit(ctx, " rescue ", rescue_body.children[1])
|
256
|
+
end
|
257
|
+
|
258
|
+
def emit(ctx, *entries)
|
259
|
+
entries.each do |e|
|
260
|
+
case e
|
261
|
+
when RubyVM::AbstractSyntaxTree::Node, FakeNode
|
262
|
+
convert(ctx, e)
|
263
|
+
when Array
|
264
|
+
ctx[:buffer] << "\n"
|
265
|
+
e.each { |e2| convert(ctx, e2) }
|
266
|
+
ctx[:buffer] << "\n"
|
267
|
+
when String
|
268
|
+
ctx[:buffer] << e
|
269
|
+
when nil
|
270
|
+
# ignore
|
271
|
+
else
|
272
|
+
raise "Invalid entry #{e.inspect}"
|
273
|
+
end
|
274
|
+
end
|
275
|
+
end
|
276
|
+
end
|
metadata
ADDED
@@ -0,0 +1,80 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: rephrase
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: '0.1'
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Sharon Rosner
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2021-11-16 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: minitest
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - '='
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: 5.11.3
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - '='
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: 5.11.3
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rake
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '12.0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '12.0'
|
41
|
+
description:
|
42
|
+
email: ciconia@gmail.com
|
43
|
+
executables: []
|
44
|
+
extensions: []
|
45
|
+
extra_rdoc_files:
|
46
|
+
- README.md
|
47
|
+
files:
|
48
|
+
- CHANGELOG.md
|
49
|
+
- README.md
|
50
|
+
- lib/rephrase.rb
|
51
|
+
- lib/rephrase/version.rb
|
52
|
+
homepage: http://github.com/digital-fabric/rephrase
|
53
|
+
licenses:
|
54
|
+
- MIT
|
55
|
+
metadata:
|
56
|
+
source_code_uri: https://github.com/digital-fabric/rephrase
|
57
|
+
post_install_message:
|
58
|
+
rdoc_options:
|
59
|
+
- "--title"
|
60
|
+
- Rephrase
|
61
|
+
- "--main"
|
62
|
+
- README.md
|
63
|
+
require_paths:
|
64
|
+
- lib
|
65
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
66
|
+
requirements:
|
67
|
+
- - ">="
|
68
|
+
- !ruby/object:Gem::Version
|
69
|
+
version: '2.7'
|
70
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
71
|
+
requirements:
|
72
|
+
- - ">="
|
73
|
+
- !ruby/object:Gem::Version
|
74
|
+
version: '0'
|
75
|
+
requirements: []
|
76
|
+
rubygems_version: 3.1.2
|
77
|
+
signing_key:
|
78
|
+
specification_version: 4
|
79
|
+
summary: 'Rephrase: a gem for manipulating Ruby code'
|
80
|
+
test_files: []
|