live_ast 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGES.rdoc +6 -0
- data/MANIFEST +54 -0
- data/README.rdoc +388 -0
- data/Rakefile +19 -0
- data/devel/jumpstart.rb +983 -0
- data/lib/live_ast/ast_eval.rb +13 -0
- data/lib/live_ast/ast_load.rb +15 -0
- data/lib/live_ast/base.rb +56 -0
- data/lib/live_ast/cache.rb +14 -0
- data/lib/live_ast/error.rb +30 -0
- data/lib/live_ast/evaler.rb +66 -0
- data/lib/live_ast/linker.rb +107 -0
- data/lib/live_ast/loader.rb +69 -0
- data/lib/live_ast/parser.rb +48 -0
- data/lib/live_ast/replace_load.rb +14 -0
- data/lib/live_ast/replace_raise.rb +21 -0
- data/lib/live_ast/to_ast.rb +17 -0
- data/lib/live_ast/to_ruby.rb +12 -0
- data/lib/live_ast/version.rb +3 -0
- data/lib/live_ast.rb +4 -0
- data/test/ast_eval_feature_test.rb +11 -0
- data/test/ast_load_feature_test.rb +11 -0
- data/test/backtrace_test.rb +159 -0
- data/test/covert_define_method_test.rb +23 -0
- data/test/def_test.rb +35 -0
- data/test/define_method_test.rb +41 -0
- data/test/define_singleton_method_test.rb +15 -0
- data/test/encoding_test/bad.rb +1 -0
- data/test/encoding_test/cp932.rb +6 -0
- data/test/encoding_test/default.rb +5 -0
- data/test/encoding_test/eucjp.rb +6 -0
- data/test/encoding_test/koi8.rb +6 -0
- data/test/encoding_test/koi8_shebang.rb +7 -0
- data/test/encoding_test/usascii.rb +6 -0
- data/test/encoding_test/utf8.rb +6 -0
- data/test/encoding_test.rb +51 -0
- data/test/error_test.rb +115 -0
- data/test/eval_test.rb +269 -0
- data/test/flush_cache_test.rb +98 -0
- data/test/lambda_test.rb +56 -0
- data/test/load_path_test.rb +84 -0
- data/test/load_test.rb +85 -0
- data/test/noninvasive_test.rb +51 -0
- data/test/readme_test.rb +11 -0
- data/test/recursive_eval_test.rb +52 -0
- data/test/redefine_method_test.rb +83 -0
- data/test/reload_test.rb +108 -0
- data/test/shared/ast_generators.rb +124 -0
- data/test/shared/main.rb +110 -0
- data/test/stdlib_test.rb +11 -0
- data/test/thread_test.rb +44 -0
- data/test/to_ast_feature_test.rb +15 -0
- data/test/to_ruby_feature_test.rb +15 -0
- data/test/to_ruby_test.rb +86 -0
- metadata +223 -0
data/CHANGES.rdoc
ADDED
data/MANIFEST
ADDED
@@ -0,0 +1,54 @@
|
|
1
|
+
CHANGES.rdoc
|
2
|
+
MANIFEST
|
3
|
+
README.rdoc
|
4
|
+
Rakefile
|
5
|
+
devel/jumpstart.rb
|
6
|
+
lib/live_ast.rb
|
7
|
+
lib/live_ast/ast_eval.rb
|
8
|
+
lib/live_ast/ast_load.rb
|
9
|
+
lib/live_ast/base.rb
|
10
|
+
lib/live_ast/cache.rb
|
11
|
+
lib/live_ast/error.rb
|
12
|
+
lib/live_ast/evaler.rb
|
13
|
+
lib/live_ast/linker.rb
|
14
|
+
lib/live_ast/loader.rb
|
15
|
+
lib/live_ast/parser.rb
|
16
|
+
lib/live_ast/replace_load.rb
|
17
|
+
lib/live_ast/replace_raise.rb
|
18
|
+
lib/live_ast/to_ast.rb
|
19
|
+
lib/live_ast/to_ruby.rb
|
20
|
+
lib/live_ast/version.rb
|
21
|
+
test/ast_eval_feature_test.rb
|
22
|
+
test/ast_load_feature_test.rb
|
23
|
+
test/backtrace_test.rb
|
24
|
+
test/covert_define_method_test.rb
|
25
|
+
test/def_test.rb
|
26
|
+
test/define_method_test.rb
|
27
|
+
test/define_singleton_method_test.rb
|
28
|
+
test/encoding_test.rb
|
29
|
+
test/encoding_test/bad.rb
|
30
|
+
test/encoding_test/cp932.rb
|
31
|
+
test/encoding_test/default.rb
|
32
|
+
test/encoding_test/eucjp.rb
|
33
|
+
test/encoding_test/koi8.rb
|
34
|
+
test/encoding_test/koi8_shebang.rb
|
35
|
+
test/encoding_test/usascii.rb
|
36
|
+
test/encoding_test/utf8.rb
|
37
|
+
test/error_test.rb
|
38
|
+
test/eval_test.rb
|
39
|
+
test/flush_cache_test.rb
|
40
|
+
test/lambda_test.rb
|
41
|
+
test/load_path_test.rb
|
42
|
+
test/load_test.rb
|
43
|
+
test/noninvasive_test.rb
|
44
|
+
test/readme_test.rb
|
45
|
+
test/recursive_eval_test.rb
|
46
|
+
test/redefine_method_test.rb
|
47
|
+
test/reload_test.rb
|
48
|
+
test/shared/ast_generators.rb
|
49
|
+
test/shared/main.rb
|
50
|
+
test/stdlib_test.rb
|
51
|
+
test/thread_test.rb
|
52
|
+
test/to_ast_feature_test.rb
|
53
|
+
test/to_ruby_feature_test.rb
|
54
|
+
test/to_ruby_test.rb
|
data/README.rdoc
ADDED
@@ -0,0 +1,388 @@
|
|
1
|
+
|
2
|
+
= LiveAST
|
3
|
+
|
4
|
+
== Summary
|
5
|
+
|
6
|
+
A pure Ruby library for obtaining live abstract syntax trees of
|
7
|
+
methods and procs.
|
8
|
+
|
9
|
+
== Synopsis
|
10
|
+
|
11
|
+
require 'live_ast'
|
12
|
+
|
13
|
+
class Greet
|
14
|
+
def default
|
15
|
+
"hello"
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
#### ASTs of methods
|
20
|
+
|
21
|
+
m = Greet.instance_method(:default)
|
22
|
+
|
23
|
+
p m.to_ast
|
24
|
+
# => s(:defn, :default, s(:args), s(:scope, s(:block, s(:str, "hello"))))
|
25
|
+
|
26
|
+
#### ASTs of lambdas, procs, blocks
|
27
|
+
|
28
|
+
f = lambda { "foo" }
|
29
|
+
|
30
|
+
p f.to_ast
|
31
|
+
# => s(:iter, s(:call, nil, :lambda, s(:arglist)), nil, s(:str, "foo"))
|
32
|
+
|
33
|
+
def query(&block)
|
34
|
+
p block.to_ast
|
35
|
+
# => s(:iter, s(:call, nil, :query, s(:arglist)), nil, s(:str, "bar"))
|
36
|
+
end
|
37
|
+
|
38
|
+
query do
|
39
|
+
"bar"
|
40
|
+
end
|
41
|
+
|
42
|
+
#### ASTs from dynamic code
|
43
|
+
|
44
|
+
f = ast_eval "lambda { 'dynamic' }", binding
|
45
|
+
|
46
|
+
p f.to_ast
|
47
|
+
# => s(:iter, s(:call, nil, :lambda, s(:arglist)), nil, s(:str, "dynamic"))
|
48
|
+
|
49
|
+
ast_eval "def g ; 'dynamic' ; end", binding
|
50
|
+
m = method(:g)
|
51
|
+
|
52
|
+
p m.to_ast
|
53
|
+
# => s(:defn, :g, s(:args), s(:scope, s(:block, s(:str, "dynamic"))))
|
54
|
+
|
55
|
+
== Install
|
56
|
+
|
57
|
+
% gem install live_ast
|
58
|
+
|
59
|
+
== Description
|
60
|
+
|
61
|
+
LiveAST enables a program to find the ASTs of objects created by
|
62
|
+
dynamically generated code. It may be used in a strictly noninvasive
|
63
|
+
manner, where no standard classes or methods are modified, or it may
|
64
|
+
be transparently integrated into Ruby (experimental). The default
|
65
|
+
setting is in between.
|
66
|
+
|
67
|
+
RubyParser is responsible for parsing and building the ASTs, though
|
68
|
+
another parser may be easily substituted (in fact the name +to_ast+ is
|
69
|
+
used instead of +to_sexp+ because LiveAST has no understanding of what
|
70
|
+
the parser outputs).
|
71
|
+
|
72
|
+
LiveAST is thread-safe.
|
73
|
+
|
74
|
+
Ruby 1.9.2 or higher is required.
|
75
|
+
|
76
|
+
== Links
|
77
|
+
|
78
|
+
* Documentation: http://liveast.rubyforge.org
|
79
|
+
* Rubyforge home: http://rubyforge.org/projects/liveast/
|
80
|
+
* Repository: http://github.com/quix/live_ast
|
81
|
+
|
82
|
+
== +to_ruby+
|
83
|
+
|
84
|
+
Although the ruby2ruby package (<code>gem install ruby2ruby</code>) is
|
85
|
+
not an official dependency of LiveAST, for convenience
|
86
|
+
|
87
|
+
require 'live_ast/to_ruby'
|
88
|
+
|
89
|
+
will require ruby2ruby and define the +to_ruby+ method for +Method+,
|
90
|
+
+UnboundMethod+, and +Proc+. These methods are one-liners which pass
|
91
|
+
the extracted ASTs to ruby2ruby.
|
92
|
+
|
93
|
+
require 'live_ast'
|
94
|
+
require 'live_ast/to_ruby'
|
95
|
+
|
96
|
+
p lambda { |x, y| x + y }.to_ruby # => "lambda { |x, y| (x + y) }"
|
97
|
+
|
98
|
+
class A
|
99
|
+
def f
|
100
|
+
"A#f"
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
p A.instance_method(:f).to_ruby # => "def f\n \"A#f\"\nend"
|
105
|
+
|
106
|
+
== Loading Source
|
107
|
+
|
108
|
+
Objects created via +require+ and +load+ will be AST-accessible.
|
109
|
+
However +ast_eval+ must be used instead of +eval+ for AST-accessible
|
110
|
+
objects. +ast_eval+ has the same semantics as +eval+ except that the
|
111
|
+
binding argument is required.
|
112
|
+
|
113
|
+
require 'live_ast'
|
114
|
+
|
115
|
+
class A
|
116
|
+
ast_eval %{
|
117
|
+
def f
|
118
|
+
"A#f"
|
119
|
+
end
|
120
|
+
|
121
|
+
# nested evals OK
|
122
|
+
ast_eval %{
|
123
|
+
def g
|
124
|
+
"A#g"
|
125
|
+
end
|
126
|
+
}, binding
|
127
|
+
|
128
|
+
}, binding
|
129
|
+
end
|
130
|
+
|
131
|
+
p A.instance_method(:f).to_ast
|
132
|
+
# => s(:defn, :f, s(:args), s(:scope, s(:block, s(:str, "A#f"))))
|
133
|
+
|
134
|
+
p A.instance_method(:g).to_ast
|
135
|
+
# => s(:defn, :g, s(:args), s(:scope, s(:block, s(:str, "A#g"))))
|
136
|
+
|
137
|
+
== Limitations
|
138
|
+
|
139
|
+
A method or block definition must not share a line with other methods
|
140
|
+
or blocks in order for its AST to be available.
|
141
|
+
|
142
|
+
require 'live_ast'
|
143
|
+
|
144
|
+
class A
|
145
|
+
def f ; end ; def g ; end
|
146
|
+
end
|
147
|
+
A.instance_method(:f).to_ast # => raises LiveAST::MultipleDefinitionsOnSameLineError
|
148
|
+
|
149
|
+
a = lambda { } ; b = lambda { }
|
150
|
+
a.to_ast # => raises LiveAST::MultipleDefinitionsOnSameLineError
|
151
|
+
|
152
|
+
== Technical Issues
|
153
|
+
|
154
|
+
You can probably ignore this section. Goodbye.
|
155
|
+
|
156
|
+
=== Replacing the Parser
|
157
|
+
|
158
|
+
Despite its name, LiveAST knows nothing about ASTs. It merely reports
|
159
|
+
what it finds in the line-to-AST hash obtained from
|
160
|
+
<code>LiveAST::Parser#parse</code>. Replacing the +Parser+ class is
|
161
|
+
therefore easy: the only specification is that the +parse+ method
|
162
|
+
return such a hash.
|
163
|
+
|
164
|
+
Supposing your new <code>LiveAST::Parser</code> is defined in
|
165
|
+
<code>/path/to/my/code/live_ast/parser.rb</code>,
|
166
|
+
|
167
|
+
$LOAD_PATH.unshift '/path/to/my/code'
|
168
|
+
require 'live_ast'
|
169
|
+
|
170
|
+
will override LiveAST's default parser with your own. To test it,
|
171
|
+
provide some examples of what your ASTs look like in
|
172
|
+
<code>tests/shared/ast_generators.rb</code>.
|
173
|
+
|
174
|
+
=== Noninvasive Mode
|
175
|
+
|
176
|
+
For safety purposes, <code>require 'live_ast'</code> performs the
|
177
|
+
invasive act of redefining +load+ (but not +require+); otherwise bad
|
178
|
+
things can happen to the unwary. The addition of +to_ast+ to a few
|
179
|
+
standard Ruby classes is also a meddlesome move.
|
180
|
+
|
181
|
+
To avoid these modifications,
|
182
|
+
|
183
|
+
require 'live_ast/base'
|
184
|
+
|
185
|
+
will provide the essentials of LiveAST but will not touch core classes
|
186
|
+
or methods.
|
187
|
+
|
188
|
+
To select features individually,
|
189
|
+
|
190
|
+
require 'live_ast/to_ast' # define to_ast for Method, UnboundMethod, Proc
|
191
|
+
require 'live_ast/to_ruby' # define to_ruby for Method, UnboundMethod, Proc
|
192
|
+
require 'live_ast/ast_eval' # define Kernel#ast_eval
|
193
|
+
require 'live_ast/ast_load' # define Kernel#ast_load (mentioned below)
|
194
|
+
require 'live_ast/replace_load' # redefine Kernel#load
|
195
|
+
|
196
|
+
=== Noninvasive Interface
|
197
|
+
|
198
|
+
The following alternative interface is available.
|
199
|
+
|
200
|
+
require 'live_ast/base'
|
201
|
+
|
202
|
+
class A
|
203
|
+
def f
|
204
|
+
"A#f"
|
205
|
+
end
|
206
|
+
end
|
207
|
+
|
208
|
+
p LiveAST.ast(A.instance_method(:f))
|
209
|
+
# => s(:defn, :f, s(:args), s(:scope, s(:block, s(:str, "A#f"))))
|
210
|
+
|
211
|
+
p LiveAST.ast(lambda { })
|
212
|
+
# => s(:iter, s(:call, nil, :lambda, s(:arglist)), nil, nil)
|
213
|
+
|
214
|
+
f = LiveAST.eval("lambda { }", binding)
|
215
|
+
|
216
|
+
p LiveAST.ast(f)
|
217
|
+
# => s(:iter, s(:call, nil, :lambda, s(:arglist)), nil, nil)
|
218
|
+
|
219
|
+
ast_eval # => raises NameError
|
220
|
+
|
221
|
+
=== Reloading Files In Noninvasive Mode
|
222
|
+
|
223
|
+
Use +ast_load+ or (equivalently) <code>LiveAST.load</code> when
|
224
|
+
reloading an AST-aware file.
|
225
|
+
|
226
|
+
require 'live_ast/ast_load'
|
227
|
+
require 'live_ast/to_ast'
|
228
|
+
|
229
|
+
require "foo"
|
230
|
+
Foo.instance_method(:bar).to_ast # caches AST
|
231
|
+
|
232
|
+
# ... the bar method is changed in foo.rb ...
|
233
|
+
|
234
|
+
ast_load "foo.rb"
|
235
|
+
p Foo.instance_method(:bar).to_ast # => updated AST
|
236
|
+
|
237
|
+
Note if +load+ is called instead of +ast_load+ then the last line will
|
238
|
+
give the old AST,
|
239
|
+
|
240
|
+
load "foo.rb" # oops! forgot to use ast_load
|
241
|
+
p Foo.instance_method(:bar).to_ast # => stale AST
|
242
|
+
|
243
|
+
Realize that +foo.rb+ may be referenced by an unknown number of
|
244
|
+
methods and blocks. If the original +foo.rb+ source were dumped in
|
245
|
+
favor of the modified +foo.rb+, then an unknown number of those
|
246
|
+
references would be invalidated (and some may even point to the wrong
|
247
|
+
AST!).
|
248
|
+
|
249
|
+
This is the reason for the caching that results in the stale AST
|
250
|
+
above. It should now be clear why the default behavior of
|
251
|
+
<code>require 'live_ast'</code> is to redefine +load+: doing so
|
252
|
+
prevents this problem entirely. On the other hand if it is fully known
|
253
|
+
where and when files are being reloaded (if at all) then there's no
|
254
|
+
need for paranoia; this noninvasive option may be most the
|
255
|
+
appropriate.
|
256
|
+
|
257
|
+
=== The Source/AST Cache
|
258
|
+
|
259
|
+
+ast_eval+ and +load+ cache all incoming code, while
|
260
|
+
<code>require</code>d files are cached on a need-to-know basis. When
|
261
|
+
an AST is requested, the corresponding source is parsed and discarded,
|
262
|
+
leaving behind method and block ASTs. +to_ast+ removes an AST from the
|
263
|
+
cache and attaches it to the appropriate object (a Proc or Module).
|
264
|
+
|
265
|
+
Ignored, unextracted ASTs will therefore linger in the cache. Since
|
266
|
+
sexps are generally small there is little need for concern unless one
|
267
|
+
is continually evaling/reloading <em>and</em> failing to extract the
|
268
|
+
sexps. Nevertheless it is possible that old ASTs will eventually need
|
269
|
+
to be garbage collected. To flush the cache,
|
270
|
+
|
271
|
+
(1) Check that +to_ast+ has been called on all objects whose ASTs are
|
272
|
+
desired.
|
273
|
+
|
274
|
+
(2) Call <code>LiveAST.flush_cache</code>.
|
275
|
+
|
276
|
+
Calling +to_ast+ prevents the object's AST from being flushed (since
|
277
|
+
it grafts the AST onto the object).
|
278
|
+
|
279
|
+
ASTs of procs and methods whose sources lie in <code>require</code>d
|
280
|
+
files will never be flushed. However a method redefined via +ast_eval+
|
281
|
+
or +load+ is susceptible to +flush_cache+ even when its original
|
282
|
+
definition pointed to a <code>require</code>d file.
|
283
|
+
|
284
|
+
=== About +require+
|
285
|
+
|
286
|
+
No measures have been taken to detect manipulations of
|
287
|
+
<code>$LOADED_FEATURES</code> which would cause +require+ to load the
|
288
|
+
same file twice. Though +require+ <em>could</em> be replaced in
|
289
|
+
similar fashion to +load+--heading off problems arising from such
|
290
|
+
"raw" reloads--the overhead would seem inappropriate in relation to
|
291
|
+
the rarity of this case.
|
292
|
+
|
293
|
+
Therefore the working assumption is that +require+ will load a file
|
294
|
+
only once. Furthermore, if a file has not been reloaded then it is
|
295
|
+
assumed that the file is unmodified between the moment it is
|
296
|
+
<code>require</code>d and the moment the first AST is pulled from it.
|
297
|
+
|
298
|
+
=== Backtraces
|
299
|
+
|
300
|
+
+ast_eval+ is meant to be compatible with +eval+. For instance the
|
301
|
+
first line of the backtrace should be identical to that of +eval+:
|
302
|
+
|
303
|
+
require 'live_ast'
|
304
|
+
|
305
|
+
ast_eval %{ raise "boom" }, binding
|
306
|
+
# => test.rb:3:in `<main>': boom (RuntimeError)
|
307
|
+
|
308
|
+
Let's make a slight change,
|
309
|
+
|
310
|
+
require 'live_ast'
|
311
|
+
|
312
|
+
f = ast_eval %{ lambda { raise "boom" } }, binding
|
313
|
+
f.call
|
314
|
+
# => test.rb|ast@a:3:in `block in <main>': boom (RuntimeError)
|
315
|
+
|
316
|
+
Oh no! What the heck is '<code>|ast@a</code>' doing there? LiveAST's
|
317
|
+
implementation has just been exposed: each source input is assigned a
|
318
|
+
unique key that enables a Ruby object to find its own definition.
|
319
|
+
|
320
|
+
In the first case above, +ast_eval+ has removed the key from the
|
321
|
+
exception backtrace. But in the second case there is no opportunity to
|
322
|
+
remove it since +ast_eval+ has already returned.
|
323
|
+
|
324
|
+
If you find this to be problem--for example if you cannot add a filter
|
325
|
+
for the jump-to-location feature in your editor--then +raise+ may be
|
326
|
+
redefined to strip these tokens,
|
327
|
+
|
328
|
+
require 'live_ast'
|
329
|
+
require 'live_ast/replace_raise'
|
330
|
+
|
331
|
+
f = ast_eval %{ lambda { raise "boom" } }, binding
|
332
|
+
f.call
|
333
|
+
# => test.rb:4:in `block in <main>': boom (RuntimeError)
|
334
|
+
|
335
|
+
However this only applies to a +raise+ call originating from Ruby
|
336
|
+
code. An exception raised within a native method will likely still
|
337
|
+
contain the token in its backtrace (e.g., in MRI the exception raised
|
338
|
+
by <code>1/0</code> comes from C). In principle this could be fixed by
|
339
|
+
having the Ruby interpreter dynamically call +raise+.
|
340
|
+
|
341
|
+
|
342
|
+
=== Replacing +eval+
|
343
|
+
|
344
|
+
If +ast_eval+ did not require a binding argument then it could assume
|
345
|
+
the role of +eval+, thereby making LiveAST fully transparent to the
|
346
|
+
user. Is this possible in pure Ruby?
|
347
|
+
|
348
|
+
The only option which has been investigated thus far is MRI, which can
|
349
|
+
summon <code>Binding.of_caller</code> (recently rewritten for 1.9.2)
|
350
|
+
to fill in the missing binding argument. Unfortunately a limitation
|
351
|
+
with tracing events in MRI places a few odd restrictions on the syntax
|
352
|
+
surrounding +eval+, though all restrictions can be trivially
|
353
|
+
sidestepped. Nonetheless it does work (it passes rubyspec minus the
|
354
|
+
backtrace issue) despite being somewhat impractical.
|
355
|
+
|
356
|
+
This (mis)feature is maintained in a separate branch named
|
357
|
+
+replace_eval+ on github (not part of the gem). For more information see
|
358
|
+
replace_eval.rb[http://github.com/quix/live_ast/blob/replace_eval/lib/live_ast/replace_eval.rb].
|
359
|
+
|
360
|
+
== Author
|
361
|
+
|
362
|
+
* James M. Lawrence < quixoticsycophant@gmail.com >
|
363
|
+
|
364
|
+
== License
|
365
|
+
|
366
|
+
Copyright (c) 2011 James M. Lawrence. All rights reserved.
|
367
|
+
|
368
|
+
Permission is hereby granted, free of charge, to any person
|
369
|
+
obtaining a copy of this software and associated documentation files
|
370
|
+
(the "Software"), to deal in the Software without restriction,
|
371
|
+
including without limitation the rights to use, copy, modify, merge,
|
372
|
+
publish, distribute, sublicense, and/or sell copies of the Software,
|
373
|
+
and to permit persons to whom the Software is furnished to do so,
|
374
|
+
subject to the following conditions:
|
375
|
+
|
376
|
+
The above copyright notice and this permission notice shall be
|
377
|
+
included in all copies or substantial portions of the Software.
|
378
|
+
|
379
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
380
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
381
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
382
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
383
|
+
BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
384
|
+
ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
385
|
+
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
386
|
+
SOFTWARE.
|
387
|
+
|
388
|
+
|
data/Rakefile
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
require_relative 'devel/jumpstart'
|
2
|
+
|
3
|
+
Jumpstart.new "live_ast" do |s|
|
4
|
+
s.developer "James M. Lawrence", "quixoticsycophant@gmail.com"
|
5
|
+
s.rubyforge_user = "quix"
|
6
|
+
s.rubyforge_name = "liveast"
|
7
|
+
s.camel_name = "LiveAST"
|
8
|
+
s.rdoc_title = "LiveAST: Live Abstract Syntax Trees"
|
9
|
+
|
10
|
+
# my code compensates for a ruby_parser bug; make this equal for now
|
11
|
+
s.dependency("ruby_parser", "= 2.0.5")
|
12
|
+
|
13
|
+
s.rdoc_files = %w[
|
14
|
+
README.rdoc
|
15
|
+
lib/live_ast/ast_eval.rb
|
16
|
+
lib/live_ast/base.rb
|
17
|
+
lib/live_ast/version.rb
|
18
|
+
]
|
19
|
+
end
|