to_source 0.0.1 → 0.1.3
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.
- data/Readme.md +8 -1
- data/lib/to_source/core_ext/node.rb +5 -2
- data/lib/to_source/version.rb +1 -1
- data/lib/to_source/visitor.rb +140 -0
- data/test/to_source/visitor_test.rb +76 -0
- metadata +4 -4
data/Readme.md
CHANGED
|
@@ -18,7 +18,14 @@ transform themselves into source code. It's the reverse of Rubinius' builtin
|
|
|
18
18
|
|
|
19
19
|
to_source needs Rubinius 2.0 to run, in either 1.8 or 1.9 mode.
|
|
20
20
|
|
|
21
|
-
|
|
21
|
+
To install it as a gem:
|
|
22
|
+
|
|
23
|
+
$ gem install to_source
|
|
24
|
+
|
|
25
|
+
And `require 'to_source'` from your code. Automatically, your AST nodes respond
|
|
26
|
+
to the `#to_source` method.
|
|
27
|
+
|
|
28
|
+
But if you're using Bundler, just put this in your Gemfile:
|
|
22
29
|
|
|
23
30
|
gem 'to_source'
|
|
24
31
|
|
|
@@ -9,8 +9,11 @@ module Rubinius
|
|
|
9
9
|
#
|
|
10
10
|
# Returns nothing.
|
|
11
11
|
def lazy_visit(visitor, parent=nil, indent=false)
|
|
12
|
-
|
|
13
|
-
|
|
12
|
+
name = node_name
|
|
13
|
+
name = "#{name}_def" if %w[ class module ].include?(name)
|
|
14
|
+
|
|
15
|
+
args = [name, self, parent]
|
|
16
|
+
args << true if indent
|
|
14
17
|
|
|
15
18
|
visitor.__send__ *args
|
|
16
19
|
end
|
data/lib/to_source/version.rb
CHANGED
data/lib/to_source/visitor.rb
CHANGED
|
@@ -17,6 +17,42 @@ module ToSource
|
|
|
17
17
|
' ' * @indentation
|
|
18
18
|
end
|
|
19
19
|
|
|
20
|
+
def class_def(node, parent)
|
|
21
|
+
emit "class %s" % node.name.name
|
|
22
|
+
|
|
23
|
+
superclass = node.superclass
|
|
24
|
+
unless superclass.is_a?(Rubinius::AST::NilLiteral)
|
|
25
|
+
emit " < %s" % superclass.name
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
node.body.lazy_visit self, node, true
|
|
29
|
+
|
|
30
|
+
emit "\n"
|
|
31
|
+
emit "end"
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def module_def(node, parent)
|
|
35
|
+
emit "module %s" % node.name.name
|
|
36
|
+
|
|
37
|
+
node.body.lazy_visit self, node, true
|
|
38
|
+
|
|
39
|
+
emit "\n"
|
|
40
|
+
emit "end"
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def empty_body(*)
|
|
44
|
+
# do nothing
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
def class_scope(node, parent, indent)
|
|
48
|
+
emit "\n"
|
|
49
|
+
@indentation += 1 if indent
|
|
50
|
+
node.body.lazy_visit self, node, indent
|
|
51
|
+
ensure
|
|
52
|
+
@indentation -= 1 if indent
|
|
53
|
+
end
|
|
54
|
+
alias module_scope class_scope
|
|
55
|
+
|
|
20
56
|
def local_variable_assignment(node, parent)
|
|
21
57
|
emit "%s = " % node.name
|
|
22
58
|
node.value.lazy_visit self, node
|
|
@@ -26,6 +62,15 @@ module ToSource
|
|
|
26
62
|
emit node.name
|
|
27
63
|
end
|
|
28
64
|
|
|
65
|
+
def instance_variable_assignment(node, parent)
|
|
66
|
+
emit "%s = " % node.name
|
|
67
|
+
node.value.lazy_visit self, node
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
def instance_variable_access(node, parent)
|
|
71
|
+
emit node.name
|
|
72
|
+
end
|
|
73
|
+
|
|
29
74
|
def fixnum_literal(node, parent)
|
|
30
75
|
emit node.value.to_s
|
|
31
76
|
end
|
|
@@ -87,6 +132,12 @@ module ToSource
|
|
|
87
132
|
node.finish.lazy_visit self, node
|
|
88
133
|
end
|
|
89
134
|
|
|
135
|
+
def range_exclude(node, parent)
|
|
136
|
+
node.start.lazy_visit self, node
|
|
137
|
+
emit '...'
|
|
138
|
+
node.finish.lazy_visit self, node
|
|
139
|
+
end
|
|
140
|
+
|
|
90
141
|
def regex_literal(node, parent)
|
|
91
142
|
emit '/'
|
|
92
143
|
emit node.source
|
|
@@ -207,6 +258,11 @@ module ToSource
|
|
|
207
258
|
node.right.lazy_visit self, node
|
|
208
259
|
end
|
|
209
260
|
|
|
261
|
+
def toplevel_constant(node, parent)
|
|
262
|
+
emit "::"
|
|
263
|
+
emit node.name
|
|
264
|
+
end
|
|
265
|
+
|
|
210
266
|
def constant_access(node, parent)
|
|
211
267
|
emit node.name
|
|
212
268
|
end
|
|
@@ -217,6 +273,90 @@ module ToSource
|
|
|
217
273
|
emit node.name
|
|
218
274
|
end
|
|
219
275
|
|
|
276
|
+
def if(node, parent)
|
|
277
|
+
body, else_body = node.body, node.else
|
|
278
|
+
keyword = 'if'
|
|
279
|
+
|
|
280
|
+
if node.body.is_a?(Rubinius::AST::NilLiteral) && !node.else.is_a?(Rubinius::AST::NilLiteral)
|
|
281
|
+
|
|
282
|
+
body, else_body = else_body, body
|
|
283
|
+
keyword = 'unless'
|
|
284
|
+
end
|
|
285
|
+
|
|
286
|
+
emit keyword << ' '
|
|
287
|
+
node.condition.lazy_visit self, node
|
|
288
|
+
emit "\n"
|
|
289
|
+
|
|
290
|
+
@indentation += 1
|
|
291
|
+
|
|
292
|
+
if body.is_a?(Rubinius::AST::Block)
|
|
293
|
+
body.lazy_visit self, parent, true
|
|
294
|
+
else
|
|
295
|
+
emit current_indentation
|
|
296
|
+
body.lazy_visit self, parent
|
|
297
|
+
end
|
|
298
|
+
|
|
299
|
+
emit "\n"
|
|
300
|
+
|
|
301
|
+
if else_body.is_a?(Rubinius::AST::NilLiteral)
|
|
302
|
+
emit 'end'
|
|
303
|
+
return
|
|
304
|
+
end
|
|
305
|
+
|
|
306
|
+
emit "else\n"
|
|
307
|
+
|
|
308
|
+
if else_body.is_a?(Rubinius::AST::Block)
|
|
309
|
+
else_body.lazy_visit self, parent, true
|
|
310
|
+
else
|
|
311
|
+
emit current_indentation
|
|
312
|
+
else_body.lazy_visit self, parent
|
|
313
|
+
end
|
|
314
|
+
|
|
315
|
+
emit "\n"
|
|
316
|
+
emit 'end'
|
|
317
|
+
end
|
|
318
|
+
|
|
319
|
+
def while(node, parent)
|
|
320
|
+
emit 'while '
|
|
321
|
+
node.condition.lazy_visit self, node
|
|
322
|
+
emit "\n"
|
|
323
|
+
|
|
324
|
+
@indentation += 1
|
|
325
|
+
|
|
326
|
+
if node.body.is_a?(Rubinius::AST::Block)
|
|
327
|
+
node.body.lazy_visit self, parent, true
|
|
328
|
+
else
|
|
329
|
+
emit current_indentation
|
|
330
|
+
node.body.lazy_visit self, parent
|
|
331
|
+
end
|
|
332
|
+
|
|
333
|
+
emit "\n"
|
|
334
|
+
emit "end"
|
|
335
|
+
end
|
|
336
|
+
|
|
337
|
+
def until(node, parent)
|
|
338
|
+
emit 'until '
|
|
339
|
+
node.condition.lazy_visit self, node
|
|
340
|
+
emit "\n"
|
|
341
|
+
|
|
342
|
+
@indentation += 1
|
|
343
|
+
|
|
344
|
+
if node.body.is_a?(Rubinius::AST::Block)
|
|
345
|
+
node.body.lazy_visit self, parent, true
|
|
346
|
+
else
|
|
347
|
+
emit current_indentation
|
|
348
|
+
node.body.lazy_visit self, parent
|
|
349
|
+
end
|
|
350
|
+
|
|
351
|
+
emit "\n"
|
|
352
|
+
emit "end"
|
|
353
|
+
end
|
|
354
|
+
|
|
355
|
+
def return(node, parent)
|
|
356
|
+
emit 'return '
|
|
357
|
+
node.value.lazy_visit self, parent
|
|
358
|
+
end
|
|
359
|
+
|
|
220
360
|
private
|
|
221
361
|
|
|
222
362
|
def process_binary_operator(node, parent)
|
|
@@ -15,14 +15,46 @@ module ToSource
|
|
|
15
15
|
assert_equal expected, visit(code)
|
|
16
16
|
end
|
|
17
17
|
|
|
18
|
+
def test_class
|
|
19
|
+
assert_source "class TestClass\nend"
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def test_class_with_superclass
|
|
23
|
+
assert_source "class TestClass < Object\nend"
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def test_class_with_body
|
|
27
|
+
assert_source "class TestClass\n 1\nend"
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def test_module
|
|
31
|
+
assert_source "module TestModule\nend"
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def test_module_with_body
|
|
35
|
+
assert_source "module TestModule\n 1\nend"
|
|
36
|
+
end
|
|
37
|
+
|
|
18
38
|
def test_local_assignment
|
|
19
39
|
assert_source "foo = 1"
|
|
20
40
|
end
|
|
21
41
|
|
|
42
|
+
def test_ivar_assignment
|
|
43
|
+
assert_source "@foo = 1"
|
|
44
|
+
end
|
|
45
|
+
|
|
22
46
|
def test_local_access
|
|
23
47
|
assert_source "foo = 1\nfoo"
|
|
24
48
|
end
|
|
25
49
|
|
|
50
|
+
def test_ivar_access
|
|
51
|
+
assert_source "@foo"
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
def test_toplevel_constant_access
|
|
55
|
+
assert_source "::Rubinius"
|
|
56
|
+
end
|
|
57
|
+
|
|
26
58
|
def test_constant_access
|
|
27
59
|
assert_source "Rubinius"
|
|
28
60
|
end
|
|
@@ -71,6 +103,10 @@ module ToSource
|
|
|
71
103
|
assert_source '20..34'
|
|
72
104
|
end
|
|
73
105
|
|
|
106
|
+
def test_range_exclude
|
|
107
|
+
assert_source '20...34'
|
|
108
|
+
end
|
|
109
|
+
|
|
74
110
|
def test_regex
|
|
75
111
|
assert_source '/.*/'
|
|
76
112
|
end
|
|
@@ -122,5 +158,45 @@ module ToSource
|
|
|
122
158
|
assert_source "!1"
|
|
123
159
|
assert_source "!!1"
|
|
124
160
|
end
|
|
161
|
+
|
|
162
|
+
def test_if
|
|
163
|
+
assert_source "if 3\n 9\nend"
|
|
164
|
+
end
|
|
165
|
+
|
|
166
|
+
def test_if_with_multiple_blocks
|
|
167
|
+
assert_source "if 3\n 9\n 8\nend"
|
|
168
|
+
end
|
|
169
|
+
|
|
170
|
+
def test_else
|
|
171
|
+
assert_source "if 3\n 9\nelse\n 9\nend"
|
|
172
|
+
end
|
|
173
|
+
|
|
174
|
+
def test_else_with_multiple_blocks
|
|
175
|
+
assert_source "if 3\n 9\n 8\nelse\n 9\n 8\nend"
|
|
176
|
+
end
|
|
177
|
+
|
|
178
|
+
def test_unless
|
|
179
|
+
assert_source "unless 3\n 9\nend"
|
|
180
|
+
end
|
|
181
|
+
|
|
182
|
+
def test_while
|
|
183
|
+
assert_source "while false\n 3\nend"
|
|
184
|
+
end
|
|
185
|
+
|
|
186
|
+
def test_while_with_multiple_blocks
|
|
187
|
+
assert_source "while false\n 3\n 5\nend"
|
|
188
|
+
end
|
|
189
|
+
|
|
190
|
+
def test_until
|
|
191
|
+
assert_source "until false\n 3\nend"
|
|
192
|
+
end
|
|
193
|
+
|
|
194
|
+
def test_until_with_multiple_blocks
|
|
195
|
+
assert_source "while false\n 3\n 5\nend"
|
|
196
|
+
end
|
|
197
|
+
|
|
198
|
+
def test_return
|
|
199
|
+
assert_source "return 9"
|
|
200
|
+
end
|
|
125
201
|
end
|
|
126
202
|
end
|
metadata
CHANGED
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: to_source
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 0.1.3
|
|
4
5
|
prerelease:
|
|
5
|
-
version: 0.0.1
|
|
6
6
|
platform: ruby
|
|
7
7
|
authors:
|
|
8
8
|
- Josep M. Bach
|
|
9
9
|
autorequire:
|
|
10
10
|
bindir: bin
|
|
11
11
|
cert_chain: []
|
|
12
|
-
date: 2012-
|
|
12
|
+
date: 2012-04-12 00:00:00.000000000 Z
|
|
13
13
|
dependencies: []
|
|
14
14
|
description: Transform your Rubinius AST nodes back to source code. Reverse parsing!
|
|
15
15
|
email:
|
|
@@ -37,17 +37,17 @@ rdoc_options: []
|
|
|
37
37
|
require_paths:
|
|
38
38
|
- lib
|
|
39
39
|
required_ruby_version: !ruby/object:Gem::Requirement
|
|
40
|
-
none: false
|
|
41
40
|
requirements:
|
|
42
41
|
- - ! '>='
|
|
43
42
|
- !ruby/object:Gem::Version
|
|
44
43
|
version: '0'
|
|
45
|
-
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
46
44
|
none: false
|
|
45
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
47
46
|
requirements:
|
|
48
47
|
- - ! '>='
|
|
49
48
|
- !ruby/object:Gem::Version
|
|
50
49
|
version: '0'
|
|
50
|
+
none: false
|
|
51
51
|
requirements: []
|
|
52
52
|
rubyforge_project:
|
|
53
53
|
rubygems_version: 1.8.12
|