lodestone-assert-agile 0.4.1
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/CHANGELOG +1 -0
- data/LICENSE +22 -0
- data/README +16 -0
- data/Rakefile +0 -0
- data/assert-agile.gemspec +32 -0
- data/init.rb +1 -0
- data/install.rb +0 -0
- data/lib/assert_agile.rb +219 -0
- data/lib/assert_latest_and_greatest.rb +65 -0
- data/lib/ruby_reflector.rb +831 -0
- data/tasks/assert_agile_tasks.rb +0 -0
- data/test/assert_agile_test.rb +0 -0
- data/uninstall.rb +0 -0
- metadata +93 -0
data/CHANGELOG
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
0.4.1 Updated README
|
data/LICENSE
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2008 Matt Petty (matt@kizmeta.com)
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person
|
4
|
+
obtaining a copy of this software and associated documentation
|
5
|
+
files (the "Software"), to deal in the Software without
|
6
|
+
restriction, including without limitation the rights to use,
|
7
|
+
copy, modify, merge, publish, distribute, sublicense, and/or sell
|
8
|
+
copies of the Software, and to permit persons to whom the
|
9
|
+
Software is furnished to do so, subject to the following
|
10
|
+
conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be
|
13
|
+
included in all copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
16
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
17
|
+
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
18
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
19
|
+
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
20
|
+
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
21
|
+
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
22
|
+
OTHER DEALINGS IN THE SOFTWARE.
|
data/README
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
A fork of Phlip's assert2 (http://assert2.rubyforge.org) with bug fixes and merged assert_latest
|
2
|
+
|
3
|
+
assert { foo == 42 }
|
4
|
+
|
5
|
+
# For Rails or anything responding to .maximum and .find
|
6
|
+
assert_latest Account, User do
|
7
|
+
account = Account.create(:name => 'Foo Mart')
|
8
|
+
account.users.create(:login => 'foo-guy')
|
9
|
+
end
|
10
|
+
|
11
|
+
# You can grab the created records thusly:
|
12
|
+
account, user = assert_latest Account, User do
|
13
|
+
account = Account.create(:name => 'Foo Mart')
|
14
|
+
account.users.create(:login => 'foo-guy')
|
15
|
+
end
|
16
|
+
|
data/Rakefile
ADDED
File without changes
|
@@ -0,0 +1,32 @@
|
|
1
|
+
Gem::Specification.new do |s|
|
2
|
+
s.name = "assert-agile"
|
3
|
+
s.version = "0.4.1"
|
4
|
+
s.date = "2008-11-07"
|
5
|
+
s.summary = "Assert with radioactive spider power."
|
6
|
+
s.email = "matt@kizmeta.com"
|
7
|
+
s.homepage = "http://github.com/lodestone/assert-agile"
|
8
|
+
s.description = "Assertion Sugar. Better block assertions - Forked from assert2.rubyforge.org"
|
9
|
+
s.has_rdoc = true
|
10
|
+
s.authors = ["Matt Petty"]
|
11
|
+
s.files = [
|
12
|
+
"CHANGELOG",
|
13
|
+
"LICENSE",
|
14
|
+
"assert-agile.gemspec",
|
15
|
+
"init.rb",
|
16
|
+
"install.rb",
|
17
|
+
"lib/assert_agile.rb",
|
18
|
+
"lib/assert_latest_and_greatest.rb",
|
19
|
+
"lib/ruby_reflector.rb",
|
20
|
+
"Rakefile",
|
21
|
+
"README",
|
22
|
+
"tasks/assert_agile_tasks.rb",
|
23
|
+
"test/assert_agile_test.rb",
|
24
|
+
"uninstall.rb"
|
25
|
+
]
|
26
|
+
s.test_files = ["test/assert_agile_test.rb"]
|
27
|
+
s.rdoc_options = ["--main", "README"]
|
28
|
+
s.extra_rdoc_files = ["CHANGELOG", "README"]
|
29
|
+
s.add_dependency("diff-lcs", ["> 0.0.0"])
|
30
|
+
s.add_dependency("mime-types", ["> 0.0.0"])
|
31
|
+
s.add_dependency("open4", ["> 0.0.0"])
|
32
|
+
end
|
data/init.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require 'assert_agile' if RAILS_ENV == 'test'
|
data/install.rb
ADDED
File without changes
|
data/lib/assert_agile.rb
ADDED
@@ -0,0 +1,219 @@
|
|
1
|
+
require 'test/unit'
|
2
|
+
require File.dirname(__FILE__) + '/ruby_reflector'
|
3
|
+
require File.dirname(__FILE__) + '/assert_latest_and_greatest'
|
4
|
+
|
5
|
+
|
6
|
+
# FIXME evaluate parts[3]
|
7
|
+
# ERGO if the block is a block, decorate with do-end
|
8
|
+
# ERGO decorate assert_latest's block at fault time
|
9
|
+
|
10
|
+
module AssertAgile
|
11
|
+
|
12
|
+
include RubyNodeReflector
|
13
|
+
include Coulor #:nodoc:
|
14
|
+
include AssertLatestAndGreatest
|
15
|
+
# This assertion calls a block, and faults if this returns
|
16
|
+
# +false+ or +nil+. The fault diagnostic will reflect the
|
17
|
+
# intermediate value of every variable and expression in the
|
18
|
+
# block.
|
19
|
+
#
|
20
|
+
# The first argument can be a diagnostic string:
|
21
|
+
#
|
22
|
+
# assert("foo failed"){ foo() }
|
23
|
+
#
|
24
|
+
# The fault diagnostic will print that line.
|
25
|
+
#
|
26
|
+
# The next time you think to write any of these assertions...
|
27
|
+
#
|
28
|
+
# - +assert+
|
29
|
+
# - +assert_equal+
|
30
|
+
# - +assert_instance_of+
|
31
|
+
# - +assert_kind_of+
|
32
|
+
# - +assert_operator+
|
33
|
+
# - +assert_match+
|
34
|
+
# - +assert_not_nil+
|
35
|
+
#
|
36
|
+
# use <code>assert{ 2.0 }</code> instead.
|
37
|
+
#
|
38
|
+
# If no block is provided, the assertion calls +assert_classic+,
|
39
|
+
# which simulates RubyUnit's standard <code>assert()</code>.
|
40
|
+
#
|
41
|
+
# Note: This only works for Ruby 1.8.6 so far...
|
42
|
+
#
|
43
|
+
def assert(*args, &block)
|
44
|
+
if block
|
45
|
+
assert_ args.first, '', &block
|
46
|
+
else
|
47
|
+
assert_classic *args
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
# The new <code>assert()</code> calls this to interpret
|
52
|
+
# blocks of assertive statements.
|
53
|
+
#
|
54
|
+
def assert_(diagnostic = nil, twizzler = '_', &block)
|
55
|
+
# puts reflect(&block) # activate this line and test to see all your successes!
|
56
|
+
result = nil
|
57
|
+
|
58
|
+
begin
|
59
|
+
result = block.call
|
60
|
+
rescue => e
|
61
|
+
diagnostic = [diagnostic, e.inspect, *e.backtrace].compact.join("\n\t")
|
62
|
+
_flunk_2_0("\nassert#{ twizzler }{ ", diagnostic, block, result)
|
63
|
+
end
|
64
|
+
|
65
|
+
add_assertion and return if result
|
66
|
+
_flunk_2_0("assert#{ twizzler }{ ", diagnostic, block, result)
|
67
|
+
end
|
68
|
+
|
69
|
+
# This assertion replaces:
|
70
|
+
#
|
71
|
+
# - +assert_nil+
|
72
|
+
# - +assert_no_match+
|
73
|
+
# - +assert_not_equal+
|
74
|
+
#
|
75
|
+
# It faults, and prints its block's contents and values,
|
76
|
+
# if its block returns non-+false+ and non-+nil+.
|
77
|
+
#
|
78
|
+
def deny(diagnostic = nil, &block)
|
79
|
+
# "None shall pass!" --the Black Knight
|
80
|
+
# puts reflect(&block) # activate this line and test to see all your denials!
|
81
|
+
result = nil
|
82
|
+
|
83
|
+
begin
|
84
|
+
result = block.call
|
85
|
+
rescue => e
|
86
|
+
diagnostic = [diagnostic, e.inspect, *e.backtrace].compact.join("\n\t")
|
87
|
+
_flunk_2_0("\ndeny{ ", diagnostic, block, result)
|
88
|
+
end
|
89
|
+
|
90
|
+
return unless result
|
91
|
+
_flunk_2_0('deny{ ', diagnostic, block, result)
|
92
|
+
end # "You're a looney!" -- King Arthur
|
93
|
+
|
94
|
+
# Assert that a block raises a given Exception type matching
|
95
|
+
# a given message
|
96
|
+
#
|
97
|
+
# * +types+ - single exception class or array of classes
|
98
|
+
# * +matcher+ - Regular Expression to match the inner_text of XML nodes
|
99
|
+
# * +diagnostic+ - optional string to add to failure message
|
100
|
+
# * +block+ - Ruby statements that should raise an exception
|
101
|
+
#
|
102
|
+
# Examples:
|
103
|
+
# %transclude AssertXPathSuite#test_assert_raise_message_detects_assertion_failure
|
104
|
+
#
|
105
|
+
# %transclude AssertXPathSuite#test_assert_raise_message_raises_message
|
106
|
+
#
|
107
|
+
# See: {assert_raise - Don't Just Say "No"}[http://www.oreillynet.com/onlamp/blog/2007/07/assert_raise_on_ruby_dont_just.html]
|
108
|
+
#
|
109
|
+
def assert_raise_message(types, matcher, diagnostic = nil, &block)
|
110
|
+
args = [types].flatten + [diagnostic]
|
111
|
+
exception = assert_raise(*args, &block)
|
112
|
+
|
113
|
+
assert_match matcher,
|
114
|
+
exception.message,
|
115
|
+
[ diagnostic,
|
116
|
+
"incorrect #{ exception.class.name
|
117
|
+
} message raised from block:",
|
118
|
+
"\t"+reflect_source(&block).split("\n").join("\n\t")
|
119
|
+
].compact.join("\n")
|
120
|
+
|
121
|
+
return exception
|
122
|
+
end
|
123
|
+
|
124
|
+
def deny_raise_message(types, matcher, diagnostic = nil, &block) #:nodoc:
|
125
|
+
exception = assert_raise_message(types, //, diagnostic, &block)
|
126
|
+
|
127
|
+
assert_no_match matcher,
|
128
|
+
exception.message,
|
129
|
+
[ diagnostic,
|
130
|
+
"exception #{ exception.class.name
|
131
|
+
} with this message should not raise from block:",
|
132
|
+
"\t"+reflect_source(&block).split("\n").join("\n\t")
|
133
|
+
].compact.join("\n")
|
134
|
+
|
135
|
+
return exception.message
|
136
|
+
end
|
137
|
+
|
138
|
+
def assert_flunked(gripe, diagnostic = nil, &block) #:nodoc:
|
139
|
+
assert_raise_message Test::Unit::AssertionFailedError,
|
140
|
+
gripe,
|
141
|
+
diagnostic,
|
142
|
+
&block
|
143
|
+
end
|
144
|
+
|
145
|
+
def deny_flunked(gripe, diagnostic = nil, &block) #:nodoc:
|
146
|
+
deny_raise_message Test::Unit::AssertionFailedError,
|
147
|
+
gripe,
|
148
|
+
diagnostic,
|
149
|
+
&block
|
150
|
+
end # ERGO move to assert{ 2.0 }, reflect, and leave there!
|
151
|
+
|
152
|
+
# This is a copy of the classic assert, so your pre�xisting
|
153
|
+
# +assert+ calls will not change their behavior
|
154
|
+
#
|
155
|
+
def assert_classic(boolean, message=nil)
|
156
|
+
_wrap_assertion do
|
157
|
+
assert_block("assert<classic> should not be called with a block.") { !block_given? }
|
158
|
+
assert_block(build_message(message, "<?> is not true.", boolean)) { boolean }
|
159
|
+
end
|
160
|
+
end
|
161
|
+
|
162
|
+
# wrap this common idiom:
|
163
|
+
# foo = assemble()
|
164
|
+
# deny{ foo.bar() }
|
165
|
+
# foo.activate()
|
166
|
+
# assert{ foo.bar() }
|
167
|
+
#
|
168
|
+
# that becomes:
|
169
|
+
# foo = assemble()
|
170
|
+
#
|
171
|
+
# assert_yin_yang proc{ foo.bar() } do
|
172
|
+
# foo.activate()
|
173
|
+
# end
|
174
|
+
#
|
175
|
+
def assert_yin_yang(*args, &block)
|
176
|
+
# prock, diagnostic = nil, &block)
|
177
|
+
procks, diagnostic = args.partition{|p| p.respond_to? :call }
|
178
|
+
block ||= procks.shift
|
179
|
+
source = reflect_source(&block)
|
180
|
+
fuss = [diagnostic, "fault before calling:", source].compact.join("\n")
|
181
|
+
procks.each do |prock| deny(fuss, &prock); end
|
182
|
+
block.call
|
183
|
+
fuss = [diagnostic, "fault after calling:", source].compact.join("\n")
|
184
|
+
procks.each do |prock| assert(fuss, &prock); end
|
185
|
+
end
|
186
|
+
|
187
|
+
# the prock assertion must pass on both sides of the called block
|
188
|
+
#
|
189
|
+
def deny_yin_yang(prock, diagnostic = nil, &block)
|
190
|
+
source = reflect_source(&block)
|
191
|
+
fuss = [diagnostic, "fault before calling:", source].compact.join("\n")
|
192
|
+
assert fuss, &prock
|
193
|
+
block.call
|
194
|
+
fuss = [diagnostic, "fault after calling:", source].compact.join("\n")
|
195
|
+
assert fuss, &prock
|
196
|
+
end
|
197
|
+
|
198
|
+
private
|
199
|
+
def build_message_(diagnostic, reflection)
|
200
|
+
diagnostic = nil if diagnostic == ''
|
201
|
+
return [diagnostic, reflection].compact.join("\n")
|
202
|
+
end
|
203
|
+
|
204
|
+
def _flunk_2_0(polarity, diagnostic, block, result)
|
205
|
+
rf = RubyReflector.new(block)
|
206
|
+
effect = " - should #{ 'not ' if polarity =~ /deny/ }pass\n"
|
207
|
+
|
208
|
+
report = magenta(polarity) + bold(rf.result) + magenta(" }") +
|
209
|
+
red(arrow_result(result) + effect) +
|
210
|
+
rf.format_evaluations
|
211
|
+
|
212
|
+
flunk build_message_(diagnostic, report)
|
213
|
+
end
|
214
|
+
|
215
|
+
end # "Eagle-eyes it!"
|
216
|
+
|
217
|
+
class Test::Unit::TestCase #:nodoc:
|
218
|
+
include AssertAgile
|
219
|
+
end
|
@@ -0,0 +1,65 @@
|
|
1
|
+
|
2
|
+
module AssertLatestAndGreatest
|
3
|
+
|
4
|
+
# This collects every model in the given class that appears while its block runs
|
5
|
+
def assert_latest(*models, &block)
|
6
|
+
models, diagnostic = _get_latest_args(models, 'assert')
|
7
|
+
latests = get_latest(models, &block)
|
8
|
+
latests.compact.length == models.length and add_assertion or
|
9
|
+
_flunk_latest(models, latests, diagnostic, true, block)
|
10
|
+
return *latests
|
11
|
+
end
|
12
|
+
|
13
|
+
def _get_latest_args(models, what) #:nodoc:
|
14
|
+
diagnostic = nil
|
15
|
+
diagnostic = models.pop if models.last.kind_of? String
|
16
|
+
|
17
|
+
unless models.length > 0 and
|
18
|
+
(diagnostic.nil? or diagnostic.kind_of? String)
|
19
|
+
raise "call #{ what }_latest(models..., diagnostic) with any number " +
|
20
|
+
'of Model classes, followed by an optional diagnostic message'
|
21
|
+
end
|
22
|
+
return models, diagnostic
|
23
|
+
end
|
24
|
+
private :_get_latest_args
|
25
|
+
|
26
|
+
def deny_latest(*models, &block)
|
27
|
+
models, diagnostic = _get_latest_args(models, 'deny')
|
28
|
+
latests = get_latest(models, &block)
|
29
|
+
return if latests.compact.empty?
|
30
|
+
models = [latests].flatten.compact.map(&:class)
|
31
|
+
_flunk_latest(models, latests, diagnostic, false, block)
|
32
|
+
end
|
33
|
+
|
34
|
+
def get_latest(models, &block)
|
35
|
+
max_ids = models.map{|model| model.maximum(:id) || 0 }
|
36
|
+
block.call
|
37
|
+
index = -1
|
38
|
+
return models.map{|model|
|
39
|
+
any = *model.find( :all,
|
40
|
+
:conditions => "id > #{max_ids[index += 1]}",
|
41
|
+
:order => "id asc" )
|
42
|
+
any # * returns nil for [],
|
43
|
+
# one object for [x],
|
44
|
+
# or an array with more than one item
|
45
|
+
}
|
46
|
+
end
|
47
|
+
|
48
|
+
def _flunk_latest(models, latests, diagnostic, polarity, block) #:nodoc:
|
49
|
+
model_names = models.map(&:name)
|
50
|
+
model_names.each_with_index do |it, index|
|
51
|
+
model_names[index] = nil if !!latests[index] == polarity
|
52
|
+
end
|
53
|
+
model_names = model_names.compact.join(', ')
|
54
|
+
rationale = "should#{ ' not' unless polarity
|
55
|
+
} create new #{ model_names
|
56
|
+
} record(s) in block:\n\t\t#{
|
57
|
+
reflect_source(&block).gsub("\n", "\n\t\t")
|
58
|
+
}\n"
|
59
|
+
# RubyNodeReflector::RubyReflector.new(block, false).result }"
|
60
|
+
# note we don't evaluate...
|
61
|
+
flunk build_message(diagnostic, rationale)
|
62
|
+
end
|
63
|
+
private :_flunk_latest
|
64
|
+
|
65
|
+
end
|
@@ -0,0 +1,831 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'rubynode'
|
3
|
+
require 'pp'
|
4
|
+
|
5
|
+
|
6
|
+
module RubyNodeReflector
|
7
|
+
|
8
|
+
# ERGO
|
9
|
+
# :bmethod => [:cval],
|
10
|
+
# :cfunc => [:argc, :cfnc],
|
11
|
+
# :cref => [:next, :clss],
|
12
|
+
# :defs => [:mid, :defn, :recv],
|
13
|
+
# :dmethod => [:cval],
|
14
|
+
# :dot2 => [:beg, :end],
|
15
|
+
# :dot3 => [:beg, :end],
|
16
|
+
# :dregx_once => [:next, :lit, :cflag],
|
17
|
+
# :fbody => [:orig, :mid, :head],
|
18
|
+
# :flip2 => [:cnt, :beg, :end],
|
19
|
+
# :flip3 => [:cnt, :beg, :end],
|
20
|
+
# :gasgn => [:vid, :value], # entry not supported
|
21
|
+
# :ifunc => [:tval, :state, :cfnc],
|
22
|
+
# :lasgn => [:vid, :cnt, :value],
|
23
|
+
# :last => [],
|
24
|
+
# :match => [:lit],
|
25
|
+
# :memo => {:u1_value=>:u1_value}, # different uses in enum.c, variabe.c and eval.c ...
|
26
|
+
# :method => [:body, :noex, :cnt], # cnt seems to be always 0 in 1.8.4
|
27
|
+
# :module => [:cpath, :body],
|
28
|
+
# :next => [:stts],
|
29
|
+
# :opt_n => [:body],
|
30
|
+
# :to_ary => [:head],
|
31
|
+
|
32
|
+
# This +reflect+s a block of code, by evaluating it, reflecting its
|
33
|
+
# source, and reflecting all its intermediate values
|
34
|
+
#
|
35
|
+
def reflect(&block)
|
36
|
+
result = block.call
|
37
|
+
rf = RubyReflector.new(block)
|
38
|
+
|
39
|
+
begin
|
40
|
+
waz = rf.colorize?
|
41
|
+
rf.colorize(false)
|
42
|
+
return rf.result + arrow_result(result) + "\n" + rf.format_evaluations
|
43
|
+
ensure
|
44
|
+
rf.colorize(waz)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
def arrow_result(result) #:nodoc:
|
49
|
+
return "\t--> #{ result.inspect }"
|
50
|
+
end
|
51
|
+
private :arrow_result
|
52
|
+
|
53
|
+
# This +reflect+s a block of code, /without/ evaluating it.
|
54
|
+
# The function only compiles the source and reflects it as
|
55
|
+
# a string of disassembled Ruby
|
56
|
+
#
|
57
|
+
def reflect_source(&block)
|
58
|
+
return RubyReflector.new(block, false).result
|
59
|
+
end
|
60
|
+
|
61
|
+
# This compiles a string and +reflect+s its source...
|
62
|
+
# as another string.
|
63
|
+
#
|
64
|
+
def reflect_string(string)
|
65
|
+
rf = RubyReflector.new(proc{})
|
66
|
+
rf.reflect_values = false
|
67
|
+
# pp string.parse_to_nodes.transform
|
68
|
+
got = rf.reflect_nodes(string.parse_to_nodes)
|
69
|
+
return got
|
70
|
+
end
|
71
|
+
|
72
|
+
module Coulor #:nodoc:
|
73
|
+
def colorize(we_color)
|
74
|
+
@@we_color = we_color
|
75
|
+
end
|
76
|
+
unless defined? BOLD
|
77
|
+
BOLD = "\e[1m"
|
78
|
+
CLEAR = "\e[0m"
|
79
|
+
end # ERGO modularize these; anneal with Win32
|
80
|
+
def colour(text, colour_code)
|
81
|
+
return colour_code + text + CLEAR if colorize?
|
82
|
+
return text
|
83
|
+
end
|
84
|
+
def colorize? # ERGO how other libraries set these options transparent??
|
85
|
+
we_color = (@@we_color rescue true ) # ERGO parens needed?
|
86
|
+
return (we_color == :always or we_color && $stdout.tty?)
|
87
|
+
end
|
88
|
+
def bold(text)
|
89
|
+
return BOLD + text + CLEAR if colorize?
|
90
|
+
return text
|
91
|
+
end
|
92
|
+
def green(text); colour(text, "\e[32m"); end
|
93
|
+
def red(text); colour(text, "\e[31m"); end
|
94
|
+
def magenta(text); colour(text, "\e[35m"); end
|
95
|
+
def blue(text); colour(text, "\e[34m"); end
|
96
|
+
def orange(text); colour(text, "\e[3Bm"); end
|
97
|
+
end
|
98
|
+
|
99
|
+
class RubyReflector # turn hamburger back into live cattle
|
100
|
+
include Coulor
|
101
|
+
attr_reader :evaluations,
|
102
|
+
:result
|
103
|
+
attr_writer :reflect_values
|
104
|
+
|
105
|
+
def initialize(block, reflect_values = true) # note that a block, from your context, is not optional
|
106
|
+
@reflect_values = reflect_values
|
107
|
+
@evaluations = []
|
108
|
+
@result = ''
|
109
|
+
@block = block
|
110
|
+
@line = 0
|
111
|
+
reflect_nodes(@block.body_node)
|
112
|
+
end
|
113
|
+
|
114
|
+
def reflect_nodes(body_node)
|
115
|
+
return unless body_node
|
116
|
+
@transformation = body_node.transform(:include_node => true)
|
117
|
+
return @result = _send(@transformation)
|
118
|
+
rescue
|
119
|
+
puts "\nOffending line: #{ @line }"
|
120
|
+
# pp @transformation
|
121
|
+
# puts @result
|
122
|
+
raise
|
123
|
+
end
|
124
|
+
|
125
|
+
def eval_intermediate_guarded(expression)
|
126
|
+
begin
|
127
|
+
intermediate = eval(expression, @block.binding)
|
128
|
+
@evaluations << [expression, intermediate, nil]
|
129
|
+
rescue SyntaxError => e
|
130
|
+
if e.message.index('syntax error, unexpected \',\'') and expression !~ /\[ /
|
131
|
+
return eval_intermediate_guarded('[ ' + expression + ' ]')
|
132
|
+
end # faint prayer to infinite recursion diety here! (-;
|
133
|
+
|
134
|
+
@evaluations << [expression, nil, e.message]
|
135
|
+
rescue => e
|
136
|
+
@evaluations << [expression, nil, e.message]
|
137
|
+
end
|
138
|
+
end
|
139
|
+
|
140
|
+
def eval_intermediate(expression)
|
141
|
+
eval_intermediate_guarded(expression) if @reflect_values
|
142
|
+
return expression
|
143
|
+
end
|
144
|
+
|
145
|
+
def short_inspect(intermediate)
|
146
|
+
pretty = intermediate.inspect
|
147
|
+
# ERGO Proc is prob'ly rare here!
|
148
|
+
pretty = { '#<Proc' => '<Proc>' }.fetch(pretty.split(':').first, pretty)
|
149
|
+
prettier = pretty[0..90]
|
150
|
+
prettier << '*** ' unless prettier == pretty
|
151
|
+
return prettier
|
152
|
+
end
|
153
|
+
private :short_inspect
|
154
|
+
|
155
|
+
# ERGO spew the backrefs (?) any regular expression matchers may emit!
|
156
|
+
# ERGO don't eval the caller of a block without its block!
|
157
|
+
|
158
|
+
def format_evaluations
|
159
|
+
max_line = @evaluations.map{|exp, val, prob| exp.length}.sort.last
|
160
|
+
already = {}
|
161
|
+
lines = []
|
162
|
+
|
163
|
+
@evaluations.each do |exp, val, prob|
|
164
|
+
line = " #{ exp.center(max_line) } "
|
165
|
+
|
166
|
+
line << if prob then
|
167
|
+
orange('--? ' + prob)
|
168
|
+
else
|
169
|
+
green('--> ') + bold(short_inspect(val))
|
170
|
+
end
|
171
|
+
|
172
|
+
lines << line unless already[line] == true
|
173
|
+
already[line] = true
|
174
|
+
end
|
175
|
+
|
176
|
+
return lines.compact.join("\n")
|
177
|
+
end
|
178
|
+
|
179
|
+
def _send(node, thence = '')
|
180
|
+
return '' unless node
|
181
|
+
return node.to_s + thence if node.class == Symbol
|
182
|
+
target = :"_#{ node.first }"
|
183
|
+
last = node.last
|
184
|
+
(@line = last[:node].line) rescue nil
|
185
|
+
exp = send(target, last)
|
186
|
+
exp << thence if exp.length > 0
|
187
|
+
return exp
|
188
|
+
end
|
189
|
+
|
190
|
+
%w( args beg body cond cpath defn else end ensr
|
191
|
+
first head iter ivar lit mid next second
|
192
|
+
stts recv resq rest value var vid ).each do |sender|
|
193
|
+
define_method sender + '_' do |node, *args|
|
194
|
+
return _send(node[sender.to_sym], *args)
|
195
|
+
end
|
196
|
+
end
|
197
|
+
|
198
|
+
########################################################
|
199
|
+
#### structures
|
200
|
+
|
201
|
+
def _block(node)
|
202
|
+
return node.map{|n| _send(n, "\n") }.join
|
203
|
+
end
|
204
|
+
|
205
|
+
def _module(node, what = 'module')
|
206
|
+
return what + ' ' + cpath_(node) + "\n" +
|
207
|
+
body_(node) +
|
208
|
+
"\nend\n"
|
209
|
+
end
|
210
|
+
|
211
|
+
def _method(node)
|
212
|
+
p node
|
213
|
+
return ''
|
214
|
+
end
|
215
|
+
|
216
|
+
def _class(node); _module(node, 'class'); end
|
217
|
+
def _self(node); 'self'; end
|
218
|
+
def _defn(node); _defs(node); end
|
219
|
+
def _super(node); 'super(' + args_(node) + ')'; end
|
220
|
+
def _zsuper(node); 'super'; end
|
221
|
+
def _begin(node); "begin\n" + body_(node) + "\nend\n"; end
|
222
|
+
def _ensure(node); head_(node) + "\nensure\n" + ensr_(node); end
|
223
|
+
|
224
|
+
def _sclass(node)
|
225
|
+
return 'class << ' + recv_(node) +
|
226
|
+
head_body(node) +
|
227
|
+
"end\n"
|
228
|
+
end
|
229
|
+
|
230
|
+
class ScopeMethod #:nodoc:
|
231
|
+
# this is complex because Ruby gloms several different
|
232
|
+
# kinds of variables into one "scope" token, and they
|
233
|
+
# don't directly match their layout in the source code
|
234
|
+
|
235
|
+
def _scopic(ref, node)
|
236
|
+
@ref = ref
|
237
|
+
@node = node
|
238
|
+
@expression = ''
|
239
|
+
@previously = false
|
240
|
+
@block_arg = false
|
241
|
+
@splat_arg = false
|
242
|
+
@previous_splat = false
|
243
|
+
|
244
|
+
if @node[:tbl]
|
245
|
+
@expression << '('
|
246
|
+
render_argument_list
|
247
|
+
@expression << ')'
|
248
|
+
end
|
249
|
+
|
250
|
+
@expression << "\n"
|
251
|
+
@expression << @ref.next_(@node)
|
252
|
+
return @expression
|
253
|
+
end
|
254
|
+
|
255
|
+
def ulterior_comma(token)
|
256
|
+
@expression << ', ' if @index > 0
|
257
|
+
@expression << token
|
258
|
+
@index = 0
|
259
|
+
end
|
260
|
+
|
261
|
+
def possible_comma(token)
|
262
|
+
@expression << ', ' if @index > 0
|
263
|
+
@expression << @ref._send(token)
|
264
|
+
end
|
265
|
+
|
266
|
+
def render_argument_list
|
267
|
+
@nekst = @node[:next]
|
268
|
+
@block = @nekst.last if @nekst && @nekst.first == :block
|
269
|
+
@args = @block.first.last if @block && @block.first.first == :args
|
270
|
+
@rest = @args[:rest] if @args
|
271
|
+
@opt = @args[:opt] if @args
|
272
|
+
|
273
|
+
@node[:tbl].each_with_index do |_n, _index|
|
274
|
+
@n, @index = _n, _index
|
275
|
+
render_argument
|
276
|
+
break if @block_arg
|
277
|
+
end
|
278
|
+
end
|
279
|
+
|
280
|
+
def render_argument
|
281
|
+
@splat_arg = @block_arg = false
|
282
|
+
|
283
|
+
if @rest and @rest.first == :lasgn and
|
284
|
+
(@n == nil or @rest.last[:vid] == @n)
|
285
|
+
ulterior_comma('*')
|
286
|
+
@splat_arg = true
|
287
|
+
end
|
288
|
+
|
289
|
+
if @block and (ba = @block[1]) and
|
290
|
+
ba.first == :block_arg and ba.last[:vid] == @n
|
291
|
+
ulterior_comma('&')
|
292
|
+
@block_arg = true
|
293
|
+
end
|
294
|
+
|
295
|
+
# ERGO Ruby 1.9 changes these rules!!
|
296
|
+
|
297
|
+
if !@previous_splat or @block_arg
|
298
|
+
if @opt and @opt.first == :block and # ERGO why a @block??
|
299
|
+
(lasgn = @opt.last.first).first == :lasgn and
|
300
|
+
lasgn.last[:vid] == @n
|
301
|
+
@previously = true
|
302
|
+
possible_comma(@opt.last.first)
|
303
|
+
else
|
304
|
+
possible_comma(@n)
|
305
|
+
@expression << ' = nil' if @previously and !@block_arg and !@splat_arg
|
306
|
+
end
|
307
|
+
|
308
|
+
@previous_splat ||= @splat_arg
|
309
|
+
end
|
310
|
+
end
|
311
|
+
end
|
312
|
+
|
313
|
+
def _scope(node)
|
314
|
+
return ScopeMethod.new._scopic(self, node)
|
315
|
+
end
|
316
|
+
|
317
|
+
def _defs(node)
|
318
|
+
return 'def ' + recv_(node, '.') + mid_(node) +
|
319
|
+
defn_(node) +
|
320
|
+
"end\n"
|
321
|
+
end
|
322
|
+
|
323
|
+
def _rescue(node)
|
324
|
+
if node[:else] == false and node[:head] and
|
325
|
+
node[:resq] and node[:head].first == :vcall
|
326
|
+
return head_(node) + ' rescue ' + resq_(node)
|
327
|
+
else
|
328
|
+
exp = head_(node) +
|
329
|
+
else_(node) +
|
330
|
+
"rescue"
|
331
|
+
if node[:resq] and node[:resq].first == :resbody
|
332
|
+
body = node[:resq].last
|
333
|
+
exp << ' ' + args_(body) if body and body[:args]
|
334
|
+
end
|
335
|
+
return exp + "\n" + resq_(node)
|
336
|
+
end
|
337
|
+
end
|
338
|
+
|
339
|
+
def _resbody(node)
|
340
|
+
return body_(node)
|
341
|
+
# already emitted: head_(node) + ' ' + args_(node)
|
342
|
+
end
|
343
|
+
|
344
|
+
def _yield(node)
|
345
|
+
exp = 'yield'
|
346
|
+
exp << '(' + head_(node) + ')' if node[:head]
|
347
|
+
return exp
|
348
|
+
end
|
349
|
+
|
350
|
+
def _alias(node)
|
351
|
+
return "alias #{ lit_(node[:new].last) } #{ lit_(node[:old].last) }"
|
352
|
+
end
|
353
|
+
|
354
|
+
def _valias(node)
|
355
|
+
return "alias #{ node[:new] } #{ node[:old] }"
|
356
|
+
end
|
357
|
+
|
358
|
+
########################################################
|
359
|
+
#### control flow
|
360
|
+
|
361
|
+
def _if(node)
|
362
|
+
expression = '( if ' + eval_parenz{cond_(node)} + ' then '
|
363
|
+
expression << eval_parenz{body_(node)} if node[:body]
|
364
|
+
expression << ' else ' +
|
365
|
+
eval_parenz{else_(node)} if node[:else]
|
366
|
+
expression << ' end )'
|
367
|
+
return expression
|
368
|
+
end
|
369
|
+
|
370
|
+
def _while(node, concept = 'while')
|
371
|
+
return '( ' + concept + ' ' + cond_(node) +
|
372
|
+
head_body(node) +
|
373
|
+
"\nend )"
|
374
|
+
end
|
375
|
+
|
376
|
+
def _for(node)
|
377
|
+
return '( for ' + var_(node) + ' in ' + iter_(node) + "\n" +
|
378
|
+
body_(node) + "\n" +
|
379
|
+
'end )'
|
380
|
+
end
|
381
|
+
|
382
|
+
def _args(node); return ''; end # _call and _fcall insert the real args
|
383
|
+
def _until(node); _while(node, 'until'); end
|
384
|
+
def _break(node); 'break'; end
|
385
|
+
def _next(node); 'next' ; end
|
386
|
+
def _case(node); '( case ' + head_body(node) + "\nend )"; end
|
387
|
+
def _when(node); 'when ' + head_body(node) + "\n" + next_(node); end
|
388
|
+
def _retry(node); 'retry'; end
|
389
|
+
def _redo(node); 'redo'; end
|
390
|
+
def head_body(node); head_(node) + "\n" + body_(node); end
|
391
|
+
|
392
|
+
def _return(node)
|
393
|
+
exp = 'return'
|
394
|
+
return exp unless stts = node[:stts]
|
395
|
+
exp << ' '
|
396
|
+
|
397
|
+
if stts.first == :array
|
398
|
+
exp << '[' + stts_(node) + ']'
|
399
|
+
elsif stts.first == :svalue
|
400
|
+
exp << stts_(node)
|
401
|
+
else
|
402
|
+
exp << eval_parenz{stts_(node)}
|
403
|
+
end
|
404
|
+
|
405
|
+
return exp
|
406
|
+
end
|
407
|
+
|
408
|
+
def _postexe(node)
|
409
|
+
raise '_postexe called with unexpected arguments' unless node == {} or node.keys == [:node]
|
410
|
+
return 'END'
|
411
|
+
end
|
412
|
+
|
413
|
+
# :argscat => [:body, :head],
|
414
|
+
|
415
|
+
########################################################
|
416
|
+
#### assignments
|
417
|
+
|
418
|
+
def _dasgn_curr(node)
|
419
|
+
expression = vid_(node)
|
420
|
+
return expression unless value = node[:value]
|
421
|
+
expression << ' = '
|
422
|
+
we_b_array = value.first == :array
|
423
|
+
expression << nest_if(we_b_array, '[', ']'){ value_(node) }
|
424
|
+
return expression
|
425
|
+
end
|
426
|
+
|
427
|
+
def _cdecl(node)
|
428
|
+
return _send(node[ node[:vid] == 0 ? :else : :vid ]) + ' = ' + value_(node)
|
429
|
+
end
|
430
|
+
|
431
|
+
def _dasgn(node); _dasgn_curr(node); end
|
432
|
+
def _iasgn(node); _dasgn_curr(node); end
|
433
|
+
def _gasgn(node); _dasgn_curr(node); end
|
434
|
+
def _lasgn(node); _dasgn_curr(node); end
|
435
|
+
def _cvasgn(node); _dasgn_curr(node); end
|
436
|
+
|
437
|
+
def _op_asgn2(node)
|
438
|
+
expression = ''
|
439
|
+
|
440
|
+
if node[:recv].first == :self
|
441
|
+
expression << 'self'
|
442
|
+
else
|
443
|
+
expression << recv_(node)
|
444
|
+
end
|
445
|
+
|
446
|
+
expression << '.'
|
447
|
+
expression << vid_(node[:next].last) + ' ||= ' + value_(node)
|
448
|
+
return expression
|
449
|
+
end
|
450
|
+
|
451
|
+
########################################################
|
452
|
+
#### operators
|
453
|
+
|
454
|
+
def _and(node, und = 'and')
|
455
|
+
return eval_intermediate( '( ' +
|
456
|
+
eval_parenz{ first_(node)} + ' ' + und + ' ' +
|
457
|
+
eval_parenz{second_(node)} + ' )' )
|
458
|
+
end
|
459
|
+
|
460
|
+
def _back_ref(node); '$' + node[:nth].chr; end
|
461
|
+
def _colon2(node); head_(node, '::') + mid_(node); end
|
462
|
+
def _colon3(node); '::' + mid_(node); end
|
463
|
+
def _cvar(node); _lvar(node); end
|
464
|
+
def _cvdecl(node); vid_(node) + ' = ' + value_(node); end
|
465
|
+
def _defined(node); 'defined? ' + head_(node); end
|
466
|
+
def _dot2(node); '( ' + beg_(node) + ' .. ' + end_(node) + ' )'; end
|
467
|
+
def _dot3(node); '( ' + beg_(node) + ' ... ' + end_(node) + ' )'; end
|
468
|
+
def _dregx(node); _dstr(node, '/'); end
|
469
|
+
def _dregx_once(node); _dstr(node, '/'); end
|
470
|
+
def _dsym(node); ':' + _lit(node[:lit]) + ' ' + rest_(node); end
|
471
|
+
def _dvar(node); eval_intermediate(vid_(node)); end
|
472
|
+
def _dxstr(node); _dstr(node, '`'); end
|
473
|
+
def eval_parenz; eval_intermediate('( ' + yield + ' )'); end
|
474
|
+
def _evstr(node); body_(node); end
|
475
|
+
def _false(nada); 'false'; end
|
476
|
+
def _gvar(node); vid_(node); end
|
477
|
+
def _ivar(node); _dvar(node); end
|
478
|
+
def _lit(node); node[:lit].inspect; end
|
479
|
+
def _lvar(node); eval_intermediate(vid_(node)); end
|
480
|
+
def _match(node); node[:lit].inspect; end
|
481
|
+
def neg_one(node); node == -1 ? '' : _send(node); end
|
482
|
+
def _nil(nada); 'nil' ; end
|
483
|
+
def _not(node); '(not(' + body_(node) + '))'; end
|
484
|
+
def _nth_ref(node); "$#{ node[:nth] }"; end # ERGO eval it?
|
485
|
+
def _op_asgn_and(node); _op_asgn_or(node, ' &&= '); end
|
486
|
+
def _or(node); _and(node, 'or'); end
|
487
|
+
def _str(node); _lit(node); end
|
488
|
+
def _svalue(node); head_(node); end
|
489
|
+
def _to_ary(node); head_(node); end
|
490
|
+
def _true(nada); 'true' ; end
|
491
|
+
def _undef(node); 'undef ' + mid_(node); end
|
492
|
+
def _vcall(node); mid_(node); end
|
493
|
+
def we_b(node); node.first.first; end
|
494
|
+
def _xstr(node); '`' + scrape_literal(node) + '`'; end
|
495
|
+
def _zarray(node); return '[]'; end
|
496
|
+
|
497
|
+
def _flip2(node) # ERGO what the heck is this??
|
498
|
+
p node
|
499
|
+
p node.keys
|
500
|
+
return ''
|
501
|
+
end
|
502
|
+
|
503
|
+
def _masgn(node)
|
504
|
+
|
505
|
+
#{:value=>
|
506
|
+
# [:splat,
|
507
|
+
# {:head=>
|
508
|
+
# [:fcall,
|
509
|
+
# {:mid=>:calc_stack,
|
510
|
+
# :args=>
|
511
|
+
# [:array,
|
512
|
+
# [[:vcall, {:mid=>:insn}],
|
513
|
+
# [:vcall, {:mid=>:from}],
|
514
|
+
# [:vcall, {:mid=>:after}],
|
515
|
+
# [:vcall, {:mid=>:opops}]]]}]}],
|
516
|
+
# :args=>false,
|
517
|
+
# :head=>
|
518
|
+
# [:array,
|
519
|
+
# [[:dasgn_curr, {:value=>false, :vid=>:name}],
|
520
|
+
# [:dasgn_curr, {:value=>false, :vid=>:pops}],
|
521
|
+
# [:dasgn_curr, {:value=>false, :vid=>:rets}],
|
522
|
+
# [:dasgn_curr, {:value=>false, :vid=>:pushs1}],
|
523
|
+
# [:dasgn_curr, {:value=>false, :vid=>:pushs2}]]]}
|
524
|
+
|
525
|
+
value, head, args = node.values_at(:value, :head, :args)
|
526
|
+
|
527
|
+
if value
|
528
|
+
return '( ' + head_(node) + ' = *' + head_(value.last) + ' )' if value.first == :splat
|
529
|
+
|
530
|
+
if head and args
|
531
|
+
exp = head_(node)
|
532
|
+
return exp + ', * = ' + value_(node) if args == -1
|
533
|
+
return exp + ', *' + args_(node) + ' = ' + value_(node)
|
534
|
+
end
|
535
|
+
|
536
|
+
return '( ' + head_(node) + ' = ' + value_(node) + ' )' if args == false
|
537
|
+
end
|
538
|
+
|
539
|
+
if value == false and head == false and args
|
540
|
+
return '*' + neg_one(args)
|
541
|
+
end
|
542
|
+
|
543
|
+
if head.kind_of?(Array) and head.first == :array
|
544
|
+
return head.last.map{|n|
|
545
|
+
nest_if(n.first == :masgn, '(', ')'){ _send(n) }
|
546
|
+
}.join(', ')
|
547
|
+
end
|
548
|
+
|
549
|
+
if head == false and args and value
|
550
|
+
return '*' + args_(node) + ' = ' + value_(node)
|
551
|
+
end
|
552
|
+
|
553
|
+
return head_(node)
|
554
|
+
end
|
555
|
+
|
556
|
+
def _splat(node)
|
557
|
+
if (head = node[:head]) and
|
558
|
+
((we_b_array = head.first == :array) or head.first == :lvar)
|
559
|
+
return '*' + nest_if(we_b_array, '[', ']'){ head_(node) }
|
560
|
+
end
|
561
|
+
|
562
|
+
return '*' + head_(node)
|
563
|
+
end # ERGO raise if any other key!
|
564
|
+
|
565
|
+
def _const(node)
|
566
|
+
expression = vid_(node)
|
567
|
+
q = eval(expression, @block.binding)
|
568
|
+
eval_intermediate(expression) unless q.kind_of?(Module)
|
569
|
+
return expression
|
570
|
+
rescue # ERGO will someone need to see whatever this was?
|
571
|
+
return expression
|
572
|
+
end
|
573
|
+
|
574
|
+
def scrape_literal(node, regex = false)
|
575
|
+
lit = node[:lit].inspect.gsub(/^"/, '').gsub(/"$/, '')
|
576
|
+
lit.gsub!('\\\\', '\\') if regex
|
577
|
+
return lit
|
578
|
+
end
|
579
|
+
|
580
|
+
def _dstr(node, delim = '"')
|
581
|
+
regex = delim == '/'
|
582
|
+
expression = delim + scrape_literal(node, regex)
|
583
|
+
|
584
|
+
if node[:next] and node[:next].first == :array
|
585
|
+
(node[:next].last || []).each do |n|
|
586
|
+
expression << if n.first == :str
|
587
|
+
scrape_literal(n.last, regex)
|
588
|
+
else
|
589
|
+
'#{ ' + _send(n) + ' }'
|
590
|
+
end
|
591
|
+
end
|
592
|
+
end
|
593
|
+
|
594
|
+
return eval_intermediate(expression + delim)
|
595
|
+
end
|
596
|
+
|
597
|
+
def _retry(node)
|
598
|
+
raise '_retry called with unexpected arguments' unless node == {} or node.keys == [:node]
|
599
|
+
return 'retry'
|
600
|
+
end
|
601
|
+
|
602
|
+
def recv_zero_self(node, plus = '')
|
603
|
+
recv = node[:recv]
|
604
|
+
return 'self' + plus if recv == 0
|
605
|
+
return recv_(node, plus)
|
606
|
+
end
|
607
|
+
|
608
|
+
def _attrasgn(node)
|
609
|
+
recv, args = node.values_at(:recv, :args)
|
610
|
+
|
611
|
+
if args
|
612
|
+
if args.first == :array
|
613
|
+
if node[:mid].class == Symbol
|
614
|
+
if node[:mid] == :'[]='
|
615
|
+
return recv_zero_self(node) + '[' +
|
616
|
+
_send(args.last.first) + '] = ' +
|
617
|
+
_send(args.last.last)
|
618
|
+
end
|
619
|
+
return recv_zero_self(node, '.') + mid_(node) + '(' + _send(args.last.last) + ')'
|
620
|
+
end
|
621
|
+
end
|
622
|
+
|
623
|
+
return recv_zero_self(node) +
|
624
|
+
'[' + head_(args.last) + '] = ' +
|
625
|
+
body_(args.last)
|
626
|
+
end
|
627
|
+
|
628
|
+
return recv_zero_self(node, '.') + node[:mid].to_s.gsub(/=$/, '')
|
629
|
+
end
|
630
|
+
|
631
|
+
def _op_asgn_or(node, op = ' ||= ')
|
632
|
+
# CONSIDER what be :aid?
|
633
|
+
#{:value=>[:lasgn, {:value=>[:str, {:lit=>"vm_opts.h"}], :cnt=>2, :vid=>:file}],
|
634
|
+
# :aid=>0,
|
635
|
+
# :head=>[:lvar, {:cnt=>2, :vid=>:file}]}
|
636
|
+
return head_(node) + op + value_(node[:value].last)
|
637
|
+
end
|
638
|
+
|
639
|
+
def fcall_args(node = nil, methodic = false)
|
640
|
+
expression = ''
|
641
|
+
return expression unless node
|
642
|
+
expression << ' ' unless methodic
|
643
|
+
return expression + nest_if(methodic, '(', ')'){ _send(node) }
|
644
|
+
end
|
645
|
+
|
646
|
+
def _fcall(node)
|
647
|
+
exp = mid_(node) + fcall_args(node[:args], true)
|
648
|
+
eval_intermediate(exp) unless %w(lambda proc).include?(exp)
|
649
|
+
return exp
|
650
|
+
end
|
651
|
+
|
652
|
+
def _block_pass(node)
|
653
|
+
fcall = node[:iter].last
|
654
|
+
return eval_intermediate(recv_(fcall, '.') +
|
655
|
+
mid_(fcall) + '(' + args_(fcall, ', ') +
|
656
|
+
'&' + body_(node) + ')' )
|
657
|
+
end
|
658
|
+
|
659
|
+
def _iter(node)
|
660
|
+
var = node[:var]
|
661
|
+
|
662
|
+
return eval_intermediate(
|
663
|
+
iter_(node) +
|
664
|
+
'{' +
|
665
|
+
nest_if(var != false, '|', '|'){ var_(node) unless var == 0 } +
|
666
|
+
nest_if(node[:body] , ' ', ' '){ body_(node) } +
|
667
|
+
'}')
|
668
|
+
end
|
669
|
+
|
670
|
+
def _array(node)
|
671
|
+
nest_if we_b(node) == :array, '[', ']' do
|
672
|
+
node.map{ |z|
|
673
|
+
exp = _send(z)
|
674
|
+
exp << ', ' unless z.object_id == node.last.object_id
|
675
|
+
exp
|
676
|
+
}.join
|
677
|
+
end
|
678
|
+
end
|
679
|
+
|
680
|
+
def _hash(node)
|
681
|
+
return '{}' unless node[:head] and (array = node[:head].last)
|
682
|
+
expression = '{ '
|
683
|
+
|
684
|
+
array.in_groups_of 2 do |key, value|
|
685
|
+
expression << _send(key) + ' => ' + _send(value)
|
686
|
+
expression << ', ' if value != array.last
|
687
|
+
end
|
688
|
+
|
689
|
+
return expression + ' }'
|
690
|
+
end
|
691
|
+
|
692
|
+
def _match2(node)
|
693
|
+
# ERGO should this work like match3?
|
694
|
+
return recv_(node) + ' =~ ' + value_(node)
|
695
|
+
end
|
696
|
+
|
697
|
+
def we_b_op(node)
|
698
|
+
return node[:mid] && node[:mid].to_s !~ /^[a-z]/i
|
699
|
+
end
|
700
|
+
|
701
|
+
def _match3(node)
|
702
|
+
# ERGO do :lit and :value exclude each other?
|
703
|
+
return recv_(node) + ' =~ ' + _send(node[:lit] || node[:value])
|
704
|
+
end
|
705
|
+
|
706
|
+
def _block_arg(node) # is this ever called?
|
707
|
+
return '' # note that _scope should not take care of this
|
708
|
+
end
|
709
|
+
|
710
|
+
class CallMethod
|
711
|
+
def bracket_args
|
712
|
+
return false unless @mid == '[]'
|
713
|
+
@expression << '[' + @ref.args_(@node) + ']'
|
714
|
+
return true
|
715
|
+
end
|
716
|
+
|
717
|
+
def insert_method_call
|
718
|
+
@expression << '.'
|
719
|
+
@expression << @mid
|
720
|
+
@expression << '(' + @ref.args_(@node) + ')'
|
721
|
+
@ref.eval_intermediate(@expression) if @methodic
|
722
|
+
end
|
723
|
+
|
724
|
+
def operator_and_arguments
|
725
|
+
@mid = @ref.mid_(@node)
|
726
|
+
|
727
|
+
unless bracket_args
|
728
|
+
@methodic = @mid =~ /[a-z]/i
|
729
|
+
|
730
|
+
if @methodic
|
731
|
+
insert_method_call
|
732
|
+
else
|
733
|
+
@expression << ' '
|
734
|
+
@expression << @mid
|
735
|
+
@expression << ' '
|
736
|
+
nest_args
|
737
|
+
end
|
738
|
+
end
|
739
|
+
end
|
740
|
+
|
741
|
+
def nest_args
|
742
|
+
return unless @args = @node[:args]
|
743
|
+
|
744
|
+
nest_me = @args.first == :array &&
|
745
|
+
@args.last.length == 1 &&
|
746
|
+
(call = @args.last.first).first == :call &&
|
747
|
+
@ref.we_b_op(call.last)
|
748
|
+
|
749
|
+
exp = @ref.nest_if(nest_me, '( ', ' )'){ @ref.args_(@node) }
|
750
|
+
@ref.eval_intermediate(exp) if nest_me
|
751
|
+
@expression << exp
|
752
|
+
end
|
753
|
+
|
754
|
+
def caller(ref, node)
|
755
|
+
@ref, @node = ref, node
|
756
|
+
@expression = ''
|
757
|
+
@recv = @node[:recv]
|
758
|
+
|
759
|
+
if @recv.first == :block_pass
|
760
|
+
@expression << @ref.recv_(@node)
|
761
|
+
operator_and_arguments
|
762
|
+
else
|
763
|
+
nest_me = @recv.first == :call && @ref.we_b_op(@recv.last)
|
764
|
+
|
765
|
+
exp = if @recv.first == :array
|
766
|
+
@ref.nest_if(true, '[ ', ' ]'){ @ref.recv_(node) }
|
767
|
+
else
|
768
|
+
exp2 = @ref.nest_if(nest_me, '( ', ' )'){ @ref.recv_(node) }
|
769
|
+
@ref.eval_intermediate(exp2) if nest_me
|
770
|
+
exp2
|
771
|
+
end
|
772
|
+
|
773
|
+
@expression << exp
|
774
|
+
operator_and_arguments
|
775
|
+
end
|
776
|
+
return @expression
|
777
|
+
end
|
778
|
+
end
|
779
|
+
|
780
|
+
def _call(node); CallMethod.new.caller(self, node); end
|
781
|
+
|
782
|
+
def nest_if(condition, before, after, &block)
|
783
|
+
exp = ''
|
784
|
+
exp << before if condition
|
785
|
+
exp << (block.call || '')
|
786
|
+
exp << after if condition
|
787
|
+
return exp
|
788
|
+
end
|
789
|
+
|
790
|
+
def _op_asgn1(node) # ERGO just look up the list of these?
|
791
|
+
return '' unless args = node[:args]
|
792
|
+
exp = recv_(node)
|
793
|
+
|
794
|
+
if [:'-', :'+', :'*', :'**', :'/', :^, :|, :&,
|
795
|
+
:'<<', :'>>',
|
796
|
+
].include?(node[:mid]) and
|
797
|
+
node[:recv] and args.first == :argscat
|
798
|
+
|
799
|
+
return exp +
|
800
|
+
"[#{ body_(args.last) }] #{ node[:mid] }= " + head_(args.last)
|
801
|
+
end
|
802
|
+
|
803
|
+
raise "unexpected mid value #{ node[:mid].inspect } in opcode for X= " unless node[:mid] == 0
|
804
|
+
|
805
|
+
if args.first == :argscat and args.last[:body]
|
806
|
+
exp << '[' + body_(args.last) + ']'
|
807
|
+
exp << ' ||= ' + head_(args.last)
|
808
|
+
else
|
809
|
+
raise "unexpected arguments in opcode for ||= "
|
810
|
+
end
|
811
|
+
|
812
|
+
return exp
|
813
|
+
end
|
814
|
+
|
815
|
+
def _argscat(node)
|
816
|
+
return head_(node) + ', *' +
|
817
|
+
nest_if(node[:body].first == :array, '[', ']'){ body_(node) }
|
818
|
+
end
|
819
|
+
|
820
|
+
end
|
821
|
+
|
822
|
+
end
|
823
|
+
|
824
|
+
class Array
|
825
|
+
def in_groups_of(number, fill_with = nil, &block)
|
826
|
+
require 'enumerator'
|
827
|
+
collection = dup
|
828
|
+
collection << fill_with until collection.size.modulo(number).zero?
|
829
|
+
collection.each_slice(number, &block)
|
830
|
+
end
|
831
|
+
end
|
File without changes
|
File without changes
|
data/uninstall.rb
ADDED
File without changes
|
metadata
ADDED
@@ -0,0 +1,93 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: lodestone-assert-agile
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.4.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Matt Petty
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
|
12
|
+
date: 2008-11-07 00:00:00 -08:00
|
13
|
+
default_executable:
|
14
|
+
dependencies:
|
15
|
+
- !ruby/object:Gem::Dependency
|
16
|
+
name: diff-lcs
|
17
|
+
version_requirement:
|
18
|
+
version_requirements: !ruby/object:Gem::Requirement
|
19
|
+
requirements:
|
20
|
+
- - ">"
|
21
|
+
- !ruby/object:Gem::Version
|
22
|
+
version: 0.0.0
|
23
|
+
version:
|
24
|
+
- !ruby/object:Gem::Dependency
|
25
|
+
name: mime-types
|
26
|
+
version_requirement:
|
27
|
+
version_requirements: !ruby/object:Gem::Requirement
|
28
|
+
requirements:
|
29
|
+
- - ">"
|
30
|
+
- !ruby/object:Gem::Version
|
31
|
+
version: 0.0.0
|
32
|
+
version:
|
33
|
+
- !ruby/object:Gem::Dependency
|
34
|
+
name: open4
|
35
|
+
version_requirement:
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: 0.0.0
|
41
|
+
version:
|
42
|
+
description: Assertion Sugar. Better block assertions - Forked from assert2.rubyforge.org
|
43
|
+
email: matt@kizmeta.com
|
44
|
+
executables: []
|
45
|
+
|
46
|
+
extensions: []
|
47
|
+
|
48
|
+
extra_rdoc_files:
|
49
|
+
- CHANGELOG
|
50
|
+
- README
|
51
|
+
files:
|
52
|
+
- CHANGELOG
|
53
|
+
- LICENSE
|
54
|
+
- assert-agile.gemspec
|
55
|
+
- init.rb
|
56
|
+
- install.rb
|
57
|
+
- lib/assert_agile.rb
|
58
|
+
- lib/assert_latest_and_greatest.rb
|
59
|
+
- lib/ruby_reflector.rb
|
60
|
+
- Rakefile
|
61
|
+
- README
|
62
|
+
- tasks/assert_agile_tasks.rb
|
63
|
+
- test/assert_agile_test.rb
|
64
|
+
- uninstall.rb
|
65
|
+
has_rdoc: true
|
66
|
+
homepage: http://github.com/lodestone/assert-agile
|
67
|
+
post_install_message:
|
68
|
+
rdoc_options:
|
69
|
+
- --main
|
70
|
+
- README
|
71
|
+
require_paths:
|
72
|
+
- lib
|
73
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
74
|
+
requirements:
|
75
|
+
- - ">="
|
76
|
+
- !ruby/object:Gem::Version
|
77
|
+
version: "0"
|
78
|
+
version:
|
79
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
80
|
+
requirements:
|
81
|
+
- - ">="
|
82
|
+
- !ruby/object:Gem::Version
|
83
|
+
version: "0"
|
84
|
+
version:
|
85
|
+
requirements: []
|
86
|
+
|
87
|
+
rubyforge_project:
|
88
|
+
rubygems_version: 1.2.0
|
89
|
+
signing_key:
|
90
|
+
specification_version: 2
|
91
|
+
summary: Assert with radioactive spider power.
|
92
|
+
test_files:
|
93
|
+
- test/assert_agile_test.rb
|