vcs 0.1 → 0.2.148

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 (132) hide show
  1. data/Rakefile +17 -3
  2. data/bin/vcs +57 -34
  3. data/doc/jamis.rb +564 -0
  4. data/ruby_ex/abstract.rb +254 -0
  5. data/ruby_ex/abstract_node.rb +85 -0
  6. data/ruby_ex/algorithms/simulated_annealing.rb +140 -0
  7. data/ruby_ex/array_each_pair.rb +18 -0
  8. data/ruby_ex/ask.rb +101 -0
  9. data/ruby_ex/attributed_class.rb +302 -0
  10. data/ruby_ex/cache.rb +373 -0
  11. data/ruby_ex/checkout.rb +12 -0
  12. data/ruby_ex/choose.rb +271 -0
  13. data/ruby_ex/commands.rb +18 -0
  14. data/ruby_ex/commands/command.rb +401 -0
  15. data/ruby_ex/commands/datas.rb +16 -0
  16. data/ruby_ex/commands/datas/data.rb +33 -0
  17. data/ruby_ex/commands/datas/factory.rb +66 -0
  18. data/ruby_ex/commands/factory.rb +66 -0
  19. data/ruby_ex/commands/helpers.rb +67 -0
  20. data/ruby_ex/commands/pipe.rb +64 -0
  21. data/ruby_ex/commands/runners.rb +17 -0
  22. data/ruby_ex/commands/runners/exec.rb +49 -0
  23. data/ruby_ex/commands/runners/fork.rb +97 -0
  24. data/ruby_ex/commands/runners/runner.rb +107 -0
  25. data/ruby_ex/commands/seq.rb +27 -0
  26. data/ruby_ex/config_file.rb +96 -0
  27. data/ruby_ex/const_regexp.rb +59 -0
  28. data/ruby_ex/daemon.rb +134 -0
  29. data/ruby_ex/diff.rb +667 -0
  30. data/ruby_ex/dlogger.rb +62 -0
  31. data/ruby_ex/drb/dispatcher.rb +252 -0
  32. data/ruby_ex/drb/dispatcher_server_test.rb +29 -0
  33. data/ruby_ex/drb/drb_observable.rb +97 -0
  34. data/ruby_ex/drb/drb_observable_pool.rb +27 -0
  35. data/ruby_ex/drb/drb_service.rb +43 -0
  36. data/ruby_ex/drb/drb_undumped_attributes.rb +55 -0
  37. data/ruby_ex/drb/drb_undumped_indexed_object.rb +54 -0
  38. data/ruby_ex/drb/insecure_protected_methods.rb +103 -0
  39. data/ruby_ex/drb/session_client_test.rb +40 -0
  40. data/ruby_ex/drb/session_manager.rb +246 -0
  41. data/ruby_ex/drb/session_server.rb +53 -0
  42. data/ruby_ex/dtime.rb +143 -0
  43. data/ruby_ex/dumpable_proc.rb +63 -0
  44. data/ruby_ex/exception.rb +32 -0
  45. data/ruby_ex/filetype.rb +229 -0
  46. data/ruby_ex/fileutils_ex.rb +44 -0
  47. data/ruby_ex/fold.rb +58 -0
  48. data/ruby_ex/generate_id.rb +44 -0
  49. data/ruby_ex/hookable.rb +262 -0
  50. data/ruby_ex/hooker.rb +54 -0
  51. data/ruby_ex/inactive_timeout.rb +137 -0
  52. data/ruby_ex/indexed_node.rb +66 -0
  53. data/ruby_ex/io_marshal.rb +100 -0
  54. data/ruby_ex/ioo.rb +194 -0
  55. data/ruby_ex/labeled_node.rb +63 -0
  56. data/ruby_ex/logger_observer.rb +23 -0
  57. data/ruby_ex/md5sum.rb +66 -0
  58. data/ruby_ex/mktemp.rb +208 -0
  59. data/ruby_ex/module/attr_once.rb +36 -0
  60. data/ruby_ex/module/autoload_tree.rb +75 -0
  61. data/ruby_ex/module/hierarchy.rb +335 -0
  62. data/ruby_ex/module/instance_method_visibility.rb +73 -0
  63. data/ruby_ex/module_ex.rb +11 -0
  64. data/ruby_ex/node.rb +80 -0
  65. data/ruby_ex/object_monitor.rb +145 -0
  66. data/ruby_ex/object_monitor_activity.rb +33 -0
  67. data/ruby_ex/observable.rb +140 -0
  68. data/ruby_ex/observable_pool.rb +293 -0
  69. data/ruby_ex/orderedhash.rb +252 -0
  70. data/ruby_ex/pathname_ex.rb +152 -0
  71. data/ruby_ex/pp_hierarchy.rb +29 -0
  72. data/ruby_ex/pseudo_cache.rb +190 -0
  73. data/ruby_ex/queue.rb +56 -0
  74. data/ruby_ex/random_generators.rb +25 -0
  75. data/ruby_ex/random_generators/random_generator.rb +31 -0
  76. data/ruby_ex/random_generators/ruby.rb +23 -0
  77. data/ruby_ex/safe_eval.rb +348 -0
  78. data/ruby_ex/sendmail.rb +215 -0
  79. data/ruby_ex/service_manager.rb +121 -0
  80. data/ruby_ex/session/administrable.rb +120 -0
  81. data/ruby_ex/session/client.rb +153 -0
  82. data/ruby_ex/session/const.rb +18 -0
  83. data/ruby_ex/session/dispatcher.rb +184 -0
  84. data/ruby_ex/session/error.rb +21 -0
  85. data/ruby_ex/session/fetchable.rb +57 -0
  86. data/ruby_ex/session/fetcher.rb +62 -0
  87. data/ruby_ex/session/hookable.rb +26 -0
  88. data/ruby_ex/session/profile.rb +110 -0
  89. data/ruby_ex/session/server.rb +582 -0
  90. data/ruby_ex/session/test/administrable_test.rb +337 -0
  91. data/ruby_ex/session/test/basic_test.rb +523 -0
  92. data/ruby_ex/session/test/dispatcher_test.rb +409 -0
  93. data/ruby_ex/session/test/fetchable_test.rb +119 -0
  94. data/ruby_ex/session/test/sub_server_test.rb +188 -0
  95. data/ruby_ex/shuffle.rb +30 -0
  96. data/ruby_ex/spring.rb +136 -0
  97. data/ruby_ex/spring_set.rb +137 -0
  98. data/ruby_ex/string_ex.rb +28 -0
  99. data/ruby_ex/symtbl.rb +106 -0
  100. data/ruby_ex/synflow.rb +474 -0
  101. data/ruby_ex/test/unit/ui/yaml/testrunner.rb +164 -0
  102. data/ruby_ex/thread_mutex.rb +10 -0
  103. data/ruby_ex/timeout_ex.rb +81 -0
  104. data/ruby_ex/top_down.rb +73 -0
  105. data/ruby_ex/trace.rb +26 -0
  106. data/ruby_ex/uri/druby.rb +81 -0
  107. data/ruby_ex/uri/file.rb +65 -0
  108. data/ruby_ex/uri/ftp_ex.rb +37 -0
  109. data/ruby_ex/uri/http_ex.rb +43 -0
  110. data/ruby_ex/uri/ssh.rb +92 -0
  111. data/ruby_ex/uri/svn.rb +118 -0
  112. data/ruby_ex/uri_ex.rb +45 -0
  113. data/ruby_ex/verbose_object.rb +30 -0
  114. data/ruby_ex/version.rb +66 -0
  115. data/ruby_ex/yaml/basenode_ext.rb +63 -0
  116. data/ruby_ex/yaml/chop_header.rb +23 -0
  117. data/ruby_ex/yaml/transform.rb +449 -0
  118. data/ruby_ex/yaml/yregexpath.rb +76 -0
  119. data/src/changelog.rb +28 -18
  120. data/src/conflict.rb +20 -0
  121. data/src/diff.rb +18 -0
  122. data/src/diffstat.rb +9 -3
  123. data/src/last_changed_date.rb +18 -0
  124. data/src/mail.rb +33 -65
  125. data/src/message.rb +15 -9
  126. data/src/mycommit.rb +29 -14
  127. data/src/news.rb +24 -3
  128. data/src/status.rb +17 -0
  129. data/src/svn.rb +2 -2
  130. data/src/vcs.rb +24 -3
  131. metadata +124 -5
  132. data/lrdetools.rb +0 -12
@@ -0,0 +1,335 @@
1
+ # Copyright: Copyright (c) 2004 Nicolas Despres. All rights reserved.
2
+ # Author: Nicolas Despres <polrop@lrde.epita.fr>.
3
+ # License: Gnu General Public License.
4
+
5
+ # $LastChangedBy: polrop $
6
+ # $Id: hierarchy.rb 194 2005-04-11 10:03:22Z polrop $
7
+
8
+
9
+ # Extend the Module class with method to manipulate inheritance relation
10
+ # between constants of a module.
11
+ class Module
12
+
13
+ # Return the list of all sub classes of base_class (including itself).
14
+ # If force_autoload is false, not yet loaded constants will be ignored.
15
+ # If recursive is true sub modules will also be traversed.
16
+ def sub_classes(base_class, force_autoload=false, recursive=false)
17
+ check_const_is_class?(base_class)
18
+ result = []
19
+ constants.each do |const_name|
20
+ if autoload?(const_name).nil? or force_autoload
21
+ const = const_get(const_name)
22
+ if const.is_a?(Module)
23
+ if const.is_a?(Class)
24
+ result << const if const.ancestors.include?(base_class)
25
+ elsif recursive
26
+ result += const.sub_classes(base_class, force_autoload, recursive)
27
+ end
28
+ end
29
+ end
30
+ end
31
+ result
32
+ end
33
+
34
+ # Remove a class from the hierarchy using remove_const. Sub classes of this
35
+ # class are also removed. It returns an array of the removed class name.
36
+ # See sub_classes for a description of the recursive argument.
37
+ def remove_class(base_class, recursive=false)
38
+ subs = sub_classes(base_class, true, recursive)
39
+ re = Regexp.new("^#{name}::")
40
+ result = []
41
+ subs.each do |sub|
42
+ sub_name = sub.to_s.sub!(re, '')
43
+ if sub_name =~ /^(.+)::(.+)$/
44
+ const_get($1).module_eval { remove_const($2.to_sym) }
45
+ else
46
+ remove_const(sub_name.to_sym)
47
+ end
48
+ result << sub_name
49
+ end
50
+ result
51
+ end
52
+
53
+ # Return the inheritance tree of the base_class.
54
+ # Example:
55
+ #
56
+ # module M
57
+ # class A; end
58
+ # class B < A; end
59
+ # class C < B; end
60
+ # class D < B; end
61
+ # class E < A; end
62
+ # module N
63
+ # class F < A; end
64
+ # class G < F; end
65
+ # class H < D; end
66
+ # class I < H; end
67
+ # class J < E; end
68
+ # class Y; end
69
+ # end
70
+ # class Z; end
71
+ # FOO = 42
72
+ # end
73
+ #
74
+ # M.sub_classes_tree(M::A)
75
+ #
76
+ # produces:
77
+ #
78
+ # {
79
+ # M::A => {
80
+ # M::B => {
81
+ # M::D => {},
82
+ # M::C => {}
83
+ # },
84
+ # M::E => {}
85
+ # }
86
+ # }
87
+ #
88
+ # and
89
+ #
90
+ # M.sub_classes_tree(M::A, false, true)
91
+ #
92
+ # produces:
93
+ #
94
+ # {
95
+ # M::A => {
96
+ # M::N::F => {
97
+ # M::N::G => {}
98
+ # },
99
+ # M::B => {
100
+ # M::C => {},
101
+ # M::D => {
102
+ # M::N::H => {
103
+ # M::N::I => {}
104
+ # }
105
+ # }
106
+ # },
107
+ # M::E => {
108
+ # M::N::J => {}
109
+ # }
110
+ # }
111
+ # }
112
+ def sub_classes_tree(base_class, force_autoload=false, recursive=false)
113
+ subs = sub_classes(base_class, force_autoload, recursive)
114
+ sub_classes_tree_rec([base_class], subs)
115
+ end
116
+
117
+ private
118
+ def sub_classes_tree_rec(base_classes, csts)
119
+ result = {}
120
+ next_csts = []
121
+ base_classes.each do |b|
122
+ next_base_classes = []
123
+ csts.each do |c|
124
+ c.superclass == b ? next_base_classes << c : next_csts << c;
125
+ end
126
+ result[b] = sub_classes_tree_rec(next_base_classes, next_csts)
127
+ end
128
+ result
129
+ end
130
+
131
+ private
132
+ def check_const_is_class?(*base_classes)
133
+ base_classes.each do |b|
134
+ raise(TypeError, "`#{b}' - not a class") unless b.is_a?(Class)
135
+ end
136
+ end
137
+
138
+ end # class Module
139
+
140
+
141
+ if (not defined? HIERARCHY_TESTED) and (defined? TEST_MODE or __FILE__ == $0)
142
+ HIERARCHY_TESTED = true
143
+
144
+ require 'test/unit/ui/console/testrunner'
145
+ require 'diff'
146
+
147
+
148
+ class HierarchyTest < Test::Unit::TestCase
149
+
150
+ module M
151
+
152
+ class A; end
153
+ class B < A; end
154
+ class C; end
155
+ FOO = 42
156
+
157
+ end
158
+
159
+ def test_sub_classes
160
+ sub_classes = M.sub_classes(HierarchyTest::M::A)
161
+ assert_equal(2, sub_classes.size)
162
+ [HierarchyTest::M::B, HierarchyTest::M::A].each do |x|
163
+ assert(sub_classes.include?(x))
164
+ end
165
+ assert_equal([HierarchyTest::M::C], M.sub_classes(M::C))
166
+ end
167
+
168
+ module Mautoload
169
+
170
+ class A; end
171
+ class B < A; end
172
+ autoload(:C, '/foo')
173
+ FOO = 42
174
+
175
+ end
176
+
177
+ def test_sub_classes_force_autoload
178
+ sub_classes = Mautoload.sub_classes(Mautoload::A)
179
+ assert_equal(2, sub_classes.size)
180
+ [Mautoload::B, Mautoload::A].each do |x|
181
+ assert(sub_classes.include?(x))
182
+ end
183
+ assert_equal(4, Mautoload.constants.size)
184
+ assert_not_nil(Mautoload.autoload?(:C))
185
+ assert_raises(LoadError) { Mautoload.sub_classes(Mautoload::A, true) }
186
+ assert_equal(3, Mautoload.constants.size)
187
+ assert_nil(Mautoload.autoload?(:C))
188
+ end
189
+
190
+ module Mrec
191
+ class A; end
192
+ class B < A; end
193
+ module M
194
+ class C < A; end
195
+ class D < B; end
196
+ class E < D; end
197
+ class Y; end
198
+ end
199
+ class Z; end
200
+ FOO = 42
201
+ end
202
+
203
+ def test_sub_classes_recursive
204
+ sub_classes = Mrec.sub_classes(Mrec::A)
205
+ assert_equal(2, sub_classes.size)
206
+ [Mrec::B, Mrec::A].each do |x|
207
+ assert(sub_classes.include?(x))
208
+ end
209
+ sub_classes = Mrec.sub_classes(Mrec::A, false, true)
210
+ assert_equal(5, sub_classes.size)
211
+ [Mrec::B, Mrec::A, Mrec::M::C, Mrec::M::D, Mrec::M::E].each do |x|
212
+ assert(sub_classes.include?(x))
213
+ end
214
+ r = Mrec.remove_class(Mrec::A, true)
215
+ assert_equal(5, r.size)
216
+ ['B', 'A', 'M::E', 'M::C', 'M::D'].each do |x|
217
+ assert(r.include?(x))
218
+ end
219
+ assert_equal(3, Mrec.constants.size)
220
+ ['FOO', 'M', 'Z'].each { |x| assert(Mrec.constants.include?(x)) }
221
+ assert_equal(1, Mrec::M.constants.size)
222
+ ['Y'].each { |x| assert(Mrec::M.constants.include?(x)) }
223
+ end
224
+
225
+ module Tree
226
+
227
+ class A; end
228
+ class B < A; end
229
+ class C < B; end
230
+ class D < B; end
231
+ class E < A; end
232
+ module M
233
+ class F < A; end
234
+ class G < F; end
235
+ class H < D; end
236
+ class I < H; end
237
+ class J < E; end
238
+ class Y; end
239
+ end
240
+ class Z; end
241
+ FOO = 42
242
+
243
+ end
244
+
245
+ def test_sub_classes_tree_rec
246
+ r = Tree.sub_classes_tree(HierarchyTest::Tree::A, false, true)
247
+ ref = {
248
+ HierarchyTest::Tree::A => {
249
+ HierarchyTest::Tree::M::F => {
250
+ HierarchyTest::Tree::M::G => {}
251
+ },
252
+ HierarchyTest::Tree::B => {
253
+ HierarchyTest::Tree::C => {},
254
+ HierarchyTest::Tree::D => {
255
+ HierarchyTest::Tree::M::H => {
256
+ HierarchyTest::Tree::M::I=>{}
257
+ }
258
+ }
259
+ },
260
+ HierarchyTest::Tree::E=> {
261
+ HierarchyTest::Tree::M::J=>{}
262
+ }
263
+ }
264
+ }
265
+ d = r.diff(ref)
266
+ assert_equal({}, d[:different])
267
+ assert_equal({}, d[:additional])
268
+ assert_equal({}, d[:missing])
269
+ end
270
+
271
+ def test_sub_classes_tree
272
+ r = Tree.sub_classes_tree(HierarchyTest::Tree::A)
273
+ ref = {
274
+ HierarchyTest::Tree::A => {
275
+ HierarchyTest::Tree::B => {
276
+ HierarchyTest::Tree::D => {},
277
+ HierarchyTest::Tree::C => {}
278
+ },
279
+ HierarchyTest::Tree::E => {}
280
+ }
281
+ }
282
+ d = r.diff(ref)
283
+ assert_equal({}, d[:different])
284
+ assert_equal({}, d[:additional])
285
+ assert_equal({}, d[:missing])
286
+ end
287
+
288
+ module Error
289
+ module M; end
290
+ end
291
+
292
+ def test_sub_classes_error
293
+ assert_raises(TypeError) do
294
+ Error.sub_classes_tree(HierarchyTest::Error::M)
295
+ end
296
+ assert_raises(TypeError) do
297
+ Error.sub_classes(HierarchyTest::Error::M)
298
+ end
299
+ assert_raises(TypeError) do
300
+ Error.remove_class(HierarchyTest::Error::M)
301
+ end
302
+ end
303
+
304
+ module RemoveClass
305
+
306
+ class A; end
307
+ class B < A; end
308
+ class C < B; end
309
+ class D < B; end
310
+ class E < D; end
311
+ class F < A; end
312
+ class Z; end
313
+ module M
314
+ class Y; end
315
+ end
316
+ BAR = 51
317
+
318
+ end
319
+
320
+ def test_remove_class
321
+ r = RemoveClass.remove_class(HierarchyTest::RemoveClass::B)
322
+ assert_equal(4, r.size)
323
+ ['B', 'D', 'E', 'C'].each { |x| assert(r.include?(x)) }
324
+ assert_equal(5, RemoveClass.constants.size)
325
+ ['A', 'F', 'Z', 'M', 'BAR'].each do |x|
326
+ assert(RemoveClass.constants.include?(x))
327
+ end
328
+ end
329
+
330
+ end # class HierarchyTest
331
+
332
+
333
+ end
334
+
335
+
@@ -0,0 +1,73 @@
1
+ # Copyright: Copyright (c) 2004 Nicolas Despres. All rights reserved.
2
+ # Author: Nicolas Despres <polrop@lrde.epita.fr>.
3
+ # License: Gnu General Public License.
4
+
5
+ # $LastChangedBy: polrop $
6
+ # $Id: instance_method_visibility.rb 143 2005-01-30 14:06:43Z polrop $
7
+
8
+
9
+ class Module
10
+
11
+ def instance_method_visibility(name)
12
+ if private_method_defined?(name)
13
+ :private
14
+ elsif protected_method_defined?(name)
15
+ :protected
16
+ elsif public_method_defined?(name)
17
+ :public
18
+ else
19
+ raise(NoMethodError,
20
+ "`#{name}' - not an instance method of `#{self.name}'")
21
+ end
22
+ end
23
+
24
+ end # class Module
25
+
26
+
27
+ if (not defined? INSTANCE_METHOD_VISIBILITY_TESTED) and
28
+ (defined? TEST_MODE or __FILE__ == $0)
29
+ INSTANCE_METHOD_VISIBILITY_TESTED = true
30
+
31
+ require 'test/unit/ui/console/testrunner'
32
+
33
+
34
+ class InstanceMethodVisibilityTest < Test::Unit::TestCase
35
+
36
+ class A
37
+
38
+ def pub; end
39
+ def pri; end
40
+ def pro; end
41
+
42
+ public :pub
43
+ private :pri
44
+ protected :pro
45
+
46
+ end # class A
47
+
48
+ def test_simple
49
+ assert_equal(:public, A.instance_method_visibility('pub'))
50
+ assert_equal(:private, A.instance_method_visibility('pri'))
51
+ assert_equal(:protected, A.instance_method_visibility('pro'))
52
+ assert_raises(NoMethodError) { A.instance_method_visibility('new') }
53
+ end
54
+
55
+ class AA
56
+ def f; end
57
+ end
58
+ class BB < AA
59
+ private :f
60
+ end
61
+
62
+ def test_inheritance
63
+ assert_equal(:public, AA.instance_method_visibility('f'))
64
+ assert(! BB.public_method_defined?('f'))
65
+ assert_equal(:private, BB.instance_method_visibility('f'))
66
+ end
67
+
68
+ end # class InstanceMethodVisibilityTest
69
+
70
+
71
+ end
72
+
73
+
@@ -0,0 +1,11 @@
1
+ # Copyright: Copyright (c) 2004 Nicolas Despres. All rights reserved.
2
+ # Author: Nicolas Despres <polrop@lrde.epita.fr>.
3
+ # License: Gnu General Public License.
4
+
5
+ # $LastChangedBy: polrop $
6
+ # $Id: module_ex.rb 107 2005-01-17 03:31:39Z polrop $
7
+
8
+
9
+ Dir["#{File.dirname(__FILE__)}/module/**/*.rb"].each do |filename|
10
+ require filename
11
+ end
@@ -0,0 +1,80 @@
1
+ # Copyright: Copyright (c) 2004 Nicolas Despres. All rights reserved.
2
+ # Author: Nicolas Despres <polrop@lrde.epita.fr>.
3
+ # License: Gnu General Public License.
4
+
5
+ # $LastChangedBy: polrop $
6
+ # $Id: node.rb 171 2005-03-29 09:12:47Z polrop $
7
+
8
+
9
+ class Node
10
+
11
+ def initialize(data=nil, *sub_nodes)
12
+ @data = data
13
+ sub_nodes.each { |sub_node| check_sub_node_type(sub_node) }
14
+ @sub_nodes = sub_nodes
15
+ end
16
+
17
+ attr_reader :data, :sub_nodes
18
+
19
+ def [](sub_node_index)
20
+ @sub_nodes[sub_node_index]
21
+ end
22
+
23
+ def []=(sub_node_index, sub_node)
24
+ check_sub_node_type(sub_node)
25
+ @sub_nodes[sub_node_index] = sub_node
26
+ end
27
+
28
+ def <<(sub_node)
29
+ check_sub_node_type(sub_node)
30
+ @sub_nodes << sub_node
31
+ end
32
+
33
+ def each_pair(&block)
34
+ @sub_nodes.each_with_index { |sub_node, i| block[i, sub_node] }
35
+ end
36
+
37
+ def each_node(&block)
38
+ @sub_nodes.each_with_index { |sub_node, index| block[sub_node] }
39
+ end
40
+
41
+ alias :each :each_node
42
+
43
+ def each_index(&block)
44
+ @sub_nodes.each_with_index { |sub_node, index| block[index] }
45
+ end
46
+
47
+ def delete(sub_node)
48
+ @sub_nodes.delete(sub_node)
49
+ end
50
+
51
+ def nb_sub_nodes
52
+ @sub_nodes.size
53
+ end
54
+
55
+ alias size nb_sub_nodes
56
+ alias length nb_sub_nodes
57
+
58
+ def leaf?
59
+ @sub_nodes.empty?
60
+ end
61
+
62
+ def pre_depth_first(&block)
63
+ block[self]
64
+ @sub_nodes.each { |sub_node| sub_node.pre_depth_first(&block) }
65
+ nil
66
+ end
67
+
68
+ # FIXME: implement me
69
+ # def breadth_first(&block)
70
+ # end
71
+
72
+ protected
73
+ def check_sub_node_type(sub_node)
74
+ unless sub_node.is_a?(self.class)
75
+ raise(TypeError, "`#{sub_node}' - must be a #{self.class}")
76
+ end
77
+ end
78
+
79
+ end # class Node
80
+