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 +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
|