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 +2 -0
- data/Manifest.txt +2 -0
- data/lib/rewrite/prelude/andand.rb +1 -1
- data/lib/rewrite/prelude/please.rb +195 -0
- data/lib/rewrite/prelude/try.rb +90 -0
- data/lib/rewrite/prelude.rb +6 -1
- data/lib/rewrite/version.rb +1 -1
- data/website/index.html +1 -1
- metadata +3 -1
data/History.txt
CHANGED
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
|
@@ -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
|
data/lib/rewrite/prelude.rb
CHANGED
data/lib/rewrite/version.rb
CHANGED
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.
|
36
|
+
<a href="http://rubyforge.org/projects/rewrite" class="numbers">0.0.4</a>
|
37
37
|
</div>
|
38
38
|
<h1>→ ‘rewrite’</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.
|
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
|