superchris-rubyjs 0.8.2

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 (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