opal 0.3.19 → 0.3.20

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 (66) hide show
  1. data/.gitignore +3 -1
  2. data/Gemfile +3 -2
  3. data/README.md +304 -48
  4. data/Rakefile +1 -2
  5. data/core/alpha.rb +2 -1
  6. data/core/array.rb +92 -96
  7. data/core/basic_object.rb +1 -10
  8. data/core/boolean.rb +6 -18
  9. data/core/class.rb +9 -10
  10. data/core/comparable.rb +1 -1
  11. data/core/enumerable.rb +11 -11
  12. data/core/enumerator.rb +2 -10
  13. data/core/error.rb +16 -31
  14. data/core/hash.rb +32 -36
  15. data/core/json.rb +50 -0
  16. data/core/kernel.rb +48 -57
  17. data/core/load_order +3 -5
  18. data/core/module.rb +37 -35
  19. data/core/nil_class.rb +4 -0
  20. data/core/numeric.rb +10 -30
  21. data/core/proc.rb +1 -1
  22. data/core/range.rb +3 -4
  23. data/core/regexp.rb +21 -6
  24. data/core/runtime.js +278 -370
  25. data/core/string.rb +21 -37
  26. data/core/struct.rb +11 -3
  27. data/core/time.rb +44 -37
  28. data/lib/opal.rb +3 -3
  29. data/lib/opal/builder.rb +48 -27
  30. data/lib/opal/builder_task.rb +3 -20
  31. data/lib/opal/grammar.rb +18 -13
  32. data/lib/opal/grammar.y +7 -4
  33. data/lib/opal/parser.rb +290 -199
  34. data/lib/opal/scope.rb +187 -176
  35. data/lib/opal/version.rb +1 -1
  36. data/test/core/kernel/define_singleton_method_spec.rb +21 -0
  37. data/test/core/time/at_spec.rb +7 -0
  38. data/test/core/time/day_spec.rb +5 -0
  39. data/test/core/time/friday_spec.rb +9 -0
  40. data/test/core/time/hour_spec.rb +5 -0
  41. data/test/core/time/min_spec.rb +5 -0
  42. data/test/core/time/monday_spec.rb +9 -0
  43. data/test/core/time/month_spec.rb +5 -0
  44. data/test/core/time/now_spec.rb +5 -0
  45. data/test/core/time/saturday_spec.rb +9 -0
  46. data/test/index.html +2 -1
  47. data/test/language/singleton_class_spec.rb +0 -16
  48. data/test/opal/array/to_json_spec.rb +7 -0
  49. data/test/opal/boolean/singleton_class_spec.rb +9 -0
  50. data/test/opal/boolean/to_json_spec.rb +9 -0
  51. data/test/opal/hash/to_json_spec.rb +9 -0
  52. data/test/opal/json/parse_spec.rb +31 -0
  53. data/test/opal/kernel/to_json_spec.rb +5 -0
  54. data/test/opal/nil/to_json_spec.rb +5 -0
  55. data/test/opal/numeric/to_json_spec.rb +6 -0
  56. data/test/opal/runtime/call_spec.rb +16 -0
  57. data/test/opal/runtime/defined_spec.rb +11 -0
  58. data/test/opal/runtime/super_spec.rb +16 -0
  59. data/test/opal/string/to_json_spec.rb +6 -0
  60. data/test/spec_helper.rb +1 -3
  61. metadata +48 -15
  62. data/core/dir.rb +0 -89
  63. data/core/file.rb +0 -85
  64. data/core/match_data.rb +0 -35
  65. data/core/rational.rb +0 -16
  66. data/test/core/file/expand_path_spec.rb +0 -20
@@ -20,10 +20,11 @@ class Regexp < `RegExp`
20
20
  var result = this.exec(string);
21
21
 
22
22
  if (result) {
23
- var match = new #{MatchData}._alloc();
24
- match.$data = result;
23
+ result.$to_s = match_to_s;
24
+ result.$inspect = match_inspect;
25
+ result._real = result._klass = #{ MatchData };
25
26
 
26
- #{$~ = `match`};
27
+ #{$~ = `result`};
27
28
  }
28
29
  else {
29
30
  #{$~ = nil};
@@ -44,10 +45,11 @@ class Regexp < `RegExp`
44
45
  var result = this.exec(pattern);
45
46
 
46
47
  if (result) {
47
- var match = new #{MatchData}._alloc();
48
- match.$data = result;
48
+ result.$to_s = match_to_s;
49
+ result.$inspect = match_inspect;
50
+ result._real = result._klass = #{ MatchData };
49
51
 
50
- return #{$~ = `match`};
52
+ return #{$~ = `result`};
51
53
  }
52
54
  else {
53
55
  return #{$~ = nil};
@@ -58,4 +60,17 @@ class Regexp < `RegExp`
58
60
  def to_s
59
61
  `this.source`
60
62
  end
63
+
64
+ %x{
65
+ function match_inspect() {
66
+ return "<#MatchData " + this[0].$inspect() + ">";
67
+ }
68
+
69
+ function match_to_s() {
70
+ return this[0];
71
+ }
72
+ }
61
73
  end
74
+
75
+ class MatchData
76
+ end
@@ -1,14 +1,35 @@
1
- // Top level Object scope (used by object and top_self).
2
- var top_const_alloc = function(){};
3
- var top_const_scope = top_const_alloc.prototype;
4
- top_const_scope.alloc = top_const_alloc;
1
+ // The Opal object that is exposed globally
2
+ var Opal = this.Opal = {};
5
3
 
6
- var Opal = this.Opal = top_const_scope;
4
+ // Very root class
5
+ function BasicObject(){}
7
6
 
7
+ // Core Object class
8
+ function Object(){}
9
+
10
+ // Class' class
11
+ function Class(){}
12
+
13
+ // Modules are just classes that cannot be instantiated
14
+ var Module = Class;
15
+
16
+ // the class of nil
17
+ function NilClass(){}
18
+
19
+ // TopScope is used for inheriting constants from the top scope
20
+ var TopScope = function(){};
21
+
22
+ // Opal just acts as the top scope
23
+ TopScope.prototype = Opal;
24
+
25
+ // To inherit scopes
26
+ Opal.alloc = TopScope;
27
+
28
+ // This is a useful reference to global object inside ruby files
8
29
  Opal.global = this;
9
30
 
10
31
  // Minify common function calls
11
- var __hasOwn = Object.prototype.hasOwnProperty;
32
+ var __hasOwn = Opal.hasOwnProperty;
12
33
  var __slice = Opal.slice = Array.prototype.slice;
13
34
 
14
35
  // Generates unique id for every ruby object
@@ -20,35 +41,80 @@ Opal.cvars = {};
20
41
  // Globals table
21
42
  Opal.gvars = {};
22
43
 
23
- Opal.klass = function(base, superklass, id, body) {
44
+ // Runtime method used to either define a new class, or re-open an old
45
+ // class. The base may be an object (rather than a class), which is
46
+ // always the case when defining classes in the top level as the top
47
+ // level is just the 'main' Object instance.
48
+ //
49
+ // The given ruby code:
50
+ //
51
+ // class Foo
52
+ // 42
53
+ // end
54
+ //
55
+ // class Bar < Foo
56
+ // 3.142
57
+ // end
58
+ //
59
+ // Would be compiled to something like:
60
+ //
61
+ // var __klass = Opal.klass;
62
+ //
63
+ // __klass(this, null, 'Foo', function() {
64
+ // return 42;
65
+ // });
66
+ //
67
+ // __klass(this, __scope.Foo, 'Bar', function() {
68
+ // return 3.142;
69
+ // });
70
+ //
71
+ // @param [RubyObject] base the scope in which to define the class
72
+ // @param [RubyClass] superklass the superklass, may be null
73
+ // @param [String] id the name for the class
74
+ // @param [Function] body the class body
75
+ // @return returns last value from running body
76
+ Opal.klass = function(base, superklass, id, constructor) {
24
77
  var klass;
25
78
  if (base._isObject) {
26
79
  base = base._real;
27
80
  }
28
81
 
29
82
  if (superklass === null) {
30
- superklass = RubyObject;
83
+ superklass = Object;
31
84
  }
32
85
 
33
86
  if (__hasOwn.call(base._scope, id)) {
34
87
  klass = base._scope[id];
35
88
  }
36
- else if (!superklass._klass || !superklass._proto) {
37
- klass = bridge_class(superklass, id);
38
- }
39
89
  else {
40
- klass = define_class(base, id, superklass);
90
+ if (!superklass._methods) {
91
+ var bridged = superklass;
92
+ superklass = Object;
93
+ klass = bridge_class(bridged);
94
+ }
95
+ else {
96
+ klass = boot_class(superklass, constructor);
97
+ }
98
+
99
+ klass._name = (base === Object ? id : base._name + '::' + id);
100
+
101
+ var const_alloc = function() {};
102
+ var const_scope = const_alloc.prototype = new base._scope.alloc();
103
+ klass._scope = const_scope;
104
+ const_scope.alloc = const_alloc;
105
+
106
+ base[id] = base._scope[id] = klass;
107
+
108
+ if (superklass.$inherited) {
109
+ superklass.$inherited(klass);
110
+ }
41
111
  }
42
112
 
43
- return body.call(klass);
113
+ return klass;
44
114
  };
45
115
 
46
- Opal.sklass = function(shift, body) {
47
- var klass = shift.$singleton_class();
48
- return body.call(klass);
49
- }
50
-
51
- Opal.module = function(base, id, body) {
116
+ // Define new module (or return existing module)
117
+ Opal.module = function(base, id, constructor) {
52
118
  var klass;
53
119
  if (base._isObject) {
54
120
  base = base._real;
@@ -58,10 +124,8 @@ Opal.module = function(base, id, body) {
58
124
  klass = base._scope[id];
59
125
  }
60
126
  else {
61
- klass = boot_module();
62
- klass._name = (base === RubyObject ? id : base._name + '::' + id);
63
-
64
- make_metaclass(klass, RubyModule);
127
+ klass = boot_module(constructor, id);
128
+ klass._name = (base === Object ? id : base._name + '::' + id);
65
129
 
66
130
  klass._isModule = true;
67
131
  klass.$included_in = [];
@@ -71,268 +135,161 @@ Opal.module = function(base, id, body) {
71
135
  klass._scope = const_scope;
72
136
  const_scope.alloc = const_alloc;
73
137
 
74
- base._scope[id] = klass;
138
+ base[id] = base._scope[id] = klass;
75
139
  }
76
140
 
77
- return body.call(klass);
141
+ return klass;
78
142
  }
79
143
 
80
- /**
81
- This function serves two purposes. The first is to allow methods
82
- defined in modules to be included into classes that have included
83
- them. This is done at the end of a module body by calling this
84
- method will all the defined methods. They are then passed onto
85
- the includee classes.
86
-
87
- The second purpose is to store an array of all the methods defined
88
- directly in this class or module. This makes features such as
89
- #methods and #instance_methods work. It is also used internally to
90
- create subclasses of Arrays, as an annoyance with javascript is that
91
- arrays cannot be subclassed (or they can't without problems arrising
92
- with tracking the array length). Therefore, when a new instance of a
93
- subclass is created, behind the scenes we copy all the methods from
94
- the subclass onto an array prototype.
95
-
96
- If the includee is also included into other modules or classes, then
97
- this method will also set up donations for that module. If this is
98
- the case, then 'indirect' will be set to true as we don't want those
99
- modules/classes to think they had that method set on themselves. This
100
- stops `Object` thinking it defines `#sprintf` when it is actually
101
- `Kernel` that defines that method. Indirect is false by default when
102
- called by generated code in the compiler output.
103
-
104
- @param [RubyClass] klass the class or module that defined methods
105
- @param [Array<String>] methods an array of jsid method names defined
106
- @param [Boolean] indirect whether this is an indirect method define
107
- */
108
- Opal.donate = function(klass, methods, indirect) {
109
- var included_in = klass.$included_in, includee, method,
110
- table = klass._proto, dest;
111
-
112
- if (!indirect) {
113
- klass._methods = klass._methods.concat(methods);
114
- }
115
-
116
- if (included_in) {
117
- for (var i = 0, length = included_in.length; i < length; i++) {
118
- includee = included_in[i];
119
- dest = includee._proto;
120
-
121
- for (var j = 0, jj = methods.length; j < jj; j++) {
122
- method = methods[j];
123
- dest[method] = table[method];
124
- }
125
-
126
- if (includee.$included_in) {
127
- Opal.donate(includee, methods, true);
128
- }
129
- }
130
- }
131
- };
132
-
133
- var mid_to_jsid = Opal.mid_to_jsid = function(mid) {
134
- if (method_names[mid]) {
135
- return method_names[mid];
136
- }
137
-
138
- return '$' + mid.replace('!', '$b').replace('?', '$p').replace('=', '$e');
139
- };
140
-
141
- var jsid_to_mid = Opal.jsid_to_mid = function(jsid) {
142
- if (reverse_method_names[jsid]) {
143
- return reverse_method_names[jsid];
144
- }
145
-
146
- jsid = jsid.substr(1); // remove '$'
147
-
148
- return jsid.replace('$b', '!').replace('$p', '?').replace('$e', '=');
144
+ // Convert a ruby method name into a javascript identifier
145
+ var mid_to_jsid = function(mid) {
146
+ return method_names[mid] ||
147
+ ('$' + mid.replace('!', '$b').replace('?', '$p').replace('=', '$e'));
149
148
  };
150
149
 
150
+ // Utility function to raise a "no block given" error
151
151
  var no_block_given = function() {
152
152
  throw new Error('no block given');
153
153
  };
154
154
 
155
- // Boot a base class (makes instances).
156
- function boot_defclass(superklass) {
157
- var cls = function() {
158
- this._id = unique_id++;
159
- };
155
+ // An array of all classes inside Opal. Used for donating methods from
156
+ // Module and Class.
157
+ var classes = Opal.classes = [];
160
158
 
159
+ // Boot a base class (makes instances).
160
+ var boot_defclass = function(id, constructor, superklass) {
161
161
  if (superklass) {
162
162
  var ctor = function() {};
163
163
  ctor.prototype = superklass.prototype;
164
164
 
165
- cls.prototype = new ctor();
165
+ constructor.prototype = new ctor();
166
166
  }
167
167
 
168
- cls.prototype.constructor = cls;
169
- cls.prototype._isObject = true;
168
+ var prototype = constructor.prototype;
170
169
 
171
- return cls;
172
- }
173
-
174
- // Boot actual (meta classes) of core objects.
175
- function boot_makemeta(id, klass, superklass) {
176
- var meta = function() {
177
- this._id = unique_id++;
178
- };
170
+ prototype.constructor = constructor;
171
+ prototype._isObject = true;
172
+ prototype._klass = constructor;
173
+ prototype._real = constructor;
179
174
 
180
- var ctor = function() {};
181
- ctor.prototype = superklass.prototype;
175
+ constructor._included_in = [];
176
+ constructor._isClass = true;
177
+ constructor._name = id;
178
+ constructor._super = superklass;
179
+ constructor._methods = [];
180
+ constructor._smethods = [];
181
+ constructor._isObject = false;
182
+ constructor._subclasses = [];
182
183
 
183
- meta.prototype = new ctor();
184
+ constructor._donate = __donate;
185
+ constructor._sdonate = __sdonate;
184
186
 
185
- var proto = meta.prototype;
186
- proto.$included_in = [];
187
- proto._alloc = klass;
188
- proto._isClass = true;
189
- proto._name = id;
190
- proto._super = superklass;
191
- proto.constructor = meta;
192
- proto._methods = [];
193
- proto._isObject = false;
187
+ Opal[id] = constructor;
194
188
 
195
- var result = new meta();
196
- klass.prototype._klass = result;
197
- klass.prototype._real = result;
189
+ classes.push(constructor);
198
190
 
199
- result._proto = klass.prototype;
200
-
201
- top_const_scope[id] = result;
202
-
203
- return result;
204
- }
191
+ return constructor;
192
+ };
205
193
 
206
194
  // Create generic class with given superclass.
207
- function boot_class(superklass) {
208
- // instances
209
- var cls = function() {
210
- this._id = unique_id++;
211
- };
212
-
195
+ var boot_class = function(superklass, constructor) {
213
196
  var ctor = function() {};
214
- ctor.prototype = superklass._alloc.prototype;
215
-
216
- cls.prototype = new ctor();
217
-
218
- var proto = cls.prototype;
219
- proto.constructor = cls;
220
- proto._isObject = true;
221
-
222
- // class itself
223
- var meta = function() {
224
- this._id = unique_id++;
225
- };
226
-
227
- var mtor = function() {};
228
- mtor.prototype = superklass.constructor.prototype;
229
-
230
- meta.prototype = new mtor();
197
+ ctor.prototype = superklass.prototype;
231
198
 
232
- proto = meta.prototype;
233
- proto._alloc = cls;
234
- proto._isClass = true;
235
- proto.constructor = meta;
236
- proto._super = superklass;
237
- proto._methods = [];
199
+ constructor.prototype = new ctor();
200
+ var prototype = constructor.prototype;
238
201
 
239
- var result = new meta();
240
- cls.prototype._klass = result;
241
- cls.prototype._real = result;
202
+ prototype._klass = constructor;
203
+ prototype._real = constructor;
204
+ prototype.constructor = constructor;
242
205
 
243
- result._proto = cls.prototype;
206
+ constructor._included_in = [];
207
+ constructor._isClass = true;
208
+ constructor._super = superklass;
209
+ constructor._methods = [];
210
+ constructor._isObject = false;
211
+ constructor._klass = Class;
212
+ constructor._real = Class;
213
+ constructor._donate = __donate
214
+ constructor._sdonate = __sdonate;
215
+ constructor._subclasses = [];
244
216
 
245
- return result;
246
- }
217
+ constructor.$eqq$ = module_eqq;
247
218
 
248
- function boot_module() {
249
- // where module "instance" methods go. will never be instantiated so it
250
- // can be a regular object
251
- var module_cons = function(){};
252
- var module_inst = module_cons.prototype;
219
+ superklass._subclasses.push(constructor);
253
220
 
254
- // Module itself
255
- var meta = function() {
256
- this._id = unique_id++;
257
- };
221
+ var smethods;
258
222
 
259
- var mtor = function(){};
260
- mtor.prototype = RubyModule.constructor.prototype;
261
- meta.prototype = new mtor();
223
+ smethods = superklass._smethods.slice();
262
224
 
263
- var proto = meta.prototype;
225
+ constructor._smethods = smethods;
226
+ for (var i = 0, length = smethods.length; i < length; i++) {
227
+ var m = smethods[i];
228
+ constructor[m] = superklass[m];
229
+ }
264
230
 
265
- proto._alloc = module_cons;
266
- proto._isModule = true;
267
- proto.constructor = meta;
268
- proto._super = null;
269
- proto._methods = [];
231
+ classes.push(constructor);
270
232
 
271
- var module = new meta();
272
- module._proto = module_inst;
233
+ return constructor;
234
+ };
273
235
 
274
- return module;
275
- }
236
+ var boot_module = function(constructor, id) {
237
+ var ctor = function() {};
238
+ ctor.prototype = Module.prototype;
276
239
 
277
- // Make metaclass for the given class
278
- function make_metaclass(klass, superklass) {
279
- if (klass._isClass) {
280
- if (klass._isSingleton) {
281
- throw RubyException.$new('too much meta: return klass?');
282
- }
283
- else {
284
- var class_id = "#<Class:" + klass._name + ">",
285
- meta = boot_class(superklass);
240
+ constructor.prototype = new ctor();
241
+ var prototype = constructor.prototype;
286
242
 
287
- meta._name = class_id;
288
- meta._alloc.prototype = klass.constructor.prototype;
289
- meta._proto = meta._alloc.prototype;
290
- meta._isSingleton = true;
291
- meta._klass = RubyClass;
292
- meta._real = RubyClass;
243
+ prototype.constructor = constructor;
293
244
 
294
- klass._klass = meta;
245
+ constructor._isModule = true;
246
+ constructor._name = id;
247
+ constructor._methods = [];
248
+ constructor._smethods = [];
249
+ constructor._klass = Module;
250
+ constructor._donate = __donate;
251
+ constructor._sdonate = function(){};
295
252
 
296
- meta._scope = klass._scope;
297
- meta.__attached__ = klass;
253
+ classes.push(constructor);
298
254
 
299
- return meta;
300
- }
255
+ var smethods = constructor._smethods = Module._methods.slice();
256
+ for (var i = 0, length = smethods.length; i < length; i++) {
257
+ var m = smethods[i];
258
+ constructor[m] = Object[m];
301
259
  }
302
- else {
303
- var orig_class = klass._klass,
304
- class_id = "#<Class:#<" + orig_class._name + ":" + orig_class._id + ">>";
305
260
 
306
- var meta = boot_class(orig_class);
307
- meta._name = class_id;
261
+ return constructor;
262
+ };
308
263
 
309
- meta._isSingleton = true;
310
- meta._proto = klass;
311
- // FIXME: this should be removed. _proto should always point to this.
312
- meta._alloc.prototype = klass;
313
- klass._klass = meta;
314
- meta.__attached__ = klass;
315
- meta._klass = orig_class._real._klass
264
+ var bridge_class = function(constructor) {
265
+ constructor.prototype._klass = constructor;
266
+ constructor.prototype._real = constructor;
316
267
 
317
- return meta;
318
- }
319
- }
268
+ constructor._included_in = [];
269
+ constructor._isClass = true;
270
+ constructor._super = Object;
271
+ constructor._klass = Class;
272
+ constructor._methods = [];
273
+ constructor._smethods = [];
274
+ constructor._isObject = false;
275
+ constructor._subclasses = [];
320
276
 
321
- function bridge_class(constructor, id) {
322
- var klass = define_class(RubyObject, id, RubyObject),
323
- prototype = constructor.prototype;
277
+ constructor._donate = function(){};
278
+ constructor._sdonate = __sdonate;
324
279
 
325
- klass._alloc = constructor;
326
- klass._proto = prototype;
280
+ constructor.$eqq$ = module_eqq;
327
281
 
328
- bridged_classes.push(klass);
282
+ var smethods = constructor._smethods = Module._methods.slice();
283
+ for (var i = 0, length = smethods.length; i < length; i++) {
284
+ var m = smethods[i];
285
+ constructor[m] = Object[m];
286
+ }
329
287
 
330
- prototype._klass = klass;
331
- prototype._real = klass;
332
- prototype._isObject = true;
288
+ bridgedClasses.push(constructor);
289
+ classes.push(constructor);
333
290
 
334
291
  var allocator = function(initializer) {
335
- var result, kls = this, methods = kls._methods, proto = kls._proto;
292
+ var result, kls = this, methods = kls._methods, proto = kls.prototype;
336
293
 
337
294
  if (initializer == null) {
338
295
  result = new constructor
@@ -341,7 +298,7 @@ function bridge_class(constructor, id) {
341
298
  result = new constructor(initializer);
342
299
  }
343
300
 
344
- if (kls === klass) {
301
+ if (kls === constructor) {
345
302
  return result;
346
303
  }
347
304
 
@@ -356,71 +313,32 @@ function bridge_class(constructor, id) {
356
313
  return result;
357
314
  };
358
315
 
359
- klass.constructor.prototype.$allocate = allocator;
316
+ var table = Object.prototype, methods = Object._methods;
360
317
 
361
- var donator = RubyObject, table, methods;
362
-
363
- while (donator) {
364
- table = donator._proto;
365
- methods = donator._methods;
366
-
367
- for (var i = 0, length = methods.length; i < length; i++) {
368
- var method = methods[i];
369
- prototype[method] = table[method];
370
- }
371
-
372
- donator = donator._super;
318
+ for (var i = 0, length = methods.length; i < length; i++) {
319
+ var m = methods[i];
320
+ constructor.prototype[m] = table[m];
373
321
  }
374
322
 
375
- return klass;
376
- }
323
+ constructor.$allocate = allocator;
377
324
 
378
- /**
379
- Actually define a new class with the name `id`. The superklass is
380
- required, and Object is currently the root class. The base is the
381
- parent scope of this class. For example, defining a root `Foo`
382
- class would have `Object` as the parent. Defining `Foo::Bar` would
383
- use `Foo` as the parent.
384
-
385
- @param [RubyClass] base the base class/module for this new class
386
- @param [String] id the name for this class
387
- @param [RubyClass] superklass the super class
388
- @return [RubyClass] returns new class with given attributes
389
- */
390
- function define_class(base, id, superklass) {
391
- var klass = boot_class(superklass);
392
- klass._name = (base === RubyObject ? id : base._name + '::' + id);
393
-
394
- make_metaclass(klass, superklass._klass);
395
-
396
- var const_alloc = function() {};
397
- var const_scope = const_alloc.prototype = new base._scope.alloc();
398
- klass._scope = const_scope;
399
- const_scope.alloc = const_alloc;
400
-
401
- base._scope[id] = klass;
402
-
403
- if (superklass.$inherited) {
404
- superklass.$inherited(klass);
405
- }
325
+ constructor._smethods.push('$allocate');
406
326
 
407
- return klass;
408
- }
327
+ return constructor;
328
+ };
409
329
 
410
- /**
411
- An IClass is a fake class created when a module is included into a
412
- class or another module. It is a "copy" of the module that is then
413
- injected into the hierarchy so it appears internally that the iclass
414
- is the super of the class instead of the old super class. This is
415
- actually hidden from the ruby side of things, but allows internal
416
- features such as super() etc to work. All useful properties from the
417
- module are copied onto this iclass.
418
-
419
- @param [RubyClass] klass the klass which is including the module
420
- @param [RubyModule] module the module which is being included
421
- @return [RubyIClass] returns newly created iclass
422
- */
423
- function define_iclass(klass, module) {
330
+ // An IClass is a fake class created when a module is included into a
331
+ // class or another module. It is a "copy" of the module that is then
332
+ // injected into the hierarchy so it appears internally that the iclass
333
+ // is the super of the class instead of the old super class. This is
334
+ // actually hidden from the ruby side of things, but allows internal
335
+ // features such as super() etc to work. All useful properties from the
336
+ // module are copied onto this iclass.
337
+ //
338
+ // @param [RubyClass] klass the klass which is including the module
339
+ // @param [RubyModule] module the module which is being included
340
+ // @return [RubyIClass] returns newly created iclass
341
+ var define_iclass = function(klass, module) {
424
342
  var iclass = {
425
343
  _proto: module._proto,
426
344
  _super: klass._super,
@@ -433,112 +351,102 @@ function define_iclass(klass, module) {
433
351
  klass._super = iclass;
434
352
 
435
353
  return iclass;
436
- }
437
-
438
- /**
439
- This is a map of all file ids to their bodies. The file id is the
440
- id used to require a file, and it does not have an extension name.
354
+ };
441
355
 
442
- @type { String: Function }
443
- */
444
- var factories = Opal.factories = {};
356
+ // Initialization
357
+ // --------------
445
358
 
446
- /**
447
- This holds the name of the current file being executed by opal. This
448
- gets set in require() below and it allows the file to get the
449
- __FILE__ variable. This should never be accessed manually.
359
+ boot_defclass('BasicObject', BasicObject);
360
+ boot_defclass('Object', Object, BasicObject);
361
+ boot_defclass('Class', Class, Object);
450
362
 
451
- @type {String}
452
- */
453
- Opal.file = "";
363
+ Class.prototype = Function.prototype;
454
364
 
455
- /**
456
- Register the body for the given file id name. This will then allow
457
- the file to be loaded with require().
365
+ BasicObject._klass = Object._klass = Class._klass = Class;
458
366
 
459
- @param [String] id the file id
460
- @param [Function] body the body representing the file
461
- */
462
- Opal.define = function(id, body) {
463
- factories[id] = body;
367
+ Module._donate = function(defined) {
368
+ // ...
464
369
  };
465
370
 
466
- /**
467
- Require a specific file by id.
371
+ // Implementation of Module#===
372
+ function module_eqq(object) {
373
+ if (object == null) {
374
+ return false;
375
+ }
468
376
 
469
- @param [String] id file id to require
470
- @return [Boolean] if file has already been required
471
- */
472
- Opal.require = function(id) {
473
- var body = factories[id];
377
+ var search = object._klass;
474
378
 
475
- if (!body) {
476
- throw new Error("No file: '" + id + "'");
477
- }
379
+ while (search) {
380
+ if (search === this) {
381
+ return true;
382
+ }
478
383
 
479
- if (body._loaded) {
480
- return false;
384
+ search = search._super;
481
385
  }
482
386
 
483
- Opal.file = id;
387
+ return false;
388
+ }
484
389
 
485
- body._loaded = true;
486
- body.call(Opal.top);
390
+ // Donator for all 'normal' classes and modules
391
+ function __donate(defined, indirect) {
392
+ var methods = this._methods, included_in = this.$included_in;
487
393
 
488
- return true;
489
- };
394
+ if (!indirect) {
395
+ this._methods = methods.concat(defined);
396
+ }
490
397
 
491
- // Initialization
492
- // --------------
398
+ if (included_in) {
399
+ for (var i = 0, length = included_in.length; i < length; i++) {
400
+ var includee = included_in[i];
401
+ var dest = includee.prototype;
493
402
 
494
- // The *instances* of core objects
495
- var BootBasicObject = boot_defclass();
496
- var BootObject = boot_defclass(BootBasicObject);
497
- var BootModule = boot_defclass(BootObject);
498
- var BootClass = boot_defclass(BootModule);
403
+ for (var j = 0, jj = defined.length; j < jj; j++) {
404
+ var method = defined[j];
405
+ dest[method] = this.prototype[method];
406
+ }
499
407
 
500
- // The *classes' of core objects
501
- var RubyBasicObject = boot_makemeta('BasicObject', BootBasicObject, BootClass);
502
- var RubyObject = boot_makemeta('Object', BootObject, RubyBasicObject.constructor);
503
- var RubyModule = boot_makemeta('Module', BootModule, RubyObject.constructor);
504
- var RubyClass = boot_makemeta('Class', BootClass, RubyModule.constructor);
408
+ if (includee.$included_in) {
409
+ includee._donate(defined, true);
410
+ }
411
+ }
505
412
 
506
- // Fix boot classes to use meta class
507
- RubyBasicObject._klass = RubyClass;
508
- RubyObject._klass = RubyClass;
509
- RubyModule._klass = RubyClass;
510
- RubyClass._klass = RubyClass;
413
+ }
414
+ }
415
+
416
+ // Donator for singleton (class) methods
417
+ function __sdonate(defined) {
418
+ var smethods = this._smethods, subclasses = this._subclasses;
419
+
420
+ this._smethods = smethods.concat(defined);
511
421
 
512
- // fix superclasses
513
- RubyBasicObject._super = null;
514
- RubyObject._super = RubyBasicObject;
515
- RubyModule._super = RubyObject;
516
- RubyClass._super = RubyModule;
422
+ for (var i = 0, length = subclasses.length; i < length; i++) {
423
+ var s = subclasses[i];
517
424
 
518
- var bridged_classes = RubyObject.$included_in = [];
519
- RubyBasicObject.$included_in = bridged_classes;
425
+ for (var j = 0, jj = defined.length; j < jj; j++) {
426
+ }
427
+ }
428
+ }
520
429
 
521
- RubyObject._scope = RubyBasicObject._scope = top_const_scope;
430
+ var bridgedClasses = Object.$included_in = [];
431
+ BasicObject.$included_in = bridgedClasses;
522
432
 
523
- var module_const_alloc = function(){};
524
- var module_const_scope = new top_const_alloc();
525
- module_const_scope.alloc = module_const_alloc;
526
- RubyModule._scope = module_const_scope;
433
+ BasicObject._scope = Object._scope = Opal;
434
+ Opal.Module = Opal.Class;
435
+ Opal.Kernel = Object;
527
436
 
528
437
  var class_const_alloc = function(){};
529
- var class_const_scope = new top_const_alloc();
438
+ var class_const_scope = new TopScope();
530
439
  class_const_scope.alloc = class_const_alloc;
531
- RubyClass._scope = class_const_scope;
440
+ Class._scope = class_const_scope;
532
441
 
533
- RubyObject._proto.toString = function() {
442
+ Object.prototype.toString = function() {
534
443
  return this.$to_s();
535
444
  };
536
445
 
537
- Opal.top = new RubyObject._alloc();
446
+ Opal.top = new Object;
538
447
 
539
- var RubyNilClass = define_class(RubyObject, 'NilClass', RubyObject);
540
- Opal.nil = new RubyNilClass._alloc();
448
+ Opal.klass(Object, Object, 'NilClass', NilClass)
449
+ Opal.nil = new NilClass;
541
450
  Opal.nil.call = Opal.nil.apply = no_block_given;
542
451
 
543
- var breaker = Opal.breaker = new Error('unexpected break');
544
- breaker.$t = function() { throw this; };
452
+ Opal.breaker = new Error('unexpected break');