rewrite 0.0.3 → 0.0.4

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/History.txt CHANGED
@@ -6,3 +6,5 @@
6
6
  * Got the manifest right
7
7
  * 3 tiny enhancement:
8
8
  * added Please to the Prelude
9
+ * 4 tiny enhancement:
10
+ * added Try to the Prelude
data/Manifest.txt CHANGED
@@ -12,6 +12,8 @@ lib/rewrite/evaluation_strategies.rb
12
12
  lib/rewrite/prelude.rb
13
13
  lib/rewrite/prelude/andand.rb
14
14
  lib/rewrite/prelude/called_by_name.rb
15
+ lib/rewrite/prelude/please.rb
16
+ lib/rewrite/prelude/try.rb
15
17
  lib/rewrite/variables.rb
16
18
  lib/rewrite/version.rb
17
19
  lib/rewrite/with.rb
@@ -33,7 +33,7 @@ module Rewrite
33
33
  # end
34
34
  # }.call(numbers)
35
35
  #
36
- # See also: Try
36
+ # See also: Please, Try
37
37
  #
38
38
  class Andand < SexpProcessor
39
39
 
@@ -0,0 +1,195 @@
1
+ $:.unshift File.dirname(__FILE__)
2
+
3
+ require 'rubygems'
4
+ require 'parse_tree'
5
+ require 'sexp_processor'
6
+ require 'sexp'
7
+
8
+ module Rewrite
9
+
10
+ module Prelude
11
+
12
+ # Adds a polite method invocation to Ruby:
13
+ #
14
+ # with(please) do
15
+ # ...
16
+ # @phone = Location.find(:first, ...elided... ).please.phone
17
+ # ...
18
+ # end
19
+ #
20
+ # Based on "try()":http://ozmm.org/posts/try.html by Chris Wanstrath, but
21
+ # with method chaining syntax instead of with a send-like syntax.
22
+ #
23
+ # It also works with parameters, blocks, and procs passed as blocks.
24
+ #
25
+ # Works by rewriting expressions like:
26
+ #
27
+ # numbers.please.inject(&:+)
28
+ #
29
+ # Into:
30
+ #
31
+ # lambda { |__1234567890__|
32
+ # if __1234567890__.respond_to? :inject
33
+ # __1234567890__.inject(&:+)
34
+ # end
35
+ # }.call(numbers)
36
+ #
37
+ # See also: Try, Andand
38
+ #
39
+ class Please < SexpProcessor
40
+
41
+ def process_iter(exp)
42
+ exp.shift
43
+ receiver_sexp = exp.first #[:call, [:call, [:lit, 1..10], :please], :inject]
44
+ if receiver_sexp[0] == :call && matches_please_invocation(receiver_sexp[1])
45
+ exp.shift
46
+ mono_parameter = Rewrite.gensym()
47
+ s(:call,
48
+ s(:iter,
49
+ s(:fcall, :lambda),
50
+ s(:dasgn_curr, mono_parameter),
51
+ #[:if, [:call, [:dvar, :mono], :respond_to?, [:array, [:lit, :foo]]], [:call, [:dvar, :mono], :foo], nil]
52
+ s(:if,
53
+ s(:call, s(:dvar, mono_parameter), :respond_to?, s(:array, s(:lit, receiver_sexp[2]))),
54
+ begin
55
+ s(:iter,
56
+ s(:call,
57
+ s(:dvar, mono_parameter),
58
+ *(receiver_sexp[2..-1].map { |inner| process_inner_expr inner })
59
+ ),
60
+ *(exp.map { |inner| process_inner_expr inner })
61
+ )
62
+ ensure
63
+ exp.clear
64
+ end,
65
+ s(:nil)
66
+ )
67
+ ),
68
+ :call,
69
+ s(:array,
70
+ process_inner_expr(receiver_sexp[1][1]) # s(:lit, 1..10)
71
+ )
72
+ )
73
+ else
74
+ begin
75
+ s(:iter,
76
+ *(exp.map { |inner| process_inner_expr inner })
77
+ )
78
+ ensure
79
+ exp.clear
80
+ end
81
+ end
82
+ end
83
+
84
+ def process_call(exp)
85
+ # s(:call, s(:call, s(:lit, :foo), :please), :bar)
86
+ exp.shift
87
+ # s(s(:call, s(:lit, :foo), :please), :bar)
88
+ receiver_sexp = exp.first
89
+ if matches_please_invocation(receiver_sexp) # s(:call, s(:lit, :foo), :please)
90
+ exp.shift
91
+ # s( :bar )
92
+ mono_parameter = Rewrite.gensym()
93
+ s(:call,
94
+ s(:iter,
95
+ s(:fcall, :lambda),
96
+ s(:dasgn_curr, mono_parameter),
97
+ s(:if,
98
+ s(:call, s(:dvar, mono_parameter), :respond_to?, s(:array, s(:lit, receiver_sexp[2]))),
99
+ begin
100
+ s(:call,
101
+ s(:dvar, mono_parameter),
102
+ *(exp.map { |inner| process_inner_expr inner })
103
+ )
104
+ ensure
105
+ exp.clear
106
+ end
107
+ s(:nil)
108
+ )
109
+ ),
110
+ :call,
111
+ s(:array,
112
+ process_inner_expr(receiver_sexp[1]) # s(:lit, :foo)
113
+ )
114
+ )
115
+ else
116
+ # pass through
117
+ begin
118
+ s(:call,
119
+ *(exp.map { |inner| process_inner_expr inner })
120
+ )
121
+ ensure
122
+ exp.clear
123
+ end
124
+ end
125
+ end
126
+
127
+ def process_block_pass(exp)
128
+ orig = lambda { |exp_dup|
129
+ lambda { Ruby2Ruby.new.process(exp_dup) }
130
+ }.call(exp)
131
+ # [:block_pass, [:lit, :+], [:call, [:call, [:vcall, :foo], :please], :bar]]
132
+ # [:block_pass, [:lit, :blitz], [:call, [:call, [:vcall, :foo], :please], :bar, [:array, [:lit, :bash]]]]
133
+ exp.shift
134
+ # [[:lit, :+], [:call, [:call, [:vcall, :foo], :please], :bar]]
135
+ # [[:lit, :blitz], [:call, [:call, [:vcall, :foo], :please], :bar, [:array, [:lit, :bash]]]]
136
+ block_exp = process_inner_expr(exp.shift)
137
+ call_exp = exp.shift
138
+ raise "expected block_pass to have a receiver and a call form near #{orig.call}" unless exp.empty?
139
+ # [:call, [:call, [:vcall, :foo], :please], :bar]
140
+ # [:call, [:call, [:vcall, :foo], :please], :bar, [:array, [:lit, :bash]]]
141
+ raise 'confused' unless call_exp.shift == :call
142
+ # [[:call, [:vcall, :foo], :please], :bar]
143
+ # [[:call, [:vcall, :foo], :please], :bar, [:array, [:lit, :bash]]]
144
+ receiver_sexp = call_exp.first
145
+ if matches_please_invocation(receiver_sexp) # [:call, [:vcall, :foo], :please]
146
+ call_exp.shift
147
+ # [:bar]
148
+ # [:bar, [:array, [:lit, :bash]]]
149
+ mono_parameter = Rewrite.gensym()
150
+ s(:call,
151
+ s(:iter,
152
+ s(:fcall, :lambda),
153
+ s(:dasgn_curr, mono_parameter),
154
+ s(:if,
155
+ s(:call, s(:dvar, mono_parameter), :respond_to?, s(:array, s(:lit, receiver_sexp[2]))),
156
+ s(:block_pass,
157
+ block_exp,
158
+ s(:call,
159
+ s(:dvar, mono_parameter),
160
+ *(call_exp.map { |inner| process_inner_expr inner })
161
+ )
162
+ ),
163
+ s(:nil)
164
+ )
165
+ ),
166
+ :call,
167
+ s(:array,
168
+ process_inner_expr(receiver_sexp[1]) # s(:lit, :foo)
169
+ )
170
+ )
171
+ else
172
+ s(:block_pass,
173
+ block_exp,
174
+ s(:call,
175
+ *(call_exp.map { |inner| process_inner_expr inner })
176
+ )
177
+ )
178
+ end
179
+ end
180
+
181
+ private
182
+
183
+ def process_inner_expr(inner)
184
+ inner.kind_of?(Array) ? process(inner) : inner
185
+ end
186
+
187
+ def matches_please_invocation(sexp)
188
+ sexp[0] == :call && sexp[2] == :please
189
+ end
190
+
191
+ end
192
+
193
+ end
194
+
195
+ end
@@ -0,0 +1,90 @@
1
+ $:.unshift File.dirname(__FILE__)
2
+
3
+ require 'rubygems'
4
+ require 'parse_tree'
5
+ require 'sexp_processor'
6
+ require 'sexp'
7
+
8
+ module Rewrite
9
+
10
+ module Prelude
11
+
12
+ # Adds a polite method invocation to Ruby:
13
+ #
14
+ # with(try) do
15
+ # ...
16
+ # @phone = Location.find(:first, ...elided... ).try.phone
17
+ # ...
18
+ # end
19
+ #
20
+ # Based on "try()":http://ozmm.org/posts/try.html by Chris Wanstrath, but
21
+ # with method chaining syntax instead of with a send-like syntax.
22
+ #
23
+ # It also works with parameters, blocks, and procs passed as blocks.
24
+ #
25
+ # Works by rewriting expressions like:
26
+ #
27
+ # numbers.try(:sum)
28
+ #
29
+ # Into:
30
+ #
31
+ # lambda { |receiver, message|
32
+ # receiver.send message if receiver.respond_to? message
33
+ # }.call(numbers, :sum)
34
+ #
35
+ # See also: Please, Andand
36
+ #
37
+ class Try < SexpProcessor
38
+
39
+ def process_call(exp)
40
+ # [:call, [:dvar, :foo], :try, [:array, [:lit, :bar]]]
41
+ exp.shift
42
+ # [[:dvar, :foo], :try, [:array, [:lit, :bar]]]]
43
+ receiver_sexp = exp.first
44
+ if exp[1] == :try
45
+ message_expression = exp[2][1]
46
+ exp.clear
47
+ s(:call,
48
+ s(:iter,
49
+ s(:fcall, :lambda),
50
+ s(:masgn,
51
+ s(:array,
52
+ s(:dasgn_curr, :receiver),
53
+ s(:dasgn_curr, :message)
54
+ )
55
+ ),
56
+ s(:if,
57
+ s(:call, s(:dvar, :receiver), :respond_to?, s(:array, s(:dvar, :receiver))),
58
+ s(:call, s(:dvar, :receiver), :send, s(:array, s(:dvar, :message))),
59
+ s(:nil)
60
+ )
61
+ ),
62
+ :call,
63
+ s(:array,
64
+ process_inner_expr(receiver_sexp), # [:dvar, :foo]
65
+ process_inner_expr(message_expression)
66
+ )
67
+ )
68
+ else
69
+ # pass through
70
+ begin
71
+ s(:call,
72
+ *(exp.map { |inner| process_inner_expr inner })
73
+ )
74
+ ensure
75
+ exp.clear
76
+ end
77
+ end
78
+ end
79
+
80
+ private
81
+
82
+ def process_inner_expr(inner)
83
+ inner.kind_of?(Array) ? process(inner) : inner
84
+ end
85
+
86
+ end
87
+
88
+ end
89
+
90
+ end
@@ -34,7 +34,12 @@ module Rewrite
34
34
 
35
35
  # Instantiate Please rewriting
36
36
  def please()
37
- Andand.new
37
+ Please.new
38
+ end
39
+
40
+ # Instantiate Try rewriting
41
+ def try()
42
+ Try.new
38
43
  end
39
44
 
40
45
  end
@@ -2,7 +2,7 @@ module Rewrite #:nodoc:
2
2
  module VERSION #:nodoc:
3
3
  MAJOR = 0
4
4
  MINOR = 0
5
- TINY = 3
5
+ TINY = 4
6
6
 
7
7
  STRING = [MAJOR, MINOR, TINY].join('.')
8
8
  end
data/website/index.html CHANGED
@@ -33,7 +33,7 @@
33
33
  <h1>rewrite</h1>
34
34
  <div id="version" class="clickable" onclick='document.location = "http://rubyforge.org/projects/rewrite"; return false'>
35
35
  <p>Get Version</p>
36
- <a href="http://rubyforge.org/projects/rewrite" class="numbers">0.0.3</a>
36
+ <a href="http://rubyforge.org/projects/rewrite" class="numbers">0.0.4</a>
37
37
  </div>
38
38
  <h1>&#x2192; &#8216;rewrite&#8217;</h1>
39
39
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rewrite
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.3
4
+ version: 0.0.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Reg Braithwaite
@@ -42,6 +42,8 @@ files:
42
42
  - lib/rewrite/prelude.rb
43
43
  - lib/rewrite/prelude/andand.rb
44
44
  - lib/rewrite/prelude/called_by_name.rb
45
+ - lib/rewrite/prelude/please.rb
46
+ - lib/rewrite/prelude/try.rb
45
47
  - lib/rewrite/variables.rb
46
48
  - lib/rewrite/version.rb
47
49
  - lib/rewrite/with.rb