nitro 0.10.0 → 0.11.0
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/AUTHORS +4 -1
- data/ChangeLog +290 -7
- data/README +3 -3
- data/RELEASES +94 -0
- data/Rakefile +7 -7
- data/benchmark/og/bench.rb +11 -10
- data/{ChangeLog.1 → doc/ChangeLog.1} +0 -0
- data/doc/apache.txt +9 -0
- data/doc/architecture.txt +1 -27
- data/doc/bugs.txt +11 -4
- data/doc/config.txt +22 -0
- data/doc/og_config.txt +35 -0
- data/doc/og_tutorial.txt +595 -0
- data/doc/tutorial.txt +22 -0
- data/examples/blog/conf/apache.conf +30 -0
- data/examples/blog/conf/lhttpd.conf +2 -2
- data/examples/blog/lib/blog/controller.rb +11 -2
- data/examples/blog/log/apache.error_log +5528 -0
- data/examples/blog/root/fcgi.rb +1 -1
- data/examples/blog/run.rb +9 -3
- data/examples/flash/run.rb +2 -2
- data/examples/no_xsl_blog/conf/apache.conf +30 -0
- data/examples/no_xsl_blog/conf/lhttpd.conf +1 -1
- data/examples/no_xsl_blog/lib/blog/controller.rb +2 -2
- data/examples/no_xsl_blog/log/apache.error_log +68 -0
- data/examples/no_xsl_blog/root/fcgi.rb +2 -2
- data/examples/no_xsl_blog/run.rb +3 -3
- data/examples/og/run.rb +1 -1
- data/examples/tiny/conf/apache.conf +29 -4
- data/examples/tiny/conf/lhttpd.conf +1 -1
- data/examples/tiny/log/apache.error_log +30 -0
- data/examples/tiny/root/fcgi.rb +2 -2
- data/examples/tiny/root/index.xhtml +1 -1
- data/examples/tiny/run.rb +3 -2
- data/examples/wee_style/run.rb +7 -9
- data/examples/why_wiki/README +5 -0
- data/examples/why_wiki/run.rb +57 -0
- data/examples/why_wiki/wiki.yml +6 -0
- data/examples/wiki.yml +1 -0
- data/lib/glue/array.rb +14 -33
- data/lib/glue/hash.rb +32 -53
- data/lib/glue/pool.rb +9 -12
- data/lib/glue/property.rb +31 -9
- data/lib/nitro.rb +30 -8
- data/lib/nitro/adapters/cgi.rb +23 -3
- data/lib/nitro/adapters/webrick.rb +9 -3
- data/lib/nitro/builders/form.rb +21 -13
- data/lib/nitro/builders/rss.rb +20 -9
- data/lib/nitro/builders/table.rb +69 -10
- data/lib/nitro/builders/xhtml.rb +13 -4
- data/lib/nitro/component.rb +15 -0
- data/lib/nitro/conf.rb +4 -3
- data/lib/nitro/context.rb +22 -14
- data/lib/nitro/controller.rb +63 -5
- data/lib/nitro/dispatcher.rb +11 -6
- data/lib/nitro/output.rb +28 -0
- data/lib/nitro/render.rb +78 -59
- data/lib/nitro/request.rb +5 -1
- data/lib/nitro/runner.rb +20 -6
- data/lib/nitro/session.rb +89 -18
- data/lib/nitro/session/drb.rb +31 -0
- data/lib/nitro/session/drbserver.rb +71 -0
- data/lib/nitro/session/memory.rb +13 -0
- data/lib/nitro/simple.rb +7 -0
- data/lib/nitro/ui/date-select.rb +2 -5
- data/lib/nitro/ui/pager.rb +4 -4
- data/lib/nitro/ui/tabs.rb +2 -4
- data/lib/nitro/uri.rb +7 -4
- data/lib/og.rb +20 -12
- data/lib/og/adapter.rb +40 -13
- data/lib/og/adapters/filesys.rb +121 -0
- data/lib/og/adapters/mysql.rb +10 -5
- data/lib/og/adapters/oracle.rb +374 -0
- data/lib/og/adapters/psql.rb +10 -23
- data/lib/og/adapters/sqlite.rb +3 -3
- data/lib/og/backend.rb +2 -2
- data/lib/og/connection.rb +6 -6
- data/lib/og/database.rb +5 -5
- data/lib/og/enchant.rb +6 -2
- data/lib/og/meta.rb +56 -26
- data/lib/og/mock.rb +1 -1
- data/lib/og/typemacros.rb +23 -0
- data/lib/parts/content.rb +4 -10
- data/test/nitro/adapters/tc_cgi.rb +1 -1
- data/test/nitro/builders/tc_rss.rb +1 -1
- data/test/nitro/builders/tc_table.rb +30 -0
- data/test/nitro/tc_context.rb +4 -0
- data/test/nitro/tc_controller.rb +9 -2
- data/test/og/tc_filesys.rb +83 -0
- data/test/og/tc_meta.rb +55 -0
- data/test/tc_og.rb +115 -36
- data/vendor/README +11 -5
- data/vendor/breakpoint.rb +35 -38
- data/vendor/breakpoint_client.rb +119 -80
- data/vendor/composite_sexp_processor.rb +43 -0
- data/vendor/parse_tree.rb +745 -0
- data/vendor/sexp_processor.rb +453 -0
- metadata +34 -7
- data/examples/no_xsl_blog/conf/app.conf.rb +0 -47
data/vendor/breakpoint_client.rb
CHANGED
@@ -2,16 +2,18 @@ require 'breakpoint'
|
|
2
2
|
require 'optparse'
|
3
3
|
require 'timeout'
|
4
4
|
|
5
|
-
|
5
|
+
Options = {
|
6
6
|
:ClientURI => nil,
|
7
7
|
:ServerURI => "druby://localhost:42531",
|
8
|
-
:RetryDelay =>
|
8
|
+
:RetryDelay => 2,
|
9
|
+
:Permanent => true,
|
10
|
+
:Verbose => false
|
9
11
|
}
|
10
12
|
|
11
13
|
ARGV.options do |opts|
|
12
14
|
script_name = File.basename($0)
|
13
15
|
opts.banner = [
|
14
|
-
"Usage: ruby #{script_name} [
|
16
|
+
"Usage: ruby #{script_name} [Options] [server uri]",
|
15
17
|
"",
|
16
18
|
"This tool lets you connect to a breakpoint service ",
|
17
19
|
"which was started via Breakpoint.activate_drb.",
|
@@ -28,13 +30,13 @@ ARGV.options do |opts|
|
|
28
30
|
"connections from the server.",
|
29
31
|
"Default: Find a good URI automatically.",
|
30
32
|
"Example: -c druby://localhost:12345"
|
31
|
-
) { |
|
33
|
+
) { |Options[:ClientURI]| }
|
32
34
|
|
33
35
|
opts.on("-s", "--server-uri=uri",
|
34
36
|
"Connect to the server specified at the",
|
35
37
|
"specified uri.",
|
36
38
|
"Default: druby://localhost:42531"
|
37
|
-
) { |
|
39
|
+
) { |Options[:ServerURI]| }
|
38
40
|
|
39
41
|
opts.on("-R", "--retry-delay=delay", Integer,
|
40
42
|
"Automatically try to reconnect to the",
|
@@ -43,112 +45,149 @@ ARGV.options do |opts|
|
|
43
45
|
"A value of 0 disables automatical",
|
44
46
|
"reconnecting completely.",
|
45
47
|
"Default: 10"
|
46
|
-
) { |
|
48
|
+
) { |Options[:RetryDelay]| }
|
49
|
+
|
50
|
+
opts.on("-P", "--[no-]permanent",
|
51
|
+
"Run the breakpoint client in permanent mode.",
|
52
|
+
"This means that the client will keep continue",
|
53
|
+
"running even after the server has closed the",
|
54
|
+
"connection. Useful for example in Rails."
|
55
|
+
) { |Options[:Permanent]| }
|
56
|
+
|
57
|
+
opts.on("-V", "--[no-]verbose",
|
58
|
+
"Run the breakpoint client in verbose mode.",
|
59
|
+
"Will produce more messages, for example between",
|
60
|
+
"individual breakpoints. This might help in seeing",
|
61
|
+
"that the breakpoint client is still alive, but adds",
|
62
|
+
"quite a bit of clutter."
|
63
|
+
) { |Options[:Verbose]| }
|
47
64
|
|
48
65
|
opts.separator ""
|
49
66
|
|
50
67
|
opts.on("-h", "--help",
|
51
68
|
"Show this help message."
|
52
69
|
) { puts opts; exit }
|
70
|
+
opts.on("-v", "--version",
|
71
|
+
"Display the version information."
|
72
|
+
) do
|
73
|
+
id = %q$Id: breakpoint_client.rb 91 2005-02-04 22:34:08Z flgr $
|
74
|
+
puts id.sub("Id: ", "")
|
75
|
+
puts "(Breakpoint::Version = #{Breakpoint::Version})"
|
76
|
+
exit
|
77
|
+
end
|
53
78
|
|
54
79
|
opts.parse!
|
55
80
|
end
|
56
81
|
|
57
|
-
|
82
|
+
Options[:ServerURI] = ARGV[0] if ARGV[0]
|
58
83
|
|
59
|
-
|
60
|
-
|
84
|
+
module Handlers
|
85
|
+
extend self
|
61
86
|
|
62
|
-
|
63
|
-
|
87
|
+
def breakpoint_handler(workspace, message)
|
88
|
+
puts message
|
89
|
+
IRB.start(nil, nil, workspace)
|
64
90
|
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
puts "",
|
69
|
-
" *** Breakpoint service didn't respond to ping request ***",
|
70
|
-
" This likely happened because of a misconfigured ACL (see the",
|
71
|
-
" documentation of Breakpoint.activate_drb, note that by default",
|
72
|
-
" you can only connect to a remote Breakpoint service via a SSH",
|
73
|
-
" tunnel), but might also be caused by an extremely slow connection.",
|
74
|
-
""
|
75
|
-
raise
|
91
|
+
puts ""
|
92
|
+
if Options[:Verbose] then
|
93
|
+
puts "Resumed execution. Waiting for next breakpoint...", ""
|
76
94
|
end
|
95
|
+
end
|
77
96
|
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
end
|
87
|
-
|
88
|
-
service.register_collision_handler do
|
89
|
-
msg = [
|
90
|
-
" *** Breakpoint service collision ***",
|
91
|
-
" Another Breakpoint service tried to use the",
|
92
|
-
" port already occupied by this one. It will",
|
93
|
-
" keep waiting until this Breakpoint service",
|
94
|
-
" is shut down.",
|
95
|
-
" ",
|
96
|
-
" If you are using the Breakpoint library for",
|
97
|
-
" debugging a Rails or other CGI application",
|
98
|
-
" this likely means that this Breakpoint",
|
99
|
-
" session belongs to an earlier, outdated",
|
100
|
-
" request and should be shut down via 'exit'."
|
101
|
-
].join("\n")
|
102
|
-
|
103
|
-
if RUBY_PLATFORM["win"] then
|
104
|
-
# This sucks. Sorry, I'm not doing this because
|
105
|
-
# I like funky message boxes -- I need to do this
|
106
|
-
# because on Windows I have no way of displaying
|
107
|
-
# my notification via puts() when gets() is still
|
108
|
-
# being performed on STDIN. I have not found a
|
109
|
-
# better solution.
|
110
|
-
begin
|
111
|
-
require 'tk'
|
112
|
-
root = TkRoot.new { withdraw }
|
113
|
-
Tk.messageBox('message' => msg, 'type' => 'ok')
|
114
|
-
root.destroy
|
115
|
-
rescue Exception
|
116
|
-
puts "", msg, ""
|
117
|
-
end
|
118
|
-
else
|
119
|
-
puts "", msg, ""
|
120
|
-
end
|
121
|
-
end
|
97
|
+
def eval_handler(code)
|
98
|
+
result = eval(code, TOPLEVEL_BINDING)
|
99
|
+
if result then
|
100
|
+
DRbObject.new(result)
|
101
|
+
else
|
102
|
+
result
|
103
|
+
end
|
104
|
+
end
|
122
105
|
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
106
|
+
def collision_handler()
|
107
|
+
msg = [
|
108
|
+
" *** Breakpoint service collision ***",
|
109
|
+
" Another Breakpoint service tried to use the",
|
110
|
+
" port already occupied by this one. It will",
|
111
|
+
" keep waiting until this Breakpoint service",
|
112
|
+
" is shut down.",
|
113
|
+
" ",
|
114
|
+
" If you are using the Breakpoint library for",
|
115
|
+
" debugging a Rails or other CGI application",
|
116
|
+
" this likely means that this Breakpoint",
|
117
|
+
" session belongs to an earlier, outdated",
|
118
|
+
" request and should be shut down via 'exit'."
|
119
|
+
].join("\n")
|
120
|
+
|
121
|
+
if RUBY_PLATFORM["win"] then
|
122
|
+
# This sucks. Sorry, I'm not doing this because
|
123
|
+
# I like funky message boxes -- I need to do this
|
124
|
+
# because on Windows I have no way of displaying
|
125
|
+
# my notification via puts() when gets() is still
|
126
|
+
# being performed on STDIN. I have not found a
|
127
|
+
# better solution.
|
128
|
+
begin
|
129
|
+
require 'tk'
|
130
|
+
root = TkRoot.new { withdraw }
|
131
|
+
Tk.messageBox('message' => msg, 'type' => 'ok')
|
132
|
+
root.destroy
|
133
|
+
rescue Exception
|
134
|
+
puts "", msg, ""
|
127
135
|
end
|
136
|
+
else
|
137
|
+
puts "", msg, ""
|
138
|
+
end
|
139
|
+
end
|
140
|
+
end
|
128
141
|
|
129
|
-
|
142
|
+
# Used for checking whether we are currently in the reconnecting loop.
|
143
|
+
reconnecting = false
|
144
|
+
|
145
|
+
loop do
|
146
|
+
DRb.start_service(Options[:ClientURI])
|
147
|
+
|
148
|
+
begin
|
149
|
+
service = DRbObject.new(nil, Options[:ServerURI])
|
150
|
+
|
151
|
+
begin
|
152
|
+
ehandler = Handlers.method(:eval_handler)
|
153
|
+
chandler = Handlers.method(:collision_handler)
|
154
|
+
handler = Handlers.method(:breakpoint_handler)
|
155
|
+
service.eval_handler = ehandler
|
156
|
+
service.collision_handler = chandler
|
157
|
+
service.handler = handler
|
158
|
+
|
159
|
+
reconnecting = false
|
160
|
+
if Options[:Verbose] then
|
161
|
+
puts "Connection established. Waiting for breakpoint...", ""
|
162
|
+
end
|
130
163
|
|
131
164
|
loop do
|
132
165
|
begin
|
133
166
|
service.ping
|
134
167
|
rescue DRb::DRbConnError => error
|
135
|
-
puts "Server exited. Closing connection..."
|
168
|
+
puts "Server exited. Closing connection...", ""
|
169
|
+
exit! unless Options[:Permanent]
|
136
170
|
break
|
137
171
|
end
|
138
172
|
|
139
173
|
sleep(0.5)
|
140
174
|
end
|
141
175
|
ensure
|
142
|
-
service.
|
176
|
+
service.eval_handler = nil
|
177
|
+
service.collision_handler = nil
|
178
|
+
service.handler = nil
|
143
179
|
end
|
144
180
|
rescue Exception => error
|
145
|
-
if
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
181
|
+
if Options[:RetryDelay] > 0 then
|
182
|
+
if not reconnecting then
|
183
|
+
reconnecting = true
|
184
|
+
puts "No connection to breakpoint service at #{Options[:ServerURI]} " +
|
185
|
+
"(#{error.class})"
|
186
|
+
puts error.backtrace if $DEBUG
|
187
|
+
puts "Tries to connect will be made every #{Options[:RetryDelay]} seconds..."
|
188
|
+
end
|
189
|
+
|
190
|
+
sleep Options[:RetryDelay]
|
152
191
|
retry
|
153
192
|
else
|
154
193
|
raise
|
@@ -0,0 +1,43 @@
|
|
1
|
+
require 'sexp_processor'
|
2
|
+
|
3
|
+
##
|
4
|
+
# Implements the Composite pattern on SexpProcessor. Need we say more?
|
5
|
+
#
|
6
|
+
# Yeah... probably. Implements a SexpProcessor of SexpProcessors so
|
7
|
+
# you can easily chain multiple to each other. At some stage we plan
|
8
|
+
# on having all of them run +process+ and but only ever output
|
9
|
+
# something when +generate+ is called, allowing for deferred final
|
10
|
+
# processing.
|
11
|
+
|
12
|
+
class CompositeSexpProcessor < SexpProcessor
|
13
|
+
|
14
|
+
##
|
15
|
+
# The list o' processors to run.
|
16
|
+
|
17
|
+
attr_reader :processors
|
18
|
+
|
19
|
+
def initialize # :nodoc:
|
20
|
+
super
|
21
|
+
@processors = []
|
22
|
+
end
|
23
|
+
|
24
|
+
##
|
25
|
+
# Add a +processor+ to the list of processors to run.
|
26
|
+
|
27
|
+
def <<(processor)
|
28
|
+
raise ArgumentError, "Can only add sexp processors" unless
|
29
|
+
SexpProcessor === processor
|
30
|
+
@processors << processor
|
31
|
+
end
|
32
|
+
|
33
|
+
##
|
34
|
+
# Run +exp+ through all of the processors, returning the final
|
35
|
+
# result.
|
36
|
+
|
37
|
+
def process(exp)
|
38
|
+
@processors.each do |processor|
|
39
|
+
exp = processor.process(exp)
|
40
|
+
end
|
41
|
+
exp
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,745 @@
|
|
1
|
+
#!/usr/local/bin/ruby -w
|
2
|
+
|
3
|
+
begin
|
4
|
+
require 'rubygems'
|
5
|
+
require_gem 'RubyInline'
|
6
|
+
rescue LoadError
|
7
|
+
require "inline"
|
8
|
+
end
|
9
|
+
|
10
|
+
##
|
11
|
+
# ParseTree is a RubyInline-style extension that accesses and
|
12
|
+
# traverses the internal parse tree created by ruby.
|
13
|
+
#
|
14
|
+
# class Example
|
15
|
+
# def blah
|
16
|
+
# return 1 + 1
|
17
|
+
# end
|
18
|
+
# end
|
19
|
+
#
|
20
|
+
# ParseTree.new.parse_tree(Example)
|
21
|
+
# => [[:class, :Example, :Object,
|
22
|
+
# [:defn,
|
23
|
+
# "blah",
|
24
|
+
# [:scope,
|
25
|
+
# [:block,
|
26
|
+
# [:args],
|
27
|
+
# [:return, [:call, [:lit, 1], "+", [:array, [:lit, 1]]]]]]]]]
|
28
|
+
|
29
|
+
class ParseTree
|
30
|
+
|
31
|
+
VERSION = '1.3.3'
|
32
|
+
|
33
|
+
##
|
34
|
+
# Initializes a ParseTree instance. Includes newline nodes if
|
35
|
+
# +include_newlines+ which defaults to +$DEBUG+.
|
36
|
+
|
37
|
+
def initialize(include_newlines=$DEBUG)
|
38
|
+
@include_newlines = include_newlines
|
39
|
+
end
|
40
|
+
|
41
|
+
##
|
42
|
+
# Main driver for ParseTree. Returns an array of arrays containing
|
43
|
+
# the parse tree for +klasses+.
|
44
|
+
#
|
45
|
+
# Structure:
|
46
|
+
#
|
47
|
+
# [[:class, classname, superclassname, [:defn :method1, ...], ...], ...]
|
48
|
+
#
|
49
|
+
# NOTE: v1.0 - v1.1 had the signature (klass, meth=nil). This wasn't
|
50
|
+
# used much at all and since parse_tree_for_method already existed,
|
51
|
+
# it was deemed more useful to expand this method to do multiple
|
52
|
+
# classes.
|
53
|
+
|
54
|
+
def parse_tree(*klasses)
|
55
|
+
result = []
|
56
|
+
klasses.each do |klass|
|
57
|
+
# TODO: remove this on v 1.1
|
58
|
+
raise "You should call parse_tree_for_method(#{klasses.first}, #{klass}) instead of parse_tree" if Symbol === klass or String === klass
|
59
|
+
klassname = klass.name || '' # HACK klass.name should never be nil
|
60
|
+
# Tempfile's DelegateClass(File) seems to
|
61
|
+
# cause this
|
62
|
+
klassname = "UnnamedClass_#{klass.object_id}" if klassname.empty?
|
63
|
+
klassname = klassname.to_sym
|
64
|
+
|
65
|
+
code = if Class === klass then
|
66
|
+
superclass = klass.superclass.name
|
67
|
+
superclass = "nil" if superclass.empty?
|
68
|
+
superclass = superclass.to_sym
|
69
|
+
[:class, klassname, superclass]
|
70
|
+
else
|
71
|
+
[:module, klassname]
|
72
|
+
end
|
73
|
+
|
74
|
+
klass.instance_methods(false).sort.each do |m|
|
75
|
+
$stderr.puts "parse_tree_for_method(#{klass}, #{m}):" if $DEBUG
|
76
|
+
code << parse_tree_for_method(klass, m.to_sym)
|
77
|
+
end
|
78
|
+
result << code
|
79
|
+
end
|
80
|
+
return result
|
81
|
+
end
|
82
|
+
|
83
|
+
##
|
84
|
+
# Returns the parse tree for just one +method+ of a class +klass+.
|
85
|
+
#
|
86
|
+
# Format:
|
87
|
+
#
|
88
|
+
# [:defn, :name, :body]
|
89
|
+
|
90
|
+
def parse_tree_for_method(klass, method)
|
91
|
+
parse_tree_for_meth(klass, method.to_sym, @include_newlines)
|
92
|
+
end
|
93
|
+
|
94
|
+
############################################################
|
95
|
+
# END of rdoc methods
|
96
|
+
############################################################
|
97
|
+
|
98
|
+
inline do |builder|
|
99
|
+
builder.add_type_converter("VALUE", '', '')
|
100
|
+
builder.add_type_converter("ID *", '', '')
|
101
|
+
builder.add_type_converter("NODE *", '(NODE *)', '(VALUE)')
|
102
|
+
builder.include '"intern.h"'
|
103
|
+
builder.include '"node.h"'
|
104
|
+
builder.include '"st.h"'
|
105
|
+
builder.include '"env.h"'
|
106
|
+
builder.add_compile_flags "-Wall"
|
107
|
+
builder.add_compile_flags "-W"
|
108
|
+
builder.add_compile_flags "-Wpointer-arith"
|
109
|
+
builder.add_compile_flags "-Wcast-qual"
|
110
|
+
builder.add_compile_flags "-Wcast-align"
|
111
|
+
builder.add_compile_flags "-Wwrite-strings"
|
112
|
+
builder.add_compile_flags "-Wmissing-noreturn"
|
113
|
+
# NOTE: If you get weird compiler errors like:
|
114
|
+
# dereferencing type-punned pointer will break strict-aliasing rules
|
115
|
+
# PLEASE do one of the following:
|
116
|
+
# 1) Get me a login on your box so I can repro this and get it fixed.
|
117
|
+
# 2) Fix it and send me the patch
|
118
|
+
# 3) (quick, but dirty and bad), comment out the following line:
|
119
|
+
builder.add_compile_flags "-Werror"
|
120
|
+
# NOTE: this flag doesn't work w/ gcc 2.95.x - the FreeBSD default
|
121
|
+
# builder.add_compile_flags "-Wno-strict-aliasing"
|
122
|
+
# ruby.h screws these up hardcore:
|
123
|
+
# builder.add_compile_flags "-Wundef"
|
124
|
+
# builder.add_compile_flags "-Wconversion"
|
125
|
+
# builder.add_compile_flags "-Wstrict-prototypes"
|
126
|
+
# builder.add_compile_flags "-Wmissing-prototypes"
|
127
|
+
# builder.add_compile_flags "-Wsign-compare"
|
128
|
+
|
129
|
+
builder.prefix %q{
|
130
|
+
#define nd_3rd u3.node
|
131
|
+
|
132
|
+
struct METHOD {
|
133
|
+
VALUE klass, rklass;
|
134
|
+
VALUE recv;
|
135
|
+
ID id, oid;
|
136
|
+
NODE *body;
|
137
|
+
};
|
138
|
+
|
139
|
+
struct BLOCK {
|
140
|
+
NODE *var;
|
141
|
+
NODE *body;
|
142
|
+
VALUE self;
|
143
|
+
struct FRAME frame;
|
144
|
+
struct SCOPE *scope;
|
145
|
+
VALUE klass;
|
146
|
+
NODE *cref;
|
147
|
+
int iter;
|
148
|
+
int vmode;
|
149
|
+
int flags;
|
150
|
+
int uniq;
|
151
|
+
struct RVarmap *dyna_vars;
|
152
|
+
VALUE orig_thread;
|
153
|
+
VALUE wrapper;
|
154
|
+
VALUE block_obj;
|
155
|
+
struct BLOCK *outer;
|
156
|
+
struct BLOCK *prev;
|
157
|
+
};
|
158
|
+
|
159
|
+
static char node_type_string[][60] = {
|
160
|
+
// 00
|
161
|
+
"method", "fbody", "cfunc", "scope", "block",
|
162
|
+
"if", "case", "when", "opt_n", "while",
|
163
|
+
// 10
|
164
|
+
"until", "iter", "for", "break", "next",
|
165
|
+
"redo", "retry", "begin", "rescue", "resbody",
|
166
|
+
// 20
|
167
|
+
"ensure", "and", "or", "not", "masgn",
|
168
|
+
"lasgn", "dasgn", "dasgn_curr", "gasgn", "iasgn",
|
169
|
+
// 30
|
170
|
+
"cdecl", "cvasgn", "cvdecl", "op_asgn1", "op_asgn2",
|
171
|
+
"op_asgn_and", "op_asgn_or", "call", "fcall", "vcall",
|
172
|
+
// 40
|
173
|
+
"super", "zsuper", "array", "zarray", "hash",
|
174
|
+
"return", "yield", "lvar", "dvar", "gvar",
|
175
|
+
// 50
|
176
|
+
"ivar", "const", "cvar", "nth_ref", "back_ref",
|
177
|
+
"match", "match2", "match3", "lit", "str",
|
178
|
+
// 60
|
179
|
+
"dstr", "xstr", "dxstr", "evstr", "dregx",
|
180
|
+
"dregx_once", "args", "argscat", "argspush", "splat",
|
181
|
+
// 70
|
182
|
+
"to_ary", "svalue", "block_arg", "block_pass", "defn",
|
183
|
+
"defs", "alias", "valias", "undef", "class",
|
184
|
+
// 80
|
185
|
+
"module", "sclass", "colon2", "colon3", "cref",
|
186
|
+
"dot2", "dot3", "flip2", "flip3", "attrset",
|
187
|
+
// 90
|
188
|
+
"self", "nil", "true", "false", "defined",
|
189
|
+
// 95
|
190
|
+
"newline", "postexe",
|
191
|
+
#ifdef C_ALLOCA
|
192
|
+
"alloca",
|
193
|
+
#endif
|
194
|
+
"dmethod", "bmethod",
|
195
|
+
// 100 / 99
|
196
|
+
"memo", "ifunc", "dsym", "attrasgn",
|
197
|
+
// 104 / 103
|
198
|
+
"last"
|
199
|
+
};
|
200
|
+
}
|
201
|
+
|
202
|
+
builder.c_raw %q^
|
203
|
+
static void add_to_parse_tree(VALUE ary,
|
204
|
+
NODE * n,
|
205
|
+
VALUE newlines,
|
206
|
+
ID * locals) {
|
207
|
+
NODE * volatile node = n;
|
208
|
+
NODE * volatile contnode = NULL;
|
209
|
+
VALUE old_ary = Qnil;
|
210
|
+
VALUE current;
|
211
|
+
VALUE node_name;
|
212
|
+
|
213
|
+
if (!node) return;
|
214
|
+
|
215
|
+
again:
|
216
|
+
|
217
|
+
if (node) {
|
218
|
+
node_name = ID2SYM(rb_intern(node_type_string[nd_type(node)]));
|
219
|
+
if (RTEST(ruby_debug)) {
|
220
|
+
fprintf(stderr, "%15s: %s%s%s\n",
|
221
|
+
node_type_string[nd_type(node)],
|
222
|
+
(RNODE(node)->u1.node != NULL ? "u1 " : " "),
|
223
|
+
(RNODE(node)->u2.node != NULL ? "u2 " : " "),
|
224
|
+
(RNODE(node)->u3.node != NULL ? "u3 " : " "));
|
225
|
+
}
|
226
|
+
} else {
|
227
|
+
node_name = ID2SYM(rb_intern("ICKY"));
|
228
|
+
}
|
229
|
+
|
230
|
+
current = rb_ary_new();
|
231
|
+
rb_ary_push(ary, current);
|
232
|
+
rb_ary_push(current, node_name);
|
233
|
+
|
234
|
+
again_no_block:
|
235
|
+
|
236
|
+
switch (nd_type(node)) {
|
237
|
+
|
238
|
+
case NODE_BLOCK:
|
239
|
+
if (contnode) {
|
240
|
+
add_to_parse_tree(current, node, newlines, locals);
|
241
|
+
break;
|
242
|
+
}
|
243
|
+
|
244
|
+
contnode = node->nd_next;
|
245
|
+
|
246
|
+
// NOTE: this will break the moment there is a block w/in a block
|
247
|
+
old_ary = ary;
|
248
|
+
ary = current;
|
249
|
+
node = node->nd_head;
|
250
|
+
goto again;
|
251
|
+
break;
|
252
|
+
|
253
|
+
case NODE_FBODY:
|
254
|
+
case NODE_DEFINED:
|
255
|
+
add_to_parse_tree(current, node->nd_head, newlines, locals);
|
256
|
+
break;
|
257
|
+
|
258
|
+
case NODE_COLON2:
|
259
|
+
add_to_parse_tree(current, node->nd_head, newlines, locals);
|
260
|
+
rb_ary_push(current, ID2SYM(node->nd_mid));
|
261
|
+
break;
|
262
|
+
|
263
|
+
case NODE_MATCH2:
|
264
|
+
case NODE_MATCH3:
|
265
|
+
add_to_parse_tree(current, node->nd_recv, newlines, locals);
|
266
|
+
add_to_parse_tree(current, node->nd_value, newlines, locals);
|
267
|
+
break;
|
268
|
+
|
269
|
+
case NODE_BEGIN:
|
270
|
+
case NODE_OPT_N:
|
271
|
+
case NODE_NOT:
|
272
|
+
add_to_parse_tree(current, node->nd_body, newlines, locals);
|
273
|
+
break;
|
274
|
+
|
275
|
+
case NODE_IF:
|
276
|
+
add_to_parse_tree(current, node->nd_cond, newlines, locals);
|
277
|
+
if (node->nd_body) {
|
278
|
+
add_to_parse_tree(current, node->nd_body, newlines, locals);
|
279
|
+
} else {
|
280
|
+
rb_ary_push(current, Qnil);
|
281
|
+
}
|
282
|
+
if (node->nd_else) {
|
283
|
+
add_to_parse_tree(current, node->nd_else, newlines, locals);
|
284
|
+
} else {
|
285
|
+
rb_ary_push(current, Qnil);
|
286
|
+
}
|
287
|
+
break;
|
288
|
+
|
289
|
+
case NODE_CASE:
|
290
|
+
add_to_parse_tree(current, node->nd_head, newlines, locals); /* expr */
|
291
|
+
node = node->nd_body;
|
292
|
+
while (node) {
|
293
|
+
add_to_parse_tree(current, node, newlines, locals);
|
294
|
+
if (nd_type(node) == NODE_WHEN) { /* when */
|
295
|
+
node = node->nd_next;
|
296
|
+
} else {
|
297
|
+
break; /* else */
|
298
|
+
}
|
299
|
+
if (! node) {
|
300
|
+
rb_ary_push(current, Qnil); /* no else */
|
301
|
+
}
|
302
|
+
}
|
303
|
+
break;
|
304
|
+
|
305
|
+
case NODE_WHEN:
|
306
|
+
add_to_parse_tree(current, node->nd_head, newlines, locals); /* args */
|
307
|
+
if (node->nd_body) {
|
308
|
+
add_to_parse_tree(current, node->nd_body, newlines, locals); /* body */
|
309
|
+
} else {
|
310
|
+
rb_ary_push(current, Qnil);
|
311
|
+
}
|
312
|
+
break;
|
313
|
+
|
314
|
+
case NODE_WHILE:
|
315
|
+
case NODE_UNTIL:
|
316
|
+
add_to_parse_tree(current, node->nd_cond, newlines, locals);
|
317
|
+
add_to_parse_tree(current, node->nd_body, newlines, locals);
|
318
|
+
break;
|
319
|
+
|
320
|
+
case NODE_BLOCK_PASS:
|
321
|
+
add_to_parse_tree(current, node->nd_body, newlines, locals);
|
322
|
+
add_to_parse_tree(current, node->nd_iter, newlines, locals);
|
323
|
+
break;
|
324
|
+
|
325
|
+
case NODE_ITER:
|
326
|
+
case NODE_FOR:
|
327
|
+
add_to_parse_tree(current, node->nd_iter, newlines, locals);
|
328
|
+
if (node->nd_var != (NODE *)1
|
329
|
+
&& node->nd_var != (NODE *)2
|
330
|
+
&& node->nd_var != NULL) {
|
331
|
+
add_to_parse_tree(current, node->nd_var, newlines, locals);
|
332
|
+
} else {
|
333
|
+
rb_ary_push(current, Qnil);
|
334
|
+
}
|
335
|
+
add_to_parse_tree(current, node->nd_body, newlines, locals);
|
336
|
+
break;
|
337
|
+
|
338
|
+
case NODE_BREAK:
|
339
|
+
case NODE_NEXT:
|
340
|
+
case NODE_YIELD:
|
341
|
+
if (node->nd_stts)
|
342
|
+
add_to_parse_tree(current, node->nd_stts, newlines, locals);
|
343
|
+
break;
|
344
|
+
|
345
|
+
case NODE_RESCUE:
|
346
|
+
add_to_parse_tree(current, node->nd_1st, newlines, locals);
|
347
|
+
add_to_parse_tree(current, node->nd_2nd, newlines, locals);
|
348
|
+
add_to_parse_tree(current, node->nd_3rd, newlines, locals);
|
349
|
+
break;
|
350
|
+
|
351
|
+
// rescue body:
|
352
|
+
// begin stmt rescue exception => var; stmt; [rescue e2 => v2; s2;]* end
|
353
|
+
// stmt rescue stmt
|
354
|
+
// a = b rescue c
|
355
|
+
|
356
|
+
case NODE_RESBODY:
|
357
|
+
add_to_parse_tree(current, node->nd_3rd, newlines, locals);
|
358
|
+
add_to_parse_tree(current, node->nd_2nd, newlines, locals);
|
359
|
+
add_to_parse_tree(current, node->nd_1st, newlines, locals);
|
360
|
+
break;
|
361
|
+
|
362
|
+
case NODE_ENSURE:
|
363
|
+
add_to_parse_tree(current, node->nd_head, newlines, locals);
|
364
|
+
if (node->nd_ensr) {
|
365
|
+
add_to_parse_tree(current, node->nd_ensr, newlines, locals);
|
366
|
+
}
|
367
|
+
break;
|
368
|
+
|
369
|
+
case NODE_AND:
|
370
|
+
case NODE_OR:
|
371
|
+
add_to_parse_tree(current, node->nd_1st, newlines, locals);
|
372
|
+
add_to_parse_tree(current, node->nd_2nd, newlines, locals);
|
373
|
+
break;
|
374
|
+
|
375
|
+
case NODE_DOT2:
|
376
|
+
case NODE_DOT3:
|
377
|
+
case NODE_FLIP2:
|
378
|
+
case NODE_FLIP3:
|
379
|
+
add_to_parse_tree(current, node->nd_beg, newlines, locals);
|
380
|
+
add_to_parse_tree(current, node->nd_end, newlines, locals);
|
381
|
+
break;
|
382
|
+
|
383
|
+
case NODE_RETURN:
|
384
|
+
if (node->nd_stts)
|
385
|
+
add_to_parse_tree(current, node->nd_stts, newlines, locals);
|
386
|
+
break;
|
387
|
+
|
388
|
+
case NODE_ARGSCAT:
|
389
|
+
case NODE_ARGSPUSH:
|
390
|
+
add_to_parse_tree(current, node->nd_head, newlines, locals);
|
391
|
+
add_to_parse_tree(current, node->nd_body, newlines, locals);
|
392
|
+
break;
|
393
|
+
|
394
|
+
case NODE_CALL:
|
395
|
+
case NODE_FCALL:
|
396
|
+
case NODE_VCALL:
|
397
|
+
if (nd_type(node) != NODE_FCALL)
|
398
|
+
add_to_parse_tree(current, node->nd_recv, newlines, locals);
|
399
|
+
rb_ary_push(current, ID2SYM(node->nd_mid));
|
400
|
+
if (node->nd_args || nd_type(node) != NODE_FCALL)
|
401
|
+
add_to_parse_tree(current, node->nd_args, newlines, locals);
|
402
|
+
break;
|
403
|
+
|
404
|
+
case NODE_SUPER:
|
405
|
+
add_to_parse_tree(current, node->nd_args, newlines, locals);
|
406
|
+
break;
|
407
|
+
|
408
|
+
case NODE_BMETHOD:
|
409
|
+
{
|
410
|
+
struct BLOCK *data;
|
411
|
+
Data_Get_Struct(node->nd_cval, struct BLOCK, data);
|
412
|
+
add_to_parse_tree(current, data->var, newlines, locals);
|
413
|
+
add_to_parse_tree(current, data->body, newlines, locals);
|
414
|
+
break;
|
415
|
+
}
|
416
|
+
break;
|
417
|
+
|
418
|
+
case NODE_DMETHOD:
|
419
|
+
{
|
420
|
+
struct METHOD *data;
|
421
|
+
Data_Get_Struct(node->nd_cval, struct METHOD, data);
|
422
|
+
rb_ary_push(current, ID2SYM(data->id));
|
423
|
+
add_to_parse_tree(current, data->body, newlines, locals);
|
424
|
+
break;
|
425
|
+
}
|
426
|
+
|
427
|
+
case NODE_METHOD:
|
428
|
+
fprintf(stderr, "u1 = %p u2 = %p u3 = %p\n", node->nd_1st, node->nd_2nd, node->nd_3rd);
|
429
|
+
add_to_parse_tree(current, node->nd_3rd, newlines, locals);
|
430
|
+
break;
|
431
|
+
|
432
|
+
case NODE_SCOPE:
|
433
|
+
add_to_parse_tree(current, node->nd_next, newlines, node->nd_tbl);
|
434
|
+
break;
|
435
|
+
|
436
|
+
case NODE_OP_ASGN1:
|
437
|
+
add_to_parse_tree(current, node->nd_recv, newlines, locals);
|
438
|
+
add_to_parse_tree(current, node->nd_args->nd_next, newlines, locals);
|
439
|
+
add_to_parse_tree(current, node->nd_args->nd_head, newlines, locals);
|
440
|
+
break;
|
441
|
+
|
442
|
+
case NODE_OP_ASGN2:
|
443
|
+
add_to_parse_tree(current, node->nd_recv, newlines, locals);
|
444
|
+
add_to_parse_tree(current, node->nd_value, newlines, locals);
|
445
|
+
break;
|
446
|
+
|
447
|
+
case NODE_OP_ASGN_AND:
|
448
|
+
case NODE_OP_ASGN_OR:
|
449
|
+
add_to_parse_tree(current, node->nd_head, newlines, locals);
|
450
|
+
add_to_parse_tree(current, node->nd_value, newlines, locals);
|
451
|
+
break;
|
452
|
+
|
453
|
+
case NODE_MASGN:
|
454
|
+
add_to_parse_tree(current, node->nd_head, newlines, locals);
|
455
|
+
if (node->nd_args) {
|
456
|
+
if (node->nd_args != (NODE *)-1) {
|
457
|
+
add_to_parse_tree(current, node->nd_args, newlines, locals);
|
458
|
+
}
|
459
|
+
}
|
460
|
+
add_to_parse_tree(current, node->nd_value, newlines, locals);
|
461
|
+
break;
|
462
|
+
|
463
|
+
case NODE_LASGN:
|
464
|
+
case NODE_IASGN:
|
465
|
+
case NODE_DASGN:
|
466
|
+
case NODE_DASGN_CURR:
|
467
|
+
case NODE_CDECL:
|
468
|
+
case NODE_CVASGN:
|
469
|
+
case NODE_CVDECL:
|
470
|
+
case NODE_GASGN:
|
471
|
+
rb_ary_push(current, ID2SYM(node->nd_vid));
|
472
|
+
add_to_parse_tree(current, node->nd_value, newlines, locals);
|
473
|
+
break;
|
474
|
+
|
475
|
+
case NODE_ALIAS: // u1 u2 (alias :blah :blah2)
|
476
|
+
case NODE_VALIAS: // u1 u2 (alias $global $global2)
|
477
|
+
rb_ary_push(current, ID2SYM(node->u1.id));
|
478
|
+
rb_ary_push(current, ID2SYM(node->u2.id));
|
479
|
+
break;
|
480
|
+
|
481
|
+
case NODE_COLON3: // u2 (::OUTER_CONST)
|
482
|
+
case NODE_UNDEF: // u2 (undef instvar)
|
483
|
+
rb_ary_push(current, ID2SYM(node->u2.id));
|
484
|
+
break;
|
485
|
+
|
486
|
+
case NODE_HASH:
|
487
|
+
{
|
488
|
+
NODE *list;
|
489
|
+
|
490
|
+
list = node->nd_head;
|
491
|
+
while (list) {
|
492
|
+
add_to_parse_tree(current, list->nd_head, newlines, locals);
|
493
|
+
list = list->nd_next;
|
494
|
+
if (list == 0)
|
495
|
+
rb_bug("odd number list for Hash");
|
496
|
+
add_to_parse_tree(current, list->nd_head, newlines, locals);
|
497
|
+
list = list->nd_next;
|
498
|
+
}
|
499
|
+
}
|
500
|
+
break;
|
501
|
+
|
502
|
+
case NODE_ARRAY:
|
503
|
+
while (node) {
|
504
|
+
add_to_parse_tree(current, node->nd_head, newlines, locals);
|
505
|
+
node = node->nd_next;
|
506
|
+
}
|
507
|
+
break;
|
508
|
+
|
509
|
+
case NODE_DSTR:
|
510
|
+
case NODE_DXSTR:
|
511
|
+
case NODE_DREGX:
|
512
|
+
case NODE_DREGX_ONCE:
|
513
|
+
{
|
514
|
+
NODE *list = node->nd_next;
|
515
|
+
if (nd_type(node) == NODE_DREGX || nd_type(node) == NODE_DREGX_ONCE) {
|
516
|
+
break;
|
517
|
+
}
|
518
|
+
rb_ary_push(current, rb_str_new3(node->nd_lit));
|
519
|
+
while (list) {
|
520
|
+
if (list->nd_head) {
|
521
|
+
switch (nd_type(list->nd_head)) {
|
522
|
+
case NODE_STR:
|
523
|
+
add_to_parse_tree(current, list->nd_head, newlines, locals);
|
524
|
+
break;
|
525
|
+
case NODE_EVSTR:
|
526
|
+
add_to_parse_tree(current, list->nd_head->nd_body, newlines, locals);
|
527
|
+
break;
|
528
|
+
default:
|
529
|
+
add_to_parse_tree(current, list->nd_head, newlines, locals);
|
530
|
+
break;
|
531
|
+
}
|
532
|
+
}
|
533
|
+
list = list->nd_next;
|
534
|
+
}
|
535
|
+
}
|
536
|
+
break;
|
537
|
+
|
538
|
+
case NODE_DEFN:
|
539
|
+
case NODE_DEFS:
|
540
|
+
if (node->nd_defn) {
|
541
|
+
if (nd_type(node) == NODE_DEFS)
|
542
|
+
add_to_parse_tree(current, node->nd_recv, newlines, locals);
|
543
|
+
rb_ary_push(current, ID2SYM(node->nd_mid));
|
544
|
+
add_to_parse_tree(current, node->nd_defn, newlines, locals);
|
545
|
+
}
|
546
|
+
break;
|
547
|
+
|
548
|
+
case NODE_CLASS:
|
549
|
+
case NODE_MODULE:
|
550
|
+
rb_ary_push(current, ID2SYM((ID)node->nd_cpath->nd_mid));
|
551
|
+
if (node->nd_super && nd_type(node) == NODE_CLASS) {
|
552
|
+
add_to_parse_tree(current, node->nd_super, newlines, locals);
|
553
|
+
}
|
554
|
+
add_to_parse_tree(current, node->nd_body, newlines, locals);
|
555
|
+
break;
|
556
|
+
|
557
|
+
case NODE_SCLASS:
|
558
|
+
add_to_parse_tree(current, node->nd_recv, newlines, locals);
|
559
|
+
add_to_parse_tree(current, node->nd_body, newlines, locals);
|
560
|
+
break;
|
561
|
+
|
562
|
+
case NODE_ARGS:
|
563
|
+
if (locals &&
|
564
|
+
(node->nd_cnt || node->nd_opt || node->nd_rest != -1)) {
|
565
|
+
int i;
|
566
|
+
NODE *optnode;
|
567
|
+
long arg_count;
|
568
|
+
|
569
|
+
for (i = 0; i < node->nd_cnt; i++) {
|
570
|
+
// regular arg names
|
571
|
+
rb_ary_push(current, ID2SYM(locals[i + 3]));
|
572
|
+
}
|
573
|
+
|
574
|
+
optnode = node->nd_opt;
|
575
|
+
while (optnode) {
|
576
|
+
// optional arg names
|
577
|
+
rb_ary_push(current, ID2SYM(locals[i + 3]));
|
578
|
+
i++;
|
579
|
+
optnode = optnode->nd_next;
|
580
|
+
}
|
581
|
+
|
582
|
+
arg_count = node->nd_rest;
|
583
|
+
if (arg_count > 0) {
|
584
|
+
// *arg name
|
585
|
+
rb_ary_push(current, ID2SYM(locals[node->nd_rest + 1]));
|
586
|
+
} else if (arg_count == -1) {
|
587
|
+
// nothing to do in this case, handled above
|
588
|
+
} else if (arg_count == -2) {
|
589
|
+
// nothing to do in this case, no name == no use
|
590
|
+
} else {
|
591
|
+
puts("not a clue what this arg value is");
|
592
|
+
exit(1);
|
593
|
+
}
|
594
|
+
|
595
|
+
optnode = node->nd_opt;
|
596
|
+
// block?
|
597
|
+
if (optnode) {
|
598
|
+
add_to_parse_tree(current, node->nd_opt, newlines, locals);
|
599
|
+
}
|
600
|
+
}
|
601
|
+
break;
|
602
|
+
|
603
|
+
case NODE_LVAR:
|
604
|
+
case NODE_DVAR:
|
605
|
+
case NODE_IVAR:
|
606
|
+
case NODE_CVAR:
|
607
|
+
case NODE_GVAR:
|
608
|
+
case NODE_CONST:
|
609
|
+
case NODE_ATTRSET:
|
610
|
+
rb_ary_push(current, ID2SYM(node->nd_vid));
|
611
|
+
break;
|
612
|
+
|
613
|
+
case NODE_XSTR: // u1 (%x{ls})
|
614
|
+
case NODE_STR: // u1
|
615
|
+
case NODE_LIT:
|
616
|
+
case NODE_MATCH:
|
617
|
+
rb_ary_push(current, node->nd_lit);
|
618
|
+
break;
|
619
|
+
|
620
|
+
case NODE_NEWLINE:
|
621
|
+
rb_ary_push(current, INT2FIX(nd_line(node)));
|
622
|
+
rb_ary_push(current, rb_str_new2(node->nd_file));
|
623
|
+
|
624
|
+
if (! RTEST(newlines)) rb_ary_pop(ary); // nuke it
|
625
|
+
|
626
|
+
node = node->nd_next;
|
627
|
+
goto again;
|
628
|
+
break;
|
629
|
+
|
630
|
+
case NODE_NTH_REF: // u2 u3 ($1) - u3 is local_cnt('~') ignorable?
|
631
|
+
rb_ary_push(current, INT2FIX(node->nd_nth));
|
632
|
+
break;
|
633
|
+
|
634
|
+
case NODE_BACK_REF: // u2 u3 ($& etc)
|
635
|
+
{
|
636
|
+
char c = node->nd_nth;
|
637
|
+
rb_ary_push(current, rb_str_intern(rb_str_new(&c, 1)));
|
638
|
+
}
|
639
|
+
break;
|
640
|
+
|
641
|
+
case NODE_BLOCK_ARG: // u1 u3 (def x(&b)
|
642
|
+
rb_ary_push(current, ID2SYM(node->u1.id));
|
643
|
+
break;
|
644
|
+
|
645
|
+
// these nodes are empty and do not require extra work:
|
646
|
+
case NODE_RETRY:
|
647
|
+
case NODE_FALSE:
|
648
|
+
case NODE_NIL:
|
649
|
+
case NODE_SELF:
|
650
|
+
case NODE_TRUE:
|
651
|
+
case NODE_ZARRAY:
|
652
|
+
case NODE_ZSUPER:
|
653
|
+
case NODE_REDO:
|
654
|
+
break;
|
655
|
+
|
656
|
+
case NODE_SPLAT:
|
657
|
+
case NODE_TO_ARY:
|
658
|
+
case NODE_SVALUE: // a = b, c
|
659
|
+
add_to_parse_tree(current, node->nd_head, newlines, locals);
|
660
|
+
break;
|
661
|
+
|
662
|
+
case NODE_ATTRASGN: // literal.meth = y u1 u2 u3
|
663
|
+
// node id node
|
664
|
+
if (node->nd_1st == RNODE(1)) {
|
665
|
+
add_to_parse_tree(current, NEW_SELF(), newlines, locals);
|
666
|
+
} else {
|
667
|
+
add_to_parse_tree(current, node->nd_1st, newlines, locals);
|
668
|
+
}
|
669
|
+
rb_ary_push(current, ID2SYM(node->u2.id));
|
670
|
+
add_to_parse_tree(current, node->nd_3rd, newlines, locals);
|
671
|
+
break;
|
672
|
+
|
673
|
+
case NODE_DSYM: // :"#{foo}" u1 u2 u3
|
674
|
+
add_to_parse_tree(current, node->nd_3rd, newlines, locals);
|
675
|
+
break;
|
676
|
+
|
677
|
+
case NODE_EVSTR:
|
678
|
+
add_to_parse_tree(current, node->nd_2nd, newlines, locals);
|
679
|
+
break;
|
680
|
+
|
681
|
+
case NODE_POSTEXE: // END { ... }
|
682
|
+
// Nothing to do here... we are in an iter block
|
683
|
+
break;
|
684
|
+
|
685
|
+
case NODE_CFUNC:
|
686
|
+
rb_ary_push(current, INT2FIX(node->nd_cfnc));
|
687
|
+
rb_ary_push(current, INT2FIX(node->nd_argc));
|
688
|
+
break;
|
689
|
+
|
690
|
+
// Nodes we found but have yet to decypher
|
691
|
+
// I think these are all runtime only... not positive but...
|
692
|
+
case NODE_MEMO: // enum.c zip
|
693
|
+
case NODE_CREF:
|
694
|
+
case NODE_IFUNC:
|
695
|
+
// #defines:
|
696
|
+
// case NODE_LMASK:
|
697
|
+
// case NODE_LSHIFT:
|
698
|
+
default:
|
699
|
+
rb_warn("Unhandled node #%d type '%s'", nd_type(node), node_type_string[nd_type(node)]);
|
700
|
+
if (RNODE(node)->u1.node != NULL) rb_warning("unhandled u1 value");
|
701
|
+
if (RNODE(node)->u2.node != NULL) rb_warning("unhandled u2 value");
|
702
|
+
if (RNODE(node)->u3.node != NULL) rb_warning("unhandled u3 value");
|
703
|
+
if (RTEST(ruby_debug)) fprintf(stderr, "u1 = %p u2 = %p u3 = %p\n", node->nd_1st, node->nd_2nd, node->nd_3rd);
|
704
|
+
rb_ary_push(current, INT2FIX(-99));
|
705
|
+
rb_ary_push(current, INT2FIX(nd_type(node)));
|
706
|
+
break;
|
707
|
+
}
|
708
|
+
|
709
|
+
// finish:
|
710
|
+
if (contnode) {
|
711
|
+
node = contnode;
|
712
|
+
contnode = NULL;
|
713
|
+
current = ary;
|
714
|
+
ary = old_ary;
|
715
|
+
old_ary = Qnil;
|
716
|
+
goto again_no_block;
|
717
|
+
}
|
718
|
+
}
|
719
|
+
^ # end of add_to_parse_tree block
|
720
|
+
|
721
|
+
builder.c %q{
|
722
|
+
static VALUE parse_tree_for_meth(VALUE klass, VALUE method, VALUE newlines) {
|
723
|
+
VALUE n;
|
724
|
+
NODE *node = NULL;
|
725
|
+
ID id;
|
726
|
+
VALUE result = rb_ary_new();
|
727
|
+
|
728
|
+
(void) self; // quell warnings
|
729
|
+
(void) argc; // quell warnings
|
730
|
+
|
731
|
+
id = rb_to_id(method);
|
732
|
+
if (st_lookup(RCLASS(klass)->m_tbl, id, &n)) {
|
733
|
+
node = (NODE*)n;
|
734
|
+
rb_ary_push(result, ID2SYM(rb_intern("defn")));
|
735
|
+
rb_ary_push(result, ID2SYM(id));
|
736
|
+
add_to_parse_tree(result, node->nd_body, newlines, NULL);
|
737
|
+
} else {
|
738
|
+
rb_ary_push(result, Qnil);
|
739
|
+
}
|
740
|
+
|
741
|
+
return result;
|
742
|
+
}
|
743
|
+
}
|
744
|
+
end # inline call
|
745
|
+
end # ParseTree class
|