mvz-live_ast 1.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/CHANGES.rdoc +93 -0
- data/README.rdoc +419 -0
- data/Rakefile +21 -0
- data/devel/levitate.rb +853 -0
- data/devel/levitate_config.rb +4 -0
- data/lib/live_ast.rb +4 -0
- data/lib/live_ast/ast_eval.rb +11 -0
- data/lib/live_ast/ast_load.rb +15 -0
- data/lib/live_ast/base.rb +73 -0
- data/lib/live_ast/common.rb +48 -0
- data/lib/live_ast/error.rb +20 -0
- data/lib/live_ast/evaler.rb +32 -0
- data/lib/live_ast/full.rb +2 -0
- data/lib/live_ast/irb_spy.rb +43 -0
- data/lib/live_ast/linker.rb +122 -0
- data/lib/live_ast/loader.rb +60 -0
- data/lib/live_ast/reader.rb +26 -0
- data/lib/live_ast/replace_eval.rb +121 -0
- data/lib/live_ast/replace_load.rb +14 -0
- data/lib/live_ast/replace_raise.rb +18 -0
- data/lib/live_ast/ruby_parser.rb +36 -0
- data/lib/live_ast/ruby_parser/test.rb +197 -0
- data/lib/live_ast/ruby_parser/unparser.rb +13 -0
- data/lib/live_ast/to_ast.rb +26 -0
- data/lib/live_ast/to_ruby.rb +24 -0
- data/lib/live_ast/version.rb +3 -0
- data/test/ast_eval_feature_test.rb +11 -0
- data/test/ast_load_feature_test.rb +11 -0
- data/test/attr_test.rb +24 -0
- data/test/backtrace_test.rb +158 -0
- data/test/covert_define_method_test.rb +23 -0
- data/test/def_test.rb +35 -0
- data/test/define_method_test.rb +67 -0
- data/test/define_singleton_method_test.rb +15 -0
- data/test/encoding_test.rb +52 -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/koi8_with_utf8bom.rb +6 -0
- data/test/encoding_test/usascii.rb +6 -0
- data/test/encoding_test/usascii_with_utf8bom.rb +6 -0
- data/test/encoding_test/utf8.rb +6 -0
- data/test/encoding_test/utf8bom.rb +6 -0
- data/test/encoding_test/utf8bom_only.rb +5 -0
- data/test/encoding_test/utf8dos.rb +6 -0
- data/test/encoding_test/utf8mac.rb +6 -0
- data/test/encoding_test/utf8mac_alt.rb +6 -0
- data/test/encoding_test/utf8unix.rb +6 -0
- data/test/error_test.rb +116 -0
- data/test/eval_test.rb +269 -0
- data/test/flush_cache_test.rb +98 -0
- data/test/irb_test.rb +25 -0
- data/test/lambda_test.rb +56 -0
- data/test/load_path_test.rb +78 -0
- data/test/load_test.rb +123 -0
- data/test/main.rb +140 -0
- data/test/nested_test.rb +29 -0
- data/test/noninvasive_test.rb +51 -0
- data/test/readme_test.rb +16 -0
- data/test/recursive_eval_test.rb +52 -0
- data/test/redefine_method_test.rb +83 -0
- data/test/reload_test.rb +105 -0
- data/test/replace_eval_test.rb +405 -0
- data/test/rubygems_test.rb +25 -0
- data/test/rubyspec_test.rb +39 -0
- data/test/singleton_test.rb +25 -0
- data/test/stdlib_test.rb +13 -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 +87 -0
- metadata +275 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 4396a6fdc53cf54aeb3b6266167f0068549d7d2c
|
4
|
+
data.tar.gz: bdd39a8334d5f29c054d72c5125d21347b0dfa19
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 81b894dcecb96cb803a65c06d77f99f374a91c877721dd5d6fd220b7f5bf79fe5a951d0426d65973d99d404146d146977995942b0ee7344bf3c6c685f2d128c6
|
7
|
+
data.tar.gz: 8ff9b6c24ff52fffd01bb0acca72c391fdab696b5954892da9a98441859eaf109da06798a9362ff347cc221204325ccafdf4c743cc3c08a71e0c3f1d69b3eb10
|
data/CHANGES.rdoc
ADDED
@@ -0,0 +1,93 @@
|
|
1
|
+
|
2
|
+
= live_ast Changes
|
3
|
+
|
4
|
+
== Version 1.1.0
|
5
|
+
|
6
|
+
* incorporate default parser in the main gem
|
7
|
+
* update RubyParser dependency
|
8
|
+
* use binding_of_caller gem instead of boc
|
9
|
+
|
10
|
+
== Version 1.0.2
|
11
|
+
|
12
|
+
* handle -unix, -dos, -mac special encoding suffixes
|
13
|
+
|
14
|
+
== Version 1.0.1
|
15
|
+
|
16
|
+
* add tests for "def self.f" and "def A.f" (plugins were missing this construct)
|
17
|
+
|
18
|
+
== Version 1.0.0
|
19
|
+
|
20
|
+
* no known bugs; API is settled
|
21
|
+
* ast_load respects $VERBOSE=true
|
22
|
+
|
23
|
+
== Version 0.7.3
|
24
|
+
|
25
|
+
* live_ast/full now available for jruby (via boc gem)
|
26
|
+
* fix instance_eval with BasicObject instance
|
27
|
+
|
28
|
+
== Version 0.7.2
|
29
|
+
|
30
|
+
* fix old find&replace accident with boc; rubyspec test now enabled by default
|
31
|
+
|
32
|
+
== Version 0.7.1
|
33
|
+
|
34
|
+
* fix rubygems problem when parser not loaded after live_ast/full
|
35
|
+
|
36
|
+
== Version 0.7.0
|
37
|
+
|
38
|
+
* eval replacement option now included in the gem
|
39
|
+
* new 'boc' gem for eval replacement -- no more syntax restrictions
|
40
|
+
* add require 'live_ast/full' -- shortcut for live_ast + live_ast/replace_eval
|
41
|
+
* rubyspec conformance for require 'live_ast/full'
|
42
|
+
* added required_ruby_version to gemspec
|
43
|
+
* fixed error when IRB is partially required
|
44
|
+
|
45
|
+
== Version 0.6.3
|
46
|
+
|
47
|
+
* minor change for Ruby 1.9.3
|
48
|
+
|
49
|
+
== Version 0.6.2
|
50
|
+
|
51
|
+
* simplified irb handling; readline no longer required
|
52
|
+
* add -e notes to readme
|
53
|
+
|
54
|
+
== Version 0.6.1
|
55
|
+
|
56
|
+
* enable usage inside irb
|
57
|
+
|
58
|
+
== Version 0.6.0
|
59
|
+
|
60
|
+
* removed FlushError and NoSourceError -- not possible to distinguish these
|
61
|
+
* added more tests
|
62
|
+
* refined testing API for plugins
|
63
|
+
|
64
|
+
== Version 0.5.2
|
65
|
+
|
66
|
+
* fix default plugin version
|
67
|
+
|
68
|
+
== Version 0.5.1
|
69
|
+
|
70
|
+
* protect against user needlessly requiring default parser
|
71
|
+
|
72
|
+
== Version 0.5.0
|
73
|
+
|
74
|
+
* new parser plugin API
|
75
|
+
|
76
|
+
== Version 0.2.3
|
77
|
+
|
78
|
+
* fix a utf-8 BOM issue
|
79
|
+
|
80
|
+
== Version 0.2.2
|
81
|
+
|
82
|
+
* handle utf-8 BOMs in loading
|
83
|
+
|
84
|
+
== Version 0.2.1
|
85
|
+
|
86
|
+
* fixed some rdoc issues
|
87
|
+
* removed rubyforge references
|
88
|
+
* update ruby_parser
|
89
|
+
* less MRI-centric tests
|
90
|
+
|
91
|
+
== Version 0.2.0
|
92
|
+
|
93
|
+
* initial release
|
data/README.rdoc
ADDED
@@ -0,0 +1,419 @@
|
|
1
|
+
|
2
|
+
= LiveAST
|
3
|
+
|
4
|
+
== Summary
|
5
|
+
|
6
|
+
Live abstract syntax trees of methods and procs. Fork of +live_ast+
|
7
|
+
(http://quix.github.com/live_ast).
|
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
|
+
p Greet.instance_method(:default).to_ast
|
22
|
+
# => s(:defn, :default, s(:args), s(:str, "hello"))
|
23
|
+
|
24
|
+
#### ASTs of lambdas, procs, blocks
|
25
|
+
|
26
|
+
f = lambda { "foo" }
|
27
|
+
p f.to_ast
|
28
|
+
# => s(:iter, s(:call, nil, :lambda), s(:args), s(:str, "foo"))
|
29
|
+
|
30
|
+
def query(&block)
|
31
|
+
p block.to_ast
|
32
|
+
# => s(:iter, s(:call, nil, :query), s(:args), s(:str, "bar"))
|
33
|
+
end
|
34
|
+
|
35
|
+
query do
|
36
|
+
"bar"
|
37
|
+
end
|
38
|
+
|
39
|
+
#### ASTs from dynamic code -- pure ruby version
|
40
|
+
|
41
|
+
u = ast_eval "lambda { 'dynamic3' }", binding
|
42
|
+
p u.to_ast
|
43
|
+
# => s(:iter, s(:call, nil, :lambda), s(:args), s(:str, "dynamic3"))
|
44
|
+
|
45
|
+
ast_eval "def v ; 'dynamic4' ; end", binding
|
46
|
+
p method(:v).to_ast
|
47
|
+
# => s(:defn, :v, s(:args), s(:str, "dynamic4"))
|
48
|
+
|
49
|
+
#### ASTs from dynamic code -- fully integrated version
|
50
|
+
|
51
|
+
require 'live_ast/full'
|
52
|
+
|
53
|
+
f = eval "lambda { 'dynamic1' }"
|
54
|
+
p f.to_ast
|
55
|
+
# => s(:iter, s(:call, nil, :lambda), s(:args), s(:str, "dynamic1"))
|
56
|
+
|
57
|
+
eval "def g ; 'dynamic2' ; end"
|
58
|
+
p method(:g).to_ast
|
59
|
+
# => s(:defn, :g, s(:args), s(:str, "dynamic2"))
|
60
|
+
|
61
|
+
== Install
|
62
|
+
|
63
|
+
% gem install mvz-live_ast
|
64
|
+
|
65
|
+
== Description
|
66
|
+
|
67
|
+
LiveAST enables a program to find the ASTs of objects created by
|
68
|
+
dynamically generated code. It may be used in a strictly noninvasive
|
69
|
+
manner, where no standard classes or methods are modified, or it may
|
70
|
+
be transparently integrated into Ruby. The default setting is in
|
71
|
+
between.
|
72
|
+
|
73
|
+
RubyParser is the default parsing engine. To replace it with Ripper,
|
74
|
+
<code>gem install live_ast_ripper</code> and then <code>require
|
75
|
+
'live_ast_ripper'</code>. A simple plug-in interface allows LiveAST to
|
76
|
+
work with any parser.
|
77
|
+
|
78
|
+
The advantage of RubyParser is that it gives the traditional ParseTree
|
79
|
+
sexps used by tools such as <code>ruby2ruby</code>.
|
80
|
+
|
81
|
+
LiveAST is thread-safe.
|
82
|
+
|
83
|
+
Ruby 1.9.2 or higher is required.
|
84
|
+
|
85
|
+
== Links
|
86
|
+
|
87
|
+
* Home: https://github.com/mvz/live_ast
|
88
|
+
* Feature Requests, Bug Reports: https://github.com/mvz/live_ast/issues
|
89
|
+
|
90
|
+
== +to_ruby+
|
91
|
+
|
92
|
+
When the default parser is active,
|
93
|
+
|
94
|
+
require 'live_ast/to_ruby'
|
95
|
+
|
96
|
+
will define the +to_ruby+ method for the +Method+, +UnboundMethod+,
|
97
|
+
and +Proc+ classes. These methods are one-liners which pass the
|
98
|
+
extracted ASTs to <code>ruby2ruby</code>.
|
99
|
+
|
100
|
+
require 'live_ast/to_ruby'
|
101
|
+
|
102
|
+
p lambda { |x, y| x + y }.to_ruby # => "lambda { |x, y| (x + y) }"
|
103
|
+
|
104
|
+
class A
|
105
|
+
def f
|
106
|
+
"A#f"
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
p A.instance_method(:f).to_ruby # => "def f\n \"A#f\"\nend"
|
111
|
+
|
112
|
+
In general, +to_ruby+ will hook into the unparser provided by the
|
113
|
+
parser plug-in, if one is found.
|
114
|
+
|
115
|
+
== Pure Ruby and +ast_eval+
|
116
|
+
|
117
|
+
An essential feature of <code>require 'live_ast'</code> is that it is
|
118
|
+
implemented in pure ruby. However since pure ruby is not powerful
|
119
|
+
enough to replace +eval+, in this case +ast_eval+ must be used instead
|
120
|
+
of +eval+ for AST-accessible objects. +ast_eval+ has the same
|
121
|
+
semantics as +eval+ except that the binding argument is required.
|
122
|
+
|
123
|
+
require 'live_ast'
|
124
|
+
|
125
|
+
u = ast_eval "lambda { 'dynamic3' }", binding
|
126
|
+
p u.to_ast
|
127
|
+
# => s(:iter, s(:call, nil, :lambda), s(:args), s(:str, "dynamic3"))
|
128
|
+
|
129
|
+
== Full Integration
|
130
|
+
|
131
|
+
In order for LiveAST to be transparent to the user, +eval+ must be
|
132
|
+
replaced. This is accomplished with the help of the +binding_of_caller+ gem
|
133
|
+
(https://github.com/banister/binding_of_caller).
|
134
|
+
|
135
|
+
To replace +eval+,
|
136
|
+
|
137
|
+
require 'live_ast/full'
|
138
|
+
|
139
|
+
The new AST-electrified +eval+, +instance_eval+, +module_eval+,
|
140
|
+
+class_eval+, and <code>Binding#eval</code> all pass RubySpec
|
141
|
+
(http://rubyspec.org) with the minor exception of backtraces sometimes
|
142
|
+
not matching that of the original +eval+ (see the "Backtraces" section
|
143
|
+
below for details).
|
144
|
+
|
145
|
+
require 'live_ast/full'
|
146
|
+
|
147
|
+
f = eval "lambda { 'dynamic1' }"
|
148
|
+
p f.to_ast
|
149
|
+
# => s(:iter, s(:call, nil, :lambda), s(:args), s(:str, "dynamic1"))
|
150
|
+
|
151
|
+
Since LiveAST itself is pure ruby, any platforms supported by
|
152
|
+
+binding_of_caller+ should work with <code>live_ast/full</code>.
|
153
|
+
|
154
|
+
== Limitations
|
155
|
+
|
156
|
+
A method or block definition must not share a line with other methods
|
157
|
+
or blocks in order for its AST to be accessible.
|
158
|
+
|
159
|
+
require 'live_ast'
|
160
|
+
|
161
|
+
class A
|
162
|
+
def f ; end ; def g ; end
|
163
|
+
end
|
164
|
+
A.instance_method(:f).to_ast # => raises LiveAST::MultipleDefinitionsOnSameLineError
|
165
|
+
|
166
|
+
a = lambda { } ; b = lambda { }
|
167
|
+
a.to_ast # => raises LiveAST::MultipleDefinitionsOnSameLineError
|
168
|
+
|
169
|
+
Code given to the <code>-e</code> command-line switch is not
|
170
|
+
AST-accessible.
|
171
|
+
|
172
|
+
Evaled code appearing before <code>require 'live_ast/full'</code> is
|
173
|
+
not AST-accessible.
|
174
|
+
|
175
|
+
In some circumstances +ast_eval+ and the replaced +eval+ will not give
|
176
|
+
the same backtrace as the original +eval+ (next section).
|
177
|
+
|
178
|
+
----
|
179
|
+
== <em>Technical Issues</em>
|
180
|
+
|
181
|
+
You can probably skip these next sections. Goodbye.
|
182
|
+
----
|
183
|
+
|
184
|
+
== Backtraces
|
185
|
+
|
186
|
+
+ast_eval+ is meant to be compatible with +eval+. For instance the
|
187
|
+
first line of +ast_eval+'s backtrace should be identical to that of
|
188
|
+
+eval+:
|
189
|
+
|
190
|
+
require 'live_ast'
|
191
|
+
|
192
|
+
ast_eval %{ raise "boom" }, binding
|
193
|
+
# => test.rb:3:in `<main>': boom (RuntimeError)
|
194
|
+
|
195
|
+
Let's make a slight change,
|
196
|
+
|
197
|
+
require 'live_ast'
|
198
|
+
|
199
|
+
f = ast_eval %{ lambda { raise "boom" } }, binding
|
200
|
+
f.call
|
201
|
+
# => test.rb|ast@a:3:in `block in <main>': boom (RuntimeError)
|
202
|
+
|
203
|
+
What the heck is '<code>|ast@a</code>' doing there? LiveAST's
|
204
|
+
implementation has just been exposed: each source input is assigned a
|
205
|
+
unique key which enables a Ruby object to find its own definition.
|
206
|
+
|
207
|
+
In the first case above, +ast_eval+ has removed the key from the
|
208
|
+
exception backtrace. But in the second case there is no opportunity to
|
209
|
+
remove it since +ast_eval+ has already returned.
|
210
|
+
|
211
|
+
If you find this to be problem---for example if you cannot add a
|
212
|
+
filter for the jump-to-location feature in your editor---then +raise+
|
213
|
+
may be redefined to strip these tokens,
|
214
|
+
|
215
|
+
require 'live_ast'
|
216
|
+
require 'live_ast/replace_raise'
|
217
|
+
|
218
|
+
f = ast_eval %{ lambda { raise "boom" } }, binding
|
219
|
+
f.call
|
220
|
+
# => test.rb:4:in `block in <main>': boom (RuntimeError)
|
221
|
+
|
222
|
+
However this only applies to a +raise+ call originating from Ruby
|
223
|
+
code. An exception from within a native method will likely still
|
224
|
+
contain the token in its backtrace (e.g., in MRI the exception raised
|
225
|
+
by <code>1/0</code> comes from C).
|
226
|
+
|
227
|
+
== Replacing the Parser
|
228
|
+
|
229
|
+
Despite its name, LiveAST knows nothing about ASTs. It merely reports
|
230
|
+
what it finds in the line-to-AST hash returned by the parser's +parse+
|
231
|
+
method. Replacing the parser class is therefore easy: the only
|
232
|
+
specification is that the +parse+ instance method return such a hash.
|
233
|
+
|
234
|
+
To override the default parser with your own,
|
235
|
+
|
236
|
+
LiveAST.parser = YourParser
|
237
|
+
|
238
|
+
To test it, provide some examples of what the ASTs look like in
|
239
|
+
<code>YourParser::Test</code>. See +live_ast/ruby_parser+ for
|
240
|
+
reference.
|
241
|
+
|
242
|
+
== Noninvasive Mode
|
243
|
+
|
244
|
+
For safety purposes, <code>require 'live_ast'</code> performs the
|
245
|
+
invasive act of redefining +load+ (but not +require+); otherwise bad
|
246
|
+
things can happen to the unwary. The addition of +to_ast+ to a few
|
247
|
+
standard Ruby classes is also a meddlesome move.
|
248
|
+
|
249
|
+
To avoid these modifications,
|
250
|
+
|
251
|
+
require 'live_ast/base'
|
252
|
+
|
253
|
+
will provide the essentials of LiveAST but will not touch core classes
|
254
|
+
or methods.
|
255
|
+
|
256
|
+
To select features individually,
|
257
|
+
|
258
|
+
require 'live_ast/to_ast' # define to_ast for Method, UnboundMethod, Proc
|
259
|
+
require 'live_ast/to_ruby' # define to_ruby for Method, UnboundMethod, Proc
|
260
|
+
require 'live_ast/ast_eval' # define Kernel#ast_eval
|
261
|
+
require 'live_ast/ast_load' # define Kernel#ast_load (mentioned below)
|
262
|
+
require 'live_ast/replace_load' # redefine Kernel#load
|
263
|
+
|
264
|
+
== Noninvasive Interface
|
265
|
+
|
266
|
+
The following alternative interface is available.
|
267
|
+
|
268
|
+
require 'live_ast/base'
|
269
|
+
|
270
|
+
class A
|
271
|
+
def f
|
272
|
+
"A#f"
|
273
|
+
end
|
274
|
+
end
|
275
|
+
|
276
|
+
p LiveAST.ast(A.instance_method(:f))
|
277
|
+
# => s(:defn, :f, s(:args), s(:str, "A#f"))
|
278
|
+
|
279
|
+
p LiveAST.ast(lambda { })
|
280
|
+
# => s(:iter, s(:call, nil, :lambda), s(:args))
|
281
|
+
|
282
|
+
f = LiveAST.eval("lambda { }", binding)
|
283
|
+
|
284
|
+
p LiveAST.ast(f)
|
285
|
+
# => s(:iter, s(:call, nil, :lambda), s(:args))
|
286
|
+
|
287
|
+
ast_eval # => raises NameError
|
288
|
+
|
289
|
+
== Reloading Files In Noninvasive Mode
|
290
|
+
|
291
|
+
Use +ast_load+ or (equivalently) <code>LiveAST.load</code> when
|
292
|
+
reloading an AST-aware file.
|
293
|
+
|
294
|
+
require 'live_ast/ast_load'
|
295
|
+
require 'live_ast/to_ast'
|
296
|
+
|
297
|
+
require "foo"
|
298
|
+
Foo.instance_method(:bar).to_ast # caches AST
|
299
|
+
|
300
|
+
# ... the bar method is changed in foo.rb ...
|
301
|
+
|
302
|
+
ast_load "foo.rb"
|
303
|
+
p Foo.instance_method(:bar).to_ast # => updated AST
|
304
|
+
|
305
|
+
Note if +load+ is called instead of +ast_load+ then the last line will
|
306
|
+
give the old AST,
|
307
|
+
|
308
|
+
load "foo.rb" # oops! forgot to use ast_load
|
309
|
+
p Foo.instance_method(:bar).to_ast # => stale AST
|
310
|
+
|
311
|
+
Realize that <code>foo.rb</code> may be referenced by an unknown
|
312
|
+
number of methods and blocks. If the original <code>foo.rb</code>
|
313
|
+
source were dumped in favor of the modified <code>foo.rb</code>, then
|
314
|
+
an unknown number of those references would be invalidated (and some
|
315
|
+
may even point to the wrong AST).
|
316
|
+
|
317
|
+
This is the reason for the caching that results in the stale AST
|
318
|
+
above. It should now be clear why the default behavior of
|
319
|
+
<code>require 'live_ast'</code> is to redefine +load+: doing so
|
320
|
+
prevents this problem entirely. On the other hand if it is fully known
|
321
|
+
where files are being reloaded (if at all) then there's no need for
|
322
|
+
paranoia; the noninvasive option may be the most appropriate.
|
323
|
+
|
324
|
+
== The Source/AST Cache
|
325
|
+
|
326
|
+
+ast_eval+ and +load+ cache all incoming code, while
|
327
|
+
<code>require</code>d files are cached on a need-to-know basis. When
|
328
|
+
an AST is requested, the corresponding source file is parsed and
|
329
|
+
discarded, leaving behind method and block ASTs. +to_ast+ removes an
|
330
|
+
AST from the cache and attaches it to the appropriate object (a Proc
|
331
|
+
or Module).
|
332
|
+
|
333
|
+
Ignored, unextracted ASTs will therefore linger in the cache. Since
|
334
|
+
sexps are generally small there is little need for concern unless one
|
335
|
+
is continually evaling/reloading <em>and</em> failing to extract the
|
336
|
+
sexps. Nevertheless it is possible that old ASTs will eventually need
|
337
|
+
to be garbage collected. To flush the cache,
|
338
|
+
|
339
|
+
(1) Check that +to_ast+ has been called on all objects whose ASTs are
|
340
|
+
desired.
|
341
|
+
|
342
|
+
(2) Call <code>LiveAST.flush_cache</code>.
|
343
|
+
|
344
|
+
Calling +to_ast+ prevents the object's AST from being flushed (since
|
345
|
+
it grafts the AST onto the object).
|
346
|
+
|
347
|
+
ASTs of procs and methods whose sources lie in <code>require</code>d
|
348
|
+
files will never be flushed. However a method redefined via +ast_eval+
|
349
|
+
or +load+ is susceptible to +flush_cache+ even when its original
|
350
|
+
definition pointed to a <code>require</code>d file.
|
351
|
+
|
352
|
+
== About +require+
|
353
|
+
|
354
|
+
No measures have been taken to detect manipulations of
|
355
|
+
<code>$LOADED_FEATURES</code> which would cause +require+ to load the
|
356
|
+
same file twice. Though +require+ <em>could</em> be replaced in
|
357
|
+
similar fashion to +load+---heading off problems arising from such
|
358
|
+
"raw" reloads---the overhead would seem inappropriate in relation to
|
359
|
+
the rarity of this case.
|
360
|
+
|
361
|
+
Therefore the working assumption is that +require+ will load a file
|
362
|
+
only once. Furthermore, if a file has not been reloaded then it is
|
363
|
+
assumed that the file is unmodified between the moment it is
|
364
|
+
<code>require</code>d and the moment the first AST is pulled from it.
|
365
|
+
|
366
|
+
== Authors
|
367
|
+
|
368
|
+
* James M. Lawrence < quixoticsycophant@gmail.com >
|
369
|
+
* Matijs van Zuijlen < matijs@matijs.net >
|
370
|
+
|
371
|
+
== License
|
372
|
+
|
373
|
+
Copyright (c) 2011 James M. Lawrence. All rights reserved.
|
374
|
+
Copyright (c) 2014 Matijs van Zuijlen. All rights reserved.
|
375
|
+
|
376
|
+
Permission is hereby granted, free of charge, to any person
|
377
|
+
obtaining a copy of this software and associated documentation files
|
378
|
+
(the "Software"), to deal in the Software without restriction,
|
379
|
+
including without limitation the rights to use, copy, modify, merge,
|
380
|
+
publish, distribute, sublicense, and/or sell copies of the Software,
|
381
|
+
and to permit persons to whom the Software is furnished to do so,
|
382
|
+
subject to the following conditions:
|
383
|
+
|
384
|
+
The above copyright notice and this permission notice shall be
|
385
|
+
included in all copies or substantial portions of the Software.
|
386
|
+
|
387
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
388
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
389
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
390
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
391
|
+
BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
392
|
+
ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
393
|
+
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
394
|
+
SOFTWARE.
|
395
|
+
|
396
|
+
LiveAST includes the source code of live_ast_ruby_parser, which is licensed as
|
397
|
+
follows:
|
398
|
+
|
399
|
+
Copyright (c) 2011 James M. Lawrence. All rights reserved.
|
400
|
+
|
401
|
+
Permission is hereby granted, free of charge, to any person
|
402
|
+
obtaining a copy of this software and associated documentation files
|
403
|
+
(the "Software"), to deal in the Software without restriction,
|
404
|
+
including without limitation the rights to use, copy, modify, merge,
|
405
|
+
publish, distribute, sublicense, and/or sell copies of the Software,
|
406
|
+
and to permit persons to whom the Software is furnished to do so,
|
407
|
+
subject to the following conditions:
|
408
|
+
|
409
|
+
The above copyright notice and this permission notice shall be
|
410
|
+
included in all copies or substantial portions of the Software.
|
411
|
+
|
412
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
413
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
414
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
415
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
416
|
+
BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
417
|
+
ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
418
|
+
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
419
|
+
SOFTWARE.
|