superchris-rubyjs 0.8.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (86) hide show
  1. data/README +131 -0
  2. data/Rakefile +65 -0
  3. data/bin/rubyjs +144 -0
  4. data/rubyjs.gemspec +112 -0
  5. data/src/rubyjs.rb +3 -0
  6. data/src/rubyjs/code_generator.rb +474 -0
  7. data/src/rubyjs/compiler.rb +2061 -0
  8. data/src/rubyjs/debug_name_generator.rb +95 -0
  9. data/src/rubyjs/encoder.rb +171 -0
  10. data/src/rubyjs/eval_into.rb +59 -0
  11. data/src/rubyjs/lib/core.rb +1016 -0
  12. data/src/rubyjs/lib/dom_element.rb +66 -0
  13. data/src/rubyjs/lib/json.rb +101 -0
  14. data/src/rubyjs/lib/microunit.rb +188 -0
  15. data/src/rubyjs/model.rb +293 -0
  16. data/src/rubyjs/name_generator.rb +71 -0
  17. data/src/rwt/AbsolutePanel.rb +161 -0
  18. data/src/rwt/DOM.Konqueror.rb +89 -0
  19. data/src/rwt/DOM.Opera.rb +65 -0
  20. data/src/rwt/DOM.rb +1044 -0
  21. data/src/rwt/Event.Opera.rb +35 -0
  22. data/src/rwt/Event.rb +429 -0
  23. data/src/rwt/HTTPRequest.IE6.rb +5 -0
  24. data/src/rwt/HTTPRequest.rb +74 -0
  25. data/src/rwt/Label.rb +164 -0
  26. data/src/rwt/Panel.rb +90 -0
  27. data/src/rwt/RootPanel.rb +16 -0
  28. data/src/rwt/UIObject.rb +495 -0
  29. data/src/rwt/Widget.rb +193 -0
  30. data/src/rwt/ported-from/AbsolutePanel.java +158 -0
  31. data/src/rwt/ported-from/DOM.java +571 -0
  32. data/src/rwt/ported-from/DOMImpl.java +426 -0
  33. data/src/rwt/ported-from/DOMImplOpera.java +82 -0
  34. data/src/rwt/ported-from/DOMImplStandard.java +234 -0
  35. data/src/rwt/ported-from/HTTPRequest.java +81 -0
  36. data/src/rwt/ported-from/HTTPRequestImpl.java +103 -0
  37. data/src/rwt/ported-from/Label.java +163 -0
  38. data/src/rwt/ported-from/Panel.java +99 -0
  39. data/src/rwt/ported-from/UIObject.java +614 -0
  40. data/src/rwt/ported-from/Widget.java +221 -0
  41. data/test/benchmark/bm_vm1_block.rb +15 -0
  42. data/test/benchmark/bm_vm1_const.rb +13 -0
  43. data/test/benchmark/bm_vm1_ensure.rb +15 -0
  44. data/test/benchmark/common.rb +5 -0
  45. data/test/benchmark/params.yaml +7 -0
  46. data/test/common.Browser.rb +13 -0
  47. data/test/common.rb +8 -0
  48. data/test/gen_browser_test_suite.rb +129 -0
  49. data/test/gen_test_suite.rb +41 -0
  50. data/test/run_benchs.rb +58 -0
  51. data/test/run_tests.rb +22 -0
  52. data/test/test_args.rb +24 -0
  53. data/test/test_array.rb +22 -0
  54. data/test/test_case.rb +35 -0
  55. data/test/test_class.rb +55 -0
  56. data/test/test_eql.rb +9 -0
  57. data/test/test_exception.rb +61 -0
  58. data/test/test_expr.rb +12 -0
  59. data/test/test_hash.rb +29 -0
  60. data/test/test_hot_ruby.rb +146 -0
  61. data/test/test_if.rb +28 -0
  62. data/test/test_insertion_sort.rb +25 -0
  63. data/test/test_inspect.rb +10 -0
  64. data/test/test_lebewesen.rb +39 -0
  65. data/test/test_massign.rb +66 -0
  66. data/test/test_new.rb +12 -0
  67. data/test/test_range.rb +70 -0
  68. data/test/test_regexp.rb +22 -0
  69. data/test/test_send.rb +65 -0
  70. data/test/test_simple_output.rb +5 -0
  71. data/test/test_splat.rb +21 -0
  72. data/test/test_string.rb +51 -0
  73. data/test/test_test.rb +17 -0
  74. data/test/test_yield.rb +154 -0
  75. data/utils/js/Makefile +9 -0
  76. data/utils/js/RunScript.class +0 -0
  77. data/utils/js/RunScript.java +73 -0
  78. data/utils/js/js.jar +0 -0
  79. data/utils/js/run.sh +3 -0
  80. data/utils/jsc/Makefile +7 -0
  81. data/utils/jsc/README +3 -0
  82. data/utils/jsc/RunScript.c +93 -0
  83. data/utils/jsc/run.sh +15 -0
  84. data/utils/yuicompressor/README +1 -0
  85. data/utils/yuicompressor/yuicompressor-2.2.5.jar +0 -0
  86. metadata +157 -0
@@ -0,0 +1,66 @@
1
+ class DOMElement
2
+ def initialize(element)
3
+ @dom_element = element
4
+ end
5
+
6
+ def observe(event, &block)
7
+ element = @dom_element
8
+ `
9
+ if (#<element>.addEventListener) {
10
+ #<element>.addEventListener(#<event>, #<block>, false);
11
+ } else {
12
+ #<element>.attachEvent("on" + #<event>, #<block>);
13
+ }
14
+ `
15
+ nil
16
+ end
17
+
18
+ def [](attribute)
19
+ element = @dom_element
20
+ `return #<element>[#<attribute>]`
21
+ end
22
+
23
+ def []=(attr, value)
24
+ attr_name = attr.to_s
25
+ element = @dom_element
26
+ `#<element>[#<attr_name>] = #<value>;`
27
+ nil
28
+ end
29
+
30
+ def self.find_js_element(element)
31
+ `return document.getElementById(#<element>);`
32
+ end
33
+
34
+
35
+ def self.find(element)
36
+ dom_element = self.find_js_element(element)
37
+ DOMElement.new(dom_element)
38
+ end
39
+
40
+ #
41
+ # Gets an HTML representation (as String) of an element's children.
42
+ #
43
+ # elem:: the element whose HTML is to be retrieved
44
+ # return:: the HTML representation of the element's children
45
+ #
46
+ def inner_html
47
+ elem = @dom_element
48
+ `
49
+ var ret = #<elem>.innerHTML;
50
+ return (ret == null) ? #<nil> : ret;`
51
+ end
52
+
53
+ #
54
+ # Sets the HTML contained within an element.
55
+ #
56
+ # elem:: the element whose inner HTML is to be set
57
+ # html:: the new html
58
+ #
59
+ def inner_html=(html)
60
+ elem = @dom_element
61
+ `
62
+ #<elem>.innerHTML = #<html>;
63
+ return #<nil>;`
64
+ end
65
+
66
+ end
@@ -0,0 +1,101 @@
1
+ #
2
+ # JSON loading/dumping
3
+ #
4
+ # Parser code taken from http://www.json.org/json.js
5
+ #
6
+
7
+ class JSON
8
+ class SyntaxError < RuntimeError; end
9
+
10
+ #
11
+ # Parsing happens in three stages. In the first stage, we run the text against
12
+ # a regular expression which looks for non-JSON characters. We are especially
13
+ # concerned with '()' and 'new' because they can cause invocation, and '='
14
+ # because it can cause mutation. But just to be safe, we will reject all
15
+ # unexpected characters.
16
+ #
17
+ # We split the first stage into 4 regexp operations in order to work around
18
+ # crippling deficiencies in IE's and Safari's regexp engines. First we replace
19
+ # all backslash pairs with '@' (a non-JSON character). Second, we replace all
20
+ # simple value tokens with ']' characters. Third, we delete all open brackets
21
+ # that follow a colon or comma or that begin the text. Finally, we look to see
22
+ # that the remaining characters are only whitespace or ']' or ',' or ':' or '{'
23
+ # or '}'. If that is so, then the text is safe for eval.
24
+ #
25
+ # In the second stage we use the eval function to compile the text into a
26
+ # JavaScript structure. The '{' operator is subject to a syntactic ambiguity
27
+ # in JavaScript: it can begin a block or an object literal. We wrap the text
28
+ # in parens to eliminate the ambiguity.
29
+ #
30
+ def self._parse(str)
31
+ RubyJS::inline <<-'endjs'
32
+ if (/^[\],:{}\s]*$/.test(#<str>.replace(/\\./g, '@').
33
+ replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(:?[eE][+\-]?\d+)?/g, ']').
34
+ replace(/(?:^|:|,)(?:\s*\[)+/g, ''))) {
35
+ return eval('(' + #<str> + ')');
36
+ }
37
+ endjs
38
+
39
+ raise SyntaxError, str
40
+ end
41
+
42
+ def self.load(str)
43
+ obj = _parse(str)
44
+ `
45
+ var conv = function(obj) {
46
+ if (obj==null) return #<nil>;
47
+ else if (obj instanceof Array) {
48
+ for (var i=0; i<obj.length; i++) obj[i] = conv(obj[i]);
49
+ }
50
+ else if (typeof(obj) == 'object') {
51
+ var nobj = #<Hash>.#<m:new>();
52
+ for (var i in obj) {
53
+ nobj.#<m:[]=>(#<nil>, conv(i), conv(obj[i]));
54
+ }
55
+ return nobj;
56
+ }
57
+ return obj;
58
+ };
59
+ return conv(#<obj>);
60
+ `
61
+ end
62
+
63
+ def self.dump(obj)
64
+ obj.to_json
65
+ end
66
+ end
67
+
68
+ class Object
69
+ def to_json; raise end
70
+ end
71
+
72
+ class Boolean
73
+ alias to_json to_s
74
+ end
75
+
76
+ class NilClass
77
+ def to_json; "null" end
78
+ end
79
+
80
+ class String
81
+ alias to_json inspect # FIXME?
82
+ end
83
+
84
+ class Number
85
+ alias to_json to_s
86
+ end
87
+
88
+ class Array
89
+ def to_json
90
+ map {|a| a.to_json}.join(",")
91
+ end
92
+ end
93
+
94
+ class Hash
95
+ def to_json
96
+ str = "{"
97
+ str += map {|k, v| (k.to_json + ":" + v.to_json) }.join(",")
98
+ str += "}"
99
+ str
100
+ end
101
+ end
@@ -0,0 +1,188 @@
1
+ module MicroUnit
2
+ class TestCase
3
+ # def self.reset
4
+ # @@test_suites = {}
5
+ # end
6
+ #
7
+ # reset
8
+
9
+ # def self.inherited klass
10
+ # @test_suites ||= {}
11
+ # @test_suites[klass] = true
12
+ # end
13
+ #
14
+ # def self.test_suites
15
+ # @test_suites.keys.sort_by { |ts| ts.name }
16
+ # end
17
+
18
+ attr_accessor :_assertions
19
+
20
+ def setup
21
+
22
+ end
23
+
24
+ def teardown
25
+
26
+ end
27
+
28
+ def _increment_assertions
29
+ @_assertions ||= 0
30
+ @_assertions += 1
31
+ end
32
+
33
+ def assert test, msg = "failed assertion (no message given)"
34
+ _increment_assertions
35
+ raise StandardError, msg unless test
36
+ end
37
+
38
+ def assert_block msg = "assert_block failed."
39
+ assert yield, msg
40
+ end
41
+
42
+ def assert_equal exp, act, msg = ""
43
+ msg += '.' unless msg.empty?
44
+ assert exp == act, "#{msg}\n<#{exp.inspect}> expected but was\n<#{act.inspect}>.".strip
45
+ end
46
+
47
+ def self.main
48
+ TestRunner.run(self)
49
+ rescue StandardError => error
50
+ puts error
51
+ end
52
+
53
+ #
54
+ # def assert_in_delta exp, act, delta, msg = "Expected #{exp} to be within #{delta} of #{act}"
55
+ # assert delta.to_f > (exp.to_f - act.to_f).abs, msg
56
+ # end
57
+ #
58
+ # def assert_instance_of cls, obj, msg = "Expected #{obj.inspect} to be an instance of #{cls}"
59
+ # assert cls === obj, msg
60
+ # end
61
+ #
62
+ # def assert_kind_of cls, obj, msg = "Expected #{obj.inspect} to be a kind of #{cls}"
63
+ # assert obj.kind_of?(cls), msg
64
+ # end
65
+ #
66
+ # def assert_match exp, act, msg = "Expected #{act.inspect} to match #{exp.inspect}"
67
+ # assert act =~ exp, msg
68
+ # end
69
+ #
70
+ # def assert_nil obj, msg = "Expected #{obj.inspect} to be nil"
71
+ # assert obj.nil?, msg
72
+ # end
73
+ #
74
+ # def assert_no_match exp, act, msg = "Expected #{act.inspect} to not match #{exp.inspect}"
75
+ # assert act !~ exp, msg
76
+ # end
77
+ #
78
+ # def assert_not_equal exp, act, msg = "Expected #{act.inspect} to not be equal to #{exp.inspect}"
79
+ # assert exp != act, msg
80
+ # end
81
+ #
82
+ # def assert_not_nil obj, msg = "Expected #{obj.inspect} to not be nil"
83
+ # assert ! obj.nil?, msg
84
+ # end
85
+ #
86
+ # def assert_not_same exp, act, msg = "Expected #{act.inspect} to not be the same as #{exp.inspect}"
87
+ # assert ! exp.equal?(act), msg
88
+ # end
89
+ #
90
+ # def assert_nothing_raised
91
+ # _increment_assertions
92
+ # yield
93
+ # rescue => e
94
+ # raise StandardError, exception_details(e, "Exception raised:")
95
+ # end
96
+ #
97
+ # alias :assert_nothing_thrown :assert_nothing_raised
98
+ #
99
+ # def assert_operator o1, op, o2, msg = "<#{o1.inspect}> expected to be\n#{op.inspect}\n<#{o2.inspect}>."
100
+ # assert o1.__send__(op, o2), msg
101
+ # end
102
+ #
103
+ # def exception_details e, msg
104
+ # "#{msg}\nClass: <#{e.class}>\nMessage: <#{e.message.inspect}>\n---Backtrace---\n#{filter_backtrace(e.backtrace).join("\n")}\n---------------"
105
+ # end
106
+ #
107
+ # def assert_raises *exp
108
+ # msg = "" #exp.last.kind_of(String) ? exp.pop : nil
109
+ # exp = exp.first if exp.size == 1
110
+ # begin
111
+ # yield
112
+ # raise StandardError, "<#{exp.inspect}> exception expected but none was thrown."
113
+ # rescue Exception => e
114
+ # assert((Array === exp ? exp.include?(e) : exp === e),
115
+ # exception_details(e,
116
+ # "<#{exp.inspect}> exception expected but was"))
117
+ #
118
+ # return e
119
+ # end
120
+ # end
121
+ # alias :assert_raise :assert_raises
122
+ #
123
+ # def assert_respond_to obj, meth, msg = "Expected #{obj.inspect} of type #{obj.class} to respond_to? #{meth.inspect}"
124
+ # assert obj.respond_to?(meth), msg
125
+ # end
126
+ #
127
+ # def assert_same exp, act, msg = "Expected #{act.inspect} to be the same as #{exp.inspect}."
128
+ # assert exp.equal?(act), msg
129
+ # end
130
+ #
131
+ # def assert_send send, msg = nil
132
+ # recv, meth, *args = send
133
+ # assert(recv.__send__(meth, *args),
134
+ # msg || "<#{recv.inspect}> expected to respond to\n<#{meth.inspect}> with a true value.")
135
+ # end
136
+ #
137
+ # def assert_throws sym, msg = "<#{sym.inspect}> should have been thrown."
138
+ # caught = true
139
+ # catch(sym) do
140
+ # yield rescue nil
141
+ # caught = false
142
+ # end
143
+ # assert caught, msg
144
+ # end
145
+ #
146
+ # def flunk msg = "Flunked"
147
+ # assert false, msg
148
+ # end
149
+ end # class TestCase
150
+
151
+ class TestRunner
152
+
153
+ def self.puts(m)
154
+ message = m.to_s
155
+ `document.write(#<message>);`
156
+ end
157
+
158
+ def self.run(klass)
159
+ @failures, @errors, @assertions = 0,0,0
160
+ klass.instance_methods.each do |meth|
161
+ if (meth =~ /^test/)
162
+ inst = klass.new
163
+ begin
164
+ inst.setup
165
+ inst.send meth
166
+ puts "."
167
+ rescue Exception => e
168
+ puke(klass, meth, e)
169
+ ensure
170
+ begin
171
+ inst.teardown
172
+ rescue Exception => e
173
+ puke(klass, meth, e)
174
+ end
175
+ end
176
+ @assertions += inst._assertions
177
+ end
178
+ end
179
+ puts ("<br/>")
180
+ puts ("Assertions: #{@assertions} Failures: #{@failures}")
181
+ end
182
+
183
+ def self.puke(klass, meth, e)
184
+ puts e
185
+ @failures += 1
186
+ end
187
+ end
188
+ end
@@ -0,0 +1,293 @@
1
+ #
2
+ # Extract the class/module hierarchy and the methods.
3
+ #
4
+ # Copyright (c) 2007 by Michael Neumann (mneumann@ntecs.de).
5
+ # All rights reserved.
6
+ #
7
+
8
+ require 'parse_tree'
9
+ require 'sexp_processor'
10
+ require 'enumerator'
11
+ require 'rubyjs/encoder'
12
+ require 'set'
13
+
14
+ class MethodExtractor < SexpProcessor
15
+ attr_accessor :instance_methods, :methods
16
+
17
+ def initialize
18
+ super()
19
+
20
+ self.strict = false
21
+ self.auto_shift_type = false
22
+ self.require_empty = false
23
+
24
+ @instance_methods = {}
25
+ @methods = {}
26
+ end
27
+
28
+ def process_defs(exp)
29
+ defs, _self, name, code, *r = *exp
30
+ raise unless r.empty?
31
+ raise unless _self == s(:self)
32
+
33
+ @methods[name.to_s] = s(:defn, name, code)
34
+ return s()
35
+ end
36
+
37
+ def process_defn(exp)
38
+ defn, name, code, *r = *exp
39
+ raise unless r.empty?
40
+
41
+ @instance_methods[name.to_s] = exp
42
+ return s()
43
+ end
44
+ end
45
+
46
+ class Model < Encoder
47
+ SCOPE_R = /^RubyJS::Environment::(.*)$/
48
+
49
+ attr_accessor :models
50
+ attr_accessor :current_model
51
+
52
+ attr_reader :method_calls
53
+
54
+ def initialize
55
+ super()
56
+
57
+ #
58
+ # record all (potential) names of all method calls
59
+ #
60
+ @method_calls = Set.new
61
+
62
+
63
+ @models = {}
64
+
65
+ # all modules and classes (a Class is_a Module)
66
+ ObjectSpace.each_object {|o|
67
+ @models[o] = model_for(o) if o.is_a?(::Module) && o.name =~ SCOPE_R
68
+ }
69
+ end
70
+
71
+ def add_method_call(name)
72
+ @method_calls.add(name)
73
+ end
74
+
75
+ def iterate_all(seen, &block)
76
+ @models.each_value do |v|
77
+ iterate_rec(v, seen, &block)
78
+ end
79
+ end
80
+
81
+ def iterate_rec(model, seen, &block)
82
+ return if seen.include?(model[:for])
83
+ iterate_rec(@models[model[:superclass]], seen, &block) if model[:superclass]
84
+
85
+ model[:modules].each do |m|
86
+ iterate_rec(@models[m], seen, &block)
87
+ end
88
+
89
+ with_current_model(model) do
90
+ block.call(model)
91
+ end
92
+ seen.add(model[:for])
93
+ end
94
+
95
+ alias old_encode_constant encode_constant
96
+
97
+ def encode_constant(name)
98
+ if @current_model
99
+ lookup_constant(name)
100
+ else
101
+ old_encode_constant(name)
102
+ end
103
+ end
104
+
105
+ #
106
+ # Compile time constant lookup.
107
+ #
108
+ # Lookup rules (like Ruby 1.9+):
109
+ #
110
+ # 1. Current class
111
+ # 2. Super classes except object
112
+ # 3. lexically enclosing modules/classes
113
+ # 4. Object
114
+ #
115
+ def lookup_constant(name)
116
+ model = @current_model
117
+ prefix, *path = name.split("::")
118
+
119
+ start_lookup_at = nil
120
+ done = false
121
+
122
+ if prefix.empty?
123
+ # e.g. "::A"
124
+ start_lookup_at = RubyJS::Environment
125
+ done = true
126
+ else
127
+
128
+ # 1. Current class
129
+ if model[:for].constants.include?(prefix)
130
+ start_lookup_at = model[:for].const_get(prefix)
131
+ done = true
132
+ end
133
+
134
+ # 2. Super classes except object
135
+ unless done
136
+ m = model
137
+ loop do
138
+ if m[:superclass] and m[:superclass] != RubyJS::Environment::Object
139
+ if m[:superclass].constants.include?(prefix)
140
+ start_lookup_at = m[:superclass].const_get(prefix)
141
+ done = true
142
+ break
143
+ else
144
+ m = @models[m[:superclass]]
145
+ end
146
+ else
147
+ break
148
+ end
149
+ end
150
+ end
151
+
152
+ # 3. lexically enclosing modules/classes
153
+ # FIXME
154
+ unless done
155
+ arr = model[:name].split("::")
156
+ loop do
157
+ arr.pop
158
+
159
+ begin
160
+ start_lookup_at = eval((["RubyJS", "Environment"] + arr + [prefix]).join("::"))
161
+ done = true
162
+ break
163
+ rescue NameError
164
+ end
165
+
166
+ break if arr.empty?
167
+ end
168
+ end
169
+
170
+ # 4. Object
171
+ unless done
172
+ begin
173
+ start_lookup_at = RubyJS::Environment::Object.const_get(prefix)
174
+ done = true
175
+ rescue NameError
176
+ end
177
+ end
178
+
179
+ end
180
+
181
+ unless done
182
+ raise "failed to lookup constant prefix #{prefix}"
183
+ end
184
+
185
+ #
186
+ # follow the whole path, e.g. A::B::C
187
+ #
188
+ value = start_lookup_at
189
+ path.each do |piece|
190
+ value = value.const_get(piece)
191
+ end
192
+
193
+ if value.is_a?(::Class) or value.is_a?(::Module)
194
+ # A class or module
195
+
196
+ if model = @models[value]
197
+ return old_encode_constant(model[:name])
198
+ else
199
+ raise("unrecognized class/module referenced by constant")
200
+ end
201
+ else
202
+ # A value
203
+ if value.is_a?(Fixnum)
204
+ # If it is the receiver of a method call, we have to surround it
205
+ # with parens, e.g. (1).
206
+ # As we can't easily decide whether it's a receiver of a method
207
+ # call, we simply surround every constant Fixnum with parens.
208
+ return "(" + value.inspect + ")"
209
+ elsif value.is_a?(String)
210
+ # FIXME: Generate a reference instead?
211
+ return value.inspect
212
+ else
213
+ raise
214
+ end
215
+ end
216
+ end
217
+
218
+ def namify(klass)
219
+ name = klass.name
220
+ if name =~ SCOPE_R
221
+ name = $1
222
+ else
223
+ raise "must be scoped inside RubyJS module"
224
+ end
225
+ return name
226
+ end
227
+
228
+ def with_current_model(model)
229
+ old_current_model = @current_model
230
+ @current_model = model
231
+ begin
232
+ yield
233
+ ensure
234
+ @current_model = old_current_model
235
+ end
236
+ end
237
+
238
+ def model_for(klass)
239
+ name = namify(klass)
240
+
241
+ me = MethodExtractor.new
242
+ me.process(*ParseTree.new.parse_tree(klass))
243
+
244
+ if klass.is_a?(::Class)
245
+ a = klass.ancestors
246
+ a = a[0...(a.index(::Object))]
247
+
248
+ s = klass.superclass
249
+ s = nil if s == ::Object
250
+
251
+ # remove klass from the ancestor chain
252
+ a = a[1..-1] if a[0] == klass
253
+
254
+ # a now contains the included modules
255
+ a = a[0...(a.index(s))] if s
256
+
257
+ if klass == RubyJS::Environment::Object
258
+ raise unless s.nil?
259
+ s = nil
260
+ else
261
+ if s.nil?
262
+ s = RubyJS::Environment::Object
263
+ end
264
+ end
265
+
266
+ return {
267
+ :for => klass,
268
+ :modules => a,
269
+ :superclass => s,
270
+ :is_a => :class,
271
+ :name => name,
272
+ :instance_methods => me.instance_methods,
273
+ :methods => me.methods
274
+ }
275
+ elsif klass.is_a?(::Module)
276
+ a = klass.ancestors
277
+
278
+ # remove klass from the ancestor chain
279
+ a = a[1..-1] if a[0] == klass
280
+
281
+ return {
282
+ :for => klass,
283
+ :modules => a,
284
+ :is_a => :module,
285
+ :name => name,
286
+ :instance_methods => me.instance_methods,
287
+ :methods => me.methods
288
+ }
289
+ else
290
+ raise
291
+ end
292
+ end
293
+ end