sorcerer 0.0.7 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -44,3 +44,58 @@ Ripper may be used to produce the s-expressions used by Sorcerer. The following
44
44
  puts Sorcerer.source(sexp)
45
45
  </pre>
46
46
 
47
+ h2. Options
48
+
49
+ h3. Multi-Line Output
50
+
51
+ If you want multi-line output of source, add the multiline option to
52
+ the source command.
53
+
54
+ For example, given:
55
+
56
+ <pre style="background: LightGrey">
57
+ sexp = Ripper::SexpBuilder.new("def foo; end").parse
58
+ </pre>
59
+
60
+ Then the following
61
+
62
+ <pre style="background: LightGrey">
63
+ puts Sorcerer.source(sexp)
64
+ </pre>
65
+
66
+ generates single line output (the default):
67
+
68
+ <pre style="background: LightBlue">
69
+ def foo; end
70
+ </pre>
71
+
72
+ And the following
73
+
74
+ <pre style="background: LightGrey">
75
+ puts Sorcerer.source(sexp, multiline: true)
76
+ </pre>
77
+
78
+ generates multi-line output
79
+
80
+ <pre style="background: LightBlue">
81
+ def foo
82
+ end
83
+ </pre>
84
+
85
+ h3. Debugging Output
86
+
87
+ If you wish to see the S-Expressions processed by Sorcerer and the
88
+ output emitted, then use the debug option:
89
+
90
+ <pre style="background: LightGrey">
91
+ puts Sorcerer.source(sexp, debug: true)
92
+ </pre>
93
+
94
+ h2. History
95
+
96
+ * 0.0.7 - Basic single line version
97
+ * 0.1.0 - Added support for multi-line output. Improved rendering of a
98
+ number of constructs
99
+
100
+
101
+
data/Rakefile CHANGED
@@ -2,13 +2,13 @@
2
2
 
3
3
  require 'rake/clean'
4
4
  require 'rake/testtask'
5
- require 'rake/rdoctask'
5
+ #require 'rdoc/task'
6
6
 
7
7
  require './lib/sorcerer/version'
8
8
 
9
9
  begin
10
10
  require 'rubygems'
11
- require 'rake/gempackagetask'
11
+ require 'rubygems/package_task'
12
12
  rescue Exception
13
13
  nil
14
14
  end
@@ -25,7 +25,7 @@ PKG_FILES = FileList[
25
25
  'lib/**/*.rb',
26
26
  'test/**/*.rb',
27
27
  ]
28
-
28
+
29
29
  BASE_RDOC_OPTIONS = [
30
30
  '--line-numbers', '--inline-source',
31
31
  '--main' , 'README.textile',
@@ -34,16 +34,17 @@ BASE_RDOC_OPTIONS = [
34
34
 
35
35
  task :default => :test
36
36
 
37
- rd = Rake::RDocTask.new("rdoc") do |rdoc|
38
- rdoc.rdoc_dir = 'html'
39
- rdoc.template = 'doc/jamis.rb'
40
- rdoc.title = "Sorcerer -- Its Like Magic"
41
- rdoc.options = BASE_RDOC_OPTIONS.dup
42
- rdoc.options << '-SHN' << '-f' << 'darkfish' if defined?(DARKFISH_ENABLED) && DARKFISH_ENABLED
43
-
44
- rdoc.rdoc_files.include('README.textile')
45
- rdoc.rdoc_files.include('lib/**/*.rb', 'doc/**/*.rdoc')
46
- rdoc.rdoc_files.exclude(/\bcontrib\b/)
37
+ RDOC_FILES = FileList['lib/**/*.rb', 'doc/**/*.rdoc'].exclude(/\bcontrib\b/)
38
+
39
+ if defined?(Rake::RDocTesk)
40
+ rd = Rake::RDocTask.new("rdoc") do |rdoc|
41
+ rdoc.rdoc_dir = 'html'
42
+ rdoc.template = 'doc/jamis.rb'
43
+ rdoc.title = "Sorcerer -- Its Like Magic"
44
+ rdoc.options = BASE_RDOC_OPTIONS.dup
45
+ rdoc.options << '-SHN' << '-f' << 'darkfish' if defined?(DARKFISH_ENABLED) && DARKFISH_ENABLED
46
+ rdoc.rdoc_files = RDOC_FILES
47
+ end
47
48
  end
48
49
 
49
50
  if ! defined?(Gem)
@@ -53,13 +54,11 @@ else
53
54
  s.name = 'sorcerer'
54
55
  s.version = PKG_VERSION
55
56
  s.summary = "Generate Source from Ripper ASTs"
56
- s.description = <<-EOF
57
- Generate the original Ruby source from a Ripper-style abstract syntax tree.
58
- EOF
59
- s.files = PKG_FILES.to_a
57
+ s.description = "Generate the original Ruby source from a Ripper-style abstract syntax tree."
58
+ s.files = PKG_FILES
60
59
  s.require_path = 'lib' # Use these for libraries.
61
60
  s.has_rdoc = true
62
- s.extra_rdoc_files = rd.rdoc_files.reject { |fn| fn =~ /\.rb$/ }.to_a
61
+ s.extra_rdoc_files = RDOC_FILES.reject { |fn| fn =~ /\.rb$/ }.to_a
63
62
  s.rdoc_options = BASE_RDOC_OPTIONS
64
63
  s.author = "Jim Weirich"
65
64
  s.email = "jim.weirich@gmail.com"
@@ -67,7 +66,7 @@ else
67
66
  s.homepage = "http://github.com/jimweirich/sorcerer"
68
67
  end
69
68
 
70
- package_task = Rake::GemPackageTask.new(SPEC) do |pkg|
69
+ package_task = Gem::PackageTask.new(SPEC) do |pkg|
71
70
  pkg.need_zip = true
72
71
  pkg.need_tar = true
73
72
  end
@@ -1,7 +1,7 @@
1
1
  module Sorcerer
2
2
  # Generate the source code for teh given Ripper S-Expression.
3
- def self.source(sexp, debug=false)
4
- Sorcerer::Resource.new(sexp, debug).source
3
+ def self.source(sexp, options={})
4
+ Sorcerer::Resource.new(sexp, options).source
5
5
  end
6
6
 
7
7
  # Generate a list of interesting subexpressions for sexp.
@@ -2,62 +2,104 @@
2
2
 
3
3
  require 'ripper'
4
4
 
5
- module Sorcerer
5
+ module Sorcerer
6
6
  class Resource
7
- class NoHandlerError < StandardError
7
+ class SorcererError < StandardError
8
8
  end
9
-
10
- def initialize(sexp, debug=false)
9
+
10
+ class NoHandlerError < SorcererError
11
+ end
12
+
13
+ class NotSexpError < SorcererError
14
+ end
15
+
16
+ class UnexpectedSexpError < SorcererError
17
+ end
18
+
19
+ def initialize(sexp, options={})
11
20
  @sexp = sexp
12
21
  @source = ''
13
- @debug = debug
22
+ @debug = options[:debug]
23
+ @multiline = options[:multiline]
14
24
  @word_level = 0
25
+ @stack = []
15
26
  end
16
-
27
+
17
28
  def source
29
+ @stack.clear
18
30
  resource(@sexp)
19
31
  @source
20
32
  end
21
-
33
+
34
+ def sexp?(obj)
35
+ obj && obj.respond_to?(:each) && obj.first.is_a?(Symbol)
36
+ end
37
+
38
+ def nested_sexp?(obj)
39
+ obj && obj.respond_to?(:first) && sexp?(obj.first)
40
+ end
41
+
22
42
  def resource(sexp)
23
- return unless sexp
43
+ sexp = sexp.first if nested_sexp?(sexp)
44
+ fail NotSexpError, "Not an S-EXPER: #{sexp.inspect}" unless sexp?(sexp)
24
45
  handler = HANDLERS[sexp.first]
25
46
  raise NoHandlerError.new(sexp.first) unless handler
26
47
  if @debug
27
48
  puts "----------------------------------------------------------"
28
49
  pp sexp
29
50
  end
51
+ @stack.push(sexp.first)
30
52
  handler.call(self, sexp)
53
+ @stack.pop
31
54
  end
32
-
33
- def handle_block(sexp)
34
- resource(sexp[1]) # Arguments
55
+
56
+ def emit_block(sexp, do_word, end_word)
57
+ emit(" ")
58
+ emit(do_word)
59
+ resource(sexp[1]) if sexp[1] # Arguments
35
60
  if ! void?(sexp[2])
61
+ soft_newline
62
+ resource(sexp[2]) # Statements
63
+ end
64
+ if !void?(sexp[2])
65
+ soft_newline
66
+ else
36
67
  emit(" ")
37
- resource(sexp[2]) # Statements
38
68
  end
39
- emit(" ")
69
+ emit(end_word)
70
+ end
71
+
72
+ def params_have_parens?(sexp)
73
+ sexp.first == :arg_paren || sexp.first == :paren
40
74
  end
41
-
75
+
76
+ def params_are_empty?(sexp)
77
+ params = sexp
78
+ params = sexp[1] if sexp.first == :paren || sexp.first == :arg_paren
79
+ params[1].nil? || params[1].empty?
80
+ end
81
+
42
82
  def opt_parens(sexp)
43
- emit(" ") unless sexp.first == :arg_paren || sexp.first == :paren
83
+ if !params_have_parens?(sexp) && ! params_are_empty?(sexp)
84
+ emit(" ")
85
+ end
44
86
  resource(sexp)
45
87
  end
46
-
88
+
47
89
  def emit(string)
48
- puts "EMITTING '#{string}'" if @debug
90
+ puts "EMITTING '#{string}' (#{last_handler})" if @debug
49
91
  @source << string.to_s
50
92
  end
51
-
93
+
52
94
  def nyi(sexp)
53
95
  raise "Handler for #{sexp.first} not implemented (#{sexp.inspect})"
54
96
  end
55
-
97
+
56
98
  def emit_separator(sep, first)
57
99
  emit(sep) unless first
58
100
  false
59
101
  end
60
-
102
+
61
103
  def params(normal_args, default_args, rest_args, unknown, block_arg)
62
104
  first = true
63
105
  if normal_args
@@ -83,7 +125,7 @@ module Sorcerer
83
125
  resource(block_arg)
84
126
  end
85
127
  end
86
-
128
+
87
129
  def words(marker, sexp)
88
130
  emit("%#{marker}{") if @word_level == 0
89
131
  @word_level += 1
@@ -95,18 +137,62 @@ module Sorcerer
95
137
  @word_level -= 1
96
138
  emit("}") if @word_level == 0
97
139
  end
98
-
140
+
99
141
  VOID_STATEMENT = [:stmts_add, [:stmts_new], [:void_stmt]]
142
+ VOID_STATEMENT2 = [:stmts_add, [:stmts_new]]
100
143
  VOID_BODY = [:body_stmt, VOID_STATEMENT, nil, nil, nil]
101
144
  VOID_BODY2 = [:bodystmt, VOID_STATEMENT, nil, nil, nil]
102
-
145
+
103
146
  def void?(sexp)
104
147
  sexp.nil? ||
105
148
  sexp == VOID_STATEMENT ||
149
+ sexp == VOID_STATEMENT2 ||
106
150
  sexp == VOID_BODY ||
107
151
  sexp == VOID_BODY2
108
152
  end
109
-
153
+
154
+ def multiline?
155
+ @multiline
156
+ end
157
+
158
+ def last_handler
159
+ @stack.last
160
+ end
161
+
162
+ def newline
163
+ if multiline?
164
+ emit("\n")
165
+ else
166
+ emit("; ")
167
+ end
168
+ end
169
+
170
+ def soft_newline
171
+ if multiline?
172
+ emit("\n")
173
+ else
174
+ emit(" ")
175
+ end
176
+ end
177
+
178
+ BALANCED_DELIMS = {
179
+ '}' => '{',
180
+ ')' => '(',
181
+ '>' => '<',
182
+ ']' => '[',
183
+ }
184
+
185
+ def self.determine_regexp_delimiters(sexp)
186
+ sym, end_delim, other = sexp
187
+ fail UnexpectedSexpError, "Expected :@regexp_end, got #{sym.inspect}" unless sym == :@regexp_end
188
+ end_delim_char = end_delim[0]
189
+ first_delim = BALANCED_DELIMS[end_delim_char] || end_delim_char
190
+ if first_delim != '/'
191
+ first_delim = "%r#{first_delim}"
192
+ end
193
+ [first_delim, end_delim]
194
+ end
195
+
110
196
  NYI = lambda { |src, sexp| src.nyi(sexp) }
111
197
  DBG = lambda { |src, sexp| pp(sexp) }
112
198
  NOOP = lambda { |src, sexp| }
@@ -114,25 +200,31 @@ module Sorcerer
114
200
  PASS1 = lambda { |src, sexp| src.resource(sexp[1]) }
115
201
  PASS2 = lambda { |src, sexp| src.resource(sexp[2]) }
116
202
  EMIT1 = lambda { |src, sexp| src.emit(sexp[1]) }
117
-
203
+
118
204
  HANDLERS = {
119
205
  # parser keywords
120
-
206
+
121
207
  :BEGIN => lambda { |src, sexp|
122
208
  src.emit("BEGIN {")
123
- unless src.void?(sexp[1])
124
- src.emit(" ")
209
+ if src.void?(sexp[1])
210
+ src.emit " }"
211
+ else
212
+ src.soft_newline
125
213
  src.resource(sexp[1])
214
+ src.soft_newline
215
+ src.emit("}")
126
216
  end
127
- src.emit(" }")
128
217
  },
129
218
  :END => lambda { |src, sexp|
130
219
  src.emit("END {")
131
- unless src.void?(sexp[1])
132
- src.emit(" ")
220
+ if src.void?(sexp[1])
221
+ src.emit(" }")
222
+ else
223
+ src.soft_newline
133
224
  src.resource(sexp[1])
225
+ src.soft_newline
226
+ src.emit("}")
134
227
  end
135
- src.emit(" }")
136
228
  },
137
229
  :alias => lambda { |src, sexp|
138
230
  src.emit("alias ")
@@ -190,7 +282,7 @@ module Sorcerer
190
282
  :args_prepend => NYI,
191
283
  :array => lambda { |src, sexp|
192
284
  src.emit("[")
193
- src.resource(sexp[1])
285
+ src.resource(sexp[1]) if sexp[1]
194
286
  src.emit("]")
195
287
  },
196
288
  :assign => lambda { |src, sexp|
@@ -214,7 +306,7 @@ module Sorcerer
214
306
  },
215
307
  :bare_assoc_hash => lambda { |src, sexp|
216
308
  first = true
217
- sexp[1].each do |sx|
309
+ sexp[1].each do |sx|
218
310
  src.emit(", ") unless first
219
311
  first = false
220
312
  src.resource(sx)
@@ -222,7 +314,12 @@ module Sorcerer
222
314
  },
223
315
  :begin => lambda { |src, sexp|
224
316
  src.emit("begin")
225
- src.resource(sexp[1])
317
+ if src.void?(sexp[1])
318
+ src.emit(" ")
319
+ else
320
+ src.soft_newline
321
+ src.resource(sexp[1])
322
+ end
226
323
  src.emit("end")
227
324
  },
228
325
  :binary => lambda { |src, sexp|
@@ -243,14 +340,12 @@ module Sorcerer
243
340
  },
244
341
  :body_stmt => lambda { |src, sexp|
245
342
  src.resource(sexp[1]) # Main Body
246
- src.emit("; ")
247
- src.resource(sexp[2]) # Rescue
248
- src.resource(sexp[4]) # Ensure
343
+ src.newline unless src.void?(sexp[1])
344
+ src.resource(sexp[2]) if sexp[2] # Rescue
345
+ src.resource(sexp[4]) if sexp[4] # Ensure
249
346
  },
250
347
  :brace_block => lambda { |src, sexp|
251
- src.emit(" {")
252
- src.handle_block(sexp)
253
- src.emit("}")
348
+ src.emit_block(sexp, "{", "}")
254
349
  },
255
350
  :break => lambda { |src, sexp|
256
351
  src.emit("break")
@@ -265,9 +360,10 @@ module Sorcerer
265
360
  :case => lambda { |src, sexp|
266
361
  src.emit("case ")
267
362
  src.resource(sexp[1])
268
- src.emit(" ")
363
+ src.soft_newline
269
364
  src.resource(sexp[2])
270
- src.emit(" end")
365
+ src.newline
366
+ src.emit("end")
271
367
  },
272
368
  :class => lambda { |src, sexp|
273
369
  src.emit("class ")
@@ -276,7 +372,7 @@ module Sorcerer
276
372
  src.emit " < "
277
373
  src.resource(sexp[2])
278
374
  end
279
- src.emit("; ")
375
+ src.newline
280
376
  src.resource(sexp[3]) unless src.void?(sexp[3])
281
377
  src.emit("end")
282
378
  },
@@ -302,6 +398,7 @@ module Sorcerer
302
398
  src.emit("def ")
303
399
  src.resource(sexp[1])
304
400
  src.opt_parens(sexp[2])
401
+ src.newline
305
402
  src.resource(sexp[3])
306
403
  src.emit("end")
307
404
  },
@@ -312,9 +409,7 @@ module Sorcerer
312
409
  },
313
410
  :defs => NYI,
314
411
  :do_block => lambda { |src, sexp|
315
- src.emit(" do")
316
- src.handle_block(sexp)
317
- src.emit("end")
412
+ src.emit_block(sexp, "do", "end")
318
413
  },
319
414
  :dot2 => lambda { |src, sexp|
320
415
  src.resource(sexp[1])
@@ -332,21 +427,31 @@ module Sorcerer
332
427
  src.emit('"')
333
428
  },
334
429
  :else => lambda { |src, sexp|
335
- src.emit(" else ")
430
+ src.soft_newline
431
+ src.emit("else")
432
+ src.soft_newline
336
433
  src.resource(sexp[1])
337
434
  },
338
435
  :elsif => lambda { |src, sexp|
339
- src.emit(" elsif ")
436
+ src.soft_newline
437
+ src.emit("elsif ")
340
438
  src.resource(sexp[1])
341
- src.emit(" then ")
439
+ if src.multiline?
440
+ src.soft_newline
441
+ else
442
+ src.emit(" then ")
443
+ end
342
444
  src.resource(sexp[2])
343
- src.resource(sexp[3])
445
+ src.resource(sexp[3]) if sexp[3]
344
446
  },
345
447
  :ensure => lambda { |src, sexp|
346
- src.emit("ensure ")
347
- if sexp[1]
448
+ src.emit("ensure")
449
+ if src.void?(sexp[1])
450
+ src.soft_newline
451
+ else
452
+ src.soft_newline
348
453
  src.resource(sexp[1])
349
- src.emit("; ") unless src.void?(sexp[1])
454
+ src.newline unless src.void?(sexp[1])
350
455
  end
351
456
  },
352
457
  :excessed_comma => NYI,
@@ -370,16 +475,21 @@ module Sorcerer
370
475
  },
371
476
  :hash => lambda { |src, sexp|
372
477
  src.emit("{")
373
- src.resource(sexp[1])
478
+ src.resource(sexp[1]) if sexp[1]
374
479
  src.emit("}")
375
480
  },
376
481
  :if => lambda { |src, sexp|
377
482
  src.emit("if ")
378
483
  src.resource(sexp[1])
379
- src.emit(" then ")
484
+ if src.multiline?
485
+ src.newline
486
+ else
487
+ src.emit(" then ")
488
+ end
380
489
  src.resource(sexp[2])
381
- src.resource(sexp[3])
382
- src.emit(" end")
490
+ src.resource(sexp[3]) if sexp[3]
491
+ src.soft_newline
492
+ src.emit("end")
383
493
  },
384
494
  :if_mod => lambda { |src, sexp|
385
495
  src.resource(sexp[2])
@@ -438,8 +548,8 @@ module Sorcerer
438
548
  :module => lambda { |src, sexp|
439
549
  src.emit("module ")
440
550
  src.resource(sexp[1])
551
+ src.newline
441
552
  if src.void?(sexp[2])
442
- src.emit("; ")
443
553
  else
444
554
  src.resource(sexp[2])
445
555
  end
@@ -486,10 +596,12 @@ module Sorcerer
486
596
  :redo => lambda { |src, sexp|
487
597
  src.emit("redo")
488
598
  },
599
+ :regexp_add => PASS2,
489
600
  :regexp_literal => lambda { |src, sexp|
490
- src.emit("/")
601
+ delims = determine_regexp_delimiters(sexp[2])
602
+ src.emit(delims[0])
491
603
  src.resource(sexp[1])
492
- src.emit("/")
604
+ src.emit(delims[1])
493
605
  },
494
606
  :rescue => lambda { |src, sexp|
495
607
  src.emit("rescue")
@@ -501,17 +613,12 @@ module Sorcerer
501
613
  src.resource(sexp[1].first)
502
614
  end
503
615
  src.emit(" => ")
504
- src.resource(sexp[2])
616
+ src.resource(sexp[2])
505
617
  end
506
- src.emit(";")
507
- if sexp[3] # Rescue Code
508
- if src.void?(sexp[3])
509
- src.emit(" ")
510
- else
511
- src.emit(" ")
512
- src.resource(sexp[3])
513
- src.emit("; ")
514
- end
618
+ src.newline
619
+ if sexp[3] && ! src.void?(sexp[3])
620
+ src.resource(sexp[3])
621
+ src.newline
515
622
  end
516
623
  },
517
624
  :rescue_mod => lambda { |src, sexp|
@@ -528,18 +635,18 @@ module Sorcerer
528
635
  },
529
636
  :return => lambda { |src, sexp|
530
637
  src.emit("return")
531
- src.opt_parens(sexp[1])
638
+ src.opt_parens(sexp[1])
532
639
  },
533
640
  :return0 => lambda { |src, sexp|
534
641
  src.emit("return")
535
642
  },
536
643
  :sclass => NYI,
537
644
  :stmts_add => lambda { |src, sexp|
538
- if sexp[1] != [:stmts_new]
645
+ if sexp[1] != [:stmts_new] && ! src.void?(sexp[1])
539
646
  src.resource(sexp[1])
540
- src.emit("; ")
647
+ src.newline
541
648
  end
542
- src.resource(sexp[2])
649
+ src.resource(sexp[2]) if sexp[2]
543
650
  },
544
651
  :stmts_new => NOOP,
545
652
  :string_add => lambda { |src, sexp|
@@ -585,10 +692,15 @@ module Sorcerer
585
692
  :unless => lambda { |src, sexp|
586
693
  src.emit("unless ")
587
694
  src.resource(sexp[1])
588
- src.emit(" then ")
695
+ if src.multiline?
696
+ src.newline
697
+ else
698
+ src.emit(" then ")
699
+ end
589
700
  src.resource(sexp[2])
590
- src.resource(sexp[3])
591
- src.emit(" end")
701
+ src.resource(sexp[3]) if sexp[3]
702
+ src.soft_newline
703
+ src.emit("end")
592
704
  },
593
705
  :unless_mod => lambda { |src, sexp|
594
706
  src.resource(sexp[2])
@@ -614,19 +726,22 @@ module Sorcerer
614
726
  :when => lambda { |src, sexp|
615
727
  src.emit("when ")
616
728
  src.resource(sexp[1])
617
- src.emit("; ")
729
+ src.newline
618
730
  src.resource(sexp[2])
619
731
  if sexp[3] && sexp[3].first == :when
620
732
  src.emit(" ")
621
733
  end
622
- src.resource(sexp[3])
734
+ src.resource(sexp[3]) if sexp[3]
623
735
  },
624
736
  :while => lambda { |src, sexp|
625
737
  src.emit("while ")
626
738
  src.resource(sexp[1])
627
- src.emit(" do ")
628
- src.resource(sexp[2])
629
- src.emit(" end")
739
+ src.newline
740
+ unless src.void?(sexp[2])
741
+ src.resource(sexp[2])
742
+ src.newline
743
+ end
744
+ src.emit("end")
630
745
  },
631
746
  :while_mod => lambda { |src, sexp|
632
747
  src.resource(sexp[2])
@@ -659,9 +774,9 @@ module Sorcerer
659
774
  :zsuper => lambda { |src, sexp|
660
775
  src.emit("super")
661
776
  },
662
-
777
+
663
778
  # Scanner keywords
664
-
779
+
665
780
  :@CHAR => NYI,
666
781
  :@__end__ => NYI,
667
782
  :@backref => NYI,
@@ -711,5 +826,5 @@ module Sorcerer
711
826
  }
712
827
  HANDLERS[:bodystmt] = HANDLERS[:body_stmt]
713
828
  end
714
-
829
+
715
830
  end
@@ -1,7 +1,7 @@
1
1
  module Sorcerer
2
2
  VERSION_MAJOR = 0
3
- VERSION_MINOR = 0
4
- VERSION_BUILD = 7
3
+ VERSION_MINOR = 1
4
+ VERSION_BUILD = 0
5
5
  VERSION_BETA = 0
6
6
 
7
7
  VERSION_NUMBERS = [VERSION_MAJOR, VERSION_MINOR, VERSION_BUILD] +
@@ -5,13 +5,13 @@ require 'ripper'
5
5
  require 'sorcerer'
6
6
 
7
7
  class SourcerTest < Test::Unit::TestCase
8
- def source(string, debug=false)
9
- if debug
8
+ def source(string, options={})
9
+ if options[:debug]
10
10
  puts
11
- puts "************************************************************"
11
+ puts "***************************** options: #{options.inspect}"
12
12
  end
13
13
  sexp = Ripper::SexpBuilder.new(string).parse
14
- Sorcerer.source(sexp, debug)
14
+ Sorcerer.source(sexp, options)
15
15
  end
16
16
 
17
17
  def test_can_source_variables
@@ -48,7 +48,7 @@ class SourcerTest < Test::Unit::TestCase
48
48
  assert_resource "obj.meth()"
49
49
  end
50
50
 
51
- def test_can_source_method_call_with_args
51
+ def test_can_source_method_call_with_args
52
52
  assert_resource "obj.meth(a)"
53
53
  assert_resource "obj.meth(a, b)"
54
54
  assert_resource "obj.meth(a, b, c)"
@@ -85,7 +85,7 @@ class SourcerTest < Test::Unit::TestCase
85
85
  assert_resource "meth &code"
86
86
  assert_resource "meth a, &code"
87
87
  assert_resource "meth a, *args, &code"
88
- assert_resource "meth a, *args do |x| x.y end"
88
+ assert_resource "meth a, *args do |x| x.y end",
89
89
  end
90
90
 
91
91
  def test_can_source_method_with_bare_assoc
@@ -96,14 +96,14 @@ class SourcerTest < Test::Unit::TestCase
96
96
  end
97
97
 
98
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"
99
+ assert_resource_ml "meth do end"
100
+ assert_resource_ml "meth do |a| end"
101
+ assert_resource_ml "meth(x, y, *rest, &code) do |a, b=1, c=x, *args, &block|~one; two; three~end"
102
102
  end
103
103
 
104
104
  def test_can_source_method_with_block
105
105
  assert_resource "meth { }"
106
- assert_resource "meth { |a| }"
106
+ assert_resource "meth { |a| }"
107
107
  assert_resource "meth { |a, b| }"
108
108
  assert_resource "meth { |*args| }"
109
109
  assert_resource "meth { |a, *args| }"
@@ -138,7 +138,7 @@ class SourcerTest < Test::Unit::TestCase
138
138
  assert_resource "p.(a)"
139
139
  end
140
140
  end
141
-
141
+
142
142
  def test_can_source_numbers
143
143
  assert_resource "1"
144
144
  assert_resource "3.14"
@@ -178,12 +178,12 @@ class SourcerTest < Test::Unit::TestCase
178
178
  assert_resource '%W{a b c}'
179
179
  assert_resource '%W{Now is the time for all good men}'
180
180
  end
181
-
181
+
182
182
  def test_can_source_many_words
183
183
  assert_resource '[%w{a b}, %w{c d}]'
184
184
  assert_resource '[%W{a b}, %W{c d}]'
185
185
  end
186
-
186
+
187
187
  def test_can_source_symbols
188
188
  assert_resource ":sym"
189
189
  end
@@ -203,6 +203,19 @@ class SourcerTest < Test::Unit::TestCase
203
203
  assert_resource '/#{name}/'
204
204
  end
205
205
 
206
+ def test_can_source_regular_expressions_with_alternate_delimiters
207
+ assert_resource "%r{a}"
208
+ assert_resource "%r<a>"
209
+ assert_resource "%r[a]"
210
+ assert_resource "%r(a)"
211
+ assert_resource "%r|a|"
212
+ end
213
+
214
+ def test_can_source_regular_expressions_with_flags
215
+ assert_resource "%r{a}im"
216
+ assert_resource "/a/i"
217
+ end
218
+
206
219
  def test_can_source_range
207
220
  assert_resource "1..10"
208
221
  assert_resource "1...10"
@@ -252,7 +265,7 @@ class SourcerTest < Test::Unit::TestCase
252
265
  def test_can_source_trinary_expressions
253
266
  assert_resource "a ? b : c"
254
267
  end
255
-
268
+
256
269
  def test_can_source_complex_expressions
257
270
  assert_resource "a + 1 * 3"
258
271
  assert_resource "a + b"
@@ -308,41 +321,41 @@ class SourcerTest < Test::Unit::TestCase
308
321
  end
309
322
 
310
323
  def test_can_source_statement_sequences
311
- assert_resource "a"
312
- assert_resource "a; b"
313
- assert_resource "a; b; c"
324
+ assert_resource_ml "a"
325
+ assert_resource_ml "a; b"
326
+ assert_resource_ml "a; b; c"
314
327
  end
315
328
 
316
329
  def test_can_source_begin_end
317
- assert_resource "begin; end"
318
- assert_resource "begin; a; end"
319
- assert_resource "begin; a(); end"
320
- assert_resource "begin; a; b; c; end"
330
+ assert_resource_ml "begin end"
331
+ assert_resource_ml "begin~a; end"
332
+ assert_resource_ml "begin~a(); end"
333
+ assert_resource_ml "begin~a; b; c; end"
321
334
  end
322
335
 
323
336
  def test_can_source_begin_rescue_end
324
- assert_resource "begin; rescue; end"
325
- assert_resource "begin; rescue E => ex; b; end"
326
- assert_resource "begin; a; rescue E => ex; b; end"
327
- assert_resource "begin; a; rescue E, F => ex; b; end"
328
- assert_resource "begin; a; rescue E, F => ex; b; c; end"
329
- assert_resource "begin; rescue E, F => ex; b; c; end"
337
+ assert_resource_ml "begin~rescue; end"
338
+ assert_resource_ml "begin~rescue E => ex; b; end"
339
+ assert_resource_ml "begin~a; rescue E => ex; b; end"
340
+ assert_resource_ml "begin~a; rescue E, F => ex; b; end"
341
+ assert_resource_ml "begin~a; rescue E, F => ex; b; c; end"
342
+ assert_resource_ml "begin~rescue E, F => ex; b; c; end"
330
343
  end
331
344
 
332
345
  def test_can_source_begin_ensure_end
333
- assert_resource "begin; ensure end"
334
- assert_resource "begin; ensure b; end"
335
- assert_resource "begin; a; ensure b; end"
336
- assert_resource "begin; a; ensure ; b; end"
346
+ assert_resource_ml "begin~ensure~end"
347
+ assert_resource_ml "begin~ensure~b; end"
348
+ assert_resource_ml "begin~a; ensure~b; end"
349
+ assert_resource_ml "begin~a; ensure~b; end"
337
350
  end
338
351
 
339
352
  def test_can_source_begin_rescue_ensure_end
340
- assert_resource "begin; rescue; end"
341
- assert_resource "begin; rescue E => ex; b; ensure c; end"
342
- assert_resource "begin; a; rescue E => ex; b; ensure c; end"
343
- assert_resource "begin; a; rescue E, F => ex; b; ensure c; end"
344
- assert_resource "begin; a; rescue E, F => ex; b; c; ensure d; end"
345
- assert_resource "begin; rescue E, F => ex; b; c; ensure d; end"
353
+ assert_resource_ml "begin~rescue; end"
354
+ assert_resource_ml "begin~rescue E => ex; b; ensure~c; end"
355
+ assert_resource_ml "begin~a; rescue E => ex; b; ensure~c; end"
356
+ assert_resource_ml "begin~a; rescue E, F => ex; b; ensure~c; end"
357
+ assert_resource_ml "begin~a; rescue E, F => ex; b; c; ensure~d; end"
358
+ assert_resource_ml "begin~rescue E, F => ex; b; c; ensure~d; end"
346
359
  end
347
360
 
348
361
  def test_can_source_rescue_modifier
@@ -351,30 +364,37 @@ class SourcerTest < Test::Unit::TestCase
351
364
 
352
365
  def test_can_source_if
353
366
  assert_resource "if a then b end"
367
+ assert_resource "if a\nb\nend", multiline: true
354
368
  end
355
369
 
356
370
  def test_can_source_if_else
357
371
  assert_resource "if a then b else c end"
358
- end
359
-
360
- def test_can_source_if_elsif_else
361
- assert_resource "if a then b elsif c then d else e end"
372
+ assert_resource "if a\nb\nelse\nc\nend", multiline: true
362
373
  end
363
374
 
364
375
  def test_can_source_if_elsif
365
376
  assert_resource "if a then b elsif c then d end"
377
+ assert_resource "if a\nb\nelsif c\nd\nend", multiline: true
378
+ end
379
+
380
+ def test_can_source_if_elsif_else
381
+ assert_resource "if a then b elsif c then d else e end"
382
+ assert_resource "if a\nb\nelsif c\nd\nelse\ne\nend", multiline: true
366
383
  end
367
384
 
368
385
  def test_can_source_unless
369
386
  assert_resource "unless a then b end"
387
+ assert_resource "unless a\nb\nend", multiline: true
370
388
  end
371
389
 
372
390
  def test_can_source_unless_else
373
391
  assert_resource "unless a then b else c end"
392
+ assert_resource "unless a\nb\nelse\nc\nend", multiline: true
374
393
  end
375
394
 
376
395
  def test_can_source_while
377
- assert_resource "while c do body end"
396
+ assert_resource_ml "while c; end"
397
+ assert_resource_ml "while c; body; end"
378
398
  end
379
399
 
380
400
  def test_can_source_until
@@ -387,18 +407,19 @@ class SourcerTest < Test::Unit::TestCase
387
407
  end
388
408
 
389
409
  def test_can_source_break
390
- assert_resource "while c do a; break if b; c end"
391
- assert_resource "while c do a; break value if b; c end"
410
+ assert_resource_ml "while c; a; break if b; c; end"
411
+ assert_resource_ml "while c; a; break value if b; c; end"
392
412
  end
393
413
 
394
414
  def test_can_source_next
395
- assert_resource "while c do a; next if b; c end"
415
+ assert_resource_ml "while c; a; next if b; c; end"
416
+ assert_resource_ml "while c; a; next if b; c; end"
396
417
  end
397
418
 
398
419
  def test_can_source_case
399
- assert_resource "case a when b; c end"
400
- assert_resource "case a when b; c when d; e end"
401
- assert_resource "case a when b; c when d; e else f end"
420
+ assert_resource_ml "case a~when b; c; end"
421
+ assert_resource_ml "case a~when b; c when d; e; end"
422
+ assert_resource_ml "case a~when b; c when d; e~else~f; end"
402
423
  end
403
424
 
404
425
  def test_can_source_if_modifier
@@ -429,16 +450,16 @@ class SourcerTest < Test::Unit::TestCase
429
450
  def test_can_source_retry
430
451
  assert_resource "retry"
431
452
  end
432
-
453
+
433
454
  def test_can_source_redo
434
455
  assert_resource "redo"
435
456
  end
436
-
457
+
437
458
  def test_can_source_return
438
459
  assert_resource "return"
439
460
  assert_resource "return value"
440
461
  end
441
-
462
+
442
463
  def test_can_source_super
443
464
  assert_resource "super"
444
465
  assert_resource "super a"
@@ -457,72 +478,93 @@ class SourcerTest < Test::Unit::TestCase
457
478
  assert_resource "yield a"
458
479
  assert_resource "yield(a)"
459
480
  end
460
-
481
+
461
482
  def test_can_source_self
462
483
  assert_resource "self"
463
484
  end
464
485
 
465
486
  def test_can_source_def
466
- assert_resource "def f a; end"
467
- assert_resource "def f(); end"
468
- assert_resource "def f(a); end"
469
- assert_resource "def f(a, b); end"
470
- assert_resource "def f(a, *args); end"
471
- assert_resource "def f(a, *args, &block); end"
472
- assert_resource "def f(a); x; end"
473
- assert_resource "def f(a); x; y; end"
487
+ assert_resource_ml "def f; end"
488
+ assert_resource_ml "def f; x; end"
489
+ assert_resource_ml "def f a; end"
490
+ assert_resource_ml "def f(); end"
491
+ assert_resource_ml "def f(a); end"
492
+ assert_resource_ml "def f(a, b); end"
493
+ assert_resource_ml "def f(a, *args); end"
494
+ assert_resource_ml "def f(a, *args, &block); end"
495
+ assert_resource_ml "def f(a); x; end"
496
+ assert_resource_ml "def f(a); x; y; end"
474
497
  end
475
498
 
476
499
  def test_can_source_class_without_parent
477
- assert_resource "class X; end"
478
- assert_resource "class X; x; end"
479
- assert_resource "class X; def f(); end; end"
500
+ assert_resource_ml "class X; end"
501
+ assert_resource_ml "class X; x; end"
502
+ assert_resource_ml "class X; def f(); end; end"
480
503
  end
481
504
 
482
505
  def test_can_source_class_with_parent
483
- assert_resource "class X < Y; end"
484
- assert_resource "class X < Y; x; end"
506
+ assert_resource_ml "class X < Y; end"
507
+ assert_resource_ml "class X < Y; x; end"
485
508
  end
486
509
 
487
510
  def test_can_source_class_with_self_parent
488
- assert_resource "class X < self; end"
511
+ assert_resource_ml "class X < self; end"
489
512
  end
490
513
 
491
514
  def test_can_source_private_etc_in_class
492
- assert_resource "class X; public; def f(); end; end"
493
- assert_resource "class X; protected; def f(); end; end"
494
- assert_resource "class X; private; def f(); end; end"
495
- assert_resource "class X; def f(); end; public :f; end"
496
- assert_resource "class X; def f(); end; protected :f; end"
497
- assert_resource "class X; def f(); end; private :f; end"
515
+ assert_resource_ml "class X; public; def f(); end; end"
516
+ assert_resource_ml "class X; protected; def f(); end; end"
517
+ assert_resource_ml "class X; private; def f(); end; end"
518
+ assert_resource_ml "class X; def f(); end; public :f; end"
519
+ assert_resource_ml "class X; def f(); end; protected :f; end"
520
+ assert_resource_ml "class X; def f(); end; private :f; end"
498
521
  end
499
522
 
500
523
  def test_can_source_module
501
- assert_resource "module X; end"
502
- assert_resource "module X; x; end"
503
- assert_resource "module X; def f(); end; end"
524
+ assert_resource_ml "module X; end"
525
+ assert_resource_ml "module X; x; end"
526
+ assert_resource_ml "module X; def f(); end; end"
504
527
  end
505
528
 
506
529
  def test_can_source_BEGIN
507
- assert_resource "BEGIN { }"
508
- assert_resource "BEGIN { x }"
509
- assert_resource "BEGIN { x; y }"
530
+ assert_resource_ml "BEGIN { }"
531
+ assert_resource_ml "BEGIN {~x~}"
532
+ assert_resource_ml "BEGIN {~x; y~}"
510
533
  end
511
534
 
512
535
  def test_can_source_END
513
- assert_resource "END { }"
514
- assert_resource "END { x }"
515
- assert_resource "END { x; y }"
536
+ assert_resource_ml "END { }"
537
+ assert_resource_ml "END {~x~}"
538
+ assert_resource_ml "END {~x; y~}"
516
539
  end
517
540
 
518
541
  def test_can_source_then
519
- assert_resource "Then { a == b }"
542
+ assert_resource_ml "Then {~a == b~}"
543
+ assert_resource_ml "Then {~a == b; x~}"
544
+ end
545
+
546
+ def test_can_use_ripper_sexp_output
547
+ sexp = Ripper.sexp("a = 1")
548
+ assert_equal "a = 1", Sorcerer.source(sexp)
549
+ end
550
+
551
+ def test_can_handle_missing_statements
552
+ sexp = [:bodystmt, [:stmts_add, [:stmts_new]], nil, nil, nil]
553
+ assert_equal "", Sorcerer.source(sexp)
520
554
  end
521
555
 
522
556
  private
523
557
 
524
- def assert_resource(string, debug=nil)
525
- assert_equal string, source(string, debug)
558
+ def assert_resource(string, options={})
559
+ assert_equal string, source(string, options)
526
560
  end
527
-
561
+
562
+ def assert_resource_ml(string, options={})
563
+ expected = string.gsub(/~/, " ")
564
+ assert_equal expected, source(expected, options)
565
+
566
+ expected_ml = string.gsub(/~/, "\n").gsub(/; /, "\n")
567
+ assert_equal expected_ml, source(expected_ml, {multiline: true}.merge(options))
568
+ end
569
+
528
570
  end
metadata CHANGED
@@ -1,12 +1,8 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sorcerer
3
3
  version: !ruby/object:Gem::Version
4
- prerelease: false
5
- segments:
6
- - 0
7
- - 0
8
- - 7
9
- version: 0.0.7
4
+ prerelease:
5
+ version: 0.1.0
10
6
  platform: ruby
11
7
  authors:
12
8
  - Jim Weirich
@@ -14,18 +10,17 @@ autorequire:
14
10
  bindir: bin
15
11
  cert_chain: []
16
12
 
17
- date: 2010-04-23 00:00:00 -04:00
18
- default_executable:
13
+ date: 2012-07-01 00:00:00 Z
19
14
  dependencies: []
20
15
 
21
- description: " Generate the original Ruby source from a Ripper-style abstract syntax tree.\n"
16
+ description: Generate the original Ruby source from a Ripper-style abstract syntax tree.
22
17
  email: jim.weirich@gmail.com
23
18
  executables: []
24
19
 
25
20
  extensions: []
26
21
 
27
- extra_rdoc_files:
28
- - README.textile
22
+ extra_rdoc_files: []
23
+
29
24
  files:
30
25
  - README.textile
31
26
  - Rakefile
@@ -39,7 +34,6 @@ files:
39
34
  - lib/sorcerer.rb
40
35
  - test/sorcerer/resource_test.rb
41
36
  - test/sorcerer/subexpression_test.rb
42
- has_rdoc: true
43
37
  homepage: http://github.com/jimweirich/sorcerer
44
38
  licenses: []
45
39
 
@@ -54,23 +48,21 @@ rdoc_options:
54
48
  require_paths:
55
49
  - lib
56
50
  required_ruby_version: !ruby/object:Gem::Requirement
51
+ none: false
57
52
  requirements:
58
53
  - - ">="
59
54
  - !ruby/object:Gem::Version
60
- segments:
61
- - 0
62
55
  version: "0"
63
56
  required_rubygems_version: !ruby/object:Gem::Requirement
57
+ none: false
64
58
  requirements:
65
59
  - - ">="
66
60
  - !ruby/object:Gem::Version
67
- segments:
68
- - 0
69
61
  version: "0"
70
62
  requirements: []
71
63
 
72
64
  rubyforge_project: sorcerer
73
- rubygems_version: 1.3.6
65
+ rubygems_version: 1.8.15
74
66
  signing_key:
75
67
  specification_version: 3
76
68
  summary: Generate Source from Ripper ASTs