sorcerer 0.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.
- data/README.textile +2 -0
- data/Rakefile +74 -0
- data/lib/sorcerer.rb +1 -0
- data/lib/sorcerer/sorcerer.rb +715 -0
- data/test/sorcerer/sorcerer_test.rb +521 -0
- metadata +64 -0
data/README.textile
ADDED
data/Rakefile
ADDED
@@ -0,0 +1,74 @@
|
|
1
|
+
#!/usr/bin/env ruby"
|
2
|
+
|
3
|
+
require 'rake/clean'
|
4
|
+
require 'rake/testtask'
|
5
|
+
|
6
|
+
begin
|
7
|
+
require 'rubygems'
|
8
|
+
require 'rake/gempackagetask'
|
9
|
+
rescue Exception
|
10
|
+
nil
|
11
|
+
end
|
12
|
+
|
13
|
+
module Config
|
14
|
+
PROJ = 'sorcerer'
|
15
|
+
RUBY = 'ruby19'
|
16
|
+
|
17
|
+
BASE_RDOC_OPTIONS = [
|
18
|
+
'--line-numbers', '--inline-source',
|
19
|
+
'--main' , 'README.rdoc',
|
20
|
+
'--title', 'Rake -- Ruby Make'
|
21
|
+
]
|
22
|
+
end
|
23
|
+
|
24
|
+
PKG_VERSION = '0.0.1'
|
25
|
+
|
26
|
+
PKG_FILES = FileList[
|
27
|
+
'README.textile',
|
28
|
+
'Rakefile',
|
29
|
+
'doc/*',
|
30
|
+
'rakelib/*',
|
31
|
+
'lib/**/*.rb',
|
32
|
+
'test/**/*.rb',
|
33
|
+
]
|
34
|
+
|
35
|
+
|
36
|
+
task :default => :test
|
37
|
+
|
38
|
+
# Modify the TestTask to allow running ruby19 for the tests
|
39
|
+
class Ruby19TestTask < Rake::TestTask
|
40
|
+
def ruby(*args)
|
41
|
+
sh "#{Config::RUBY} #{args.join(' ')}"
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
Ruby19TestTask.new(:test) do |t|
|
46
|
+
t.warning = true
|
47
|
+
t.verbose = false
|
48
|
+
t.test_files = FileList["test/#{Config::PROJ}/*_test.rb"]
|
49
|
+
end
|
50
|
+
|
51
|
+
if ! defined?(Gem)
|
52
|
+
puts "Package Target requires RubyGEMs"
|
53
|
+
else
|
54
|
+
SPEC = Gem::Specification.new do |s|
|
55
|
+
s.name = 'sorcerer'
|
56
|
+
s.version = PKG_VERSION
|
57
|
+
s.summary = "Generate Source from Ripper ASTs"
|
58
|
+
s.description = <<-EOF
|
59
|
+
Generate the original Ruby source from a Ripper-style abstract syntax tree.
|
60
|
+
EOF
|
61
|
+
s.files = PKG_FILES.to_a
|
62
|
+
s.require_path = 'lib' # Use these for libraries.
|
63
|
+
s.has_rdoc = true
|
64
|
+
s.rdoc_options = Config::BASE_RDOC_OPTIONS
|
65
|
+
s.author = "Jim Weirich"
|
66
|
+
s.email = "jim.weirich@gmail.com"
|
67
|
+
s.homepage = "http://github.com/jimweirich/sorcerer"
|
68
|
+
end
|
69
|
+
|
70
|
+
package_task = Rake::GemPackageTask.new(SPEC) do |pkg|
|
71
|
+
pkg.need_zip = true
|
72
|
+
pkg.need_tar = true
|
73
|
+
end
|
74
|
+
end
|
data/lib/sorcerer.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require 'sorcerer/sorcerer'
|
@@ -0,0 +1,715 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'ripper'
|
4
|
+
|
5
|
+
class Sorcerer
|
6
|
+
class NoHandlerError < StandardError
|
7
|
+
end
|
8
|
+
|
9
|
+
# Generate the source code for teh given Ripper S-Expression.
|
10
|
+
def Sorcerer.source(sexp, debug=false)
|
11
|
+
new(sexp, debug).source
|
12
|
+
end
|
13
|
+
|
14
|
+
def initialize(sexp, debug=false)
|
15
|
+
@sexp = sexp
|
16
|
+
@source = ''
|
17
|
+
@debug = debug
|
18
|
+
@word_level = 0
|
19
|
+
end
|
20
|
+
|
21
|
+
def source
|
22
|
+
resource(@sexp)
|
23
|
+
@source
|
24
|
+
end
|
25
|
+
|
26
|
+
def resource(sexp)
|
27
|
+
return unless sexp
|
28
|
+
handler = Handlers[sexp.first]
|
29
|
+
raise NoHandlerError.new(sexp.first) unless handler
|
30
|
+
if @debug
|
31
|
+
puts "----------------------------------------------------------"
|
32
|
+
pp sexp
|
33
|
+
end
|
34
|
+
handler.call(self, sexp)
|
35
|
+
end
|
36
|
+
|
37
|
+
def handle_block(sexp)
|
38
|
+
resource(sexp[1]) # Arguments
|
39
|
+
if ! void?(sexp[2])
|
40
|
+
emit(" ")
|
41
|
+
resource(sexp[2]) # Statements
|
42
|
+
end
|
43
|
+
emit(" ")
|
44
|
+
end
|
45
|
+
|
46
|
+
def opt_parens(sexp)
|
47
|
+
emit(" ") unless sexp.first == :arg_paren || sexp.first == :paren
|
48
|
+
resource(sexp)
|
49
|
+
end
|
50
|
+
|
51
|
+
def emit(string)
|
52
|
+
puts "EMITTING '#{string}'" if @debug
|
53
|
+
@source << string
|
54
|
+
end
|
55
|
+
|
56
|
+
def nyi(sexp)
|
57
|
+
raise "Handler for #{sexp.first} not implemented (#{sexp.inspect})"
|
58
|
+
end
|
59
|
+
|
60
|
+
def emit_separator(sep, first)
|
61
|
+
emit(sep) unless first
|
62
|
+
false
|
63
|
+
end
|
64
|
+
|
65
|
+
def params(normal_args, default_args, rest_args, unknown, block_arg)
|
66
|
+
first = true
|
67
|
+
if normal_args
|
68
|
+
normal_args.each do |sx|
|
69
|
+
first = emit_separator(", ", first)
|
70
|
+
resource(sx)
|
71
|
+
end
|
72
|
+
end
|
73
|
+
if default_args
|
74
|
+
default_args.each do |sx|
|
75
|
+
first = emit_separator(", ", first)
|
76
|
+
resource(sx[0])
|
77
|
+
emit("=")
|
78
|
+
resource(sx[1])
|
79
|
+
end
|
80
|
+
end
|
81
|
+
if rest_args
|
82
|
+
first = emit_separator(", ", first)
|
83
|
+
resource(rest_args)
|
84
|
+
end
|
85
|
+
if block_arg
|
86
|
+
first = emit_separator(", ", first)
|
87
|
+
resource(block_arg)
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
def words(marker, sexp)
|
92
|
+
emit("%#{marker}{") if @word_level == 0
|
93
|
+
@word_level += 1
|
94
|
+
if sexp[1] != [:qwords_new] && sexp[1] != [:words_new]
|
95
|
+
resource(sexp[1])
|
96
|
+
emit(" ")
|
97
|
+
end
|
98
|
+
resource(sexp[2])
|
99
|
+
@word_level -= 1
|
100
|
+
emit("}") if @word_level == 0
|
101
|
+
end
|
102
|
+
|
103
|
+
VOID_STATEMENT = [:stmts_add, [:stmts_new], [:void_stmt]]
|
104
|
+
VOID_BODY = [:body_stmt, VOID_STATEMENT, nil, nil, nil]
|
105
|
+
|
106
|
+
def void?(sexp)
|
107
|
+
sexp.nil? ||
|
108
|
+
sexp == VOID_STATEMENT ||
|
109
|
+
sexp == VOID_BODY
|
110
|
+
end
|
111
|
+
|
112
|
+
NYI = lambda { |src, sexp| src.nyi(sexp) }
|
113
|
+
DBG = lambda { |src, sexp| pp(sexp) }
|
114
|
+
NOOP = lambda { |src, sexp| }
|
115
|
+
SPACE = lambda { |src, sexp| src.emit(" ") }
|
116
|
+
PASS1 = lambda { |src, sexp| src.resource(sexp[1]) }
|
117
|
+
PASS2 = lambda { |src, sexp| src.resource(sexp[2]) }
|
118
|
+
EMIT1 = lambda { |src, sexp| src.emit(sexp[1]) }
|
119
|
+
|
120
|
+
Handlers = {
|
121
|
+
# parser keywords
|
122
|
+
|
123
|
+
:BEGIN => lambda { |src, sexp|
|
124
|
+
src.emit("BEGIN {")
|
125
|
+
unless src.void?(sexp[1])
|
126
|
+
src.emit(" ")
|
127
|
+
src.resource(sexp[1])
|
128
|
+
end
|
129
|
+
src.emit(" }")
|
130
|
+
},
|
131
|
+
:END => lambda { |src, sexp|
|
132
|
+
src.emit("END {")
|
133
|
+
unless src.void?(sexp[1])
|
134
|
+
src.emit(" ")
|
135
|
+
src.resource(sexp[1])
|
136
|
+
end
|
137
|
+
src.emit(" }")
|
138
|
+
},
|
139
|
+
:alias => lambda { |src, sexp|
|
140
|
+
src.emit("alias ")
|
141
|
+
src.resource(sexp[1])
|
142
|
+
src.emit(" ")
|
143
|
+
src.resource(sexp[2])
|
144
|
+
},
|
145
|
+
:alias_error => NYI,
|
146
|
+
:aref => lambda { |src, sexp|
|
147
|
+
src.resource(sexp[1])
|
148
|
+
src.emit("[")
|
149
|
+
src.resource(sexp[2])
|
150
|
+
src.emit("]")
|
151
|
+
},
|
152
|
+
:aref_field => lambda { |src, sexp|
|
153
|
+
src.resource(sexp[1])
|
154
|
+
src.emit("[")
|
155
|
+
src.resource(sexp[2])
|
156
|
+
src.emit("]")
|
157
|
+
},
|
158
|
+
:arg_ambiguous => NYI,
|
159
|
+
:arg_paren => lambda { |src, sexp|
|
160
|
+
src.emit("(")
|
161
|
+
src.resource(sexp[1]) if sexp[1]
|
162
|
+
src.emit(")")
|
163
|
+
},
|
164
|
+
:args_add => lambda { |src, sexp|
|
165
|
+
src.resource(sexp[1])
|
166
|
+
if sexp[1].first != :args_new
|
167
|
+
src.emit(", ")
|
168
|
+
end
|
169
|
+
src.resource(sexp[2])
|
170
|
+
},
|
171
|
+
:args_add_block => lambda { |src, sexp|
|
172
|
+
src.resource(sexp[1])
|
173
|
+
if sexp[2]
|
174
|
+
if sexp[1].first != :args_new
|
175
|
+
src.emit(", ")
|
176
|
+
end
|
177
|
+
if sexp[2]
|
178
|
+
src.emit("&")
|
179
|
+
src.resource(sexp[2])
|
180
|
+
end
|
181
|
+
end
|
182
|
+
},
|
183
|
+
:args_add_star => lambda { |src, sexp|
|
184
|
+
src.resource(sexp[1])
|
185
|
+
if sexp[1].first != :args_new
|
186
|
+
src.emit(", ")
|
187
|
+
end
|
188
|
+
src.emit("*")
|
189
|
+
src.resource(sexp[2])
|
190
|
+
},
|
191
|
+
:args_new => NOOP,
|
192
|
+
:args_prepend => NYI,
|
193
|
+
:array => lambda { |src, sexp|
|
194
|
+
src.emit("[")
|
195
|
+
src.resource(sexp[1])
|
196
|
+
src.emit("]")
|
197
|
+
},
|
198
|
+
:assign => lambda { |src, sexp|
|
199
|
+
src.resource(sexp[1])
|
200
|
+
src.emit(" = ")
|
201
|
+
src.resource(sexp[2])
|
202
|
+
},
|
203
|
+
:assign_error => NYI,
|
204
|
+
:assoc_new => lambda { |src, sexp|
|
205
|
+
src.resource(sexp[1])
|
206
|
+
src.emit(" => ")
|
207
|
+
src.resource(sexp[2])
|
208
|
+
},
|
209
|
+
:assoclist_from_args => lambda { |src, sexp|
|
210
|
+
first = true
|
211
|
+
sexp[1].each do |sx|
|
212
|
+
src.emit(", ") unless first
|
213
|
+
first = false
|
214
|
+
src.resource(sx)
|
215
|
+
end
|
216
|
+
},
|
217
|
+
:bare_assoc_hash => lambda { |src, sexp|
|
218
|
+
first = true
|
219
|
+
sexp[1].each do |sx|
|
220
|
+
src.emit(", ") unless first
|
221
|
+
first = false
|
222
|
+
src.resource(sx)
|
223
|
+
end
|
224
|
+
},
|
225
|
+
:begin => lambda { |src, sexp|
|
226
|
+
src.emit("begin")
|
227
|
+
src.resource(sexp[1])
|
228
|
+
src.emit("end")
|
229
|
+
},
|
230
|
+
:binary => lambda { |src, sexp|
|
231
|
+
src.resource(sexp[1])
|
232
|
+
src.emit(" #{sexp[2]} ")
|
233
|
+
src.resource(sexp[3])
|
234
|
+
},
|
235
|
+
:block_var => lambda { |src, sexp|
|
236
|
+
src.emit(" |")
|
237
|
+
src.resource(sexp[1])
|
238
|
+
src.emit("|")
|
239
|
+
},
|
240
|
+
:block_var_add_block => NYI,
|
241
|
+
:block_var_add_star => NYI,
|
242
|
+
:blockarg => lambda { |src, sexp|
|
243
|
+
src.emit("&")
|
244
|
+
src.resource(sexp[1])
|
245
|
+
},
|
246
|
+
:body_stmt => lambda { |src, sexp|
|
247
|
+
src.resource(sexp[1]) # Main Body
|
248
|
+
src.emit("; ")
|
249
|
+
src.resource(sexp[2]) # Rescue
|
250
|
+
src.resource(sexp[4]) # Ensure
|
251
|
+
},
|
252
|
+
:brace_block => lambda { |src, sexp|
|
253
|
+
src.emit(" {")
|
254
|
+
src.handle_block(sexp)
|
255
|
+
src.emit("}")
|
256
|
+
},
|
257
|
+
:break => lambda { |src, sexp|
|
258
|
+
src.emit("break")
|
259
|
+
src.emit(" ") unless sexp[1] == [:args_new]
|
260
|
+
src.resource(sexp[1])
|
261
|
+
},
|
262
|
+
:call => lambda { |src, sexp|
|
263
|
+
src.resource(sexp[1])
|
264
|
+
src.emit(sexp[2])
|
265
|
+
src.resource(sexp[3])
|
266
|
+
},
|
267
|
+
:case => lambda { |src, sexp|
|
268
|
+
src.emit("case ")
|
269
|
+
src.resource(sexp[1])
|
270
|
+
src.emit(" ")
|
271
|
+
src.resource(sexp[2])
|
272
|
+
src.emit(" end")
|
273
|
+
},
|
274
|
+
:class => lambda { |src, sexp|
|
275
|
+
src.emit("class ")
|
276
|
+
src.resource(sexp[1])
|
277
|
+
if ! src.void?(sexp[2])
|
278
|
+
src.emit " < "
|
279
|
+
src.resource(sexp[2])
|
280
|
+
end
|
281
|
+
src.emit("; ")
|
282
|
+
src.resource(sexp[3]) unless src.void?(sexp[3])
|
283
|
+
src.emit("end")
|
284
|
+
},
|
285
|
+
:class_name_error => NYI,
|
286
|
+
:command => lambda { |src, sexp|
|
287
|
+
src.resource(sexp[1])
|
288
|
+
src.emit(" ")
|
289
|
+
src.resource(sexp[2])
|
290
|
+
},
|
291
|
+
:command_call => NYI,
|
292
|
+
:const_path_field => lambda { |src, sexp|
|
293
|
+
src.resource(sexp[1])
|
294
|
+
src.emit("::")
|
295
|
+
src.resource(sexp[2])
|
296
|
+
},
|
297
|
+
:const_path_ref => lambda { |src, sexp|
|
298
|
+
src.resource(sexp[1])
|
299
|
+
src.emit("::")
|
300
|
+
src.resource(sexp[2])
|
301
|
+
},
|
302
|
+
:const_ref => PASS1,
|
303
|
+
:def => lambda { |src, sexp|
|
304
|
+
src.emit("def ")
|
305
|
+
src.resource(sexp[1])
|
306
|
+
src.opt_parens(sexp[2])
|
307
|
+
src.resource(sexp[3])
|
308
|
+
src.emit("end")
|
309
|
+
},
|
310
|
+
:defined => lambda { |src, sexp|
|
311
|
+
src.emit("defined?(")
|
312
|
+
src.resource(sexp[1])
|
313
|
+
src.emit(")")
|
314
|
+
},
|
315
|
+
:defs => NYI,
|
316
|
+
:do_block => lambda { |src, sexp|
|
317
|
+
src.emit(" do")
|
318
|
+
src.handle_block(sexp)
|
319
|
+
src.emit("end")
|
320
|
+
},
|
321
|
+
:dot2 => lambda { |src, sexp|
|
322
|
+
src.resource(sexp[1])
|
323
|
+
src.emit("..")
|
324
|
+
src.resource(sexp[2])
|
325
|
+
},
|
326
|
+
:dot3 => lambda { |src, sexp|
|
327
|
+
src.resource(sexp[1])
|
328
|
+
src.emit("...")
|
329
|
+
src.resource(sexp[2])
|
330
|
+
},
|
331
|
+
:dyna_symbol => lambda { |src, sexp|
|
332
|
+
src.emit(':"')
|
333
|
+
src.resource(sexp[1])
|
334
|
+
src.emit('"')
|
335
|
+
},
|
336
|
+
:else => lambda { |src, sexp|
|
337
|
+
src.emit(" else ")
|
338
|
+
src.resource(sexp[1])
|
339
|
+
},
|
340
|
+
:elsif => lambda { |src, sexp|
|
341
|
+
src.emit(" elsif ")
|
342
|
+
src.resource(sexp[1])
|
343
|
+
src.emit(" then ")
|
344
|
+
src.resource(sexp[2])
|
345
|
+
src.resource(sexp[3])
|
346
|
+
},
|
347
|
+
:ensure => lambda { |src, sexp|
|
348
|
+
src.emit("ensure ")
|
349
|
+
if sexp[1]
|
350
|
+
src.resource(sexp[1])
|
351
|
+
src.emit("; ") unless src.void?(sexp[1])
|
352
|
+
end
|
353
|
+
},
|
354
|
+
:excessed_comma => NYI,
|
355
|
+
:fcall => PASS1,
|
356
|
+
:field => lambda { |src, sexp|
|
357
|
+
src.resource(sexp[1])
|
358
|
+
src.emit(sexp[2])
|
359
|
+
src.resource(sexp[3])
|
360
|
+
},
|
361
|
+
:for => lambda { |src, sexp|
|
362
|
+
src.emit("for ")
|
363
|
+
src.resource(sexp[1])
|
364
|
+
src.emit(" in ")
|
365
|
+
src.resource(sexp[2])
|
366
|
+
src.emit(" do ")
|
367
|
+
unless src.void?(sexp[3])
|
368
|
+
src.resource(sexp[3])
|
369
|
+
src.emit(" ")
|
370
|
+
end
|
371
|
+
src.emit("end")
|
372
|
+
},
|
373
|
+
:hash => lambda { |src, sexp|
|
374
|
+
src.emit("{")
|
375
|
+
src.resource(sexp[1])
|
376
|
+
src.emit("}")
|
377
|
+
},
|
378
|
+
:if => lambda { |src, sexp|
|
379
|
+
src.emit("if ")
|
380
|
+
src.resource(sexp[1])
|
381
|
+
src.emit(" then ")
|
382
|
+
src.resource(sexp[2])
|
383
|
+
src.resource(sexp[3])
|
384
|
+
src.emit(" end")
|
385
|
+
},
|
386
|
+
:if_mod => lambda { |src, sexp|
|
387
|
+
src.resource(sexp[2])
|
388
|
+
src.emit(" if ")
|
389
|
+
src.resource(sexp[1])
|
390
|
+
},
|
391
|
+
:ifop => lambda { |src, sexp|
|
392
|
+
src.resource(sexp[1])
|
393
|
+
src.emit(" ? ")
|
394
|
+
src.resource(sexp[2])
|
395
|
+
src.emit(" : ")
|
396
|
+
src.resource(sexp[3])
|
397
|
+
},
|
398
|
+
:lambda => lambda { |src, sexp|
|
399
|
+
src.emit("->")
|
400
|
+
src.resource(sexp[1])
|
401
|
+
src.emit(" {")
|
402
|
+
if ! src.void?(sexp[2])
|
403
|
+
src.emit(" ")
|
404
|
+
src.resource(sexp[2])
|
405
|
+
end
|
406
|
+
src.emit(" ")
|
407
|
+
src.emit("}")
|
408
|
+
},
|
409
|
+
:magic_comment => NYI,
|
410
|
+
:massign => lambda { |src, sexp|
|
411
|
+
src.resource(sexp[1])
|
412
|
+
src.emit(" = ")
|
413
|
+
src.resource(sexp[2])
|
414
|
+
},
|
415
|
+
:method_add_arg => lambda { |src, sexp|
|
416
|
+
src.resource(sexp[1])
|
417
|
+
src.resource(sexp[2])
|
418
|
+
},
|
419
|
+
:method_add_block => lambda { |src, sexp|
|
420
|
+
src.resource(sexp[1])
|
421
|
+
src.resource(sexp[2])
|
422
|
+
},
|
423
|
+
:mlhs_add => lambda { |src, sexp|
|
424
|
+
src.resource(sexp[1])
|
425
|
+
src.emit(", ") unless sexp[1] == [:mlhs_new]
|
426
|
+
src.resource(sexp[2])
|
427
|
+
},
|
428
|
+
:mlhs_add_star => lambda { |src, sexp|
|
429
|
+
src.resource(sexp[1])
|
430
|
+
src.emit(", ") unless sexp[1] == [:mlhs_new]
|
431
|
+
src.emit("*")
|
432
|
+
src.resource(sexp[2])
|
433
|
+
},
|
434
|
+
:mlhs_new => NOOP,
|
435
|
+
:mlhs_paren => lambda { |src, sexp|
|
436
|
+
src.emit("(")
|
437
|
+
src.resource(sexp[1])
|
438
|
+
src.emit(")")
|
439
|
+
},
|
440
|
+
:module => lambda { |src, sexp|
|
441
|
+
src.emit("module ")
|
442
|
+
src.resource(sexp[1])
|
443
|
+
if src.void?(sexp[2])
|
444
|
+
src.emit("; ")
|
445
|
+
else
|
446
|
+
src.resource(sexp[2])
|
447
|
+
end
|
448
|
+
src.emit("end")
|
449
|
+
},
|
450
|
+
:mrhs_add => lambda { |src, sexp|
|
451
|
+
src.resource(sexp[1])
|
452
|
+
src.emit(", ")
|
453
|
+
src.resource(sexp[2])
|
454
|
+
},
|
455
|
+
:mrhs_add_star => lambda { |src, sexp|
|
456
|
+
src.resource(sexp[1])
|
457
|
+
src.emit(", ")
|
458
|
+
src.emit("*")
|
459
|
+
src.resource(sexp[2])
|
460
|
+
},
|
461
|
+
:mrhs_new => NYI,
|
462
|
+
:mrhs_new_from_args => PASS1,
|
463
|
+
:next => lambda { |src, sexp|
|
464
|
+
src.emit("next")
|
465
|
+
},
|
466
|
+
:opassign => lambda { |src, sexp|
|
467
|
+
src.resource(sexp[1])
|
468
|
+
src.emit(" ")
|
469
|
+
src.resource(sexp[2])
|
470
|
+
src.emit(" ")
|
471
|
+
src.resource(sexp[3])
|
472
|
+
},
|
473
|
+
:param_error => NYI,
|
474
|
+
:params => lambda { |src, sexp|
|
475
|
+
src.params(sexp[1], sexp[2], sexp[3], sexp[4], sexp[5])
|
476
|
+
},
|
477
|
+
:paren => lambda { |src, sexp|
|
478
|
+
src.emit("(")
|
479
|
+
src.resource(sexp[1])
|
480
|
+
src.emit(")")
|
481
|
+
},
|
482
|
+
:parse_error => NYI,
|
483
|
+
:program => PASS1,
|
484
|
+
:qwords_add => lambda { |src, sexp|
|
485
|
+
src.words("w", sexp)
|
486
|
+
},
|
487
|
+
:qwords_new => NOOP,
|
488
|
+
:redo => lambda { |src, sexp|
|
489
|
+
src.emit("redo")
|
490
|
+
},
|
491
|
+
:regexp_literal => lambda { |src, sexp|
|
492
|
+
src.emit("/")
|
493
|
+
src.resource(sexp[1])
|
494
|
+
src.emit("/")
|
495
|
+
},
|
496
|
+
:rescue => lambda { |src, sexp|
|
497
|
+
src.emit("rescue")
|
498
|
+
if sexp[1] # Exception list
|
499
|
+
src.emit(" ")
|
500
|
+
if sexp[1].first.kind_of?(Symbol)
|
501
|
+
src.resource(sexp[1])
|
502
|
+
else
|
503
|
+
src.resource(sexp[1].first)
|
504
|
+
end
|
505
|
+
src.emit(" => ")
|
506
|
+
src.resource(sexp[2])
|
507
|
+
end
|
508
|
+
src.emit(";")
|
509
|
+
if sexp[3] # Rescue Code
|
510
|
+
if src.void?(sexp[3])
|
511
|
+
src.emit(" ")
|
512
|
+
else
|
513
|
+
src.emit(" ")
|
514
|
+
src.resource(sexp[3])
|
515
|
+
src.emit("; ")
|
516
|
+
end
|
517
|
+
end
|
518
|
+
},
|
519
|
+
:rescue_mod => lambda { |src, sexp|
|
520
|
+
src.resource(sexp[2])
|
521
|
+
src.emit(" rescue ")
|
522
|
+
src.resource(sexp[1])
|
523
|
+
},
|
524
|
+
:rest_param => lambda { |src, sexp|
|
525
|
+
src.emit("*")
|
526
|
+
src.resource(sexp[1])
|
527
|
+
},
|
528
|
+
:retry => lambda { |src, sexp|
|
529
|
+
src.emit("retry")
|
530
|
+
},
|
531
|
+
:return => lambda { |src, sexp|
|
532
|
+
src.emit("return")
|
533
|
+
src.opt_parens(sexp[1])
|
534
|
+
},
|
535
|
+
:return0 => lambda { |src, sexp|
|
536
|
+
src.emit("return")
|
537
|
+
},
|
538
|
+
:sclass => NYI,
|
539
|
+
:stmts_add => lambda { |src, sexp|
|
540
|
+
if sexp[1] != [:stmts_new]
|
541
|
+
src.resource(sexp[1])
|
542
|
+
src.emit("; ")
|
543
|
+
end
|
544
|
+
src.resource(sexp[2])
|
545
|
+
},
|
546
|
+
:stmts_new => NOOP,
|
547
|
+
:string_add => lambda { |src, sexp|
|
548
|
+
src.resource(sexp[1])
|
549
|
+
src.resource(sexp[2])
|
550
|
+
},
|
551
|
+
:string_concat => lambda { |src, sexp|
|
552
|
+
src.resource(sexp[1])
|
553
|
+
src.emit(" ")
|
554
|
+
src.resource(sexp[2])
|
555
|
+
},
|
556
|
+
:string_content => NOOP,
|
557
|
+
:string_dvar => NYI,
|
558
|
+
:string_embexpr => lambda { |src, sexp|
|
559
|
+
src.emit('#{')
|
560
|
+
src.resource(sexp[1])
|
561
|
+
src.emit('}')
|
562
|
+
},
|
563
|
+
:string_literal => lambda { |src, sexp|
|
564
|
+
src.emit('"')
|
565
|
+
src.resource(sexp[1])
|
566
|
+
src.emit('"')
|
567
|
+
},
|
568
|
+
:super => lambda { |src, sexp|
|
569
|
+
src.emit("super")
|
570
|
+
src.opt_parens(sexp[1])
|
571
|
+
},
|
572
|
+
:symbol => lambda { |src, sexp|
|
573
|
+
src.emit(":")
|
574
|
+
src.resource(sexp[1])
|
575
|
+
},
|
576
|
+
:symbol_literal => PASS1,
|
577
|
+
:top_const_field => NYI,
|
578
|
+
:top_const_ref => NYI,
|
579
|
+
:unary => lambda { |src, sexp|
|
580
|
+
src.emit(sexp[1].to_s[0,1])
|
581
|
+
src.resource(sexp[2])
|
582
|
+
},
|
583
|
+
:undef => lambda { |src, sexp|
|
584
|
+
src.emit("undef ")
|
585
|
+
src.resource(sexp[1].first)
|
586
|
+
},
|
587
|
+
:unless => lambda { |src, sexp|
|
588
|
+
src.emit("unless ")
|
589
|
+
src.resource(sexp[1])
|
590
|
+
src.emit(" then ")
|
591
|
+
src.resource(sexp[2])
|
592
|
+
src.resource(sexp[3])
|
593
|
+
src.emit(" end")
|
594
|
+
},
|
595
|
+
:unless_mod => lambda { |src, sexp|
|
596
|
+
src.resource(sexp[2])
|
597
|
+
src.emit(" unless ")
|
598
|
+
src.resource(sexp[1])
|
599
|
+
},
|
600
|
+
:until => lambda { |src, sexp|
|
601
|
+
src.emit("until ")
|
602
|
+
src.resource(sexp[1])
|
603
|
+
src.emit(" do ")
|
604
|
+
src.resource(sexp[2])
|
605
|
+
src.emit(" end")
|
606
|
+
},
|
607
|
+
:until_mod => lambda { |src, sexp|
|
608
|
+
src.resource(sexp[2])
|
609
|
+
src.emit(" until ")
|
610
|
+
src.resource(sexp[1])
|
611
|
+
},
|
612
|
+
:var_alias => NYI,
|
613
|
+
:var_field => PASS1,
|
614
|
+
:var_ref => PASS1,
|
615
|
+
:void_stmt => NOOP,
|
616
|
+
:when => lambda { |src, sexp|
|
617
|
+
src.emit("when ")
|
618
|
+
src.resource(sexp[1])
|
619
|
+
src.emit("; ")
|
620
|
+
src.resource(sexp[2])
|
621
|
+
if sexp[3] && sexp[3].first == :when
|
622
|
+
src.emit(" ")
|
623
|
+
end
|
624
|
+
src.resource(sexp[3])
|
625
|
+
},
|
626
|
+
:while => lambda { |src, sexp|
|
627
|
+
src.emit("while ")
|
628
|
+
src.resource(sexp[1])
|
629
|
+
src.emit(" do ")
|
630
|
+
src.resource(sexp[2])
|
631
|
+
src.emit(" end")
|
632
|
+
},
|
633
|
+
:while_mod => lambda { |src, sexp|
|
634
|
+
src.resource(sexp[2])
|
635
|
+
src.emit(" while ")
|
636
|
+
src.resource(sexp[1])
|
637
|
+
},
|
638
|
+
:word_add => PASS2,
|
639
|
+
:word_new => NOOP,
|
640
|
+
:words_add => lambda { |src, sexp|
|
641
|
+
src.words("W", sexp)
|
642
|
+
},
|
643
|
+
:words_new => NOOP,
|
644
|
+
:xstring_add => lambda { |src, sexp|
|
645
|
+
src.resource(sexp[1])
|
646
|
+
src.resource(sexp[2])
|
647
|
+
},
|
648
|
+
:xstring_literal => lambda { |src, sexp|
|
649
|
+
src.emit('"')
|
650
|
+
src.resource(sexp[1])
|
651
|
+
src.emit('"')
|
652
|
+
},
|
653
|
+
:xstring_new => NOOP,
|
654
|
+
:yield => lambda { |src, sexp|
|
655
|
+
src.emit("yield")
|
656
|
+
src.opt_parens(sexp[1])
|
657
|
+
},
|
658
|
+
:yield0 => lambda { |src, sexp|
|
659
|
+
src.emit("yield")
|
660
|
+
},
|
661
|
+
:zsuper => lambda { |src, sexp|
|
662
|
+
src.emit("super")
|
663
|
+
},
|
664
|
+
|
665
|
+
# Scanner keywords
|
666
|
+
|
667
|
+
:@CHAR => NYI,
|
668
|
+
:@__end__ => NYI,
|
669
|
+
:@backref => NYI,
|
670
|
+
:@backtick => NYI,
|
671
|
+
:@comma => NYI,
|
672
|
+
:@comment => NYI,
|
673
|
+
:@const => EMIT1,
|
674
|
+
:@cvar => EMIT1,
|
675
|
+
:@embdoc => NYI,
|
676
|
+
:@embdoc_beg => NYI,
|
677
|
+
:@embdoc_end => NYI,
|
678
|
+
:@embexpr_beg => NYI,
|
679
|
+
:@embexpr_end => NYI,
|
680
|
+
:@embvar => NYI,
|
681
|
+
:@float => EMIT1,
|
682
|
+
:@gvar => EMIT1,
|
683
|
+
:@heredoc_beg => NYI,
|
684
|
+
:@heredoc_end => NYI,
|
685
|
+
:@ident => EMIT1,
|
686
|
+
:@ignored_nl => NYI,
|
687
|
+
:@int => EMIT1,
|
688
|
+
:@ivar => EMIT1,
|
689
|
+
:@kw => EMIT1,
|
690
|
+
:@label => NYI,
|
691
|
+
:@lbrace => NYI,
|
692
|
+
:@lbracket => NYI,
|
693
|
+
:@lparen => NYI,
|
694
|
+
:@nl => NYI,
|
695
|
+
:@op => EMIT1,
|
696
|
+
:@period => NYI,
|
697
|
+
:@qwords_beg => NYI,
|
698
|
+
:@rbrace => NYI,
|
699
|
+
:@rbracket => NYI,
|
700
|
+
:@regexp_beg => NYI,
|
701
|
+
:@regexp_end => NYI,
|
702
|
+
:@rparen => NYI,
|
703
|
+
:@semicolon => NYI,
|
704
|
+
:@sp => NYI,
|
705
|
+
:@symbeg => NYI,
|
706
|
+
:@tlambda => NYI,
|
707
|
+
:@tlambeg => NYI,
|
708
|
+
:@tstring_beg => NYI,
|
709
|
+
:@tstring_content => EMIT1,
|
710
|
+
:@tstring_end => NYI,
|
711
|
+
:@words_beg => NYI,
|
712
|
+
:@words_sep => NYI,
|
713
|
+
}
|
714
|
+
end
|
715
|
+
|
@@ -0,0 +1,521 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'test/unit'
|
4
|
+
require 'ripper'
|
5
|
+
require 'sorcerer'
|
6
|
+
|
7
|
+
class SourcerTest < Test::Unit::TestCase
|
8
|
+
def source(string, debug=false)
|
9
|
+
if debug
|
10
|
+
puts
|
11
|
+
puts "************************************************************"
|
12
|
+
end
|
13
|
+
sexp = Ripper::SexpBuilder.new(string).parse
|
14
|
+
Sorcerer.source(sexp, debug)
|
15
|
+
end
|
16
|
+
|
17
|
+
def test_can_source_variables
|
18
|
+
assert_resource "a"
|
19
|
+
assert_resource "b"
|
20
|
+
end
|
21
|
+
|
22
|
+
def test_can_source_constants
|
23
|
+
assert_resource "A"
|
24
|
+
assert_resource "Mod::X"
|
25
|
+
assert_resource "Mod::NS::Y"
|
26
|
+
end
|
27
|
+
|
28
|
+
def test_can_source_constant_definition
|
29
|
+
assert_resource "X = 1"
|
30
|
+
assert_resource "X::Y = 1"
|
31
|
+
assert_resource "X::Y::Z = 1"
|
32
|
+
end
|
33
|
+
|
34
|
+
def test_can_source_instance_variables
|
35
|
+
assert_resource "@iv"
|
36
|
+
end
|
37
|
+
|
38
|
+
def test_can_source_class_instance_variables
|
39
|
+
assert_resource "@@iv"
|
40
|
+
end
|
41
|
+
|
42
|
+
def test_can_source_globals
|
43
|
+
assert_resource "$g"
|
44
|
+
end
|
45
|
+
|
46
|
+
def test_can_source_method_call_without_args
|
47
|
+
assert_resource "obj.meth"
|
48
|
+
assert_resource "obj.meth()"
|
49
|
+
end
|
50
|
+
|
51
|
+
def test_can_source_method_call_with_args
|
52
|
+
assert_resource "obj.meth(a)"
|
53
|
+
assert_resource "obj.meth(a, b)"
|
54
|
+
assert_resource "obj.meth(a, b, c)"
|
55
|
+
end
|
56
|
+
|
57
|
+
def test_can_source_method_call_with_star_args
|
58
|
+
assert_resource "obj.meth(*args)"
|
59
|
+
assert_resource "obj.meth(a, *args)"
|
60
|
+
end
|
61
|
+
|
62
|
+
def test_can_source_method_call_with_block_args
|
63
|
+
assert_resource "obj.meth(&code)"
|
64
|
+
assert_resource "obj.meth(a, &code)"
|
65
|
+
assert_resource "obj.meth(a, *args, &code)"
|
66
|
+
end
|
67
|
+
|
68
|
+
def test_can_source_method_without_explicit_target
|
69
|
+
assert_resource "meth(a)"
|
70
|
+
assert_resource "meth(a, b)"
|
71
|
+
assert_resource "meth(a, b, c)"
|
72
|
+
assert_resource "meth(*args)"
|
73
|
+
assert_resource "meth(a, *args)"
|
74
|
+
assert_resource "meth(&code)"
|
75
|
+
assert_resource "meth(a, &code)"
|
76
|
+
assert_resource "meth(a, *args, &code)"
|
77
|
+
end
|
78
|
+
|
79
|
+
def test_can_source_method_without_explicit_poetry_mode
|
80
|
+
assert_resource "meth a"
|
81
|
+
assert_resource "meth a, b"
|
82
|
+
assert_resource "meth a, b, c"
|
83
|
+
assert_resource "meth *args"
|
84
|
+
assert_resource "meth a, *args"
|
85
|
+
assert_resource "meth &code"
|
86
|
+
assert_resource "meth a, &code"
|
87
|
+
assert_resource "meth a, *args, &code"
|
88
|
+
assert_resource "meth a, *args do |x| x.y end"
|
89
|
+
end
|
90
|
+
|
91
|
+
def test_can_source_method_with_bare_assoc
|
92
|
+
assert_resource "meth(:x => 1)"
|
93
|
+
assert_resource "meth(:x => 1, :y => 2)"
|
94
|
+
assert_resource "meth(a, :x => 1)"
|
95
|
+
assert_resource "meth(a, :x => 1, :y => 2)"
|
96
|
+
end
|
97
|
+
|
98
|
+
def test_can_source_method_with_do_block
|
99
|
+
assert_resource "meth do end"
|
100
|
+
assert_resource "meth do |a| end"
|
101
|
+
assert_resource "meth(x, y, *rest, &code) do |a, b=1, c=x, *args, &block| one; two; three end"
|
102
|
+
end
|
103
|
+
|
104
|
+
def test_can_source_method_with_block
|
105
|
+
assert_resource "meth { }"
|
106
|
+
assert_resource "meth { |a| }"
|
107
|
+
assert_resource "meth { |a, b| }"
|
108
|
+
assert_resource "meth { |*args| }"
|
109
|
+
assert_resource "meth { |a, *args| }"
|
110
|
+
assert_resource "meth { |&block| }"
|
111
|
+
assert_resource "meth { |*args, &block| }"
|
112
|
+
assert_resource "meth { |a, b, *args, &block| }"
|
113
|
+
assert_resource "meth { |a, b=1, *args, &block| }"
|
114
|
+
assert_resource "meth { |a, b=1, c=x, *args, &block| }"
|
115
|
+
end
|
116
|
+
|
117
|
+
def test_can_source_method_with_block_contents
|
118
|
+
assert_resource "meth { |a| a.x }"
|
119
|
+
assert_resource "meth { |a| a.x; b.z }"
|
120
|
+
end
|
121
|
+
|
122
|
+
def test_can_source_method_with_complex_args_and_block
|
123
|
+
assert_resource "meth(x, y, *rest, &code) { |a, b=1, c=x, *args, &block| one; two; three }"
|
124
|
+
end
|
125
|
+
|
126
|
+
def test_can_source_stabby_procs
|
127
|
+
assert_resource "->() { }"
|
128
|
+
assert_resource "->(a) { }"
|
129
|
+
assert_resource "->(a, b) { }"
|
130
|
+
assert_resource "->(a, *args) { }"
|
131
|
+
assert_resource "->(a, *args, &block) { }"
|
132
|
+
assert_resource "->(a) { b }"
|
133
|
+
end
|
134
|
+
|
135
|
+
def test_can_source_numbers
|
136
|
+
assert_resource "1"
|
137
|
+
assert_resource "3.14"
|
138
|
+
end
|
139
|
+
|
140
|
+
def test_can_source_strings
|
141
|
+
assert_resource '"HI"'
|
142
|
+
assert_equal '"HI"', source("'HI'")
|
143
|
+
end
|
144
|
+
|
145
|
+
def test_can_source_strings_with_escape_chars
|
146
|
+
assert_resource '"\n"'
|
147
|
+
assert_resource '"a\nb"'
|
148
|
+
end
|
149
|
+
|
150
|
+
def test_can_source_interpolated_strings
|
151
|
+
assert_resource '"my name is #{name}"'
|
152
|
+
assert_resource '"my name is #{x.a("B")}"'
|
153
|
+
end
|
154
|
+
|
155
|
+
def test_can_source_string_concat
|
156
|
+
assert_resource '"a" "b"'
|
157
|
+
assert_resource '"a" "b" "c"'
|
158
|
+
assert_resource '"a" "b" "c" "d"'
|
159
|
+
end
|
160
|
+
|
161
|
+
def test_can_source_qwords
|
162
|
+
assert_resource '%w{a}'
|
163
|
+
assert_resource '%w{a b}'
|
164
|
+
assert_resource '%w{a b c}'
|
165
|
+
assert_resource '%w{Now is the time for all good men}'
|
166
|
+
end
|
167
|
+
|
168
|
+
def test_can_source_words
|
169
|
+
assert_resource '%W{a}'
|
170
|
+
assert_resource '%W{a b}'
|
171
|
+
assert_resource '%W{a b c}'
|
172
|
+
assert_resource '%W{Now is the time for all good men}'
|
173
|
+
end
|
174
|
+
|
175
|
+
def test_can_source_many_words
|
176
|
+
assert_resource '[%w{a b}, %w{c d}]'
|
177
|
+
assert_resource '[%W{a b}, %W{c d}]'
|
178
|
+
end
|
179
|
+
|
180
|
+
def test_can_source_symbols
|
181
|
+
assert_resource ":sym"
|
182
|
+
end
|
183
|
+
|
184
|
+
def test_can_source_fancy_symbol_literals
|
185
|
+
assert_resource ':"hello, world"'
|
186
|
+
end
|
187
|
+
|
188
|
+
def test_can_source_regular_expressions
|
189
|
+
assert_resource "/a/"
|
190
|
+
assert_resource "/^a$/"
|
191
|
+
assert_resource "/a*/"
|
192
|
+
assert_resource "/.+/"
|
193
|
+
assert_resource "/\./"
|
194
|
+
assert_resource "/[a-z]/"
|
195
|
+
assert_resource "/\[a-z\]/"
|
196
|
+
assert_resource "/#{name}/"
|
197
|
+
end
|
198
|
+
|
199
|
+
def test_can_source_range
|
200
|
+
assert_resource "1..10"
|
201
|
+
assert_resource "1...10"
|
202
|
+
end
|
203
|
+
|
204
|
+
def test_can_source_array_literals
|
205
|
+
assert_resource "[]"
|
206
|
+
assert_resource "[1]"
|
207
|
+
assert_resource "[1]"
|
208
|
+
assert_resource "[1, 2]"
|
209
|
+
assert_resource "[one, 2, :three, \"four\"]"
|
210
|
+
end
|
211
|
+
|
212
|
+
def test_can_source_array_references
|
213
|
+
assert_resource "a[1]"
|
214
|
+
assert_resource "a.b[1, 4]"
|
215
|
+
end
|
216
|
+
|
217
|
+
def test_can_source_object_array_assignments
|
218
|
+
assert_resource "obj.a[a] = x"
|
219
|
+
assert_resource "obj.a[a, b] = x"
|
220
|
+
end
|
221
|
+
|
222
|
+
def test_can_source_hash_literals
|
223
|
+
assert_resource "{}"
|
224
|
+
assert_resource "{:a => 1}"
|
225
|
+
assert_resource "{:a => 1, :b => 2}"
|
226
|
+
end
|
227
|
+
|
228
|
+
def test_can_source_unary_expression
|
229
|
+
assert_resource "+1"
|
230
|
+
assert_resource "-1"
|
231
|
+
assert_resource "+a"
|
232
|
+
assert_resource "-a"
|
233
|
+
end
|
234
|
+
|
235
|
+
def test_can_source_binary_expressions
|
236
|
+
assert_resource "a + 1"
|
237
|
+
assert_resource "a + b"
|
238
|
+
assert_resource "a - b"
|
239
|
+
assert_resource "a * b"
|
240
|
+
assert_resource "a / b"
|
241
|
+
assert_resource "a && b"
|
242
|
+
assert_resource "a || b"
|
243
|
+
end
|
244
|
+
|
245
|
+
def test_can_source_trinary_expressions
|
246
|
+
assert_resource "a ? b : c"
|
247
|
+
end
|
248
|
+
|
249
|
+
def test_can_source_complex_expressions
|
250
|
+
assert_resource "a + 1 * 3"
|
251
|
+
assert_resource "a + b"
|
252
|
+
end
|
253
|
+
|
254
|
+
def test_can_source_expressions_with_parenthesis
|
255
|
+
assert_resource "(a + 1) * 3"
|
256
|
+
assert_resource "(a + b) + c"
|
257
|
+
assert_resource "a + (b + c)"
|
258
|
+
assert_resource "((a))"
|
259
|
+
end
|
260
|
+
|
261
|
+
def test_can_source_assignment
|
262
|
+
assert_resource "a = b"
|
263
|
+
end
|
264
|
+
|
265
|
+
def test_can_source_object_assignment
|
266
|
+
assert_resource "obj.a = b"
|
267
|
+
end
|
268
|
+
|
269
|
+
def test_can_source_array_assignments
|
270
|
+
assert_resource "a[a] = x"
|
271
|
+
assert_resource "a[a, b] = x"
|
272
|
+
end
|
273
|
+
|
274
|
+
def test_can_source_operator_assignments
|
275
|
+
assert_resource "a += b"
|
276
|
+
assert_resource "a -= b"
|
277
|
+
assert_resource "a *= b"
|
278
|
+
assert_resource "a /= b"
|
279
|
+
end
|
280
|
+
|
281
|
+
def test_can_source_lambda
|
282
|
+
assert_resource "lambda { a }"
|
283
|
+
assert_resource "lambda { |x| a(x) }"
|
284
|
+
end
|
285
|
+
|
286
|
+
def test_can_source_defined
|
287
|
+
assert_resource "defined?(a)"
|
288
|
+
end
|
289
|
+
|
290
|
+
def test_can_source_undef
|
291
|
+
assert_resource "undef a"
|
292
|
+
end
|
293
|
+
|
294
|
+
def test_can_source_multiple_assignment
|
295
|
+
assert_resource "a, b, c = list"
|
296
|
+
assert_resource "a = x, y, z"
|
297
|
+
assert_resource "a, b, c = 1, 2, 3"
|
298
|
+
assert_resource "a, b, *c = 1, 2, 3, 4"
|
299
|
+
assert_resource "a, b, *c = 1, 2, *args"
|
300
|
+
assert_resource "(a, b), *c = 1, 2, *args"
|
301
|
+
end
|
302
|
+
|
303
|
+
def test_can_source_statement_sequences
|
304
|
+
assert_resource "a"
|
305
|
+
assert_resource "a; b"
|
306
|
+
assert_resource "a; b; c"
|
307
|
+
end
|
308
|
+
|
309
|
+
def test_can_source_begin_end
|
310
|
+
assert_resource "begin; end"
|
311
|
+
assert_resource "begin; a; end"
|
312
|
+
assert_resource "begin; a(); end"
|
313
|
+
assert_resource "begin; a; b; c; end"
|
314
|
+
end
|
315
|
+
|
316
|
+
def test_can_source_begin_rescue_end
|
317
|
+
assert_resource "begin; rescue; end"
|
318
|
+
assert_resource "begin; rescue E => ex; b; end"
|
319
|
+
assert_resource "begin; a; rescue E => ex; b; end"
|
320
|
+
assert_resource "begin; a; rescue E, F => ex; b; end"
|
321
|
+
assert_resource "begin; a; rescue E, F => ex; b; c; end"
|
322
|
+
assert_resource "begin; rescue E, F => ex; b; c; end"
|
323
|
+
end
|
324
|
+
|
325
|
+
def test_can_source_begin_ensure_end
|
326
|
+
assert_resource "begin; ensure end"
|
327
|
+
assert_resource "begin; ensure b; end"
|
328
|
+
assert_resource "begin; a; ensure b; end"
|
329
|
+
assert_resource "begin; a; ensure ; b; end"
|
330
|
+
end
|
331
|
+
|
332
|
+
def test_can_source_begin_rescue_ensure_end
|
333
|
+
assert_resource "begin; rescue; end"
|
334
|
+
assert_resource "begin; rescue E => ex; b; ensure c; end"
|
335
|
+
assert_resource "begin; a; rescue E => ex; b; ensure c; end"
|
336
|
+
assert_resource "begin; a; rescue E, F => ex; b; ensure c; end"
|
337
|
+
assert_resource "begin; a; rescue E, F => ex; b; c; ensure d; end"
|
338
|
+
assert_resource "begin; rescue E, F => ex; b; c; ensure d; end"
|
339
|
+
end
|
340
|
+
|
341
|
+
def test_can_source_rescue_modifier
|
342
|
+
assert_resource "a rescue b"
|
343
|
+
end
|
344
|
+
|
345
|
+
def test_can_source_if
|
346
|
+
assert_resource "if a then b end"
|
347
|
+
end
|
348
|
+
|
349
|
+
def test_can_source_if_else
|
350
|
+
assert_resource "if a then b else c end"
|
351
|
+
end
|
352
|
+
|
353
|
+
def test_can_source_if_elsif_else
|
354
|
+
assert_resource "if a then b elsif c then d else e end"
|
355
|
+
end
|
356
|
+
|
357
|
+
def test_can_source_if_elsif
|
358
|
+
assert_resource "if a then b elsif c then d end"
|
359
|
+
end
|
360
|
+
|
361
|
+
def test_can_source_unless
|
362
|
+
assert_resource "unless a then b end"
|
363
|
+
end
|
364
|
+
|
365
|
+
def test_can_source_unless_else
|
366
|
+
assert_resource "unless a then b else c end"
|
367
|
+
end
|
368
|
+
|
369
|
+
def test_can_source_while
|
370
|
+
assert_resource "while c do body end"
|
371
|
+
end
|
372
|
+
|
373
|
+
def test_can_source_until
|
374
|
+
assert_resource "until c do body end"
|
375
|
+
end
|
376
|
+
|
377
|
+
def test_can_source_for
|
378
|
+
assert_resource "for a in list do end"
|
379
|
+
assert_resource "for a in list do c end"
|
380
|
+
end
|
381
|
+
|
382
|
+
def test_can_source_break
|
383
|
+
assert_resource "while c do a; break if b; c end"
|
384
|
+
assert_resource "while c do a; break value if b; c end"
|
385
|
+
end
|
386
|
+
|
387
|
+
def test_can_source_next
|
388
|
+
assert_resource "while c do a; next if b; c end"
|
389
|
+
end
|
390
|
+
|
391
|
+
def test_can_source_case
|
392
|
+
assert_resource "case a when b; c end"
|
393
|
+
assert_resource "case a when b; c when d; e end"
|
394
|
+
assert_resource "case a when b; c when d; e else f end"
|
395
|
+
end
|
396
|
+
|
397
|
+
def test_can_source_if_modifier
|
398
|
+
assert_resource "a if b"
|
399
|
+
end
|
400
|
+
|
401
|
+
def test_can_source_unless_modifier
|
402
|
+
assert_resource "a unless b"
|
403
|
+
end
|
404
|
+
|
405
|
+
def test_can_source_while_modifier
|
406
|
+
assert_resource "a while b"
|
407
|
+
end
|
408
|
+
|
409
|
+
def test_can_source_until_modifier
|
410
|
+
assert_resource "a until b"
|
411
|
+
end
|
412
|
+
|
413
|
+
def test_can_source_alias
|
414
|
+
assert_resource "alias a b"
|
415
|
+
end
|
416
|
+
|
417
|
+
def test_can_source_fail
|
418
|
+
assert_resource "fail Err"
|
419
|
+
assert_resource "raise Err"
|
420
|
+
end
|
421
|
+
|
422
|
+
def test_can_source_retry
|
423
|
+
assert_resource "retry"
|
424
|
+
end
|
425
|
+
|
426
|
+
def test_can_source_redo
|
427
|
+
assert_resource "redo"
|
428
|
+
end
|
429
|
+
|
430
|
+
def test_can_source_return
|
431
|
+
assert_resource "return"
|
432
|
+
assert_resource "return value"
|
433
|
+
end
|
434
|
+
|
435
|
+
def test_can_source_super
|
436
|
+
assert_resource "super"
|
437
|
+
assert_resource "super a"
|
438
|
+
assert_resource "super a, b"
|
439
|
+
assert_resource "super a, *args"
|
440
|
+
assert_resource "super a, *args, &block"
|
441
|
+
assert_resource "super()"
|
442
|
+
assert_resource "super(a)"
|
443
|
+
assert_resource "super(a, b)"
|
444
|
+
assert_resource "super(a, *args)"
|
445
|
+
assert_resource "super(a, *args, &block)"
|
446
|
+
end
|
447
|
+
|
448
|
+
def test_can_source_yield
|
449
|
+
assert_resource "yield"
|
450
|
+
assert_resource "yield a"
|
451
|
+
assert_resource "yield(a)"
|
452
|
+
end
|
453
|
+
|
454
|
+
def test_can_source_self
|
455
|
+
assert_resource "self"
|
456
|
+
end
|
457
|
+
|
458
|
+
def test_can_source_def
|
459
|
+
assert_resource "def f a; end"
|
460
|
+
assert_resource "def f(); end"
|
461
|
+
assert_resource "def f(a); end"
|
462
|
+
assert_resource "def f(a, b); end"
|
463
|
+
assert_resource "def f(a, *args); end"
|
464
|
+
assert_resource "def f(a, *args, &block); end"
|
465
|
+
assert_resource "def f(a); x; end"
|
466
|
+
assert_resource "def f(a); x; y; end"
|
467
|
+
end
|
468
|
+
|
469
|
+
def test_can_source_class
|
470
|
+
assert_resource "class X; end"
|
471
|
+
assert_resource "class X; x; end"
|
472
|
+
assert_resource "class X; def f(); end; end"
|
473
|
+
end
|
474
|
+
|
475
|
+
def test_can_source_class_with_parent
|
476
|
+
assert_resource "class X < Y; end"
|
477
|
+
assert_resource "class X < Y; x; end"
|
478
|
+
end
|
479
|
+
|
480
|
+
def test_can_source_class_with_self_parent
|
481
|
+
assert_resource "class X < self; end"
|
482
|
+
end
|
483
|
+
|
484
|
+
def test_can_source_private_etc_in_class
|
485
|
+
assert_resource "class X; public; def f(); end; end"
|
486
|
+
assert_resource "class X; protected; def f(); end; end"
|
487
|
+
assert_resource "class X; private; def f(); end; end"
|
488
|
+
assert_resource "class X; def f(); end; public :f; end"
|
489
|
+
assert_resource "class X; def f(); end; protected :f; end"
|
490
|
+
assert_resource "class X; def f(); end; private :f; end"
|
491
|
+
end
|
492
|
+
|
493
|
+
def test_can_source_module
|
494
|
+
assert_resource "module X; end"
|
495
|
+
assert_resource "module X; x; end"
|
496
|
+
assert_resource "module X; def f(); end; end"
|
497
|
+
end
|
498
|
+
|
499
|
+
def test_can_source_BEGIN
|
500
|
+
assert_resource "BEGIN { }"
|
501
|
+
assert_resource "BEGIN { x }"
|
502
|
+
assert_resource "BEGIN { x; y }"
|
503
|
+
end
|
504
|
+
|
505
|
+
def test_can_source_END
|
506
|
+
assert_resource "END { }"
|
507
|
+
assert_resource "END { x }"
|
508
|
+
assert_resource "END { x; y }"
|
509
|
+
end
|
510
|
+
|
511
|
+
def test_can_source_then
|
512
|
+
assert_resource "Then { a == b }"
|
513
|
+
end
|
514
|
+
|
515
|
+
private
|
516
|
+
|
517
|
+
def assert_resource(string, debug=nil)
|
518
|
+
assert_equal string, source(string, debug)
|
519
|
+
end
|
520
|
+
|
521
|
+
end
|
metadata
ADDED
@@ -0,0 +1,64 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: sorcerer
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Jim Weirich
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
|
12
|
+
date: 2009-11-25 00:00:00 -05:00
|
13
|
+
default_executable:
|
14
|
+
dependencies: []
|
15
|
+
|
16
|
+
description: " Generate the original Ruby source from a Ripper-style abstract syntax tree.\n"
|
17
|
+
email: jim.weirich@gmail.com
|
18
|
+
executables: []
|
19
|
+
|
20
|
+
extensions: []
|
21
|
+
|
22
|
+
extra_rdoc_files: []
|
23
|
+
|
24
|
+
files:
|
25
|
+
- README.textile
|
26
|
+
- Rakefile
|
27
|
+
- lib/sorcerer/sorcerer.rb
|
28
|
+
- lib/sorcerer.rb
|
29
|
+
- test/sorcerer/sorcerer_test.rb
|
30
|
+
has_rdoc: true
|
31
|
+
homepage: http://github.com/jimweirich/sorcerer
|
32
|
+
licenses: []
|
33
|
+
|
34
|
+
post_install_message:
|
35
|
+
rdoc_options:
|
36
|
+
- --line-numbers
|
37
|
+
- --inline-source
|
38
|
+
- --main
|
39
|
+
- README.rdoc
|
40
|
+
- --title
|
41
|
+
- Rake -- Ruby Make
|
42
|
+
require_paths:
|
43
|
+
- lib
|
44
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
45
|
+
requirements:
|
46
|
+
- - ">="
|
47
|
+
- !ruby/object:Gem::Version
|
48
|
+
version: "0"
|
49
|
+
version:
|
50
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: "0"
|
55
|
+
version:
|
56
|
+
requirements: []
|
57
|
+
|
58
|
+
rubyforge_project:
|
59
|
+
rubygems_version: 1.3.5
|
60
|
+
signing_key:
|
61
|
+
specification_version: 3
|
62
|
+
summary: Generate Source from Ripper ASTs
|
63
|
+
test_files: []
|
64
|
+
|