ruby-internal 0.6.0 → 0.7.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.
Files changed (90) hide show
  1. data/README +204 -6
  2. data/ext/cached/ruby-1.6.8/internal/binding/block.h +35 -0
  3. data/ext/cached/ruby-1.6.8/internal/method/method.h +19 -0
  4. data/ext/cached/ruby-1.6.8/internal/module/classpath.c +3 -0
  5. data/ext/cached/ruby-1.6.8/internal/module/classpath.h +8 -0
  6. data/ext/cached/ruby-1.6.8/internal/node/block.h +35 -0
  7. data/ext/cached/ruby-1.6.8/internal/node/global_entry.h +15 -0
  8. data/ext/cached/ruby-1.6.8/internal/node/node_type_descrip.c +149 -0
  9. data/ext/cached/ruby-1.6.8/internal/node/nodeinfo.c +5582 -0
  10. data/ext/cached/ruby-1.6.8/internal/node/nodeinfo.h +69 -0
  11. data/ext/cached/ruby-1.6.8/internal/proc/block.h +35 -0
  12. data/ext/cached/ruby-1.6.8/internal/tag/tag.h +15 -0
  13. data/ext/cached/ruby-1.6.8/internal/vm/instruction/insns_info.c +39 -0
  14. data/ext/cached/ruby-1.6.8/internal/vm/instruction/insns_info.h +21 -0
  15. data/ext/cached/ruby-1.6.8/internal/vm/iseq/insns_info.inc +12 -0
  16. data/ext/cached/ruby-1.6.8/internal/vm/iseq/iseq_load.inc +9 -0
  17. data/ext/cached/ruby-1.8.0/internal/node/node_type_descrip.c +91 -91
  18. data/ext/cached/ruby-1.8.0/internal/node/nodeinfo.c +1909 -1909
  19. data/ext/cached/ruby-1.8.0/internal/vm/iseq/iseq_load.inc +9 -0
  20. data/ext/cached/ruby-1.8.1/internal/node/node_type_descrip.c +90 -90
  21. data/ext/cached/ruby-1.8.1/internal/node/nodeinfo.c +1946 -1946
  22. data/ext/cached/ruby-1.8.1/internal/vm/iseq/iseq_load.inc +9 -0
  23. data/ext/cached/ruby-1.8.2/internal/node/node_type_descrip.c +90 -90
  24. data/ext/cached/ruby-1.8.2/internal/node/nodeinfo.c +1946 -1946
  25. data/ext/cached/ruby-1.8.2/internal/vm/iseq/iseq_load.inc +9 -0
  26. data/ext/cached/ruby-1.8.3/internal/node/node_type_descrip.c +90 -90
  27. data/ext/cached/ruby-1.8.3/internal/node/nodeinfo.c +1946 -1946
  28. data/ext/cached/ruby-1.8.3/internal/vm/iseq/iseq_load.inc +9 -0
  29. data/ext/cached/ruby-1.8.4/internal/node/node_type_descrip.c +90 -90
  30. data/ext/cached/ruby-1.8.4/internal/node/nodeinfo.c +1946 -1946
  31. data/ext/cached/ruby-1.8.4/internal/vm/iseq/iseq_load.inc +9 -0
  32. data/ext/cached/ruby-1.8.5/internal/node/node_type_descrip.c +90 -90
  33. data/ext/cached/ruby-1.8.5/internal/node/nodeinfo.c +1909 -1909
  34. data/ext/cached/ruby-1.8.5/internal/vm/iseq/iseq_load.inc +9 -0
  35. data/ext/cached/ruby-1.8.6/internal/node/node_type_descrip.c +90 -90
  36. data/ext/cached/ruby-1.8.6/internal/node/nodeinfo.c +1909 -1909
  37. data/ext/cached/ruby-1.8.6/internal/vm/iseq/iseq_load.inc +9 -0
  38. data/ext/cached/ruby-1.8.7/internal/node/node_type_descrip.c +90 -90
  39. data/ext/cached/ruby-1.8.7/internal/node/nodeinfo.c +1909 -1909
  40. data/ext/cached/ruby-1.8.7/internal/vm/iseq/iseq_load.inc +9 -0
  41. data/ext/cached/ruby-1.9.0/internal/node/node_type_descrip.c +85 -85
  42. data/ext/cached/ruby-1.9.0/internal/node/nodeinfo.c +1800 -1800
  43. data/ext/cached/ruby-1.9.0/internal/vm/iseq/iseq_load.inc +13 -0
  44. data/ext/cached/ruby-1.9.0/internal/yarv-headers/transdb.h +51 -51
  45. data/ext/cached/ruby-1.9.1/internal/node/node_type_descrip.c +85 -85
  46. data/ext/cached/ruby-1.9.1/internal/node/nodeinfo.c +1800 -1800
  47. data/ext/cached/ruby-1.9.1/internal/vm/instruction/insns_info.h +1 -2
  48. data/ext/cached/ruby-1.9.1/internal/vm/iseq/iseq_load.inc +356 -0
  49. data/ext/cached/ruby-1.9.1/internal/yarv-headers/eval_intern.h +15 -9
  50. data/ext/cached/ruby-1.9.1/internal/yarv-headers/id.h +45 -66
  51. data/ext/cached/ruby-1.9.1/internal/yarv-headers/iseq.h +12 -3
  52. data/ext/cached/ruby-1.9.1/internal/yarv-headers/node.h +2 -2
  53. data/ext/cached/ruby-1.9.1/internal/yarv-headers/parse.h +23 -138
  54. data/ext/cached/ruby-1.9.1/internal/yarv-headers/revision.h +1 -1
  55. data/ext/cached/ruby-1.9.1/internal/yarv-headers/transcode_data.h +9 -2
  56. data/ext/cached/ruby-1.9.1/internal/yarv-headers/transdb.h +62 -0
  57. data/ext/cached/ruby-1.9.1/internal/yarv-headers/version.h +17 -23
  58. data/ext/cached/ruby-1.9.1/internal/yarv-headers/vm_core.h +20 -29
  59. data/ext/cached/ruby-1.9.1/internal/yarv-headers/vm_exec.h +4 -7
  60. data/ext/cached/ruby-1.9.1/internal/yarv-headers/vm_insnhelper.h +6 -5
  61. data/ext/internal/module/cfp.h +13 -0
  62. data/ext/internal/module/extconf.rb +2 -2
  63. data/ext/internal/module/module.c +3 -8
  64. data/ext/internal/node/nodes.rb +2 -1
  65. data/ext/internal/vm/iseq/iseq.c +2 -3
  66. data/ext/internal/vm/iseq/iseq_load.inc.rpp +61 -0
  67. data/ext/internal/yarv-headers/debug.h +36 -0
  68. data/ext/internal/yarv-headers/dln.h +41 -0
  69. data/ext/internal/yarv-headers/encdb.h +147 -0
  70. data/ext/internal/yarv-headers/eval_intern.h +215 -0
  71. data/ext/internal/yarv-headers/gc.h +75 -0
  72. data/ext/internal/yarv-headers/id.h +163 -0
  73. data/ext/internal/yarv-headers/iseq.h +103 -0
  74. data/ext/internal/yarv-headers/node.h +516 -0
  75. data/ext/internal/yarv-headers/parse.h +188 -0
  76. data/ext/internal/yarv-headers/regenc.h +207 -0
  77. data/ext/internal/yarv-headers/regint.h +842 -0
  78. data/ext/internal/yarv-headers/regparse.h +351 -0
  79. data/ext/internal/yarv-headers/revision.h +1 -0
  80. data/ext/internal/yarv-headers/thread_pthread.h +24 -0
  81. data/ext/internal/yarv-headers/thread_win32.h +33 -0
  82. data/ext/internal/yarv-headers/transcode_data.h +106 -0
  83. data/ext/internal/yarv-headers/transdb.h +147 -0
  84. data/ext/internal/yarv-headers/version.h +54 -0
  85. data/ext/internal/yarv-headers/vm_core.h +646 -0
  86. data/ext/internal/yarv-headers/vm_exec.h +184 -0
  87. data/ext/internal/yarv-headers/vm_insnhelper.h +195 -0
  88. data/ext/internal/yarv-headers/vm_opts.h +51 -0
  89. data/publish_rdoc.rb +4 -0
  90. metadata +52 -2
data/README CHANGED
@@ -1,7 +1,21 @@
1
- This is ruby-internal, a library that provides access to the internals
2
- of the ruby interpreter.
1
+ Ruby-internal is a Ruby library that provides direct access to Ruby's
2
+ (MRI or YARV) internal data structures.
3
3
 
4
- See the file LICENSE for license and copyright information.
4
+ How is ruby-internal useful? You can:
5
+
6
+ * dump and load methods and procs and classes
7
+ * inspect and pretty-print ascii charts of node trees
8
+ * inspect and print ascii charts of class hierarchies
9
+ * use the provided code obfuscator (nwobfusc.rb) so your code can't easily be read.
10
+ * use it to build a just-in-time compiler (see Ludicrous).
11
+
12
+ == Installation
13
+
14
+ To install ruby-internal:
15
+
16
+ $ gem install ruby-internal
17
+
18
+ == Building from source
5
19
 
6
20
  To build and run the tests:
7
21
  ruby setup.rb config
@@ -11,16 +25,195 @@ Or, if you are on ruby 1.9 (or another version of ruby that doesn't have
11
25
  pre-parsed ruby source included in the distribution), you'll need to
12
26
  pass a special command-line option in the config step so the build
13
27
  scripts can find ruby's source code:
28
+
14
29
  ruby setup.rb config --ruby-source-path=/path/to/ruby
15
30
  ruby setup.rb setup
16
31
 
17
32
  To install:
18
33
  ruby install.rb install
19
34
 
20
- See the generated documentation (in the doc/ directory) and the examples
21
- (in the directory example/) for usage.
35
+ == Sample code
36
+
37
+ This will dump the class Foo (including its instance methods, class variables,
38
+ etc.) and re-load it:
39
+
40
+ :include: sample/dump_class.rb
41
+
42
+ == Ruby-internal and irb
43
+
44
+ Ruby-internal is very useful as a tool for digging into the internals of Ruby
45
+ and figuring out what the interpreter is doing with your code. To use
46
+ ruby-internal with irb, put the following in your .irbrc:
47
+
48
+ :include: sample/irbrc
49
+
50
+ Now you can print node trees:
51
+
52
+ irb(main):001:0> pp (proc { 1 + 1 }.body)
53
+ NODE_NEWLINE at (irb):1
54
+ |-nth = 1
55
+ +-next = NODE_CALL at (irb):1
56
+ |-recv = NODE_LIT at (irb):1
57
+ | +-lit = 1
58
+ |-args = NODE_ARRAY at (irb):1
59
+ | |-alen = 1
60
+ | |-head = NODE_LIT at (irb):1
61
+ | | +-lit = 1
62
+ | +-next = false
63
+ +-mid = :+
64
+ => nil
65
+
66
+ And view class hierarchies:
67
+
68
+ irb(main):004:0> puts Object.new.classtree
69
+ #<Object:0x40330ce8>
70
+ +-class = Object
71
+ |-class = #<Class:Object>
72
+ | |-class = Class
73
+ | | |-class = #<Class:Class>
74
+ | | | |-class = #<Class:Class> (*)
75
+ | | | +-super = #<Class:Module>
76
+ | | | |-class = Class (*)
77
+ | | | +-super = #<Class:Object> (*)
78
+ | | +-super = Module
79
+ | | |-class = #<Class:Module> (*)
80
+ | | +-super = Object (*)
81
+ | +-super = Class (*)
82
+ +-super = #<PP::ObjectMixin?:0x40349568>
83
+ +-class = PP::ObjectMixin?
84
+ |-class = Module (*)
85
+ +-super = #<Kernel:0x4033507c>
86
+ +-class = Kernel
87
+ => nil
88
+
89
+ View method signatures:
90
+
91
+ irb(main):015:0> def foo(a, b, *rest, &block); end; method(:foo).signature
92
+ => #<MethodSig::Signature:0x4037093c @origin_class=Object, @arg_info={:b=>"b",
93
+ :block=>"&block", :a=>"a", :rest=>"*rest"}, @name="foo", @arg_names=[:a,
94
+ :b, :rest, :block]>
95
+ irb(main):016:0> proc { |x, y, *rest| }.signature
96
+ => #<Proc::Signature:0x4036cf30 @args=#<Proc::Arguments:0x4036d020 @rest_arg=2,
97
+ @multiple_assignment=true, @names=[:x, :y, :rest]>, @arg_info={:x=>"x", :y=>"y",
98
+ :rest=>"*rest"}>
99
+
100
+ And reconstruct compiled methods:
101
+
102
+ irb(main):001:0> def foo(a, b, *rest, &block)
103
+ irb(main):002:1> begin
104
+ irb(main):003:2* if not a and not b then
105
+ irb(main):004:3* raise "Need more input!"
106
+ irb(main):005:3> end
107
+ irb(main):006:2> return a + b
108
+ irb(main):007:2> ensure
109
+ irb(main):008:2* puts "In ensure block"
110
+ irb(main):009:2> end
111
+ irb(main):010:1> end
112
+ => nil
113
+ irb(main):011:0> m = method(:foo)
114
+ => #<Method: Object#foo>
115
+ irb(main):012:0> puts m.as_code
116
+ def foo(a, b, *rest, &block)
117
+ begin
118
+ (raise("Need more input!")) if (not a and not b)
119
+ return a + b
120
+ ensure
121
+ puts("In ensure block")
122
+ end
123
+ end
124
+ => nil
125
+
126
+ == YARV support
22
127
 
23
- Some notes about security:
128
+ Yes, ruby-internal works with YARV, too. The difference when using YARV
129
+ is that sometimes you have nodes, and sometimes you have instruction
130
+ sequences. So whereas pre-YARV you would have a pure AST, with YARV you
131
+ get structures that look like this:
132
+
133
+ irb(main):001:0> def foo; 1 + 1; end
134
+ => nil
135
+ irb(main):002:0> pp method(:foo).body
136
+ NODE_METHOD at (irb):1
137
+ |-noex = PUBLIC
138
+ |-body = <ISeq:foo@(irb)>
139
+ | |-0000 trace 8
140
+ | |-0002 trace 1
141
+ | |-0004 putobject 1
142
+ | |-0006 putobject 1
143
+ | |-0008 opt_plus
144
+ | |-0009 trace 16
145
+ | +-0011 leave
146
+ +-cnt = 0
147
+
148
+ You can also access the original AST with Node.compile:
149
+
150
+ irb(main):001:0> n = Node.compile_string('1+1')
151
+ => #>Node::SCOPE:0x40420af0>
152
+ irb(main):002:0> pp n
153
+ NODE_SCOPE at (compiled):1
154
+ |-rval = NODE_CALL at (compiled):1
155
+ | |-recv = NODE_LIT at (compiled):1
156
+ | | +-lit = 1
157
+ | |-args = NODE_ARRAY at (compiled):1
158
+ | | |-alen = 1
159
+ | | |-head = NODE_LIT at (compiled):1
160
+ | | | +-lit = 1
161
+ | | +-next = false
162
+ | +-mid = :+
163
+ |-tbl = nil
164
+ +-next = false
165
+
166
+ compile it to a bytecode sequence:
167
+
168
+ irb(main):003:0> is = n.bytecode_compile()
169
+ => <ISeq:<main>@(compiled)>
170
+ irb(main):004:0> puts is.disasm
171
+ == disasm: >ISeq:>main>@(compiled)>=====================================
172
+ 0000 trace 1 ( 1)
173
+ 0002 putobject 1
174
+ 0004 putobject 1
175
+ 0006 opt_plus
176
+ 0007 leave
177
+ => nil
178
+
179
+ iterate over the bytecode sequence:
180
+
181
+ irb(main):004:0> is.each { |i| puts "#{i.inspect} #{i.length} #{i.operand_types.inspect}" }
182
+ #<VM::Instruction::TRACE:0x40412324 @operands=[1]> 2 [:num]
183
+ #<VM::Instruction::PUTOBJECT:0x404121d0 @operands=[1]> 2 [:value]
184
+ #<VM::Instruction::PUTOBJECT:0x4041207c @operands=[1]> 2 [:value]
185
+ #<VM::Instruction::OPT_PLUS:0x40411f28 @operands=[]> 1 []
186
+ #<VM::Instruction::LEAVE:0x40411e24 @operands=[]> 1 []
187
+ => nil
188
+
189
+ then decompile it:
190
+
191
+ irb(main):005:0> require 'as_expression'
192
+ => true
193
+ irb(main):006:0> is.as_expression
194
+ => "1 + 1"
195
+
196
+ There are still a few missing features (particularly in the decompiler),
197
+ but expect to see more exciting tools for working with bytecode in the
198
+ future!
199
+
200
+ == Other tools
201
+
202
+ Ruby-internal comes with two useful tools, nwdump and nwobfusc. The
203
+ nwdump tool works in much the same way as the older Pragmatic nodedump
204
+ tool. If you require it from the command line:
205
+
206
+ $ ruby -rinternal/node/dump test.rb
207
+
208
+ it will dump your program's syntax tree. The nwobfusc tool is similar:
209
+
210
+ $ ruby -rinternal/obfusc test.rb > test2.rb
211
+
212
+ but its output is an obfuscated version of your program. The program
213
+ must be run on the same version of both ruby-internal and the
214
+ interpreter.
215
+
216
+ == Some notes about security
24
217
 
25
218
  - Data can always be inspected.
26
219
  - Methods that could potentially cause a crash if used incorrectly are
@@ -29,3 +222,8 @@ Some notes about security:
29
222
  disallowed with $SAFE >= 4.
30
223
  - Methods that load marshalled data do taint checks with $SAFE >= 1.
31
224
 
225
+ == Future directions
226
+
227
+ * Load/dump the state of the ruby interpreter
228
+ * Manipulate the AST/bytecode on-the-fly
229
+
@@ -0,0 +1,35 @@
1
+ #ifndef ruby_internal_block__h_
2
+ #define ruby_internal_block__h_
3
+
4
+ #include <ruby.h>
5
+
6
+ #ifndef RUBY_VM
7
+ #include "env.h"
8
+ #endif
9
+
10
+ struct BLOCKTAG {
11
+ struct RBasic super;
12
+ long dst;
13
+ long flags;
14
+ };
15
+
16
+ struct BLOCK {
17
+ NODE *var;
18
+ NODE *body;
19
+ VALUE self;
20
+ struct FRAME frame;
21
+ struct SCOPE *scope;
22
+ struct BLOCKTAG *tag;
23
+ VALUE klass;
24
+ int iter;
25
+ int vmode;
26
+ int flags;
27
+ struct RVarmap *dyna_vars;
28
+ VALUE orig_thread;
29
+ VALUE wrapper;
30
+ struct BLOCK *prev;
31
+ };
32
+
33
+
34
+ #endif
35
+
@@ -0,0 +1,19 @@
1
+ #ifndef ruby_internal_method__h_
2
+ #define ruby_internal_method__h_
3
+
4
+ #include <ruby.h>
5
+
6
+ #include "internal/node/ruby_internal_node.h"
7
+
8
+ struct METHOD {
9
+ VALUE klass, oklass;
10
+ VALUE recv;
11
+ ID id, oid;
12
+ NODE *body;
13
+ };
14
+
15
+ #define METHOD_OCLASS(m) m->klass
16
+ #define METHOD_RCLASS(m) m->klass
17
+
18
+ #endif
19
+
@@ -0,0 +1,3 @@
1
+ #include "classpath.h"
2
+
3
+
@@ -0,0 +1,8 @@
1
+ #ifndef CLASSPATH_H
2
+ #define CLASSPATH_H
3
+
4
+ #include "ruby.h"
5
+
6
+
7
+ #endif
8
+
@@ -0,0 +1,35 @@
1
+ #ifndef ruby_internal_block__h_
2
+ #define ruby_internal_block__h_
3
+
4
+ #include <ruby.h>
5
+
6
+ #ifndef RUBY_VM
7
+ #include "env.h"
8
+ #endif
9
+
10
+ struct BLOCKTAG {
11
+ struct RBasic super;
12
+ long dst;
13
+ long flags;
14
+ };
15
+
16
+ struct BLOCK {
17
+ NODE *var;
18
+ NODE *body;
19
+ VALUE self;
20
+ struct FRAME frame;
21
+ struct SCOPE *scope;
22
+ struct BLOCKTAG *tag;
23
+ VALUE klass;
24
+ int iter;
25
+ int vmode;
26
+ int flags;
27
+ struct RVarmap *dyna_vars;
28
+ VALUE orig_thread;
29
+ VALUE wrapper;
30
+ struct BLOCK *prev;
31
+ };
32
+
33
+
34
+ #endif
35
+
@@ -0,0 +1,15 @@
1
+ #ifndef global_entry__h_
2
+ #define global_entry__h_
3
+
4
+ struct global_entry {
5
+ ID id;
6
+ void *data;
7
+ VALUE (*getter)();
8
+ void (*setter)();
9
+ void (*marker)();
10
+ int block_trace;
11
+ struct trace_var *trace;
12
+ };
13
+
14
+ #endif
15
+
@@ -0,0 +1,149 @@
1
+ #include "node_type_descrip.h"
2
+ #include "version.h"
3
+
4
+ Node_Type_Descrip node_type_descrips_unsorted[] = {
5
+ { NODE_ALIAS, NEN_1ST, NEN_2ND, NEN_NONE, "ALIAS" },
6
+ #ifdef HAVE_NODE_ALLOCA
7
+ { NODE_ALLOCA, NEN_CFNC, NEN_VALUE, NEN_CNT, "ALLOCA" },
8
+ #endif
9
+ { NODE_AND, NEN_1ST, NEN_2ND, NEN_NONE, "AND" },
10
+ { NODE_ARGS, NEN_REST, NEN_OPT, NEN_CNT, "ARGS" },
11
+ { NODE_ARGSCAT, NEN_HEAD, NEN_BODY, NEN_NONE, "ARGSCAT" },
12
+ { NODE_ARGSPUSH, NEN_HEAD, NEN_BODY, NEN_NONE, "ARGSPUSH" },
13
+ { NODE_ARRAY, NEN_HEAD, NEN_ALEN, NEN_NEXT, "ARRAY" },
14
+ { NODE_ATTRSET, NEN_VID, NEN_NONE, NEN_NONE, "ATTRSET" },
15
+ { NODE_BACK_REF, NEN_NTH, NEN_CNT, NEN_NONE, "BACK_REF" },
16
+ { NODE_BEGIN, NEN_BODY, NEN_NONE, NEN_NONE, "BEGIN" },
17
+ { NODE_BLOCK, NEN_HEAD, NEN_NEXT, NEN_NONE, "BLOCK" },
18
+ { NODE_BLOCK_ARG, NEN_CNT, NEN_NONE, NEN_NONE, "BLOCK_ARG" },
19
+ { NODE_BLOCK_PASS, NEN_BODY, NEN_ITER, NEN_NONE, "BLOCK_PASS" },
20
+ { NODE_BMETHOD, NEN_CVAL, NEN_NONE, NEN_NONE, "BMETHOD" },
21
+ { NODE_BREAK, NEN_STTS, NEN_NONE, NEN_NONE, "BREAK" },
22
+ { NODE_CALL, NEN_ARGS, NEN_MID, NEN_RECV, "CALL" },
23
+ { NODE_CASE, NEN_HEAD, NEN_BODY, NEN_NEXT, "CASE" },
24
+ { NODE_CDECL, NEN_VALUE, NEN_VID, NEN_NONE, "CDECL" },
25
+ { NODE_CFUNC, NEN_CFNC, NEN_ARGC, NEN_NONE, "CFUNC" },
26
+ { NODE_CLASS, NEN_BODY, NEN_CNAME, NEN_SUPER, "CLASS" },
27
+ { NODE_COLON2, NEN_HEAD, NEN_MID, NEN_NONE, "COLON2" },
28
+ { NODE_COLON3, NEN_MID, NEN_NONE, NEN_NONE, "COLON3" },
29
+ { NODE_CONST, NEN_VID, NEN_NONE, NEN_NONE, "CONST" },
30
+ { NODE_CREF, NEN_BODY, NEN_NEXT, NEN_CLSS, "CREF" },
31
+ { NODE_CVAR, NEN_VID, NEN_NONE, NEN_NONE, "CVAR" },
32
+ { NODE_CVASGN, NEN_VALUE, NEN_VID, NEN_NONE, "CVASGN" },
33
+ { NODE_CVDECL, NEN_VALUE, NEN_VID, NEN_NONE, "CVDECL" },
34
+ { NODE_DASGN, NEN_VALUE, NEN_VID, NEN_NONE, "DASGN" },
35
+ { NODE_DASGN_CURR, NEN_VALUE, NEN_VID, NEN_NONE, "DASGN_CURR" },
36
+ { NODE_DEFINED, NEN_HEAD, NEN_NONE, NEN_NONE, "DEFINED" },
37
+ { NODE_DEFN, NEN_DEFN, NEN_MID, NEN_NOEX, "DEFN" },
38
+ { NODE_DEFS, NEN_DEFN, NEN_MID, NEN_RECV, "DEFS" },
39
+ { NODE_DMETHOD, NEN_CVAL, NEN_NONE, NEN_NONE, "DMETHOD" },
40
+ { NODE_DOT2, NEN_BEG, NEN_END, NEN_STATE, "DOT2" },
41
+ { NODE_DOT3, NEN_BEG, NEN_END, NEN_STATE, "DOT3" },
42
+ { NODE_DREGX, NEN_LIT, NEN_CFLAG, NEN_NEXT, "DREGX" },
43
+ { NODE_DREGX_ONCE, NEN_LIT, NEN_CFLAG, NEN_NEXT, "DREGX_ONCE" },
44
+ { NODE_DSTR, NEN_LIT, NEN_NEXT, NEN_NONE, "DSTR" },
45
+ { NODE_DVAR, NEN_VID, NEN_NONE, NEN_NONE, "DVAR" },
46
+ { NODE_DXSTR, NEN_LIT, NEN_NEXT, NEN_NONE, "DXSTR" },
47
+ { NODE_ENSURE, NEN_HEAD, NEN_ENSR, NEN_NONE, "ENSURE" },
48
+ { NODE_EVSTR, NEN_LIT, NEN_NONE, NEN_NONE, "EVSTR" },
49
+ { NODE_FALSE, NEN_NONE, NEN_NONE, NEN_NONE, "FALSE" },
50
+ { NODE_FBODY, NEN_HEAD, NEN_ORIG, NEN_MID, "FBODY" },
51
+ { NODE_FCALL, NEN_ARGS, NEN_MID, NEN_NONE, "FCALL" },
52
+ { NODE_FLIP2, NEN_BEG, NEN_END, NEN_CNT, "FLIP2" },
53
+ { NODE_FLIP3, NEN_BEG, NEN_END, NEN_CNT, "FLIP3" },
54
+ { NODE_FOR, NEN_BODY, NEN_ITER, NEN_VAR, "FOR" },
55
+ { NODE_GASGN, NEN_VALUE, NEN_VID, NEN_ENTRY, "GASGN" },
56
+ { NODE_GVAR, NEN_VID, NEN_ENTRY, NEN_NONE, "GVAR" },
57
+ { NODE_HASH, NEN_HEAD, NEN_NONE, NEN_NONE, "HASH" },
58
+ { NODE_IASGN, NEN_VALUE, NEN_VID, NEN_NONE, "IASGN" },
59
+ { NODE_IF, NEN_COND, NEN_BODY, NEN_ELSE, "IF" },
60
+ { NODE_IFUNC, NEN_CFNC, NEN_TVAL, NEN_STATE, "IFUNC" },
61
+ { NODE_ITER, NEN_BODY, NEN_ITER, NEN_VAR, "ITER" },
62
+ { NODE_IVAR, NEN_VID, NEN_NONE, NEN_NONE, "IVAR" },
63
+ { NODE_LASGN, NEN_VALUE, NEN_VID, NEN_CNT, "LASGN" },
64
+ { NODE_LIT, NEN_LIT, NEN_NONE, NEN_NONE, "LIT" },
65
+ { NODE_LVAR, NEN_VID, NEN_CNT, NEN_NONE, "LVAR" },
66
+ { NODE_MASGN, NEN_ARGS, NEN_HEAD, NEN_VALUE, "MASGN" },
67
+ { NODE_MATCH, NEN_HEAD, NEN_VALUE, NEN_NONE, "MATCH" },
68
+ { NODE_MATCH2, NEN_VALUE, NEN_RECV, NEN_NONE, "MATCH2" },
69
+ { NODE_MATCH3, NEN_VALUE, NEN_RECV, NEN_NONE, "MATCH3" },
70
+ { NODE_MEMO, NEN_NONE, NEN_NONE, NEN_NONE, "MEMO" },
71
+ { NODE_METHOD, NEN_BODY, NEN_NOEX, NEN_NONE, "METHOD" },
72
+ { NODE_MODULE, NEN_BODY, NEN_CNAME, NEN_NONE, "MODULE" },
73
+ { NODE_NEWLINE, NEN_NEXT, NEN_NONE, NEN_NONE, "NEWLINE" },
74
+ { NODE_NEXT, NEN_STTS, NEN_NONE, NEN_NONE, "NEXT" },
75
+ { NODE_NIL, NEN_NONE, NEN_NONE, NEN_NONE, "NIL" },
76
+ { NODE_NOT, NEN_BODY, NEN_NONE, NEN_NONE, "NOT" },
77
+ { NODE_NTH_REF, NEN_NTH, NEN_CNT, NEN_NONE, "NTH_REF" },
78
+ { NODE_OPT_N, NEN_BODY, NEN_NONE, NEN_NONE, "OPT_N" },
79
+ { NODE_OP_ASGN1, NEN_ARGS, NEN_MID, NEN_RECV, "OP_ASGN1" },
80
+ { NODE_OP_ASGN2, NEN_VALUE, NEN_NEXT, NEN_RECV, "OP_ASGN2" },
81
+ { NODE_OP_ASGN2_ARG, NEN_VID, NEN_AID, NEN_MID, "OP_ASGN2_ARG" },
82
+ { NODE_OP_ASGN_AND, NEN_VALUE, NEN_RECV, NEN_NONE, "OP_ASGN_AND" },
83
+ { NODE_OP_ASGN_OR, NEN_AID, NEN_VALUE, NEN_RECV, "OP_ASGN_OR" },
84
+ { NODE_OR, NEN_1ST, NEN_2ND, NEN_NONE, "OR" },
85
+ { NODE_POSTEXE, NEN_NONE, NEN_NONE, NEN_NONE, "POSTEXE" },
86
+ { NODE_REDO, NEN_NONE, NEN_NONE, NEN_NONE, "REDO" },
87
+ { NODE_RESBODY, NEN_HEAD, NEN_ARGS, NEN_BODY, "RESBODY" },
88
+ { NODE_RESCUE, NEN_HEAD, NEN_ELSE, NEN_RESQ, "RESCUE" },
89
+ { NODE_RETRY, NEN_NONE, NEN_NONE, NEN_NONE, "RETRY" },
90
+ { NODE_RETURN, NEN_STTS, NEN_NONE, NEN_NONE, "RETURN" },
91
+ { NODE_SCLASS, NEN_BODY, NEN_RECV, NEN_NONE, "SCLASS" },
92
+ { NODE_SCOPE, NEN_TBL, NEN_RVAL, NEN_NEXT, "SCOPE" },
93
+ { NODE_SELF, NEN_NONE, NEN_NONE, NEN_NONE, "SELF" },
94
+ { NODE_STR, NEN_LIT, NEN_NONE, NEN_NONE, "STR" },
95
+ { NODE_SUPER, NEN_ARGS, NEN_NONE, NEN_NONE, "SUPER" },
96
+ { NODE_TRUE, NEN_NONE, NEN_NONE, NEN_NONE, "TRUE" },
97
+ { NODE_UNDEF, NEN_MID, NEN_NONE, NEN_NONE, "UNDEF" },
98
+ { NODE_UNTIL, NEN_BODY, NEN_COND, NEN_STATE, "UNTIL" },
99
+ { NODE_VALIAS, NEN_1ST, NEN_2ND, NEN_NONE, "VALIAS" },
100
+ { NODE_VCALL, NEN_MID, NEN_NONE, NEN_NONE, "VCALL" },
101
+ { NODE_WHEN, NEN_HEAD, NEN_BODY, NEN_NEXT, "WHEN" },
102
+ { NODE_WHILE, NEN_BODY, NEN_COND, NEN_STATE, "WHILE" },
103
+ { NODE_XSTR, NEN_LIT, NEN_NONE, NEN_NONE, "XSTR" },
104
+ { NODE_YIELD, NEN_HEAD, NEN_STATE, NEN_NONE, "YIELD" },
105
+ { NODE_ZARRAY, NEN_NONE, NEN_NONE, NEN_NONE, "ZARRAY" },
106
+ { NODE_ZSUPER, NEN_NONE, NEN_NONE, NEN_NONE, "ZSUPER" },
107
+ { NODE_LAST, NEN_NONE, NEN_NONE, NEN_NONE, "LAST" },
108
+ };
109
+
110
+ static Node_Type_Descrip * node_type_descrips[NUM_NODE_TYPE_DESCRIPS];
111
+ static int node_type_descrips_initialized = 0;
112
+
113
+ static void init_node_type_descrips()
114
+ {
115
+ if(!node_type_descrips_initialized)
116
+ {
117
+ Node_Type_Descrip * descrip;
118
+ memset(node_type_descrips, 0, sizeof(node_type_descrips));
119
+ for(descrip = node_type_descrips_unsorted;
120
+ descrip->nt != NODE_LAST;
121
+ ++descrip)
122
+ {
123
+ if(node_type_descrips[descrip->nt])
124
+ {
125
+ rb_raise(rb_eRuntimeError, "duplicate entry for node type %d (%s is also %s)\n", descrip->nt, descrip->name, node_type_descrips[descrip->nt]->name);
126
+ }
127
+ else
128
+ {
129
+ node_type_descrips[descrip->nt] = descrip;
130
+ }
131
+ }
132
+ node_type_descrips_initialized = 1;
133
+ }
134
+ }
135
+
136
+ /* Given a node, find out the types of the three elements it contains */
137
+ Node_Type_Descrip const * node_type_descrip(enum node_type nt)
138
+ {
139
+ init_node_type_descrips();
140
+ if(node_type_descrips[nt])
141
+ {
142
+ return node_type_descrips[nt];
143
+ }
144
+ else
145
+ {
146
+ rb_raise(rb_eArgError, "Unknown node type %d", nt);
147
+ }
148
+ }
149
+