rewrite 0.0.3 → 0.0.4

Sign up to get free protection for your applications and to get access to all the features.
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